difftreelog
refactor(evaluator) use static analysis
in: master
31 files changed
Cargo.lockdiffbeforeafterboth242 packageslockfile v4
Might be heavy and slow!
ahash
0.8.12crates.io↘ 5↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75used byaho-corasick
1.1.4crates.io↘ 1↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301depends onaliasable
0.1.3crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fdused byalloca
0.4.0crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksume5a7d05ea6aea7e9e64d25b9156ba2fee3fdd659e34e41063cd2fc7cd020d7f4depends onused byallocator-api2
0.2.21crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923anes
0.1.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299used byannotate-snippets
0.12.14crates.io↘ 3↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum22b669bf35e50f130e98212b486b0df78d93e285963344e58937692705e1a21aannotated-string
0.3.0crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum298ed730801db3c02f2edba003c9420a0f57ea48d37fdc5601c536113668c059used byanstream
1.0.0crates.io↘ 7↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28ddepends onused byanstyle
1.0.14crates.io↘ 0↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000anstyle-parse
1.0.0crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130edepends onused byanstyle-query
1.1.5crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadcdepends onused byanstyle-wincon
3.0.11crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747dused byanyhow
1.0.102crates.io↘ 0↖ 10sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842car_archive_writer
0.5.1crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum7eb93bbb63b9c227414f6eb3a0adfddca591a8ce1e9b60661bb08969b87e340bdepends onused byarraydeque
0.5.1crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236used byautocfg
1.5.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumc08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8used bybase64
0.22.1crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6bitflags
2.11.0crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92afbitmaps
2.1.0crates.io↘ 1↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2depends onused byblock-buffer
0.10.4crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71depends onused bybstr
1.12.1crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cabdepends onused bybumpalo
3.20.2crates.io↘ 1↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcbdepends oncast
0.3.0crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5cc
1.2.59crates.io↘ 2↖ 5sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumb7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283depends oncfg-if
1.0.4crates.io↘ 0↖ 9sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801ciborium
0.2.2crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0eused byciborium-io
0.2.2crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757ciborium-ll
0.2.2crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9depends onused byclap
4.6.0crates.io↘ 2↖ 7sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumb193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351depends onclap_builder
4.6.0crates.io↘ 4↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069fused byclap_complete
4.6.0crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum19c9f1dde76b736e3681f28cec9d5a61299cbaae0fce80a68e43724ad56031ebdepends onused byclap_derive
4.6.0crates.io↘ 4↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6aused byclap_lex
1.1.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumc8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9used bycolorchoice
1.0.5crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570used byconsole
0.16.3crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd64e8af5551369d19cf50138de61f1c42074ab970f74e99be916646777f8fc87used bycountme
3.0.1crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636used bycpufeatures
0.2.17crates.io↘ 1↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280depends oncriterion
0.8.2crates.io↘ 17↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum950046b2aa2492f9a536f5f4f9a3de7b9e2476e575e05bd6c333371add4d98f3depends onused bycriterion-plot
0.8.2crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd8d80a2f4f5b554395e47b5d8305bc3d27813bacb73493eb1001e8f76dae29eadepends onused bycrossbeam-deque
0.8.6crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51used bycrossbeam-epoch
0.9.18crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420edepends onused bycrossbeam-utils
0.8.21crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28crypto-common
0.1.7crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60adepends onused bydigest
0.10.7crates.io↘ 2↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292depends ondprint-core
0.67.4crates.io↘ 7↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum2c1d827947704a9495f705d6aeed270fa21a67f825f22902c28f38dc3af7a9aedepends ondrop_bomb
0.1.5crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1educe
0.6.0crates.io↘ 4↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417either
1.15.0crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719encode_unicode
1.0.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0used byencoding_rs
0.8.35crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3depends onused byencoding_rs_io
0.1.7crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum1cc3c5651fb62ab8aa3103998dade57efdd028544bd300516baa31840c252a83depends onused byenum-ordinalize
4.3.2crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum4a1091a7bb1f8f2c4b28f1fe2cef4980ca2d410a3d727d67ecc3178c9b0800f0depends onused byenum-ordinalize-derive
4.3.2crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631depends onused byequivalent
1.0.2crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0ferrno
0.3.14crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efebdepends onused byextension-trait
1.0.2crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumdd65f1b59dd22d680c7a626cc4a000c1e03d241c51c3e034d2bc9f1e90734f9bdepends onused byfastrand
2.4.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma043dc74da1e37d6afe657061213aa6f425f855399a11d3463c6ecccc4dfda1fused byfind-msvc-tools
0.1.9crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582used byfnv
1.0.7crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1used byfoldhash
0.1.5crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2used byfoldhash
0.2.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdbused bygeneric-array
0.14.7crates.io↘ 2↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9adepends ongetrandom
0.3.4crates.io↘ 6↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fdgetrandom
0.4.2crates.io↘ 5↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555depends onused byglobset
0.4.18crates.io↘ 5↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3used byhalf
2.7.1crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84bdepends onused byhashbrown
0.14.5crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksume5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1used byhashbrown
0.15.5crates.io↘ 3↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1hashbrown
0.16.1crates.io↘ 3↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100heck
0.4.1crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8used byheck
0.5.0crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55eahi-doc
0.3.0crates.io↘ 10↖ 5sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumf70fb920ba34768415fb239d7d607486083bfc38ad35e3f1d558697f9f646f11depends onhi-doc-jumprope
1.2.1crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum236c25809a9c0a0249b3488feb57744e12aa64e4f3db851980eab303719c7bdddepends onused byid-arena
2.3.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954used byim-rc
15.1.0crates.io↘ 7↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumaf1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fedepends onindexmap
2.13.1crates.io↘ 4↖ 8sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ffindoc
2.0.7crates.io↘ 1↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706depends oninsta
1.47.2crates.io↘ 6↖ 6sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum7b4a6248eb93a4401ed2f37dfe8ea592d3cf05b7cf4f8efa867b6895af7e094eis_terminal_polyfill
1.70.2crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695used byitertools
0.13.0crates.io↘ 1↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186depends onitertools
0.14.0crates.io↘ 1↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285depends onitoa
1.0.18crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682used byjrsonnet-cli
0.5.0-pre98workspace↘ 5↖ 2jrsonnet-deps
0.5.0-pre98workspace↘ 5↖ 0jrsonnet-evaluator
0.5.0-pre98workspace↘ 21↖ 6depends on- annotate-snippets
0.12.14 - anyhow
1.0.102 - educe
0.6.0 - hi-doc
0.3.0 - im-rc
15.1.0 - jrsonnet-gcmodule
0.4.4 - jrsonnet-interner
0.5.0-pre98 - jrsonnet-ir
0.5.0-pre98 - jrsonnet-ir-parser
0.5.0-pre98 - jrsonnet-macros
0.5.0-pre98 - jrsonnet-peg-parser
0.5.0-pre98 - jrsonnet-types
0.5.0-pre98 - num-bigint
0.4.6 - pathdiff
0.2.3 - rustc-hash
2.1.2 - rustversion
1.0.22 - serde
1.0.228 - stacker
0.1.23 - static_assertions
1.1.0 - strsim
0.11.1 - thiserror
2.0.18
- annotate-snippets
jrsonnet-fmt
0.5.0-pre98workspace↘ 6↖ 0jrsonnet-formatter
0.5.0-pre98workspace↘ 6↖ 1jrsonnet-gcmodule
0.4.4crates.io↘ 2↖ 11sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum21dd97b40cbfb2043094219f95d96519858ba1aee4e8260eb048a1774832a517depends onjrsonnet-gcmodule-derive
0.4.4crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumede3d0445c2a7d7adab0a3cc33bdb33df78ffebebc21a2848c221526cb1795d4depends onused byjrsonnet-interner
0.5.0-pre98workspace↘ 3↖ 3jrsonnet-ir
0.5.0-pre98workspace↘ 5↖ 8depends onjrsonnet-ir-parser
0.5.0-pre98workspace↘ 4↖ 2jrsonnet-lexer
0.5.0-pre98workspace↘ 1↖ 3jrsonnet-macros
0.5.0-pre98workspace↘ 4↖ 2jrsonnet-peg-parser
0.5.0-pre98workspace↘ 4↖ 1jrsonnet-rowan-parser
0.5.0-pre98workspace↘ 9↖ 1jrsonnet-stdlib
0.5.0-pre98workspace↘ 16↖ 3depends onjrsonnet-types
0.5.0-pre98workspace↘ 2↖ 1depends onjs-sys
0.3.94crates.io↘ 2↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9depends onused bykeccak
0.1.6crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumcb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653depends onused byleb128fmt
0.1.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2used bylibc
0.2.184crates.io↘ 0↖ 9sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4aflibjsonnet
0.5.0-pre98workspace↘ 5↖ 0linux-raw-sys
0.12.1crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53used bylog
0.4.29crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897logos
0.16.1crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumeb2c55a318a87600ea870ff8c2012148b44bf18b74fad48d0f835c38c7d07c5fdepends onused bylogos-codegen
0.16.1crates.io↘ 6↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum58b3ffaa284e1350d017a57d04ada118c4583cf260c8fb01e0fe28a2e9cf8970used bylogos-derive
0.16.1crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum52d3a9855747c17eaf4383823f135220716ab49bea5fbea7dd42cc9a92f8aa31depends onused bylru
0.16.3crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593depends onused bymd5
0.8.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumae960838283323069879657ca3de837e9f7bbb4c7bf6ea7f1b290d5e9476d2e0used bymemchr
2.8.0crates.io↘ 0↖ 8sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumf8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79mimalloc-sys
0.1.6crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum4aa3cefb626f6ae3d0b2f71c5378c89d2b1d4d7bc246b0ca9a7ee61a4daad291depends onused bymimallocator
0.1.3crates.io↘ 1↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum2d44fe4ebf6b538fcf39d9975c2b90bb3232d1ba8e8bffeacd004f27b20c577adepends onnohash-hasher
0.2.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451used bynum-bigint
0.4.6crates.io↘ 3↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9num-integer
0.1.46crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858fdepends onused bynum-traits
0.2.19crates.io↘ 1↖ 7sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841depends onobject
0.37.3crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fedepends onused byonce_cell
1.21.4crates.io↘ 0↖ 5sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50once_cell_polyfill
1.70.2crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4feused byoorandom
11.1.5crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41eused byouroboros
0.18.5crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum1e0f050db9c44b97a94723127e6be766ac5c340c48f2c4bb3ffa11713744be59used byouroboros_macro
0.18.5crates.io↘ 5↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum3c7028bdd3d43083f6d8d4d5187680d0d3560d54df4cc9d752005268b41e64d0used bypage_size
0.6.0crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40dadepends onused bypathdiff
0.2.3crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumdf94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3peg
0.8.5crates.io↘ 2↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9928cfca101b36ec5163e70049ee5368a8a1c3c6efc9ca9c5f9cc2f816152477depends onpeg-macros
0.8.5crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum6298ab04c202fa5b5d52ba03269fb7b74550b150323038878fe6c372d8280f71used bypeg-runtime
0.8.5crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum132dca9b868d927b35b5dd728167b2dee150eb1ad686008fc71ccb298b776fcaused byplotters
0.3.7crates.io↘ 5↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747used byplotters-backend
0.3.7crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumdf42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172aplotters-svg
0.3.7crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670depends onused byppv-lite86
0.2.21crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9depends onused byprettyplease
0.2.37crates.io↘ 2↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62bdepends onproc-macro2
1.0.106crates.io↘ 1↖ 20sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934depends onused by- clap_derive
4.6.0 - educe
0.6.0 - enum-ordinalize-derive
4.3.2 - extension-trait
1.0.2 - jrsonnet-gcmodule-derive
0.4.4 - jrsonnet-macros
0.5.0-pre98 - logos-codegen
0.16.1 - ouroboros_macro
0.18.5 - peg-macros
0.8.5 - prettyplease
0.2.37 - proc-macro2-diagnostics
0.10.1 - quote
1.0.45 - serde_derive
1.0.228 - syn
2.0.117 - syn-dissect-closure
0.1.0 - thiserror-impl
2.0.18 - wasm-bindgen-macro-support
0.2.117 - wit-bindgen-rust-macro
0.51.0 - xtask
0.1.0 - zerocopy-derive
0.8.48
- clap_derive
proc-macro2-diagnostics
0.10.1crates.io↘ 5↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumaf066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8used bypsm
0.1.30crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum3852766467df634d74f0b2d7819bf8dc483a0eb2e3b0f50f756f9cfe8b0d18d8depends onused byquote
1.0.45crates.io↘ 1↖ 19sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924depends onused by- clap_derive
4.6.0 - educe
0.6.0 - enum-ordinalize-derive
4.3.2 - extension-trait
1.0.2 - jrsonnet-gcmodule-derive
0.4.4 - jrsonnet-macros
0.5.0-pre98 - logos-codegen
0.16.1 - ouroboros_macro
0.18.5 - peg-macros
0.8.5 - proc-macro2-diagnostics
0.10.1 - serde_derive
1.0.228 - syn
2.0.117 - syn-dissect-closure
0.1.0 - thiserror-impl
2.0.18 - wasm-bindgen-macro
0.2.117 - wasm-bindgen-macro-support
0.2.117 - wit-bindgen-rust-macro
0.51.0 - xtask
0.1.0 - zerocopy-derive
0.8.48
- clap_derive
r-efi
5.3.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0fused byr-efi
6.0.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumf8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bfused byrand
0.9.2crates.io↘ 2↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1depends onrand_chacha
0.9.0crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cbdepends onused byrand_core
0.6.4crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922cused byrand_core
0.9.5crates.io↘ 1↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83cdepends onused byrand_xoshiro
0.6.0crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaadepends onused byrandom_color
1.1.0crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd635c5e80ae160390ac62ca027d2d06c94c1dc69e5c0a12f1e3a53664dc84966depends onused byrange-map
0.2.0crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum12a5a2d6c7039059af621472a4389be1215a816df61aa4d531cfe85264aee95fdepends onused byrayon
1.11.0crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58fdepends onused byrayon-core
1.13.0crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91used byrefpool
0.4.3crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum369e86b80fa7dc8c561dd9613a5bf25c59d2d3073cd66c47fd9e39802f0ecb58used byregex
1.12.3crates.io↘ 4↖ 5sourceregistry+https://github.com/rust-lang/crates.io-indexchecksume10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276regex-automata
0.4.14crates.io↘ 3↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8fregex-syntax
0.8.10crates.io↘ 0↖ 5sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumdc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0arowan
0.16.1crates.io↘ 4↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum417a3a9f582e349834051b8a10c8d71ca88da4211e4093528e36b9845f6b5f21rustc-hash
1.1.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2used byrustc-hash
2.1.2crates.io↘ 0↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dberustix
1.1.4crates.io↘ 5↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumb6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190used byrustversion
1.0.22crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumb39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46dsame-file
1.0.6crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502depends onused bysaphyr-parser-bw
0.0.607crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum2f9bae8d059bf1ca32753cf3cdafbf5d391502de2fc2ca54510811fe9c100d90used bysemver
1.0.28crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cdserde
1.0.228crates.io↘ 2↖ 15sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9edepends onserde_core
1.0.228crates.io↘ 1↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67addepends onserde_derive
1.0.228crates.io↘ 3↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79depends onserde_json
1.0.149crates.io↘ 6↖ 9sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86serde-saphyr
0.0.17crates.io↘ 13↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumbc14a55107113a16346915d7e3d78acc539a923458385db89670e22cac106d7adepends onused bysha1
0.10.6crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksume3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6badepends onused bysha2
0.10.9crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283depends onused bysha3
0.10.8crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60depends onused bysimilar
2.7.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumbbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daaused bysized-chunks
0.6.5crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1edepends onused bysmallvec
1.15.1crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03used bysmallvec
2.0.0-alpha.12crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumef784004ca8777809dcdad6ac37629f0a97caee4c685fcea805278d81dd8b857stacker
0.1.23crates.io↘ 5↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum08d74a23609d509411d10e2176dc2a4346e3b4aea2e7b1869f19fdedbc71c013static_assertions
1.1.0crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543fstr_indices
0.4.4crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd08889ec5408683408db66ad89e0e1f93dff55c73a4ccc71c427d5b277ee47e6used bystreaming-iterator
0.1.9crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520strip-ansi-escapes
0.2.1crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum2a8f8038e7e7969abb3f1b7c2a811225e9296da208539e0f79c5251d6cac0025depends onstrsim
0.11.1crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4fsyn
2.0.117crates.io↘ 3↖ 17sourceregistry+https://github.com/rust-lang/crates.io-indexchecksume665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99used by- clap_derive
4.6.0 - educe
0.6.0 - enum-ordinalize-derive
4.3.2 - extension-trait
1.0.2 - jrsonnet-gcmodule-derive
0.4.4 - jrsonnet-macros
0.5.0-pre98 - logos-codegen
0.16.1 - ouroboros_macro
0.18.5 - prettyplease
0.2.37 - proc-macro2-diagnostics
0.10.1 - serde_derive
1.0.228 - syn-dissect-closure
0.1.0 - thiserror-impl
2.0.18 - wasm-bindgen-macro-support
0.2.117 - wit-bindgen-rust
0.51.0 - wit-bindgen-rust-macro
0.51.0 - zerocopy-derive
0.8.48
- clap_derive
syn-dissect-closure
0.1.0crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum343bae741672e4b94421cbe93f9794ba9a061434272f7e3a29ff43be26be3ac9depends onused bytempfile
3.27.0crates.io↘ 5↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bdtext-size
1.1.1crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumf18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233used bythiserror
2.0.18crates.io↘ 1↖ 6sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4depends onthiserror-impl
2.0.18crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5depends onused bytinytemplate
1.2.1crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumbe4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bcdepends onused bytree-sitter
0.26.8crates.io↘ 6↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum887bd495d0582c5e3e0d8ece2233666169fa56a9644d172fc22ad179ab2d0538depends onused bytree-sitter-highlight
0.26.8crates.io↘ 4↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumccde2b54a34b58313e69c02496a2a9ad38d59af79b196b5e1df063431752a7e0used bytree-sitter-language
0.1.7crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum009994f150cc0cd50ff54917d5bc8bffe8cad10ca10d81c34da2ec421ae61782used bytypenum
1.19.0crates.io↘ 0↖ 5sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bbungrammar
1.16.1crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma3e5df347f0bf3ec1d670aad6ca5c6a1859cd9ea61d2113125794654ccced68fused byunicode-box-drawing
0.3.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum2a1f97719cf40224391201fc11e7f5b0cc0ba21416367cfc914e2d45af4e42efused byunicode-ident
1.0.24crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksume6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75unicode-width
0.2.2crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumb4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254unicode-xid
0.2.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853used byutf8parse
0.2.2crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821version_check
0.9.5crates.io↘ 0↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105avte
0.14.1crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum231fdcd7ef3037e8330d8e17e61011a2c244126acc0a982f4040ac3f9f0bc077depends onused bywalkdir
2.5.0crates.io↘ 2↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4bdepends onused bywasip2
1.0.2+wasi-0.2.9crates.io↘ 1↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5depends onused bywasip3
0.4.0+wasi-0.3.0-rc-2026-01-06crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5depends onused bywasm-bindgen
0.2.117crates.io↘ 5↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0depends onwasm-bindgen-macro
0.2.117crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86beused bywasm-bindgen-macro-support
0.2.117crates.io↘ 5↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumdca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2used bywasm-encoder
0.244.0crates.io↘ 2↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319depends onwasm-metadata
0.244.0crates.io↘ 4↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumbb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909wasmparser
0.244.0crates.io↘ 4↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028feweb-sys
0.3.94crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumcd70027e39b12f0849461e08ffc50b9cd7688d942c1c8e3c7b22273236b4dd0adepends onused bywinapi
0.3.9crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419used bywinapi-i686-pc-windows-gnu
0.4.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6used bywinapi-util
0.1.11crates.io↘ 1↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumc2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22depends onused bywinapi-x86_64-pc-windows-gnu
0.4.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183fused bywindows_aarch64_gnullvm
0.52.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3used bywindows_aarch64_msvc
0.52.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469used bywindows_i686_gnu
0.52.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0bused bywindows_i686_gnullvm
0.52.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66used bywindows_i686_msvc
0.52.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66used bywindows_x86_64_gnu
0.52.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78used bywindows_x86_64_gnullvm
0.52.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0dused bywindows_x86_64_msvc
0.52.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ecused bywindows-link
0.2.1crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumf0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5used bywindows-sys
0.59.0crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853bdepends onused bywindows-sys
0.61.2crates.io↘ 1↖ 7sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fcdepends onwindows-targets
0.52.6crates.io↘ 8↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973depends onused bywit-bindgen
0.51.0crates.io↘ 1↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5depends onwit-bindgen-core
0.51.0crates.io↘ 3↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dcdepends onwit-bindgen-rust
0.51.0crates.io↘ 8↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumb7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21depends onused bywit-bindgen-rust-macro
0.51.0crates.io↘ 7↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17adepends onused bywit-component
0.244.0crates.io↘ 11↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2depends onused bywit-parser
0.244.0crates.io↘ 10↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736depends onxshell
0.2.7crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9e7290c623014758632efe00737145b6867b66292c42167f2ec381eb566a373ddepends onused byxshell-macros
0.2.7crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum32ac00cd3f8ec9c1d33fb3e7958a82df6989c42d747bd326c822b1d625283547used byxtask
0.1.0workspace↘ 8↖ 0yansi
1.0.1crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumcfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049zerocopy
0.8.48crates.io↘ 1↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumeed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9depends onzerocopy-derive
0.8.48crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4depends onused byzmij
1.0.21crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumb8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa
242 packageslockfile v4
Might be heavy and slow!
ahash
0.8.12crates.io↘ 5↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75used byaho-corasick
1.1.4crates.io↘ 1↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301depends onaliasable
0.1.3crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fdused byalloca
0.4.0crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksume5a7d05ea6aea7e9e64d25b9156ba2fee3fdd659e34e41063cd2fc7cd020d7f4depends onused byallocator-api2
0.2.21crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923anes
0.1.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299used byannotate-snippets
0.12.14crates.io↘ 3↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum22b669bf35e50f130e98212b486b0df78d93e285963344e58937692705e1a21aannotated-string
0.3.0crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum298ed730801db3c02f2edba003c9420a0f57ea48d37fdc5601c536113668c059used byanstream
1.0.0crates.io↘ 7↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28ddepends onused byanstyle
1.0.14crates.io↘ 0↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000anstyle-parse
1.0.0crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130edepends onused byanstyle-query
1.1.5crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadcdepends onused byanstyle-wincon
3.0.11crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747dused byanyhow
1.0.102crates.io↘ 0↖ 10sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842car_archive_writer
0.5.1crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum7eb93bbb63b9c227414f6eb3a0adfddca591a8ce1e9b60661bb08969b87e340bdepends onused byarraydeque
0.5.1crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236used byautocfg
1.5.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumc08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8used bybase64
0.22.1crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6bitflags
2.11.0crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92afbitmaps
2.1.0crates.io↘ 1↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2depends onused byblock-buffer
0.10.4crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71depends onused bybstr
1.12.1crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cabdepends onused bybumpalo
3.20.2crates.io↘ 1↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcbdepends oncast
0.3.0crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5cc
1.2.59crates.io↘ 2↖ 5sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumb7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283depends oncfg-if
1.0.4crates.io↘ 0↖ 9sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801ciborium
0.2.2crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0eused byciborium-io
0.2.2crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757ciborium-ll
0.2.2crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9depends onused byclap
4.6.0crates.io↘ 2↖ 7sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumb193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351depends onclap_builder
4.6.0crates.io↘ 4↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069fused byclap_complete
4.6.0crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum19c9f1dde76b736e3681f28cec9d5a61299cbaae0fce80a68e43724ad56031ebdepends onused byclap_derive
4.6.0crates.io↘ 4↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6aused byclap_lex
1.1.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumc8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9used bycolorchoice
1.0.5crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570used byconsole
0.16.3crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd64e8af5551369d19cf50138de61f1c42074ab970f74e99be916646777f8fc87used bycountme
3.0.1crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636used bycpufeatures
0.2.17crates.io↘ 1↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280depends oncriterion
0.8.2crates.io↘ 17↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum950046b2aa2492f9a536f5f4f9a3de7b9e2476e575e05bd6c333371add4d98f3depends onused bycriterion-plot
0.8.2crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd8d80a2f4f5b554395e47b5d8305bc3d27813bacb73493eb1001e8f76dae29eadepends onused bycrossbeam-deque
0.8.6crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51used bycrossbeam-epoch
0.9.18crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420edepends onused bycrossbeam-utils
0.8.21crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28crypto-common
0.1.7crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60adepends onused bydigest
0.10.7crates.io↘ 2↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292depends ondprint-core
0.67.4crates.io↘ 7↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum2c1d827947704a9495f705d6aeed270fa21a67f825f22902c28f38dc3af7a9aedepends ondrop_bomb
0.1.5crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1educe
0.6.0crates.io↘ 4↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417either
1.15.0crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719encode_unicode
1.0.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0used byencoding_rs
0.8.35crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3depends onused byencoding_rs_io
0.1.7crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum1cc3c5651fb62ab8aa3103998dade57efdd028544bd300516baa31840c252a83depends onused byenum-ordinalize
4.3.2crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum4a1091a7bb1f8f2c4b28f1fe2cef4980ca2d410a3d727d67ecc3178c9b0800f0depends onused byenum-ordinalize-derive
4.3.2crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631depends onused byequivalent
1.0.2crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0ferrno
0.3.14crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efebdepends onused byextension-trait
1.0.2crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumdd65f1b59dd22d680c7a626cc4a000c1e03d241c51c3e034d2bc9f1e90734f9bdepends onused byfastrand
2.4.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma043dc74da1e37d6afe657061213aa6f425f855399a11d3463c6ecccc4dfda1fused byfind-msvc-tools
0.1.9crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582used byfnv
1.0.7crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1used byfoldhash
0.1.5crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2used byfoldhash
0.2.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdbused bygeneric-array
0.14.7crates.io↘ 2↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9adepends ongetrandom
0.3.4crates.io↘ 6↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fdgetrandom
0.4.2crates.io↘ 5↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555depends onused byglobset
0.4.18crates.io↘ 5↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3used byhalf
2.7.1crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84bdepends onused byhashbrown
0.14.5crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksume5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1used byhashbrown
0.15.5crates.io↘ 3↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1hashbrown
0.16.1crates.io↘ 3↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100heck
0.4.1crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8used byheck
0.5.0crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55eahi-doc
0.3.0crates.io↘ 10↖ 5sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumf70fb920ba34768415fb239d7d607486083bfc38ad35e3f1d558697f9f646f11depends onhi-doc-jumprope
1.2.1crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum236c25809a9c0a0249b3488feb57744e12aa64e4f3db851980eab303719c7bdddepends onused byid-arena
2.3.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954used byim-rc
15.1.0crates.io↘ 7↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumaf1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fedepends onindexmap
2.13.1crates.io↘ 4↖ 8sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ffindoc
2.0.7crates.io↘ 1↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706depends oninsta
1.47.2crates.io↘ 6↖ 7sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum7b4a6248eb93a4401ed2f37dfe8ea592d3cf05b7cf4f8efa867b6895af7e094eis_terminal_polyfill
1.70.2crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695used byitertools
0.13.0crates.io↘ 1↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186depends onitertools
0.14.0crates.io↘ 1↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285depends onitoa
1.0.18crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682used byjrsonnet-cli
0.5.0-pre98workspace↘ 5↖ 2jrsonnet-deps
0.5.0-pre98workspace↘ 5↖ 0jrsonnet-evaluator
0.5.0-pre98workspace↘ 25↖ 6depends on- annotate-snippets
0.12.14 - anyhow
1.0.102 - drop_bomb
0.1.5 - educe
0.6.0 - hi-doc
0.3.0 - im-rc
15.1.0 - insta
1.47.2 - jrsonnet-gcmodule
0.4.4 - jrsonnet-interner
0.5.0-pre98 - jrsonnet-ir
0.5.0-pre98 - jrsonnet-ir-parser
0.5.0-pre98 - jrsonnet-macros
0.5.0-pre98 - jrsonnet-peg-parser
0.5.0-pre98 - jrsonnet-types
0.5.0-pre98 - num-bigint
0.4.6 - pathdiff
0.2.3 - rustc-hash
2.1.2 - rustversion
1.0.22 - serde
1.0.228 - smallvec
1.15.1 - stacker
0.1.23 - static_assertions
1.1.0 - strip-ansi-escapes
0.2.1 - strsim
0.11.1 - thiserror
2.0.18
- annotate-snippets
jrsonnet-fmt
0.5.0-pre98workspace↘ 6↖ 0jrsonnet-formatter
0.5.0-pre98workspace↘ 6↖ 1jrsonnet-gcmodule
0.4.4crates.io↘ 2↖ 11sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum21dd97b40cbfb2043094219f95d96519858ba1aee4e8260eb048a1774832a517depends onjrsonnet-gcmodule-derive
0.4.4crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumede3d0445c2a7d7adab0a3cc33bdb33df78ffebebc21a2848c221526cb1795d4depends onused byjrsonnet-interner
0.5.0-pre98workspace↘ 3↖ 3jrsonnet-ir
0.5.0-pre98workspace↘ 6↖ 7jrsonnet-ir-parser
0.5.0-pre98workspace↘ 4↖ 2jrsonnet-lexer
0.5.0-pre98workspace↘ 1↖ 3jrsonnet-macros
0.5.0-pre98workspace↘ 4↖ 2jrsonnet-peg-parser
0.5.0-pre98workspace↘ 4↖ 1jrsonnet-rowan-parser
0.5.0-pre98workspace↘ 9↖ 1jrsonnet-stdlib
0.5.0-pre98workspace↘ 15↖ 3jrsonnet-types
0.5.0-pre98workspace↘ 2↖ 1depends onjs-sys
0.3.94crates.io↘ 2↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9depends onused bykeccak
0.1.6crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumcb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653depends onused byleb128fmt
0.1.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2used bylibc
0.2.184crates.io↘ 0↖ 9sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4aflibjsonnet
0.5.0-pre98workspace↘ 5↖ 0linux-raw-sys
0.12.1crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53used bylog
0.4.29crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897logos
0.16.1crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumeb2c55a318a87600ea870ff8c2012148b44bf18b74fad48d0f835c38c7d07c5fdepends onused bylogos-codegen
0.16.1crates.io↘ 6↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum58b3ffaa284e1350d017a57d04ada118c4583cf260c8fb01e0fe28a2e9cf8970used bylogos-derive
0.16.1crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum52d3a9855747c17eaf4383823f135220716ab49bea5fbea7dd42cc9a92f8aa31depends onused bylru
0.16.3crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593depends onused bymd5
0.8.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumae960838283323069879657ca3de837e9f7bbb4c7bf6ea7f1b290d5e9476d2e0used bymemchr
2.8.0crates.io↘ 0↖ 8sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumf8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79mimalloc-sys
0.1.6crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum4aa3cefb626f6ae3d0b2f71c5378c89d2b1d4d7bc246b0ca9a7ee61a4daad291depends onused bymimallocator
0.1.3crates.io↘ 1↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum2d44fe4ebf6b538fcf39d9975c2b90bb3232d1ba8e8bffeacd004f27b20c577adepends onnohash-hasher
0.2.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451used bynum-bigint
0.4.6crates.io↘ 3↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9num-integer
0.1.46crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858fdepends onused bynum-traits
0.2.19crates.io↘ 1↖ 7sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841depends onobject
0.37.3crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fedepends onused byonce_cell
1.21.4crates.io↘ 0↖ 5sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50once_cell_polyfill
1.70.2crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4feused byoorandom
11.1.5crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41eused byouroboros
0.18.5crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum1e0f050db9c44b97a94723127e6be766ac5c340c48f2c4bb3ffa11713744be59used byouroboros_macro
0.18.5crates.io↘ 5↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum3c7028bdd3d43083f6d8d4d5187680d0d3560d54df4cc9d752005268b41e64d0used bypage_size
0.6.0crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40dadepends onused bypathdiff
0.2.3crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumdf94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3peg
0.8.5crates.io↘ 2↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9928cfca101b36ec5163e70049ee5368a8a1c3c6efc9ca9c5f9cc2f816152477depends onpeg-macros
0.8.5crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum6298ab04c202fa5b5d52ba03269fb7b74550b150323038878fe6c372d8280f71used bypeg-runtime
0.8.5crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum132dca9b868d927b35b5dd728167b2dee150eb1ad686008fc71ccb298b776fcaused byplotters
0.3.7crates.io↘ 5↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747used byplotters-backend
0.3.7crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumdf42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172aplotters-svg
0.3.7crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670depends onused byppv-lite86
0.2.21crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9depends onused byprettyplease
0.2.37crates.io↘ 2↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62bdepends onproc-macro2
1.0.106crates.io↘ 1↖ 20sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934depends onused by- clap_derive
4.6.0 - educe
0.6.0 - enum-ordinalize-derive
4.3.2 - extension-trait
1.0.2 - jrsonnet-gcmodule-derive
0.4.4 - jrsonnet-macros
0.5.0-pre98 - logos-codegen
0.16.1 - ouroboros_macro
0.18.5 - peg-macros
0.8.5 - prettyplease
0.2.37 - proc-macro2-diagnostics
0.10.1 - quote
1.0.45 - serde_derive
1.0.228 - syn
2.0.117 - syn-dissect-closure
0.1.0 - thiserror-impl
2.0.18 - wasm-bindgen-macro-support
0.2.117 - wit-bindgen-rust-macro
0.51.0 - xtask
0.1.0 - zerocopy-derive
0.8.48
- clap_derive
proc-macro2-diagnostics
0.10.1crates.io↘ 5↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumaf066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8used bypsm
0.1.30crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum3852766467df634d74f0b2d7819bf8dc483a0eb2e3b0f50f756f9cfe8b0d18d8depends onused byquote
1.0.45crates.io↘ 1↖ 19sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924depends onused by- clap_derive
4.6.0 - educe
0.6.0 - enum-ordinalize-derive
4.3.2 - extension-trait
1.0.2 - jrsonnet-gcmodule-derive
0.4.4 - jrsonnet-macros
0.5.0-pre98 - logos-codegen
0.16.1 - ouroboros_macro
0.18.5 - peg-macros
0.8.5 - proc-macro2-diagnostics
0.10.1 - serde_derive
1.0.228 - syn
2.0.117 - syn-dissect-closure
0.1.0 - thiserror-impl
2.0.18 - wasm-bindgen-macro
0.2.117 - wasm-bindgen-macro-support
0.2.117 - wit-bindgen-rust-macro
0.51.0 - xtask
0.1.0 - zerocopy-derive
0.8.48
- clap_derive
r-efi
5.3.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0fused byr-efi
6.0.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumf8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bfused byrand
0.9.2crates.io↘ 2↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1depends onrand_chacha
0.9.0crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cbdepends onused byrand_core
0.6.4crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922cused byrand_core
0.9.5crates.io↘ 1↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83cdepends onused byrand_xoshiro
0.6.0crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaadepends onused byrandom_color
1.1.0crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd635c5e80ae160390ac62ca027d2d06c94c1dc69e5c0a12f1e3a53664dc84966depends onused byrange-map
0.2.0crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum12a5a2d6c7039059af621472a4389be1215a816df61aa4d531cfe85264aee95fdepends onused byrayon
1.11.0crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58fdepends onused byrayon-core
1.13.0crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91used byrefpool
0.4.3crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum369e86b80fa7dc8c561dd9613a5bf25c59d2d3073cd66c47fd9e39802f0ecb58used byregex
1.12.3crates.io↘ 4↖ 5sourceregistry+https://github.com/rust-lang/crates.io-indexchecksume10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276regex-automata
0.4.14crates.io↘ 3↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8fregex-syntax
0.8.10crates.io↘ 0↖ 5sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumdc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0arowan
0.16.1crates.io↘ 4↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum417a3a9f582e349834051b8a10c8d71ca88da4211e4093528e36b9845f6b5f21rustc-hash
1.1.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2used byrustc-hash
2.1.2crates.io↘ 0↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dberustix
1.1.4crates.io↘ 5↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumb6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190used byrustversion
1.0.22crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumb39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46dsame-file
1.0.6crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502depends onused bysaphyr-parser-bw
0.0.607crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum2f9bae8d059bf1ca32753cf3cdafbf5d391502de2fc2ca54510811fe9c100d90used bysemver
1.0.28crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cdserde
1.0.228crates.io↘ 2↖ 15sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9edepends onserde_core
1.0.228crates.io↘ 1↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67addepends onserde_derive
1.0.228crates.io↘ 3↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79depends onserde_json
1.0.149crates.io↘ 6↖ 9sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86serde-saphyr
0.0.17crates.io↘ 13↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumbc14a55107113a16346915d7e3d78acc539a923458385db89670e22cac106d7adepends onused bysha1
0.10.6crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksume3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6badepends onused bysha2
0.10.9crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283depends onused bysha3
0.10.8crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60depends onused bysimilar
2.7.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumbbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daaused bysized-chunks
0.6.5crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1edepends onused bysmallvec
1.15.1crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03smallvec
2.0.0-alpha.12crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumef784004ca8777809dcdad6ac37629f0a97caee4c685fcea805278d81dd8b857stacker
0.1.23crates.io↘ 5↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum08d74a23609d509411d10e2176dc2a4346e3b4aea2e7b1869f19fdedbc71c013static_assertions
1.1.0crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543fstr_indices
0.4.4crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd08889ec5408683408db66ad89e0e1f93dff55c73a4ccc71c427d5b277ee47e6used bystreaming-iterator
0.1.9crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520strip-ansi-escapes
0.2.1crates.io↘ 1↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum2a8f8038e7e7969abb3f1b7c2a811225e9296da208539e0f79c5251d6cac0025depends onstrsim
0.11.1crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4fsyn
2.0.117crates.io↘ 3↖ 17sourceregistry+https://github.com/rust-lang/crates.io-indexchecksume665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99used by- clap_derive
4.6.0 - educe
0.6.0 - enum-ordinalize-derive
4.3.2 - extension-trait
1.0.2 - jrsonnet-gcmodule-derive
0.4.4 - jrsonnet-macros
0.5.0-pre98 - logos-codegen
0.16.1 - ouroboros_macro
0.18.5 - prettyplease
0.2.37 - proc-macro2-diagnostics
0.10.1 - serde_derive
1.0.228 - syn-dissect-closure
0.1.0 - thiserror-impl
2.0.18 - wasm-bindgen-macro-support
0.2.117 - wit-bindgen-rust
0.51.0 - wit-bindgen-rust-macro
0.51.0 - zerocopy-derive
0.8.48
- clap_derive
syn-dissect-closure
0.1.0crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum343bae741672e4b94421cbe93f9794ba9a061434272f7e3a29ff43be26be3ac9depends onused bytempfile
3.27.0crates.io↘ 5↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bdtext-size
1.1.1crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumf18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233used bythiserror
2.0.18crates.io↘ 1↖ 7sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4depends onthiserror-impl
2.0.18crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5depends onused bytinytemplate
1.2.1crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumbe4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bcdepends onused bytree-sitter
0.26.8crates.io↘ 6↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum887bd495d0582c5e3e0d8ece2233666169fa56a9644d172fc22ad179ab2d0538depends onused bytree-sitter-highlight
0.26.8crates.io↘ 4↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumccde2b54a34b58313e69c02496a2a9ad38d59af79b196b5e1df063431752a7e0used bytree-sitter-language
0.1.7crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum009994f150cc0cd50ff54917d5bc8bffe8cad10ca10d81c34da2ec421ae61782used bytypenum
1.19.0crates.io↘ 0↖ 5sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bbungrammar
1.16.1crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma3e5df347f0bf3ec1d670aad6ca5c6a1859cd9ea61d2113125794654ccced68fused byunicode-box-drawing
0.3.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum2a1f97719cf40224391201fc11e7f5b0cc0ba21416367cfc914e2d45af4e42efused byunicode-ident
1.0.24crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksume6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75unicode-width
0.2.2crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumb4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254unicode-xid
0.2.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853used byutf8parse
0.2.2crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821version_check
0.9.5crates.io↘ 0↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105avte
0.14.1crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum231fdcd7ef3037e8330d8e17e61011a2c244126acc0a982f4040ac3f9f0bc077depends onused bywalkdir
2.5.0crates.io↘ 2↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4bdepends onused bywasip2
1.0.2+wasi-0.2.9crates.io↘ 1↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5depends onused bywasip3
0.4.0+wasi-0.3.0-rc-2026-01-06crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5depends onused bywasm-bindgen
0.2.117crates.io↘ 5↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0depends onwasm-bindgen-macro
0.2.117crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86beused bywasm-bindgen-macro-support
0.2.117crates.io↘ 5↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumdca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2used bywasm-encoder
0.244.0crates.io↘ 2↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319depends onwasm-metadata
0.244.0crates.io↘ 4↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumbb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909wasmparser
0.244.0crates.io↘ 4↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028feweb-sys
0.3.94crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumcd70027e39b12f0849461e08ffc50b9cd7688d942c1c8e3c7b22273236b4dd0adepends onused bywinapi
0.3.9crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419used bywinapi-i686-pc-windows-gnu
0.4.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6used bywinapi-util
0.1.11crates.io↘ 1↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumc2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22depends onused bywinapi-x86_64-pc-windows-gnu
0.4.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183fused bywindows_aarch64_gnullvm
0.52.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3used bywindows_aarch64_msvc
0.52.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469used bywindows_i686_gnu
0.52.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0bused bywindows_i686_gnullvm
0.52.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66used bywindows_i686_msvc
0.52.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66used bywindows_x86_64_gnu
0.52.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78used bywindows_x86_64_gnullvm
0.52.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0dused bywindows_x86_64_msvc
0.52.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ecused bywindows-link
0.2.1crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumf0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5used bywindows-sys
0.59.0crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853bdepends onused bywindows-sys
0.61.2crates.io↘ 1↖ 7sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fcdepends onwindows-targets
0.52.6crates.io↘ 8↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973depends onused bywit-bindgen
0.51.0crates.io↘ 1↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5depends onwit-bindgen-core
0.51.0crates.io↘ 3↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dcdepends onwit-bindgen-rust
0.51.0crates.io↘ 8↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumb7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21depends onused bywit-bindgen-rust-macro
0.51.0crates.io↘ 7↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17adepends onused bywit-component
0.244.0crates.io↘ 11↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2depends onused bywit-parser
0.244.0crates.io↘ 10↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736depends onxshell
0.2.7crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9e7290c623014758632efe00737145b6867b66292c42167f2ec381eb566a373ddepends onused byxshell-macros
0.2.7crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum32ac00cd3f8ec9c1d33fb3e7958a82df6989c42d747bd326c822b1d625283547used byxtask
0.1.0workspace↘ 8↖ 0yansi
1.0.1crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumcfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049zerocopy
0.8.48crates.io↘ 1↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumeed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9depends onzerocopy-derive
0.8.48crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4depends onused byzmij
1.0.21crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumb8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa
bindings/jsonnet/src/val_modify.rsdiffbeforeafterboth--- a/bindings/jsonnet/src/val_modify.rs
+++ b/bindings/jsonnet/src/val_modify.rs
@@ -4,7 +4,7 @@
use std::{ffi::CStr, os::raw::c_char};
-use jrsonnet_evaluator::{Thunk, Val, val::ArrValue};
+use jrsonnet_evaluator::{Thunk, Val};
use crate::VM;
crates/jrsonnet-evaluator/Cargo.tomldiffbeforeafterboth--- a/crates/jrsonnet-evaluator/Cargo.toml
+++ b/crates/jrsonnet-evaluator/Cargo.toml
@@ -77,6 +77,12 @@
"PartialEq",
] }
im-rc = { version = "15.1.0", features = ["pool"] }
+smallvec = "1.15.1"
+drop_bomb.workspace = true
[build-dependencies]
rustversion = "1.0.22"
+
+[dev-dependencies]
+insta.workspace = true
+strip-ansi-escapes = "0.2.1"
crates/jrsonnet-evaluator/src/arr/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/arr/mod.rs
+++ b/crates/jrsonnet-evaluator/src/arr/mod.rs
@@ -5,10 +5,9 @@
rc::Rc,
};
-use jrsonnet_gcmodule::{Cc, cc_dyn};
-use jrsonnet_ir::Expr;
+use jrsonnet_gcmodule::{cc_dyn, Cc};
-use crate::{Context, Result, Thunk, Val, function::NativeFn, typed::IntoUntyped};
+use crate::{analyze::LExpr, function::NativeFn, typed::IntoUntyped, Context, Result, Thunk, Val};
mod spec;
pub use spec::{ArrayLike, *};
@@ -37,14 +36,18 @@
Self::new(())
}
- pub fn expr(ctx: Context, exprs: Rc<Vec<Expr>>) -> Self {
+ pub fn expr(ctx: Context, exprs: Rc<Vec<LExpr>>) -> Self {
Self::new(ExprArray::new(ctx, exprs))
}
- pub fn repeated(data: Self, repeats: usize) -> Option<Self> {
+ pub fn repeated(data: Self, repeats: u32) -> Option<Self> {
Some(Self::new(RepeatedArray::new(data, repeats)?))
}
+ pub fn make(len: u32, cb: NativeFn!((u32,)->Val)) -> Self {
+ Self::new(MakeArray::new(len, cb))
+ }
+
#[must_use]
pub fn map(self, mapper: NativeFn!((Val) -> Val)) -> Self {
Self::new(<MappedArray>::new(self, ArrayMapper::Plain(mapper)))
@@ -79,14 +82,14 @@
Ok(Self::new(out))
}
- pub fn extended(a: Self, b: Self) -> Self {
- if a.is_empty() {
+ pub fn extended(a: Self, b: Self) -> Option<Self> {
+ Some(if a.is_empty() {
b
} else if b.is_empty() {
a
} else {
- Self::new(ExtendedArray::new(a, b))
- }
+ Self::new(ExtendedArray::new(a, b)?)
+ })
}
pub fn range_exclusive(a: i32, b: i32) -> Self {
@@ -98,14 +101,14 @@
#[must_use]
pub fn slice(self, index: Option<i32>, end: Option<i32>, step: Option<NonZeroU32>) -> Self {
- let get_idx = |pos: Option<i32>, len: usize, default| match pos {
+ let get_idx = |pos: Option<i32>, len: u32, default| match pos {
#[expect(
clippy::cast_sign_loss,
reason = "abs value is used, len is limited to u31"
)]
- Some(v) if v < 0 => len.saturating_sub((-v) as usize),
+ Some(v) if v < 0 => len.saturating_add_signed(v),
#[expect(clippy::cast_sign_loss, reason = "abs value is used")]
- Some(v) => (v as usize).min(len),
+ Some(v) => (v as u32).min(len),
None => default,
};
let index = get_idx(index, self.len(), 0);
@@ -127,7 +130,7 @@
}
/// Array length.
- pub fn len(&self) -> usize {
+ pub fn len(&self) -> u32 {
self.0.len()
}
@@ -143,14 +146,14 @@
/// Get array element by index, evaluating it, if it is lazy.
///
/// Returns `None` on out-of-bounds condition.
- pub fn get(&self, index: usize) -> Result<Option<Val>> {
+ pub fn get(&self, index: u32) -> Result<Option<Val>> {
self.0.get(index)
}
/// Get array element by index, without evaluation.
///
/// Returns `None` on out-of-bounds condition.
- pub fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {
+ pub fn get_lazy(&self, index: u32) -> Option<Thunk<Val>> {
self.0.get_lazy(index)
}
crates/jrsonnet-evaluator/src/arr/spec.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/arr/spec.rs
+++ b/crates/jrsonnet-evaluator/src/arr/spec.rs
@@ -8,47 +8,47 @@
use jrsonnet_gcmodule::{Cc, Trace};
use jrsonnet_interner::{IBytes, IStr};
-use jrsonnet_ir::Expr;
use super::ArrValue;
use crate::{
- Context, Error, ObjValue, Result, Thunk, Val,
+ analyze::LExpr,
error::ErrorKind::InfiniteRecursionDetected,
- evaluate,
+ evaluate::evaluate,
function::NativeFn,
typed::{IntoUntyped, Typed},
val::ThunkValue,
+ Context, Error, ObjValue, Result, Thunk, Val,
};
pub trait ArrayLike: Any + Trace + Debug {
- fn len(&self) -> usize;
+ fn len(&self) -> u32;
fn is_empty(&self) -> bool {
self.len() == 0
}
- fn get(&self, index: usize) -> Result<Option<Val>>;
- fn get_lazy(&self, index: usize) -> Option<Thunk<Val>>;
+ fn get(&self, index: u32) -> Result<Option<Val>>;
+ fn get_lazy(&self, index: u32) -> Option<Thunk<Val>>;
fn is_cheap(&self) -> bool {
false
}
}
trait ArrayCheap {
- fn get(&self, index: usize) -> Option<Val>;
- fn len(&self) -> usize;
+ fn get(&self, index: u32) -> Option<Val>;
+ fn len(&self) -> u32;
}
impl<T> ArrayLike for T
where
T: Any + Trace + Debug + ArrayCheap,
{
- fn len(&self) -> usize {
+ fn len(&self) -> u32 {
<T as ArrayCheap>::len(self)
}
- fn get(&self, index: usize) -> Result<Option<Val>> {
+ fn get(&self, index: u32) -> Result<Option<Val>> {
Ok(<T as ArrayCheap>::get(self, index))
}
- fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {
+ fn get_lazy(&self, index: u32) -> Option<Thunk<Val>> {
<T as ArrayCheap>::get(self, index).map(Thunk::evaluated)
}
@@ -58,10 +58,10 @@
}
impl ArrayCheap for () {
- fn len(&self) -> usize {
+ fn len(&self) -> u32 {
0
}
- fn get(&self, _index: usize) -> Option<Val> {
+ fn get(&self, _index: u32) -> Option<Val> {
None
}
}
@@ -75,20 +75,20 @@
}
impl SliceArray {
- fn map_idx(&self, index: usize) -> usize {
- self.from as usize + self.step as usize * index
+ fn map_idx(&self, index: u32) -> u32 {
+ self.from + self.step * index
}
}
impl ArrayLike for SliceArray {
- fn len(&self) -> usize {
- (self.to - self.from).div_ceil(self.step) as usize
+ fn len(&self) -> u32 {
+ (self.to - self.from).div_ceil(self.step)
}
- fn get(&self, index: usize) -> Result<Option<Val>> {
+ fn get(&self, index: u32) -> Result<Option<Val>> {
self.inner.get(self.map_idx(index))
}
- fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {
+ fn get_lazy(&self, index: u32) -> Option<Thunk<Val>> {
self.inner.get_lazy(self.map_idx(index))
}
@@ -98,11 +98,13 @@
}
impl ArrayCheap for IBytes {
- fn len(&self) -> usize {
- self.as_slice().len()
+ fn len(&self) -> u32 {
+ self.as_slice().len() as u32
}
- fn get(&self, index: usize) -> Option<Val> {
- self.as_slice().get(index).map(|v| Val::Num((*v).into()))
+ fn get(&self, index: u32) -> Option<Val> {
+ self.as_slice()
+ .get(index as usize)
+ .map(|v| Val::Num((*v).into()))
}
}
@@ -117,11 +119,11 @@
#[derive(Debug, Trace, Clone)]
pub struct ExprArray {
ctx: Context,
- src: Rc<Vec<Expr>>,
+ src: Rc<Vec<LExpr>>,
cached: Cc<RefCell<Vec<ArrayThunk>>>,
}
impl ExprArray {
- pub fn new(ctx: Context, src: Rc<Vec<Expr>>) -> Self {
+ pub fn new(ctx: Context, src: Rc<Vec<LExpr>>) -> Self {
Self {
ctx,
cached: Cc::new(RefCell::new(vec![ArrayThunk::Waiting; src.len()])),
@@ -130,41 +132,36 @@
}
}
impl ArrayLike for ExprArray {
- fn len(&self) -> usize {
- self.cached.borrow().len()
+ fn len(&self) -> u32 {
+ self.cached.borrow().len() as u32
}
- fn get(&self, index: usize) -> Result<Option<Val>> {
+ fn get(&self, index: u32) -> Result<Option<Val>> {
if index >= self.len() {
return Ok(None);
}
- match &self.cached.borrow()[index] {
+ match &self.cached.borrow()[index as usize] {
ArrayThunk::Computed(c) => return Ok(Some(c.clone())),
ArrayThunk::Errored(e) => return Err(e.clone()),
ArrayThunk::Pending => return Err(InfiniteRecursionDetected.into()),
ArrayThunk::Waiting => {}
}
- let ArrayThunk::Waiting =
- replace(&mut self.cached.borrow_mut()[index], ArrayThunk::Pending)
- else {
+ let ArrayThunk::Waiting = replace(
+ &mut self.cached.borrow_mut()[index as usize],
+ ArrayThunk::Pending,
+ ) else {
unreachable!()
};
- let new_value = match evaluate(self.ctx.clone(), &self.src[index]) {
- Ok(v) => v,
- Err(e) => {
- self.cached.borrow_mut()[index] = ArrayThunk::Errored(e.clone());
- return Err(e);
- }
- };
- self.cached.borrow_mut()[index] = ArrayThunk::Computed(new_value.clone());
+ let new_value: Val = evaluate(self.ctx.clone(), &self.src[index as usize])?;
+ self.cached.borrow_mut()[index as usize] = ArrayThunk::Computed(new_value.clone());
Ok(Some(new_value))
}
- fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {
+ fn get_lazy(&self, index: u32) -> Option<Thunk<Val>> {
#[derive(Trace)]
struct ExprArrThunk {
expr: ExprArray,
- index: usize,
+ index: u32,
}
impl ThunkValue for ExprArrThunk {
type Output = Val;
@@ -180,7 +177,7 @@
if index >= self.len() {
return None;
}
- match &self.cached.borrow()[index] {
+ match &self.cached.borrow()[index as usize] {
ArrayThunk::Computed(c) => return Some(Thunk::evaluated(c.clone())),
ArrayThunk::Errored(e) => return Some(Thunk::errored(e.clone())),
ArrayThunk::Waiting | ArrayThunk::Pending => {}
@@ -200,19 +197,20 @@
pub struct ExtendedArray {
pub a: ArrValue,
pub b: ArrValue,
- split: usize,
- len: usize,
+ split: u32,
+ len: u32,
}
impl ExtendedArray {
- pub fn new(a: ArrValue, b: ArrValue) -> Self {
+ pub fn new(a: ArrValue, b: ArrValue) -> Option<Self> {
let a_len = a.len();
let b_len = b.len();
- Self {
+ let len = a_len.checked_add(b_len)?;
+ Some(Self {
a,
b,
split: a_len,
- len: a_len.checked_add(b_len).expect("too large array value"),
- }
+ len,
+ })
}
}
@@ -253,14 +251,14 @@
}
}
impl ArrayLike for ExtendedArray {
- fn get(&self, index: usize) -> Result<Option<Val>> {
+ fn get(&self, index: u32) -> Result<Option<Val>> {
if self.split > index {
self.a.get(index)
} else {
self.b.get(index - self.split)
}
}
- fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {
+ fn get_lazy(&self, index: u32) -> Option<Thunk<Val>> {
if self.split > index {
self.a.get_lazy(index)
} else {
@@ -268,7 +266,7 @@
}
}
- fn len(&self) -> usize {
+ fn len(&self) -> u32 {
self.len
}
@@ -282,19 +280,19 @@
T: IntoUntyped + Trace + fmt::Debug,
for<'a> &'a T: IntoUntyped,
{
- fn len(&self) -> usize {
- self.as_slice().len()
+ fn len(&self) -> u32 {
+ self.as_slice().len().try_into().unwrap_or(u32::MAX)
}
- fn get(&self, index: usize) -> Result<Option<Val>> {
- let Some(elem) = self.as_slice().get(index) else {
+ fn get(&self, index: u32) -> Result<Option<Val>> {
+ let Some(elem) = self.as_slice().get(index as usize) else {
return Ok(None);
};
IntoUntyped::into_untyped(elem).map(Some)
}
- fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {
- let elem = self.as_slice().get(index)?;
+ fn get_lazy(&self, index: u32) -> Option<Thunk<Val>> {
+ let elem = self.as_slice().get(index as usize)?;
Some(IntoUntyped::into_lazy_untyped(elem))
}
@@ -324,20 +322,20 @@
clippy::cast_sign_loss,
reason = "the math is valid with wrapping, sign loss works as intended"
)]
- fn size(&self) -> usize {
- (self.end as usize)
- .wrapping_sub(self.start as usize)
+ fn size(&self) -> u32 {
+ (self.end as u32)
+ .wrapping_sub(self.start as u32)
.wrapping_add(1)
}
fn range(&self) -> impl ExactSizeIterator<Item = i32> + DoubleEndedIterator {
- WithExactSize(self.start..=self.end, self.size())
+ WithExactSize(self.start..=self.end, self.size() as usize)
}
}
impl ArrayCheap for RangeArray {
- fn get(&self, index: usize) -> Option<Val> {
- self.range().nth(index).map(|i| Val::Num(i.into()))
+ fn get(&self, index: u32) -> Option<Val> {
+ self.range().nth(index as usize).map(|i| Val::Num(i.into()))
}
- fn len(&self) -> usize {
+ fn len(&self) -> u32 {
self.size()
}
}
@@ -345,15 +343,15 @@
#[derive(Debug, Trace)]
pub struct ReverseArray(pub ArrValue);
impl ArrayLike for ReverseArray {
- fn len(&self) -> usize {
+ fn len(&self) -> u32 {
self.0.len()
}
- fn get(&self, index: usize) -> Result<Option<Val>> {
+ fn get(&self, index: u32) -> Result<Option<Val>> {
self.0.get(self.0.len() - index - 1)
}
- fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {
+ fn get_lazy(&self, index: u32) -> Option<Thunk<Val>> {
self.0.get_lazy(self.0.len() - index - 1)
}
@@ -379,40 +377,37 @@
let len = inner.len();
Self {
inner,
- cached: Cc::new(RefCell::new(vec![ArrayThunk::Waiting; len])),
+ cached: Cc::new(RefCell::new(vec![ArrayThunk::Waiting; len as usize])),
mapper,
}
}
- fn evaluate(&self, index: usize, value: Val) -> Result<Val> {
+ fn evaluate(&self, index: u32, value: Val) -> Result<Val> {
match &self.mapper {
ArrayMapper::Plain(f) => f.call(value),
- #[expect(
- clippy::cast_possible_truncation,
- reason = "array len is limited to u31"
- )]
- ArrayMapper::WithIndex(f) => f.call(index as u32, value),
+ ArrayMapper::WithIndex(f) => f.call(index, value),
}
}
}
impl ArrayLike for MappedArray {
- fn len(&self) -> usize {
- self.cached.borrow().len()
+ fn len(&self) -> u32 {
+ self.cached.borrow().len() as u32
}
- fn get(&self, index: usize) -> Result<Option<Val>> {
+ fn get(&self, index: u32) -> Result<Option<Val>> {
if index >= self.len() {
return Ok(None);
}
- match &self.cached.borrow()[index] {
+ match &self.cached.borrow()[index as usize] {
ArrayThunk::Computed(c) => return Ok(Some(c.clone())),
ArrayThunk::Errored(e) => return Err(e.clone()),
ArrayThunk::Pending => return Err(InfiniteRecursionDetected.into()),
ArrayThunk::Waiting => {}
}
- let ArrayThunk::Waiting =
- replace(&mut self.cached.borrow_mut()[index], ArrayThunk::Pending)
- else {
+ let ArrayThunk::Waiting = replace(
+ &mut self.cached.borrow_mut()[index as usize],
+ ArrayThunk::Pending,
+ ) else {
unreachable!()
};
@@ -426,18 +421,18 @@
let new_value = match val {
Ok(v) => v,
Err(e) => {
- self.cached.borrow_mut()[index] = ArrayThunk::Errored(e.clone());
+ self.cached.borrow_mut()[index as usize] = ArrayThunk::Errored(e.clone());
return Err(e);
}
};
- self.cached.borrow_mut()[index] = ArrayThunk::Computed(new_value.clone());
+ self.cached.borrow_mut()[index as usize] = ArrayThunk::Computed(new_value.clone());
Ok(Some(new_value))
}
- fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {
+ fn get_lazy(&self, index: u32) -> Option<Thunk<Val>> {
#[derive(Trace)]
struct MappedArrayThunk {
arr: MappedArray,
- index: usize,
+ index: u32,
}
impl ThunkValue for MappedArrayThunk {
type Output = Val;
@@ -450,7 +445,7 @@
if index >= self.len() {
return None;
}
- match &self.cached.borrow()[index] {
+ match &self.cached.borrow()[index as usize] {
ArrayThunk::Computed(c) => return Some(Thunk::evaluated(c.clone())),
ArrayThunk::Errored(e) => return Some(Thunk::errored(e.clone())),
ArrayThunk::Waiting | ArrayThunk::Pending => {}
@@ -462,15 +457,92 @@
}))
}
}
+#[derive(Trace, Debug, Clone)]
+pub struct MakeArray {
+ cached: Cc<RefCell<Vec<ArrayThunk>>>,
+ mapper: NativeFn!((u32,)->Val),
+}
+impl MakeArray {
+ pub fn new(len: u32, mapper: NativeFn!((u32)->Val)) -> Self {
+ Self {
+ cached: Cc::new(RefCell::new(vec![ArrayThunk::Waiting; len as usize])),
+ mapper,
+ }
+ }
+}
+impl ArrayLike for MakeArray {
+ fn len(&self) -> u32 {
+ self.cached.borrow().len() as u32
+ }
+
+ fn get(&self, index: u32) -> Result<Option<Val>> {
+ if index >= self.len() {
+ return Ok(None);
+ }
+ match &self.cached.borrow()[index as usize] {
+ ArrayThunk::Computed(c) => return Ok(Some(c.clone())),
+ ArrayThunk::Errored(e) => return Err(e.clone()),
+ ArrayThunk::Pending => return Err(InfiniteRecursionDetected.into()),
+ ArrayThunk::Waiting => {}
+ }
+
+ let ArrayThunk::Waiting = replace(
+ &mut self.cached.borrow_mut()[index as usize],
+ ArrayThunk::Pending,
+ ) else {
+ unreachable!()
+ };
+
+ let val = self.mapper.call(index as u32);
+
+ let new_value = match val {
+ Ok(v) => v,
+ Err(e) => {
+ self.cached.borrow_mut()[index as usize] = ArrayThunk::Errored(e.clone());
+ return Err(e);
+ }
+ };
+ self.cached.borrow_mut()[index as usize] = ArrayThunk::Computed(new_value.clone());
+ Ok(Some(new_value))
+ }
+ fn get_lazy(&self, index: u32) -> Option<Thunk<Val>> {
+ #[derive(Trace)]
+ struct MakeArrayThunk {
+ arr: MakeArray,
+ index: u32,
+ }
+ impl ThunkValue for MakeArrayThunk {
+ type Output = Val;
+
+ fn get(&self) -> Result<Self::Output> {
+ self.arr.get(self.index).transpose().expect("index checked")
+ }
+ }
+
+ if index >= self.len() {
+ return None;
+ }
+ match &self.cached.borrow()[index as usize] {
+ ArrayThunk::Computed(c) => return Some(Thunk::evaluated(c.clone())),
+ ArrayThunk::Errored(e) => return Some(Thunk::errored(e.clone())),
+ ArrayThunk::Waiting | ArrayThunk::Pending => {}
+ }
+
+ Some(Thunk::new(MakeArrayThunk {
+ arr: self.clone(),
+ index,
+ }))
+ }
+}
#[derive(Trace, Debug)]
pub struct RepeatedArray {
data: ArrValue,
- repeats: usize,
- total_len: usize,
+ repeats: u32,
+ total_len: u32,
}
impl RepeatedArray {
- pub fn new(data: ArrValue, repeats: usize) -> Option<Self> {
+ pub fn new(data: ArrValue, repeats: u32) -> Option<Self> {
let total_len = data.len().checked_mul(repeats)?;
Some(Self {
data,
@@ -478,7 +550,7 @@
total_len,
})
}
- fn map_idx(&self, index: usize) -> Option<usize> {
+ fn map_idx(&self, index: u32) -> Option<u32> {
if index > self.total_len {
return None;
}
@@ -487,18 +559,18 @@
}
impl ArrayLike for RepeatedArray {
- fn len(&self) -> usize {
+ fn len(&self) -> u32 {
self.total_len
}
- fn get(&self, index: usize) -> Result<Option<Val>> {
+ fn get(&self, index: u32) -> Result<Option<Val>> {
let Some(idx) = self.map_idx(index) else {
return Ok(None);
};
self.data.get(idx)
}
- fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {
+ fn get_lazy(&self, index: u32) -> Option<Thunk<Val>> {
let idx = self.map_idx(index)?;
self.data.get_lazy(idx)
}
@@ -521,19 +593,19 @@
}
impl ArrayLike for PickObjectValues {
- fn len(&self) -> usize {
- self.keys.len()
+ fn len(&self) -> u32 {
+ self.keys.len() as u32
}
- fn get(&self, index: usize) -> Result<Option<Val>> {
- let Some(key) = self.keys.as_slice().get(index) else {
+ fn get(&self, index: u32) -> Result<Option<Val>> {
+ let Some(key) = self.keys.as_slice().get(index as usize) else {
return Ok(None);
};
Ok(Some(self.obj.get_or_bail(key.clone())?))
}
- fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {
- let key = self.keys.as_slice().get(index)?;
+ fn get_lazy(&self, index: u32) -> Option<Thunk<Val>> {
+ let key = self.keys.as_slice().get(index as usize)?;
Some(self.obj.get_lazy_or_bail(key.clone()))
}
@@ -561,12 +633,12 @@
}
impl ArrayLike for PickObjectKeyValues {
- fn len(&self) -> usize {
- self.keys.len()
+ fn len(&self) -> u32 {
+ self.keys.len() as u32
}
- fn get(&self, index: usize) -> Result<Option<Val>> {
- let Some(key) = self.keys.as_slice().get(index) else {
+ fn get(&self, index: u32) -> Result<Option<Val>> {
+ let Some(key) = self.keys.as_slice().get(index as usize) else {
return Ok(None);
};
Ok(Some(
@@ -578,8 +650,8 @@
))
}
- fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {
- let key = self.keys.as_slice().get(index)?;
+ fn get_lazy(&self, index: u32) -> Option<Thunk<Val>> {
+ let key = self.keys.as_slice().get(index as usize)?;
// Nothing can fail in the key part, yet value is still
// lazy-evaluated
Some(Thunk::evaluated(
crates/jrsonnet-evaluator/src/ctx.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/ctx.rs
+++ b/crates/jrsonnet-evaluator/src/ctx.rs
@@ -1,58 +1,29 @@
-use std::fmt::Debug;
+use std::{clone::Clone, fmt::Debug};
use educe::Educe;
use jrsonnet_gcmodule::{Cc, Trace};
use jrsonnet_interner::IStr;
-use rustc_hash::{FxHashMap, FxHashSet};
-use crate::{
- ObjValue, Pending, Result, SupThis, Thunk, Val, bail, error::ErrorKind::*,
- gc::WithCapacityExt as _,
-};
-/// Context keeps information about current lexical code location
-///
-/// This information includes local variables, top-level object (`$`), current object (`this`), and super object (`super`)
+use crate::{analyze::LocalId, error, error::ErrorKind::*, Pending, Result, SupThis, Thunk, Val};
+
#[derive(Debug, Trace, Clone, Educe)]
#[educe(PartialEq)]
pub struct Context(#[educe(PartialEq(method = Cc::ptr_eq))] Cc<ContextInternal>);
-#[derive(Debug, Trace)]
+#[derive(Debug, Trace, Clone)]
struct ContextInternal {
- dollar: Option<ObjValue>,
sup_this: Option<SupThis>,
- bindings: FxHashMap<IStr, Thunk<Val>>,
-
- branch_point: Option<Context>,
+ /// `bindings[i]` corresponds to `LocalId(offset + i)`.
+ bindings: Vec<Option<Thunk<Val>>>,
+ offset: u32,
+ parent: Option<Context>,
}
+
impl Context {
pub fn new_future() -> Pending<Self> {
Pending::new()
- }
-
- pub fn dollar(&self) -> Option<&ObjValue> {
- self.0.dollar.as_ref()
}
- pub fn try_dollar(&self) -> Result<ObjValue> {
- self.0
- .dollar
- .clone()
- .ok_or_else(|| CantUseSelfSupOutsideOfObject.into())
- }
-
- pub fn this(&self) -> Option<&ObjValue> {
- self.0.sup_this.as_ref().map(SupThis::this)
- }
-
- pub fn try_this(&self) -> Result<ObjValue> {
- self.0
- .sup_this
- .as_ref()
- .ok_or_else(|| CantUseSelfSupOutsideOfObject.into())
- .map(SupThis::this)
- .cloned()
- }
-
pub fn sup_this(&self) -> Option<&SupThis> {
self.0.sup_this.as_ref()
}
@@ -61,127 +32,98 @@
self.0
.sup_this
.clone()
- .ok_or_else(|| CantUseSelfSupOutsideOfObject.into())
+ .ok_or_else(|| error!(CantUseSelfSupOutsideOfObject))
}
- pub fn binding(&self, name: IStr) -> Result<Thunk<Val>> {
- use std::cmp::Ordering;
-
- use crate::bail;
+ /// Update binding in `CoW` fashion. Only useful for eager comprehension
+ /// fast-path, as it requires Cc refcount to be 1; Use `ContextBuilder` otherwise.
+ pub(crate) fn cow_fill_binding(&mut self, id: LocalId, value: Thunk<Val>) {
+ let mut value = Some(Some(value));
- if let Some(val) = self.0.bindings.get(&name).cloned() {
- return Ok(val);
- }
-
- if let Some(branch_point) = &self.0.branch_point {
- return branch_point.binding(name);
- }
+ self.0.update_with(|inner| {
+ let local_idx = (id.0 - inner.offset) as usize;
+ while inner.bindings.len() <= local_idx {
+ inner.bindings.push(None);
+ }
+ inner.bindings[local_idx] = value.take().expect("called once");
+ });
+ }
- let mut heap = Vec::new();
- for k in self.0.bindings.keys() {
- let conf = strsim::jaro_winkler(k as &str, &name as &str);
- if conf < 0.8 {
- continue;
+ pub fn binding(&self, id: LocalId) -> Option<Thunk<Val>> {
+ let id_num = id.0;
+ if id_num >= self.0.offset {
+ let local_idx = (id_num - self.0.offset) as usize;
+ if let Some(Some(thunk)) = self.0.bindings.get(local_idx) {
+ return Some(thunk.clone());
}
- heap.push((conf, k.clone()));
}
- heap.sort_by(|a, b| b.0.partial_cmp(&a.0).unwrap_or(Ordering::Equal));
+ if let Some(parent) = &self.0.parent {
+ return parent.binding(id);
+ }
+ None
+ }
- bail!(VariableIsNotDefined(
- name,
- heap.into_iter().map(|(_, k)| k).collect()
- ))
- }
- pub fn contains_binding(&self, name: IStr) -> bool {
- self.0.bindings.contains_key(&name)
- }
#[must_use]
pub fn into_future(self, ctx: Pending<Self>) -> Self {
{
ctx.clone().fill(self);
}
ctx.unwrap()
- }
-
- #[must_use]
- pub fn branch_point(self) -> Self {
- if self.0.bindings.is_empty() {
- self
- } else {
- ContextBuilder::extend(self).build()
- }
}
}
#[derive(Clone)]
pub struct ContextBuilder {
- dollar: Option<ObjValue>,
sup_this: Option<SupThis>,
- bindings: FxHashMap<IStr, Thunk<Val>>,
- filled: FxHashSet<IStr>,
- branch_point: Option<Context>,
+ bindings: Vec<Option<Thunk<Val>>>,
+ offset: u32,
+ parent: Option<Context>,
}
impl ContextBuilder {
pub fn new() -> Self {
Self {
- dollar: None,
sup_this: None,
- bindings: FxHashMap::new(),
- filled: FxHashSet::new(),
- branch_point: None,
+ bindings: Vec::new(),
+ offset: 0,
+ parent: None,
}
}
- pub fn extend_fast(parent: Context) -> Self {
+ pub(crate) fn extend(parent: Context, capacity: usize) -> Self {
+ let offset = parent.0.offset + parent.0.bindings.len() as u32;
Self {
- dollar: parent.0.dollar.clone(),
sup_this: parent.0.sup_this.clone(),
- bindings: parent.0.bindings.clone(),
- filled: FxHashSet::new(),
- branch_point: parent.0.branch_point.clone(),
+ bindings: Vec::with_capacity(capacity),
+ offset,
+ parent: Some(parent),
}
}
- pub fn extend(parent: Context) -> Self {
- Self {
- dollar: parent.0.dollar.clone(),
- sup_this: parent.0.sup_this.clone(),
- bindings: FxHashMap::new(),
- filled: FxHashSet::new(),
- branch_point: Some(parent.clone()),
+ pub(crate) fn bind(&mut self, id: LocalId, value: Thunk<Val>) {
+ debug_assert!(
+ id.0 >= self.offset,
+ "cannot bind {id:?} below offset {}",
+ self.offset,
+ );
+ let local_idx = (id.0 - self.offset) as usize;
+ self.bindings.reserve(local_idx);
+ while self.bindings.len() <= local_idx {
+ self.bindings.push(None);
}
+ self.bindings[local_idx] = Some(value);
}
- pub fn bind(&mut self, name: impl Into<IStr>, value: Thunk<Val>) {
- let _ = self.bindings.insert(name.into(), value);
- }
- /// After commit, binds would shadow the previous declarations
- #[must_use]
- pub fn commit(mut self) -> Self {
- self.filled.clear();
- self
- }
- pub fn try_bind(&mut self, name: impl Into<IStr>, value: Thunk<Val>) -> Result<()> {
- let name = name.into();
- if !self.filled.insert(name.clone()) {
- bail!(DuplicateLocalVar(name))
- }
- self.bind(name, value);
- Ok(())
- }
- pub fn build(self) -> Context {
+ pub(crate) fn build(self) -> Context {
Context(Cc::new(ContextInternal {
- dollar: self.dollar,
sup_this: self.sup_this,
bindings: self.bindings,
- branch_point: self.branch_point,
+ offset: self.offset,
+ parent: self.parent,
}))
}
- pub fn build_sup_this(mut self, st: SupThis) -> Context {
- if self.dollar.is_none() {
- self.dollar = Some(st.this().clone());
- }
+
+ pub(crate) fn build_sup_this(mut self, st: SupThis) -> Context {
self.sup_this = Some(st);
self.build()
}
@@ -192,3 +134,37 @@
Self::new()
}
}
+
+pub struct InitialContextBuilder {
+ builder: ContextBuilder,
+ externals: Vec<(IStr, LocalId)>,
+ next_id: u32,
+}
+
+impl InitialContextBuilder {
+ pub(crate) fn new() -> Self {
+ Self {
+ builder: ContextBuilder::new(),
+ externals: Vec::new(),
+ next_id: 0,
+ }
+ }
+
+ pub fn bind(&mut self, name: impl Into<IStr>, value: Thunk<Val>) {
+ let name = name.into();
+ let id = LocalId(self.next_id);
+ self.next_id += 1;
+ self.externals.push((name, id));
+ self.builder.bind(id, value);
+ }
+
+ pub(crate) fn build(self) -> (ContextBuilder, Vec<(IStr, LocalId)>) {
+ (self.builder, self.externals)
+ }
+}
+
+impl Default for InitialContextBuilder {
+ fn default() -> Self {
+ Self::new()
+ }
+}
crates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/error.rs
+++ b/crates/jrsonnet-evaluator/src/error.rs
@@ -9,16 +9,16 @@
use thiserror::Error;
use crate::{
- ObjValue, ResolvePathOwned,
function::{CallLocation, FunctionSignature, ParamName},
stdlib::format::FormatError,
typed::TypeLocError,
+ ObjValue, ResolvePathOwned,
};
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, Acyclic)]
pub struct SyntaxError {
pub message: String,
- pub location: (u32, u32),
+ pub location: Span,
}
impl fmt::Display for SyntaxError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -63,26 +63,36 @@
}
}
+pub(crate) fn suggest_names<'a, 'b>(
+ name: &'a IStr,
+ names: impl IntoIterator<Item = &'b IStr>,
+) -> Vec<IStr> {
+ let mut heap: Vec<(f64, IStr)> = names
+ .into_iter()
+ .filter_map(|def| {
+ let conf = strsim::jaro_winkler(def.as_str(), name.as_str());
+ if conf < 0.8 {
+ return None;
+ }
+ debug_assert!(
+ def.as_str() != name.as_str(),
+ "string pooling failure: look for DOC(string-pooling) comment in jrsonnet-interner"
+ );
+
+ Some((conf, def.clone()))
+ })
+ .collect();
+ heap.sort_by(|a, b| b.0.partial_cmp(&a.0).unwrap_or(Ordering::Equal));
+ heap.into_iter().map(|v| v.1).collect()
+}
+
pub(crate) fn suggest_object_fields(v: &ObjValue, key: IStr) -> Vec<IStr> {
- let mut heap = Vec::new();
- for field in v.fields_ex(
+ let fields = v.fields_ex(
true,
#[cfg(feature = "exp-preserve-order")]
false,
- ) {
- let conf = strsim::jaro_winkler(field.as_str(), key.as_str());
- if conf < 0.8 {
- continue;
- }
- assert!(
- field.as_str() != key.as_str(),
- "looks like string pooling failure, please write any info regarding this crash to https://github.com/CertainLach/jrsonnet/issues/113, thanks!"
- );
-
- heap.push((conf, field));
- }
- heap.sort_by(|a, b| b.0.partial_cmp(&a.0).unwrap_or(Ordering::Equal));
- heap.into_iter().map(|v| v.1).collect()
+ );
+ suggest_names(&key, &fields)
}
/// Possible errors
@@ -100,6 +110,9 @@
#[error("self/super/$ are only usable inside objects")]
CantUseSelfSupOutsideOfObject,
+
+ #[error("static analysis errors: {}", .0.iter().map(|d| d.message.as_str()).collect::<Vec<_>>().join("; "))]
+ StaticAnalysisError(Vec<crate::analyze::Diagnostic>),
#[error("no super found")]
NoSuperFound,
@@ -107,17 +120,12 @@
InComprehensionCanOnlyIterateOverArray,
#[error("array out of bounds: {0} is not within [0,{1})")]
- ArrayBoundsError(isize, usize),
+ ArrayBoundsError(isize, u32),
#[error("string out of bounds: {0} is not within [0,{1})")]
StringBoundsError(usize, usize),
#[error("assert failed: {}", format_empty_str(.0))]
AssertionFailed(IStr),
-
- #[error("local is not defined: {0}{found}", found = format_found(.1, "local"))]
- VariableIsNotDefined(IStr, Vec<IStr>),
- #[error("duplicate local var: {0}")]
- DuplicateLocalVar(IStr),
#[error("type mismatch: expected {expected}, got {2} {0}", expected = .1.iter().map(|e| format!("{e}")).collect::<Vec<_>>().join(", "))]
TypeMismatch(&'static str, Vec<ValType>, ValType),
@@ -172,7 +180,6 @@
#[error("syntax error: {error}")]
ImportSyntaxError {
path: Source,
- #[trace(skip)]
error: Box<SyntaxError>,
},
@@ -279,11 +286,11 @@
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- writeln!(f, "{}", self.0.0)?;
- for el in &self.0.1.0 {
+ writeln!(f, "{}", self.0 .0)?;
+ for el in &self.0 .1 .0 {
write!(f, "\t{}", el.desc)?;
if let Some(loc) = &el.location {
- write!(f, "at {}", loc.0.0.0)?;
+ write!(f, "at {}", loc.0 .0 .0)?;
loc.0.map_source_locations(&[loc.1, loc.2]);
}
writeln!(f)?;
@@ -377,6 +384,18 @@
return Err($crate::error::ErrorKind::RuntimeError($crate::jrsonnet_macros::format_istr!($l$(, $($tt)*)?)).into())
};
}
+#[macro_export]
+macro_rules! error {
+ ($w:ident$(::$i:ident)*$(($($tt:tt)*))?) => {
+ $crate::error::Error::from($w$(::$i)*$(($($tt)*))?)
+ };
+ ($w:ident$(::$i:ident)*$({$($tt:tt)*})?) => {
+ $crate::error::Error::from($w$(::$i)*$({$($tt)*})?)
+ };
+ ($l:literal$(, $($tt:tt)*)?) => {
+ <$crate::error::Error as From<$crate::error::ErrorKind>>::from($crate::error::ErrorKind::RuntimeError($crate::jrsonnet_macros::format_istr!($l$(, $($tt)*)?)).into())
+ };
+}
#[macro_export]
macro_rules! runtime_error {
crates/jrsonnet-evaluator/src/evaluate/compspec.rsdiffbeforeafterboth--- /dev/null
+++ b/crates/jrsonnet-evaluator/src/evaluate/compspec.rs
@@ -0,0 +1,330 @@
+use std::rc::Rc;
+
+use jrsonnet_types::ValType;
+
+use super::{
+ destructure::{self, evaluate_locals, evaluate_locals_unbound},
+ evaluate_field_member_static, evaluate_field_member_unbound,
+};
+use crate::{
+ analyze::{LArrComp, LBind, LCompSpec, LDestruct, LExpr, LFieldMember, LObjComp, LocalId},
+ arr::ArrValue,
+ bail,
+ error::ErrorKind::*,
+ evaluate::evaluate,
+ Context, ContextBuilder, ObjValue, ObjValueBuilder, Pending, Result, Thunk, Val,
+};
+
+trait CompCollector {
+ fn reserve(&mut self, _guaranteed: usize) {}
+ fn collect(&mut self, ctx: Context) -> Result<()>;
+}
+
+struct EagerArrCollector<'a> {
+ out: &'a mut Vec<Val>,
+ value: &'a LExpr,
+}
+impl CompCollector for EagerArrCollector<'_> {
+ fn reserve(&mut self, size_hint: usize) {
+ self.out.reserve(size_hint);
+ }
+ fn collect(&mut self, ctx: Context) -> Result<()> {
+ self.out.push(evaluate(ctx, self.value)?);
+ Ok(())
+ }
+}
+
+struct LazyArrCollector<'a> {
+ out: &'a mut Vec<Thunk<Val>>,
+ value: &'a Rc<LExpr>,
+}
+impl CompCollector for LazyArrCollector<'_> {
+ fn reserve(&mut self, size_hint: usize) {
+ self.out.reserve(size_hint);
+ }
+ fn collect(&mut self, ctx: Context) -> Result<()> {
+ let value_expr = self.value.clone();
+ self.out.push(Thunk!(move || evaluate(ctx, &value_expr)));
+ Ok(())
+ }
+}
+
+struct ObjCompCollectorStatic<'a> {
+ builder: &'a mut ObjValueBuilder,
+ locals: &'a [LBind],
+ field: &'a LFieldMember,
+}
+impl CompCollector for ObjCompCollectorStatic<'_> {
+ fn reserve(&mut self, guaranteed: usize) {
+ self.builder.reserve_fields(guaranteed);
+ }
+ fn collect(&mut self, inner_ctx: Context) -> Result<()> {
+ let value_ctx = evaluate_locals(inner_ctx.clone(), self.locals);
+ evaluate_field_member_static(self.builder, inner_ctx, value_ctx, self.field)
+ }
+}
+
+struct ObjCompCollectorUnbound<'a> {
+ builder: &'a mut ObjValueBuilder,
+ locals: Rc<Vec<LBind>>,
+ this_id: Option<LocalId>,
+ field: &'a LFieldMember,
+}
+impl CompCollector for ObjCompCollectorUnbound<'_> {
+ fn reserve(&mut self, guaranteed: usize) {
+ self.builder.reserve_fields(guaranteed);
+ }
+ fn collect(&mut self, inner_ctx: Context) -> Result<()> {
+ let uctx = evaluate_locals_unbound(inner_ctx.clone(), self.locals.clone(), self.this_id);
+ evaluate_field_member_unbound(self.builder, inner_ctx, uctx, self.field)
+ }
+}
+
+pub fn evaluate_obj_comp(
+ super_obj: Option<ObjValue>,
+ ctx: Context,
+ comp: &LObjComp,
+) -> Result<Val> {
+ let mut builder = ObjValueBuilder::new();
+ if let Some(super_obj) = super_obj {
+ builder.with_super(super_obj);
+ }
+
+ let cached_overs = cache_overs(&ctx, &comp.compspecs)?;
+ if comp.this.is_some() || comp.uses_super {
+ evaluate_compspecs(
+ ctx,
+ &comp.compspecs,
+ &cached_overs,
+ 0,
+ 0,
+ &mut ObjCompCollectorUnbound {
+ builder: &mut builder,
+ locals: comp.locals.clone(),
+ this_id: comp.this,
+ field: &comp.field,
+ },
+ )?;
+ } else {
+ evaluate_compspecs(
+ ctx,
+ &comp.compspecs,
+ &cached_overs,
+ 0,
+ 0,
+ &mut ObjCompCollectorStatic {
+ builder: &mut builder,
+ locals: &comp.locals,
+ field: &comp.field,
+ },
+ )?;
+ }
+
+ Ok(Val::Obj(builder.build()))
+}
+
+pub fn evaluate_arr_comp(ctx: Context, comp: &LArrComp) -> Result<Val> {
+ let cached_overs = cache_overs(&ctx, &comp.compspecs)?;
+
+ // In eager evaluation, Context is not captured, thus updates in CoW fashion will likely to success
+ 'eager: {
+ let mut out = Vec::new();
+
+ if evaluate_compspecs_eager(
+ ctx.clone(),
+ &comp.compspecs,
+ &cached_overs,
+ 0,
+ 0,
+ &mut EagerArrCollector {
+ out: &mut out,
+ value: &comp.value,
+ },
+ )
+ .is_err()
+ {
+ break 'eager;
+ }
+ return Ok(Val::arr(out));
+ }
+
+ let mut items: Vec<Thunk<Val>> = Vec::new();
+ evaluate_compspecs(
+ ctx,
+ &comp.compspecs,
+ &cached_overs,
+ 0,
+ 0,
+ &mut LazyArrCollector {
+ out: &mut items,
+ value: &comp.value,
+ },
+ )?;
+ Ok(Val::arr(items))
+}
+
+fn cache_overs(ctx: &Context, specs: &[LCompSpec]) -> Result<Vec<Option<ArrValue>>> {
+ specs
+ .iter()
+ .map(|spec| {
+ Ok(match spec {
+ LCompSpec::For {
+ over,
+ loop_invariant: true,
+ ..
+ } => {
+ let val = evaluate(ctx.clone(), over)?;
+ let Val::Arr(arr) = val else {
+ bail!(InComprehensionCanOnlyIterateOverArray)
+ };
+ Some(arr)
+ }
+ _ => None,
+ })
+ })
+ .collect::<Result<_>>()
+}
+
+fn evaluate_compspecs_eager(
+ ctx: Context,
+ specs: &[LCompSpec],
+ cached_overs: &[Option<ArrValue>],
+ idx: usize,
+ guaranteed_reserve: usize,
+ collector: &mut dyn CompCollector,
+) -> Result<()> {
+ if idx >= specs.len() {
+ collector.reserve(guaranteed_reserve);
+ return collector.collect(ctx.clone());
+ }
+ match &specs[idx] {
+ LCompSpec::If(cond) => {
+ let val = evaluate(ctx.clone(), cond)?;
+ let Val::Bool(b) = val else {
+ bail!(TypeMismatch(
+ "if spec condition",
+ vec![ValType::Bool],
+ val.value_type()
+ ))
+ };
+ if b {
+ evaluate_compspecs_eager(ctx, specs, cached_overs, idx + 1, 0, collector)?;
+ }
+ }
+ LCompSpec::For { destruct, over, .. } => {
+ let arr = if let Some(cached) = &cached_overs[idx] {
+ cached.clone()
+ } else {
+ let arr_val = evaluate(ctx.clone(), over)?;
+ let Val::Arr(arr) = arr_val else {
+ bail!(InComprehensionCanOnlyIterateOverArray)
+ };
+ arr
+ };
+ let inner_reserve = guaranteed_reserve.max(1) * arr.len() as usize;
+ match destruct {
+ LDestruct::Full(id) => {
+ let id = *id;
+ let mut inner_ctx = ContextBuilder::extend(ctx, 1).build();
+ for (i, item) in arr.iter().enumerate() {
+ // TODO: reuse one ContextBuilder for full evaluate_compspecs pipeline
+ inner_ctx.cow_fill_binding(id, Thunk::evaluated(item?));
+ evaluate_compspecs_eager(
+ inner_ctx.clone(),
+ specs,
+ cached_overs,
+ idx + 1,
+ if i == 0 { inner_reserve } else { 0 },
+ collector,
+ )?;
+ }
+ }
+ #[cfg(feature = "exp-destruct")]
+ _ => {
+ for (i, item) in arr.iter().enumerate() {
+ let item_val = item?;
+ let mut inner_builder = ContextBuilder::extend(ctx.clone(), 1);
+ destructure::destruct(
+ destruct,
+ Thunk::evaluated(item_val),
+ None,
+ &mut inner_builder,
+ );
+ let inner_ctx = inner_builder.build();
+ evaluate_compspecs_eager(
+ inner_ctx,
+ specs,
+ cached_overs,
+ idx + 1,
+ if i == 0 { inner_reserve } else { 0 },
+ collector,
+ )?;
+ }
+ }
+ }
+ }
+ }
+ Ok(())
+}
+
+fn evaluate_compspecs(
+ ctx: Context,
+ specs: &[LCompSpec],
+ cached_overs: &[Option<ArrValue>],
+ idx: usize,
+ guaranteed_reserve: usize,
+ collector: &mut dyn CompCollector,
+) -> Result<()> {
+ if idx >= specs.len() {
+ collector.reserve(guaranteed_reserve);
+ return collector.collect(ctx);
+ }
+ match &specs[idx] {
+ LCompSpec::If(cond) => {
+ let val = evaluate(ctx.clone(), cond)?;
+ let Val::Bool(b) = val else {
+ bail!(TypeMismatch(
+ "if spec condition",
+ vec![ValType::Bool],
+ val.value_type()
+ ))
+ };
+ if b {
+ evaluate_compspecs(ctx, specs, cached_overs, idx + 1, 0, collector)?;
+ }
+ }
+ LCompSpec::For { destruct, over, .. } => {
+ let arr = if let Some(cached) = &cached_overs[idx] {
+ cached.clone()
+ } else {
+ let arr_val = evaluate(ctx.clone(), over)?;
+ let Val::Arr(arr) = arr_val else {
+ bail!(InComprehensionCanOnlyIterateOverArray)
+ };
+ arr
+ };
+ let inner_reserve = guaranteed_reserve.max(1) * arr.len() as usize;
+ for (i, item) in arr.iter().enumerate() {
+ let item_val = item?;
+ let mut inner_builder = ContextBuilder::extend(ctx.clone(), 1);
+ let fctx = Pending::new();
+ destructure::destruct(
+ destruct,
+ Thunk::evaluated(item_val),
+ fctx.clone(),
+ &mut inner_builder,
+ );
+ let inner_ctx = inner_builder.build().into_future(fctx);
+ evaluate_compspecs(
+ inner_ctx,
+ specs,
+ cached_overs,
+ idx + 1,
+ if i == 0 { inner_reserve } else { 0 },
+ collector,
+ )?;
+ }
+ }
+ }
+ Ok(())
+}
crates/jrsonnet-evaluator/src/evaluate/destructure.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/evaluate/destructure.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/destructure.rs
@@ -1,213 +1,256 @@
-use jrsonnet_ir::{BindSpec, Destruct};
+use std::rc::Rc;
+
+use jrsonnet_gcmodule::Trace;
use crate::{
- Context, ContextBuilder, Pending, Thunk, Val, error::Result, evaluate_method,
- evaluate_named_param,
+ analyze::{LBind, LDestruct, LDestructField, LDestructRest, LExpr, LocalId},
+ bail,
+ evaluate::evaluate,
+ Context, ContextBuilder, Pending, Result, SupThis, Thunk, Unbound, Val,
};
-#[allow(clippy::too_many_lines)]
-#[allow(unused_variables)]
-pub fn destruct(
- d: &Destruct,
- parent: Thunk<Val>,
+#[allow(dead_code, reason = "not dead in exp-destruct")]
+fn destruct_array(
+ start: &[LDestruct],
+ rest: Option<LDestructRest>,
+ end: &[LDestruct],
+
+ value: Thunk<Val>,
fctx: Pending<Context>,
- new_bindings: &mut ContextBuilder,
-) -> Result<()> {
- match d {
- Destruct::Full(v) => {
- new_bindings.try_bind(v.clone(), parent)?;
+ builder: &mut ContextBuilder,
+) {
+ let min_len = start.len() + end.len();
+ let has_rest = rest.is_some();
+ let full = Thunk!(move || {
+ let v = value.evaluate()?;
+ let Val::Arr(arr) = v else {
+ bail!("expected array");
+ };
+ if !has_rest {
+ if arr.len() as usize != min_len {
+ bail!("expected {} elements, got {}", min_len, arr.len())
+ }
+ } else if (arr.len() as usize) < min_len {
+ bail!(
+ "expected at least {} elements, but array was only {}",
+ min_len,
+ arr.len()
+ )
}
- #[cfg(feature = "exp-destruct")]
- Destruct::Skip => {}
- #[cfg(feature = "exp-destruct")]
- Destruct::Array { start, rest, end } => {
- use jrsonnet_ir::DestructRest;
+ Ok(arr)
+ });
- use crate::bail;
+ for (i, d) in start.iter().enumerate() {
+ let full = full.clone();
+ destruct(
+ d,
+ Thunk!(move || Ok(full.evaluate()?.get(i as u32)?.expect("length is checked"))),
+ fctx.clone(),
+ builder,
+ );
+ }
- let min_len = start.len() + end.len();
- let has_rest = rest.is_some();
- let full = Thunk!(move || {
- let v = parent.evaluate()?;
- let Val::Arr(arr) = v else {
- bail!("expected array");
- };
- if !has_rest {
- if arr.len() != min_len {
- bail!("expected {} elements, got {}", min_len, arr.len())
- }
- } else if arr.len() < min_len {
- bail!(
- "expected at least {} elements, but array was only {}",
- min_len,
- arr.len()
- )
- }
- Ok(arr)
- });
+ let start_len = start.len() as u32;
+ let end_len = end.len() as u32;
- {
- for (i, d) in start.iter().enumerate() {
- let full = full.clone();
- destruct(
- d,
- Thunk!(move || Ok(full.evaluate()?.get(i)?.expect("length is checked"))),
- fctx.clone(),
- new_bindings,
- )?;
- }
- }
+ if let Some(crate::analyze::LDestructRest::Keep(id)) = rest {
+ let full = full.clone();
+ builder.bind(
+ id,
+ Thunk!(move || {
+ let full = full.evaluate()?;
+ let to = full.len() - end_len;
+ Ok(Val::Arr(full.slice(
+ Some(start_len as i32),
+ Some(to as i32),
+ None,
+ )))
+ }),
+ );
+ }
- match rest {
- Some(DestructRest::Keep(v)) => {
- let start = start.len();
- let end = end.len();
- let full = full.clone();
- destruct(
- &Destruct::Full(v.clone()),
- Thunk!(move || {
- let full = full.evaluate()?;
- let to = full.len() - end;
- Ok(Val::Arr(full.slice(
- Some(start as i32),
- Some(to as i32),
- None,
- )))
- }),
- fctx.clone(),
- new_bindings,
- )?;
- }
- Some(DestructRest::Drop) | None => {}
- }
+ for (i, d) in end.iter().enumerate() {
+ let full = full.clone();
+ destruct(
+ d,
+ Thunk!(move || {
+ let full = full.evaluate()?;
+ Ok(full
+ .get(full.len() - end_len + i as u32)?
+ .expect("length is checked"))
+ }),
+ fctx.clone(),
+ builder,
+ );
+ }
+}
- {
- for (i, d) in end.iter().enumerate() {
- let full = full.clone();
- let end = end.len();
- destruct(
- d,
- Thunk!(move || {
- let full = full.evaluate()?;
- Ok(full.get(full.len() - end + i)?.expect("length is checked"))
- }),
- fctx.clone(),
- new_bindings,
- )?;
- }
- }
- }
- #[cfg(feature = "exp-destruct")]
- Destruct::Object { fields, rest } => {
- use jrsonnet_ir::DestructRest;
- use rustc_hash::FxHashSet;
+#[allow(dead_code, reason = "not dead in exp-destruct")]
+fn destruct_object(
+ fields: &[LDestructField],
+ rest: Option<LDestructRest>,
- use crate::{ObjValueBuilder, bail};
+ value: Thunk<Val>,
+ fctx: Pending<Context>,
+ builder: &mut ContextBuilder,
+) {
+ use jrsonnet_interner::IStr;
+ use rustc_hash::FxHashSet;
- let captured_fields: FxHashSet<_> = fields.iter().map(|f| f.0.clone()).collect();
- let field_names: Vec<_> = fields
- .iter()
- .map(|f| (f.0.clone(), f.2.is_some()))
- .collect();
- let has_rest = rest.is_some();
- let full = Thunk!(move || {
- let v = parent.evaluate()?;
- let Val::Obj(obj) = v else {
- bail!("expected object");
- };
- for (field, has_default) in &field_names {
- if !has_default && !obj.has_field_ex(field.clone(), true) {
- bail!("missing field: {field}");
- }
- }
- if !has_rest {
- let len = obj.len();
- if len > field_names.len() {
- bail!("too many fields, and rest not found");
- }
- }
- Ok(obj)
- });
+ use crate::{bail, ObjValueBuilder};
- match rest {
- Some(DestructRest::Keep(v)) => {
- let full = full.clone();
- destruct(
- &Destruct::Full(v.clone()),
- Thunk!(move || {
- let full = full.evaluate()?;
- let mut builder = ObjValueBuilder::new();
- builder.extend_with_core(full.as_standalone());
- builder.with_fields_omitted(captured_fields);
- Ok(Val::Obj(builder.build()))
- }),
- fctx.clone(),
- new_bindings,
- )?;
- }
- Some(DestructRest::Drop) | None => {}
+ let captured_fields: FxHashSet<IStr> = fields.iter().map(|f| f.name.clone()).collect();
+ let field_names: Vec<(IStr, bool)> = fields
+ .iter()
+ .map(|f| (f.name.clone(), f.default.is_some()))
+ .collect();
+ let has_rest = rest.is_some();
+ let full = Thunk!(move || {
+ let v = value.evaluate()?;
+ let Val::Obj(obj) = v else {
+ bail!("expected object");
+ };
+ for (field, has_default) in &field_names {
+ if !has_default && !obj.has_field_ex(field.clone(), true) {
+ bail!("missing field: {field}");
+ }
+ }
+ if !has_rest {
+ let len = obj.len();
+ if len as usize > field_names.len() {
+ bail!("too many fields, and rest not found");
}
+ }
+ Ok(obj)
+ });
+
+ if let Some(crate::analyze::LDestructRest::Keep(id)) = rest {
+ let full = full.clone();
+ builder.bind(
+ id,
+ Thunk!(move || {
+ let full = full.evaluate()?;
+ let mut out = ObjValueBuilder::new();
+ out.extend_with_core(full.as_standalone());
+ out.with_fields_omitted(captured_fields);
+ Ok(Val::Obj(out.build()))
+ }),
+ );
+ }
- for (field, d, default) in fields {
- let default = default.clone().map(|e| (fctx.clone(), e));
- let value = {
- let field = field.clone();
- let full = full.clone();
- Thunk!(move || {
- let full = full.evaluate()?;
- if let Some(field) = full.get(field)? {
- Ok(field)
- } else {
- let (fctx, expr) = default.as_ref().expect("shape is checked");
- Ok(crate::evaluate(fctx.clone().unwrap(), expr)?)
- }
- })
- };
+ for field in fields {
+ let field_name = field.name.clone();
+ let default: Option<(Pending<Context>, Rc<LExpr>)> =
+ field.default.as_ref().map(|e| (fctx.clone(), e.clone()));
+ let field_full = full.clone();
+ let value_thunk = Thunk!(move || {
+ let obj = field_full.evaluate()?;
+ obj.get(field_name)?.map_or_else(
+ || {
+ let (fctx, expr) = default.as_ref().expect("shape is checked");
+ evaluate(fctx.unwrap(), expr)
+ },
+ Ok,
+ )
+ });
- if let Some(d) = d {
- destruct(d, value, fctx.clone(), new_bindings)?;
- } else {
- destruct(
- &Destruct::Full(field.clone()),
- value,
- fctx.clone(),
- new_bindings,
- )?;
- }
- }
+ if let Some(into) = &field.into {
+ destruct(into, value_thunk, fctx.clone(), builder);
+ } else {
+ unreachable!("analyzer lowers object-destruct shorthands into `into`");
}
}
- Ok(())
}
-pub fn evaluate_dest(
- d: &BindSpec,
+/// Bind a pre-built thunk to an [`LDestruct`] pattern, inserting one
+/// binding per [`LocalId`] the pattern introduces.
+///
+/// `fctx` is needed for object-destruct defaults (feature `exp-destruct`).
+#[allow(unused_variables)]
+pub fn destruct(
+ d: &LDestruct,
+ value: Thunk<Val>,
fctx: Pending<Context>,
- new_bindings: &mut ContextBuilder,
-) -> Result<()> {
+ builder: &mut ContextBuilder,
+) {
match d {
- BindSpec::Field { into, value } => {
- let name = into.name();
- let value = value.clone();
- let data = {
- let fctx = fctx.clone();
- Thunk!(move || evaluate_named_param(fctx.unwrap(), &value, name))
- };
- destruct(into, data, fctx, new_bindings)?;
+ LDestruct::Full(id) => builder.bind(*id, value),
+ #[cfg(feature = "exp-destruct")]
+ LDestruct::Skip => {}
+ #[cfg(feature = "exp-destruct")]
+ LDestruct::Array { start, rest, end } => destruct_array(start, rest, end, value, fctx, builder),
+ #[cfg(feature = "exp-destruct")]
+ LDestruct::Object { fields, rest } => destruct_object(fields, rest, value, fctx, builder),
+ }
+}
+
+/// Bind one [`LBind`] as a lazy thunk that evaluates in the given
+/// future context. Mirrors the old `evaluate_dest` — one entry per
+/// binding in a `local … ;` frame.
+pub fn evaluate_dest(bind: &LBind, fctx: Pending<Context>, builder: &mut ContextBuilder) {
+ let value = bind.value.clone();
+ let fctx_clone = fctx.clone();
+ let thunk = Thunk!(move || {
+ let ctx = fctx_clone.unwrap();
+ evaluate(ctx, &value)
+ });
+ destruct(&bind.destruct, thunk, fctx, builder);
+}
+
+/// Bind each LBind's value as a lazy thunk. Mutually recursive locals
+/// resolve lazily through the shared Pending<Context>.
+pub fn evaluate_locals(parent: Context, binds: &[LBind]) -> Context {
+ if binds.is_empty() {
+ return parent;
+ }
+ let fctx = Context::new_future();
+ let mut builder =
+ ContextBuilder::extend(parent, binds.iter().map(|b| b.destruct.ids().len()).sum());
+ for bind in binds {
+ evaluate_dest(bind, fctx.clone(), &mut builder);
+ }
+ builder.build().into_future(fctx)
+}
+
+pub trait CloneableUnbound<T>: Unbound<Bound = T> + Clone {}
+impl<V, T> CloneableUnbound<T> for V where V: Unbound<Bound = T> + Clone {}
+
+pub fn evaluate_locals_unbound(
+ fctx: Context,
+ locals: Rc<Vec<LBind>>,
+ this_id: Option<LocalId>,
+) -> impl CloneableUnbound<Context> {
+ #[derive(Trace, Clone)]
+ struct UnboundLocals {
+ fctx: Context,
+ locals: Rc<Vec<LBind>>,
+ this_id: Option<LocalId>,
+ }
+ impl Unbound for UnboundLocals {
+ type Bound = Context;
+
+ fn bind(&self, sup_this: SupThis) -> Result<Context> {
+ let parent = self.fctx.clone();
+
+ let fctx = Context::new_future();
+ let mut builder = ContextBuilder::extend(
+ parent,
+ self.locals.iter().map(|b| b.destruct.ids().len()).sum(),
+ );
+ for b in self.locals.iter() {
+ evaluate_dest(b, fctx.clone(), &mut builder);
+ }
+ if let Some(this_id) = self.this_id {
+ builder.bind(this_id, Thunk::evaluated(Val::Obj(sup_this.this().clone())));
+ }
+ let ctx = builder.build_sup_this(sup_this).into_future(fctx);
+ Ok(ctx)
}
- BindSpec::Function {
- name,
- params,
- value,
- } => {
- let params = params.clone();
- let name = name.clone();
- let value = value.clone();
- new_bindings.try_bind(
- name.clone(),
- Thunk!(move || Ok(evaluate_method(fctx.unwrap(), name, params, value))),
- )?;
- }
}
- Ok(())
+
+ UnboundLocals {
+ fctx,
+ locals,
+ this_id,
+ }
}
crates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/evaluate/mod.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/mod.rs
@@ -2,39 +2,42 @@
use jrsonnet_gcmodule::{Cc, Trace};
use jrsonnet_interner::IStr;
-use jrsonnet_ir::{
- ArgsDesc, AssertStmt, BinaryOpType, BindSpec, CompSpec, Expr, ExprParams, FieldMember,
- FieldName, ForSpecData, IfSpecData, ImportKind, LiteralType, ObjBody, ObjMembers, Spanned,
- function::ParamName,
-};
+use jrsonnet_ir::ImportKind;
use jrsonnet_types::ValType;
-use self::destructure::destruct;
+use self::{
+ compspec::{evaluate_arr_comp, evaluate_obj_comp},
+ destructure::{evaluate_locals, evaluate_locals_unbound},
+ operator::evaluate_binary_op_special,
+};
use crate::{
- Context, ContextBuilder, Error, ObjValue, ObjValueBuilder, ObjectAssertion, Pending, Result,
- ResultExt, SupThis, Unbound, Val,
- arr::ArrValue,
+ analyze::{
+ LArgsDesc, LAssertStmt, LExpr, LFieldMember, LFieldName, LFunction, LIndexPart, LObjBody,
+ LObjMembers,
+ },
bail,
- destructure::evaluate_dest,
- error::{ErrorKind::*, suggest_object_fields},
- evaluate::operator::{evaluate_binary_op_special, evaluate_unary_op},
- function::{CallLocation, FuncDesc, FuncVal, PreparedFuncVal},
- in_frame,
- typed::{FromUntyped, IntoUntyped as _, Typed},
- val::{CachedUnbound, IndexableVal, StrValue, Thunk},
- with_state,
+ error::{suggest_object_fields, ErrorKind::*},
+ evaluate::operator::evaluate_unary_op,
+ function::{prepared::PreparedFuncVal, CallLocation, FuncDesc, FuncVal},
+ in_frame, runtime_error,
+ typed::FromUntyped as _,
+ val::{CachedUnbound, Thunk},
+ with_state, Context, Error, ObjValue, ObjValueBuilder, ObjectAssertion, Result, ResultExt as _,
+ SupThis, Unbound, Val,
};
+
+pub mod compspec;
pub mod destructure;
pub mod operator;
// This is the amount of bytes that need to be left on the stack before increasing the size.
// It must be at least as large as the stack required by any code that does not call
// `ensure_sufficient_stack`.
-const RED_ZONE: usize = 100 * 1024; // 100k
+const RED_ZONE: usize = 100 * 1024;
// Only the first stack that is pushed, grows exponentially (2^n * STACK_PER_RECURSION) from then
// on. This flag has performance relevant characteristics. Don't set it too high.
-const STACK_PER_RECURSION: usize = 1024 * 1024; // 1MB
+const STACK_PER_RECURSION: usize = 1024 * 1024;
/// Grows the stack on demand to prevent stack overflow. Call this in strategic locations
/// to "break up" recursive calls. E.g. almost any call to `visit_expr` or equivalent can benefit
@@ -46,54 +49,36 @@
stacker::maybe_grow(RED_ZONE, STACK_PER_RECURSION, f)
}
-pub fn evaluate_trivial(expr: &Expr) -> Option<Val> {
- fn is_trivial(expr: &Expr) -> bool {
- match expr {
- Expr::Str(_)
- | Expr::Num(_)
- | Expr::Literal(LiteralType::False | LiteralType::True | LiteralType::Null) => true,
- Expr::Arr(a) => a.iter().all(is_trivial),
- _ => false,
- }
- }
+pub fn evaluate_trivial(expr: &LExpr) -> Option<Val> {
+ // TODO: Eager trivial array
Some(match expr {
- Expr::Str(s) => Val::string(s.clone()),
- Expr::Num(n) => Val::Num(*n),
- Expr::Literal(LiteralType::False) => Val::Bool(false),
- Expr::Literal(LiteralType::True) => Val::Bool(true),
- Expr::Literal(LiteralType::Null) => Val::Null,
- Expr::Arr(n) => {
- if n.iter().any(|e| !is_trivial(e)) {
- return None;
- }
- Val::Arr(
- n.iter()
- .map(evaluate_trivial)
- .map(|e| e.expect("checked trivial"))
- .collect(),
- )
- }
+ LExpr::Str(s) => Val::string(s.clone()),
+ LExpr::Num(n) => Val::Num(*n),
+ LExpr::Bool(false) => Val::Bool(false),
+ LExpr::Bool(true) => Val::Bool(true),
+ LExpr::Null => Val::Null,
_ => return None,
})
}
-pub fn evaluate_method(ctx: Context, name: IStr, params: ExprParams, body: Rc<Expr>) -> Val {
+/// Evaluate a method definition.
+pub fn evaluate_method(ctx: Context, name: IStr, func: &Rc<LFunction>) -> Val {
Val::Func(FuncVal::Normal(Cc::new(FuncDesc {
name,
ctx,
- params,
- body,
+ func: func.clone(),
})))
}
-pub fn evaluate_field_name(ctx: Context, field_name: &Spanned<FieldName>) -> Result<Option<IStr>> {
- Ok(match &field_name.value {
- FieldName::Fixed(n) => Some(n.clone()),
- FieldName::Dyn(expr) => in_frame(
- CallLocation::new(&field_name.span),
+pub fn evaluate_field_name(ctx: Context, field_name: &LFieldName) -> Result<Option<IStr>> {
+ Ok(match field_name {
+ LFieldName::Fixed(n) => Some(n.clone()),
+ LFieldName::Dyn(expr) => in_frame(
+ // TODO: Spanned<LFieldName>
+ CallLocation::native(),
|| "evaluating field name".to_string(),
|| {
- let v = evaluate(ctx, expr)?;
+ let v = evaluate(ctx.clone(), expr)?;
Ok(if matches!(v, Val::Null) {
None
} else {
@@ -104,371 +89,452 @@
})
}
-pub fn evaluate_comp(
- ctx: Context,
- specs: &[CompSpec],
- mut guaranteed_reserve: usize,
- callback: &mut impl FnMut(Context, usize) -> Result<()>,
-) -> Result<()> {
- match specs.first() {
- None => callback(ctx, guaranteed_reserve)?,
- Some(CompSpec::IfSpec(IfSpecData { cond, span: _ })) => {
- if bool::from_untyped(evaluate(ctx.clone(), cond)?)? {
- evaluate_comp(ctx, &specs[1..], 0, callback)?;
- }
- }
- Some(CompSpec::ForSpec(ForSpecData {
- destruct: into,
- over,
- })) => {
- match evaluate(ctx.clone(), over)? {
- Val::Arr(list) => {
- guaranteed_reserve = guaranteed_reserve.max(1) * list.len();
- for (i, item) in list.iter_lazy().enumerate() {
- let fctx = Pending::new();
- let mut ctx = ContextBuilder::extend_fast(ctx.clone());
- destruct(into, item, fctx.clone(), &mut ctx)?;
- let ctx = ctx.build().into_future(fctx);
+pub fn evaluate_thunk(ctx: Context, expr: Rc<LExpr>, tailstrict: bool) -> Result<Thunk<Val>> {
+ Ok(if tailstrict {
+ Thunk::evaluated(evaluate(ctx, &expr)?)
+ } else {
+ Thunk!(move || { evaluate(ctx, &expr) })
+ })
+}
- let specs = &specs[1..];
- evaluate_comp(
- ctx,
- specs,
- if i == 0 || !specs.is_empty() {
- guaranteed_reserve
- } else {
- 0
- },
- callback,
- )?;
- }
- }
- Val::Obj(obj) if cfg!(feature = "exp-object-iteration") => {
- let fields = obj.fields(
- // TODO: Should there be ability to preserve iteration order?
- #[cfg(feature = "exp-preserve-order")]
- false,
- );
- guaranteed_reserve = guaranteed_reserve.max(1) * fields.len();
- for (i, field) in fields.into_iter().enumerate() {
- let fctx = Pending::new();
- let mut ctx = ContextBuilder::extend_fast(ctx.clone());
- let obj = obj.clone();
- let value = Thunk::evaluated(Val::arr(vec![
- Thunk::evaluated(Val::string(field.clone())),
- obj.get_lazy(field).expect(
- "field exists, as field name was obtained from object.fields()",
- ),
- ]));
- destruct(into, value, fctx.clone(), &mut ctx)?;
- let ctx = ctx.build().into_future(fctx);
+mod names {
+ use crate::names;
- evaluate_comp(
- ctx,
- &specs[1..],
- if i == 0 || !specs.is_empty() {
- guaranteed_reserve
- } else {
- 0
- },
- callback,
- )?;
- }
- }
- _ => bail!(InComprehensionCanOnlyIterateOverArray),
- }
- }
+ names! {
+ anonymous: "anonymous",
}
- Ok(())
}
-fn evaluate_arr_comp(ctx: Context, expr: &Rc<Expr>, comp_specs: &[CompSpec]) -> Result<ArrValue> {
- let ctx = ctx.branch_point();
- 'eager: {
- let mut out = Vec::new();
+pub fn evaluate_named(name: &IStr, ctx: Context, expr: &LExpr) -> Result<Val> {
+ if let LExpr::Function(f) = &expr {
+ return Ok(evaluate_method(
+ ctx,
+ f.name.clone().unwrap_or_else(|| name.clone()),
+ f,
+ ));
+ }
+ evaluate(ctx, expr)
+}
- if evaluate_comp(ctx.clone(), comp_specs, 0, &mut |ctx, reserve| {
- if reserve != 0 {
- out.reserve(reserve);
+pub fn evaluate(ctx: Context, expr: &LExpr) -> Result<Val> {
+ Ok(match expr {
+ LExpr::Null => Val::Null,
+ LExpr::Bool(b) => Val::Bool(*b),
+ LExpr::Str(s) => Val::string(s.clone()),
+ LExpr::Num(n) => Val::Num(*n),
+ LExpr::Local(id) => {
+ let Some(thunk) = ctx.binding(*id) else {
+ bail!("should not happen: unbound local {id:?}");
+ };
+ thunk.evaluate()?
+ }
+ LExpr::BadLocal(name) => panic!("unresolvable reference: {name}"),
+ LExpr::Arr(items) => Val::Arr(crate::arr::ArrValue::expr(ctx, items.clone())),
+ LExpr::UnaryOp(op, value) => {
+ let value = evaluate(ctx, value)?;
+ evaluate_unary_op(*op, &value)?
+ }
+ LExpr::BinaryOp { lhs, op, rhs } => evaluate_binary_op_special(ctx, lhs, *op, rhs)?,
+ LExpr::LocalExpr { binds, body } => {
+ let ctx = evaluate_locals(ctx, binds);
+ evaluate(ctx, body)?
+ }
+ LExpr::IfElse {
+ cond,
+ cond_then,
+ cond_else,
+ } => {
+ let cond_val = evaluate(ctx.clone(), cond)?;
+ let Val::Bool(b) = cond_val else {
+ bail!(TypeMismatch(
+ "if condition",
+ vec![ValType::Bool],
+ cond_val.value_type()
+ ))
+ };
+ if b {
+ evaluate(ctx, cond_then)?
+ } else if let Some(e) = cond_else {
+ evaluate(ctx, e)?
+ } else {
+ Val::Null
}
- out.push(evaluate(ctx, expr)?);
- Ok(())
- })
- .is_err()
- {
- break 'eager;
}
+ LExpr::Error(s, e) => in_frame(
+ CallLocation::new(s),
+ || "error statement".to_owned(),
+ || bail!(RuntimeError(evaluate(ctx, e)?.to_string()?,)),
+ )?,
+ LExpr::AssertExpr { assert, rest } => {
+ evaluate_assert(ctx.clone(), assert)?;
+ evaluate(ctx, rest)?
+ }
- return Ok(ArrValue::new(out));
- };
- let mut out = Vec::new();
- evaluate_comp(ctx, comp_specs, 0, &mut |ctx, reserve| {
- if reserve != 0 {
- out.reserve(reserve);
+ LExpr::Function(func) => evaluate_method(
+ ctx,
+ func.name.clone().unwrap_or_else(names::anonymous),
+ func,
+ ),
+ LExpr::Apply {
+ applicable,
+ args,
+ tailstrict,
+ } => evaluate_apply(
+ ctx,
+ applicable,
+ args,
+ CallLocation::new(&args.span),
+ *tailstrict,
+ )?,
+ LExpr::Index { indexable, parts } => evaluate_index(ctx, indexable, parts)?,
+ LExpr::Obj(body) => evaluate_obj_body(None, ctx, body)?,
+ LExpr::ObjExtend(lhs, body) => {
+ let lhs_val = evaluate(ctx.clone(), lhs)?;
+ let Val::Obj(lhs_obj) = lhs_val else {
+ bail!(TypeMismatch(
+ "object extend lhs",
+ vec![ValType::Obj],
+ lhs_val.value_type(),
+ ))
+ };
+ evaluate_obj_body(Some(lhs_obj), ctx, body)?
+ }
+ LExpr::ArrComp(comp) => evaluate_arr_comp(ctx, comp)?,
+ LExpr::Slice(slice) => {
+ use crate::typed::BoundedUsize;
+ let val = evaluate(ctx.clone(), &slice.value)?;
+ let indexable = val.into_indexable()?;
+ let start = slice
+ .start
+ .as_ref()
+ .map(|e| evaluate(ctx.clone(), e))
+ .transpose()?
+ .map(|v| -> Result<i32> {
+ v.as_num()
+ .ok_or_else(|| {
+ TypeMismatch("slice start", vec![ValType::Num], v.value_type()).into()
+ })
+ .map(|n| n as i32)
+ })
+ .transpose()?;
+ let end = slice
+ .end
+ .as_ref()
+ .map(|e| evaluate(ctx.clone(), e))
+ .transpose()?
+ .map(|v| -> Result<i32> {
+ v.as_num()
+ .ok_or_else(|| {
+ TypeMismatch("slice end", vec![ValType::Num], v.value_type()).into()
+ })
+ .map(|n| n as i32)
+ })
+ .transpose()?;
+ let step = slice
+ .step
+ .as_ref()
+ .map(|e| evaluate(ctx, e))
+ .transpose()?
+ .map(|v| -> Result<BoundedUsize<1, { i32::MAX as usize }>> {
+ let n = v.as_num().ok_or_else(|| -> crate::Error {
+ TypeMismatch("slice step", vec![ValType::Num], v.value_type()).into()
+ })?;
+ BoundedUsize::new(n as usize)
+ .ok_or_else(|| runtime_error!("slice step must be >= 1"))
+ })
+ .transpose()?;
+ Val::from(indexable.slice(start, end, step)?)
}
- let expr = expr.clone();
- out.push(Thunk!(move || evaluate(ctx, &expr)));
- Ok(())
- })?;
- Ok(ArrValue::new(out))
+ LExpr::Super => Val::Obj(ctx.try_sup_this()?.standalone_super()?),
+ LExpr::Import {
+ kind,
+ kind_span,
+ path,
+ } => with_state(|state| {
+ let resolved = state.resolve_from(kind_span.0.source_path(), &path.clone())?;
+ Ok::<_, Error>(match kind.value {
+ ImportKind::Normal => in_frame(
+ CallLocation::new(&kind.span),
+ || "import".to_string(),
+ || state.import_resolved(resolved),
+ )?,
+ ImportKind::Str => Val::string(state.import_resolved_str(resolved)?),
+ ImportKind::Bin => Val::arr(state.import_resolved_bin(resolved)?),
+ })
+ })?,
+ })
}
-trait CloneableUnbound<T>: Unbound<Bound = T> + Clone {}
-impl<V, T> CloneableUnbound<T> for V where V: Unbound<Bound = T> + Clone {}
+fn evaluate_apply(
+ ctx: Context,
+ applicable: &LExpr,
+ args: &LArgsDesc,
+ loc: CallLocation<'_>,
+ tailstrict: bool,
+) -> Result<Val> {
+ let func_val = evaluate(ctx.clone(), applicable)?;
+ let Val::Func(func) = func_val else {
+ bail!(OnlyFunctionsCanBeCalledGot(func_val.value_type()))
+ };
-fn evaluate_object_locals(
- fctx: Context,
- locals: Rc<Vec<BindSpec>>,
-) -> impl CloneableUnbound<Context> {
- #[derive(Trace, Clone)]
- struct UnboundLocals {
- fctx: Context,
- locals: Rc<Vec<BindSpec>>,
- }
- impl Unbound for UnboundLocals {
- type Bound = Context;
+ let name = func.name();
+ let unnamed = args
+ .unnamed
+ .iter()
+ .cloned()
+ .map(|e| evaluate_thunk(ctx.clone(), e, tailstrict))
+ .collect::<Result<Vec<_>>>()?;
- fn bind(&self, sup_this: SupThis) -> Result<Context> {
- let fctx = Context::new_future();
- let ctx = self.fctx.clone();
- let mut ctx = ContextBuilder::extend(ctx);
- for b in self.locals.iter() {
- evaluate_dest(b, fctx.clone(), &mut ctx)?;
- }
-
- let ctx = ctx.build_sup_this(sup_this).into_future(fctx);
+ let named = args
+ .values
+ .iter()
+ .cloned()
+ .map(|e| evaluate_thunk(ctx.clone(), e, tailstrict))
+ .collect::<Result<Vec<_>>>()?;
+ let prepare = PreparedFuncVal::new(func, unnamed.len(), &args.names)
+ .with_description_src(loc, || format!("function <{name}> preparation"))?;
+ in_frame(
+ loc,
+ || format!("function <{name}> call"),
+ || prepare.call(CallLocation::native(), &unnamed, &named),
+ )
+}
- Ok(ctx)
+fn evaluate_index(ctx: Context, indexable: &LExpr, parts: &[LIndexPart]) -> Result<Val> {
+ let mut value = if let LExpr::Super = indexable {
+ let sup_this = ctx.try_sup_this()?;
+ // First part must be evaluated to get the super field name
+ if parts.is_empty() {
+ bail!(RuntimeError("super requires an index".into()))
}
- }
+ let key_val = evaluate(ctx.clone(), &parts[0].value)?;
+ let Val::Str(key) = &key_val else {
+ bail!(ValueIndexMustBeTypeGot(
+ ValType::Obj,
+ ValType::Str,
+ key_val.value_type(),
+ ))
+ };
+ let field = key.clone().into_flat();
+ if let Some(v) = sup_this.get_super(field.clone())? {
+ // Continue with remaining parts
+ let mut value = v;
+ for part in &parts[1..] {
+ value = index_val(ctx.clone(), CallLocation::new(&part.span), value, part)?;
+ }
+ return Ok(value);
+ }
+ let suggestions = suggest_object_fields(sup_this.this(), field.clone());
+ bail!(NoSuchField(field, suggestions))
+ } else {
+ evaluate(ctx.clone(), indexable)?
+ };
- UnboundLocals { fctx, locals }
+ for part in parts {
+ value = index_val(ctx.clone(), CallLocation::new(&part.span), value, part)?;
+ }
+ Ok(value)
}
-pub fn evaluate_field_member<B: Unbound<Bound = Context> + Clone>(
- builder: &mut ObjValueBuilder,
- ctx: Context,
- uctx: B,
- field: &FieldMember,
-) -> Result<()> {
- let name = evaluate_field_name(ctx, &field.name)?;
- let Some(name) = name else {
- return Ok(());
- };
-
- match field {
- FieldMember {
- plus,
- params: None,
- visibility,
- value,
- ..
- } => {
- #[derive(Trace)]
- struct UnboundValue<B: Trace> {
- uctx: B,
- value: Rc<Expr>,
- name: IStr,
+fn index_val(ctx: Context, loc: CallLocation<'_>, value: Val, part: &LIndexPart) -> Result<Val> {
+ let key_val = evaluate(ctx, &part.value)?;
+ Ok(match (&value, &key_val) {
+ (Val::Obj(obj), Val::Str(key)) => {
+ let field = key.clone().into_flat();
+ if let Some(v) = obj
+ .get(field.clone())
+ .with_description_src(loc, || format!("field <{field}> access"))?
+ {
+ v
+ } else {
+ bail!(NoSuchField(
+ field.clone(),
+ suggest_object_fields(obj, field)
+ ))
}
- impl<B: Unbound<Bound = Context>> Unbound for UnboundValue<B> {
- type Bound = Val;
- fn bind(&self, sup_this: SupThis) -> Result<Val> {
- evaluate_named(self.uctx.bind(sup_this)?, &self.value, self.name.clone())
- }
+ }
+ (Val::Arr(arr), Val::Num(idx)) => {
+ let n = idx.get();
+ if n.fract() > f64::EPSILON {
+ bail!(FractionalIndex)
}
-
- builder
- .field(name.clone())
- .with_add(*plus)
- .with_visibility(*visibility)
- .with_location(field.name.span.clone())
- .bindable(UnboundValue {
- uctx,
- value: value.clone(),
- name,
- })?;
+ if n < 0.0 {
+ bail!(ArrayBoundsError(
+ n as isize, // truncation is fine for error display
+ arr.len()
+ ));
+ }
+ #[expect(
+ clippy::cast_possible_truncation,
+ clippy::cast_sign_loss,
+ reason = "n is checked positive"
+ )]
+ let i = n as u32;
+ arr.get(i)
+ .with_description_src(loc, || format!("element <{i}> access"))?
+ .ok_or_else(|| ArrayBoundsError(i as isize, arr.len()))?
}
- FieldMember {
- params: Some(params),
- visibility,
- value,
- ..
- } => {
- #[derive(Trace)]
- struct UnboundMethod<B: Trace> {
- uctx: B,
- value: Rc<Expr>,
- params: ExprParams,
- name: IStr,
+ (Val::Str(s), Val::Num(idx)) => {
+ let n = idx.get();
+ if n.fract() > f64::EPSILON {
+ bail!(FractionalIndex)
}
- impl<B: Unbound<Bound = Context>> Unbound for UnboundMethod<B> {
- type Bound = Val;
- fn bind(&self, sup_this: SupThis) -> Result<Val> {
- Ok(evaluate_method(
- self.uctx.bind(sup_this)?,
- self.name.clone(),
- self.params.clone(),
- self.value.clone(),
- ))
- }
+ let flat = s.clone().into_flat();
+ if n < 0.0 {
+ bail!(ArrayBoundsError(
+ n as isize, // truncation is fine for error display
+ flat.chars().count() as u32
+ ));
}
-
- builder
- .field(name.clone())
- .with_visibility(*visibility)
- // .with_location(value.span())
- .bindable(UnboundMethod {
- uctx,
- value: value.clone(),
- params: params.clone(),
- name,
- })?;
+ #[expect(
+ clippy::cast_possible_truncation,
+ clippy::cast_sign_loss,
+ reason = "n is checked positive, overflow will truncate as expected"
+ )]
+ let i = n as usize;
+ let Some(char) = flat.chars().nth(i) else {
+ bail!(StringBoundsError(i, flat.chars().count()))
+ };
+ Val::string(char)
}
- }
- Ok(())
+ _ => bail!(ValueIndexMustBeTypeGot(
+ value.value_type(),
+ ValType::Str,
+ key_val.value_type()
+ )),
+ })
}
-#[derive(Trace, Clone)]
-struct DirectUnbound(Context);
-impl Unbound for DirectUnbound {
- type Bound = Context;
- fn bind(&self, sup_this: SupThis) -> Result<Context> {
- Ok(ContextBuilder::extend(self.0.clone()).build_sup_this(sup_this))
+fn evaluate_obj_body(super_obj: Option<ObjValue>, ctx: Context, body: &LObjBody) -> Result<Val> {
+ match body {
+ LObjBody::MemberList(members) => evaluate_obj_members(super_obj, ctx, members),
+ LObjBody::ObjComp(comp) => evaluate_obj_comp(super_obj, ctx, comp),
}
}
-#[allow(clippy::too_many_lines)]
-pub fn evaluate_member_list_object(
- super_obj: Option<ObjValue>,
+pub fn evaluate_field_member_unbound<B: Unbound<Bound = Context> + Clone>(
+ builder: &mut ObjValueBuilder,
ctx: Context,
- members: &ObjMembers,
-) -> Result<ObjValue> {
+ uctx: B,
+ field: &LFieldMember,
+) -> Result<()> {
#[derive(Trace)]
- struct ObjectAssert<B: Trace> {
+ struct UnboundValue<B: Trace> {
uctx: B,
- asserts: Rc<Vec<AssertStmt>>,
+ value: Rc<LExpr>,
+ name: IStr,
}
- impl<B: Unbound<Bound = Context>> ObjectAssertion for ObjectAssert<B> {
- fn run(&self, sup_this: SupThis) -> Result<()> {
- let ctx = self.uctx.bind(sup_this)?;
- for assert in &*self.asserts {
- evaluate_assert(ctx.clone(), assert)?;
- }
- Ok(())
+ impl<B: Unbound<Bound = Context>> Unbound for UnboundValue<B> {
+ type Bound = Val;
+ fn bind(&self, sup_this: SupThis) -> Result<Val> {
+ evaluate(self.uctx.bind(sup_this)?, &self.value)
}
}
- let mut builder = ObjValueBuilder::new();
- if let Some(super_obj) = super_obj {
- builder.with_super(super_obj);
+ let LFieldMember {
+ name,
+ plus,
+ visibility,
+ value,
+ } = field;
+ let Some(name) = evaluate_field_name(ctx, name)? else {
+ return Ok(());
+ };
+
+ builder
+ .field(name.clone())
+ .with_add(*plus)
+ .with_visibility(*visibility)
+ .bindable(UnboundValue {
+ uctx,
+ value: value.clone(),
+ name,
+ })
+}
+pub fn evaluate_field_member_static(
+ builder: &mut ObjValueBuilder,
+ field_ctx: Context,
+ value_ctx: Context,
+ field: &LFieldMember,
+) -> Result<()> {
+ let LFieldMember {
+ name,
+ plus,
+ visibility,
+ value,
+ } = field;
+ let Some(name) = evaluate_field_name(field_ctx, name)? else {
+ return Ok(());
+ };
+
+ let value = value.clone();
+ builder
+ .field(name)
+ .with_add(*plus)
+ .with_visibility(*visibility)
+ .try_thunk(Thunk!(move || { evaluate(value_ctx, &value) }))?;
+ Ok(())
+}
+
+fn evaluate_obj_members(
+ super_obj: Option<ObjValue>,
+ ctx: Context,
+ members: &LObjMembers,
+) -> Result<Val> {
+ let mut builder = ObjValueBuilder::with_capacity(members.fields.len());
+ if let Some(sup) = super_obj {
+ builder.with_super(sup);
}
- if members.locals.is_empty() {
- // We can use the same context for all field evaluation, it doesn't depends on locals, only on this/super
- let uctx = DirectUnbound(ctx.clone());
+ let needs_unbound = members.this.is_some() || members.uses_super;
+
+ if needs_unbound {
+ let uctx = CachedUnbound::new(evaluate_locals_unbound(
+ ctx.clone(),
+ members.locals.clone(),
+ members.this,
+ ));
for field in &members.fields {
- evaluate_field_member(&mut builder, ctx.clone(), uctx.clone(), field)?;
+ evaluate_field_member_unbound(&mut builder, ctx.clone(), uctx.clone(), field)?;
}
if !members.asserts.is_empty() {
- builder.assert(ObjectAssert {
+ builder.assert(evaluate_object_assertions_unbound(
uctx,
- asserts: members.asserts.clone(),
- });
+ members.asserts.clone(),
+ ));
}
} else {
- let locals = members.locals.clone();
- // We have single context for all fields, so we can cache them together
- let uctx = CachedUnbound::new(evaluate_object_locals(ctx.clone(), locals));
+ let field_ctx = ctx;
+ let value_ctx = evaluate_locals(field_ctx.clone(), &members.locals);
for field in &members.fields {
- evaluate_field_member(&mut builder, ctx.clone(), uctx.clone(), field)?;
+ evaluate_field_member_static(
+ &mut builder,
+ field_ctx.clone(),
+ value_ctx.clone(),
+ field,
+ )?;
}
if !members.asserts.is_empty() {
- builder.assert(ObjectAssert {
- uctx,
- asserts: members.asserts.clone(),
- });
+ builder.assert(evaluate_object_assertions_static(
+ value_ctx,
+ members.asserts.clone(),
+ ));
}
}
- Ok(builder.build())
+ Ok(Val::Obj(builder.build()))
}
-pub fn evaluate_object(
- super_obj: Option<ObjValue>,
- ctx: Context,
- object: &ObjBody,
-) -> Result<ObjValue> {
- Ok(match object {
- ObjBody::MemberList(members) => evaluate_member_list_object(super_obj, ctx, members)?,
- ObjBody::ObjComp(obj) => {
- let mut builder = ObjValueBuilder::new();
- if let Some(super_obj) = super_obj {
- builder.with_super(super_obj);
- }
- let locals = obj.locals.clone();
- evaluate_comp(
- ctx.branch_point(),
- &obj.compspecs,
- 0,
- &mut |ctx, reserve| {
- let uctx = evaluate_object_locals(ctx.clone(), locals.clone());
- builder.reserve_fields(reserve);
-
- evaluate_field_member(&mut builder, ctx, uctx, &obj.field)
- },
- )?;
-
- builder.build()
- }
- })
-}
-
-pub fn evaluate_apply(
- ctx: Context,
- value: &Expr,
- args: &ArgsDesc,
- loc: CallLocation<'_>,
- tailstrict: bool,
-) -> Result<Val> {
- let value = evaluate(ctx.clone(), value)?;
- Ok(match value {
- Val::Func(f) => {
- let name = f.name();
- let unnamed = args
- .unnamed
- .iter()
- .cloned()
- .map(|un| evaluate_thunk(ctx.clone(), un, tailstrict))
- .collect::<Result<Vec<_>>>()?;
- let named = args
- .values
- .iter()
- .cloned()
- .map(|un| evaluate_thunk(ctx.clone(), un, tailstrict))
- .collect::<Result<Vec<_>>>()?;
- let prepare = PreparedFuncVal::new(f, args.unnamed.len(), &args.names)
- .with_description_src(loc, || format!("function <{name}> call"))?;
- let body = || prepare.call(loc, &unnamed, &named);
- if tailstrict {
- body()?
- } else {
- in_frame(loc, || format!("function <{name}> call"), body)?
- }
- }
- v => bail!(OnlyFunctionsCanBeCalledGot(v.value_type())),
- })
-}
-
-pub fn evaluate_assert(ctx: Context, assertion: &AssertStmt) -> Result<()> {
- let AssertStmt { assertion, message } = assertion;
+pub fn evaluate_assert(ctx: Context, assertion: &LAssertStmt) -> Result<()> {
+ let LAssertStmt { cond, message } = assertion;
let assertion_result = in_frame(
- CallLocation::new(&assertion.span),
+ CallLocation::native(),
|| "assertion condition".to_owned(),
- || bool::from_untyped(evaluate(ctx.clone(), assertion)?),
+ || bool::from_untyped(evaluate(ctx.clone(), cond)?),
)?;
if !assertion_result {
in_frame(
- CallLocation::new(&assertion.span),
+ CallLocation::new(&cond.span),
|| "assertion failure".to_owned(),
|| {
if let Some(msg) = message {
@@ -481,306 +547,42 @@
Ok(())
}
-pub fn evaluate_named_param(ctx: Context, expr: &Expr, name: ParamName) -> Result<Val> {
- match name {
- ParamName::Named(name) => evaluate_named(ctx, expr, name),
- ParamName::Unnamed => evaluate(ctx, expr),
+fn evaluate_object_assertions_unbound<B: Unbound<Bound = Context>>(
+ uctx: B,
+ asserts: Rc<Vec<LAssertStmt>>,
+) -> impl ObjectAssertion {
+ #[derive(Trace)]
+ struct ObjectAssert<B: Trace> {
+ uctx: B,
+ asserts: Rc<Vec<LAssertStmt>>,
}
-}
-
-pub fn evaluate_named(ctx: Context, expr: &Expr, name: IStr) -> Result<Val> {
- use Expr::*;
- Ok(match expr {
- Function(params, body) => evaluate_method(ctx, name, params.clone(), body.clone()),
- _ => evaluate(ctx, expr)?,
- })
-}
-
-pub fn evaluate_thunk(ctx: Context, expr: Rc<Expr>, tailstrict: bool) -> Result<Thunk<Val>> {
- Ok(if tailstrict {
- Thunk::evaluated(evaluate(ctx, &expr)?)
- } else {
- Thunk!(move || { evaluate(ctx, &expr) })
- })
-}
-#[allow(clippy::too_many_lines)]
-pub fn evaluate(ctx: Context, expr: &Expr) -> Result<Val> {
- use Expr::*;
-
- Ok(match expr {
- Literal(LiteralType::This) => Val::Obj(ctx.try_this()?),
- Literal(LiteralType::Super) => Val::Obj(ctx.try_sup_this()?.standalone_super()?),
- Literal(LiteralType::Dollar) => Val::Obj(ctx.try_dollar()?),
- Literal(LiteralType::True) => Val::Bool(true),
- Literal(LiteralType::False) => Val::Bool(false),
- Literal(LiteralType::Null) => Val::Null,
- Str(v) => Val::string(v.clone()),
- Num(v) => Val::try_num(*v)?,
- // I have tried to remove special behavior from super by implementing standalone-super
- // expresion, but looks like this case still needs special treatment.
- //
- // Note that other jsonnet implementations will fail on `if value in (super)` expression,
- // because the standalone super literal is not supported, that is because in other
- // implementations `in super` treated differently from `in smth_else`.
- BinaryOp(bin)
- if matches!(&bin.rhs, Expr::Literal(LiteralType::Super))
- && bin.op == BinaryOpType::In =>
- {
- let sup_this = ctx.try_sup_this()?;
- // In jsonnet, "field" in e is eager, LHS expression is always executed regardless of super existence.
- // In jrsonnet, however, this wasn't true, this was kept here for compatibility.
- if !sup_this.has_super() {
- return Ok(Val::Bool(false));
- }
- let field = evaluate(ctx, &bin.lhs)?;
- Val::Bool(sup_this.field_in_super(field.to_string()?))
- }
- BinaryOp(bin) => evaluate_binary_op_special(ctx, &bin.lhs, bin.op, &bin.rhs)?,
- UnaryOp(o, v) => evaluate_unary_op(*o, &evaluate(ctx, v)?)?,
- Var(name) => in_frame(
- CallLocation::new(&name.span),
- || format!("local <{}> access", &**name),
- || ctx.binding((**name).clone())?.evaluate(),
- )?,
- Index { indexable, parts } => ensure_sufficient_stack(|| {
- let mut parts = parts.iter();
- let mut indexable = if matches!(&**indexable, Expr::Literal(LiteralType::Super)) {
- let part = parts.next().expect("at least part should exist");
- // sup_this existence check might also be skipped here for null-coalesce...
- // But I believe this might cause errors.
- let sup_this = ctx.try_sup_this()?;
- if !sup_this.has_super() {
- #[cfg(feature = "exp-null-coaelse")]
- if part.null_coaelse {
- return Ok(Val::Null);
- }
- bail!(NoSuperFound)
- }
- let name = evaluate(ctx.clone(), &part.value)?;
-
- let Val::Str(name) = name else {
- bail!(ValueIndexMustBeTypeGot(
- ValType::Obj,
- ValType::Str,
- name.value_type(),
- ))
- };
-
- let name = name.into_flat();
- match sup_this
- .get_super(name.clone())
- .with_description_src(&part.span, || format!("field <{name}> access"))?
- {
- Some(v) => v,
- #[cfg(feature = "exp-null-coaelse")]
- None if part.null_coaelse => return Ok(Val::Null),
- None => {
- let suggestions = suggest_object_fields(
- &sup_this.standalone_super().expect("super exists"),
- name.clone(),
- );
-
- bail!(NoSuchField(name, suggestions))
- }
- }
- } else {
- evaluate(ctx.clone(), indexable)?
- };
-
- for part in parts {
- indexable = match (indexable, evaluate(ctx.clone(), &part.value)?) {
- (Val::Obj(v), Val::Str(key)) => match v
- .get(key.clone().into_flat())
- .with_description_src(&part.span, || format!("field <{key}> access"))?
- {
- Some(v) => v,
- #[cfg(feature = "exp-null-coaelse")]
- None if part.null_coaelse => return Ok(Val::Null),
- None => {
- let suggestions = suggest_object_fields(&v, key.into_flat());
-
- return Err(Error::from(NoSuchField(
- key.clone().into_flat(),
- suggestions,
- )))
- .with_description_src(&part.span, || format!("field <{key}> access"));
- }
- },
- (Val::Obj(_), n) => bail!(ValueIndexMustBeTypeGot(
- ValType::Obj,
- ValType::Str,
- n.value_type(),
- )),
- (Val::Arr(v), Val::Num(n)) => {
- let n = n.get();
- if n.fract() > f64::EPSILON {
- bail!(FractionalIndex)
- }
- if n < 0.0 {
- #[expect(
- clippy::cast_possible_truncation,
- reason = "it would be truncated anyway"
- )]
- let n = n as isize;
- bail!(ArrayBoundsError(n, v.len()));
- }
- #[expect(
- clippy::cast_possible_truncation,
- clippy::cast_sign_loss,
- reason = "n is checked postive"
- )]
- v.get(n as usize)?
- .ok_or_else(|| ArrayBoundsError(n as isize, v.len()))?
- }
- (Val::Arr(_), Val::Str(n)) => {
- bail!(AttemptedIndexAnArrayWithString(n.into_flat()))
- }
- (Val::Arr(_), n) => bail!(ValueIndexMustBeTypeGot(
- ValType::Arr,
- ValType::Num,
- n.value_type(),
- )),
-
- (Val::Str(s), Val::Num(n)) => Val::Str({
- let n = n.get();
- if n.fract() > f64::EPSILON {
- bail!(FractionalIndex)
- }
- if n < 0.0 {
- #[expect(
- clippy::cast_possible_truncation,
- reason = "it would be truncated anyway"
- )]
- let n = n as isize;
- bail!(ArrayBoundsError(n, s.into_flat().chars().count()));
- }
- #[expect(
- clippy::cast_sign_loss,
- clippy::cast_possible_truncation,
- reason = "n is positive, overflow will truncate as expected"
- )]
- let n = n as usize;
- let v: IStr = s
- .clone()
- .into_flat()
- .chars()
- .skip(n)
- .take(1)
- .collect::<String>()
- .into();
- if v.is_empty() {
- bail!(StringBoundsError(n, s.into_flat().chars().count()))
- }
- StrValue::Flat(v)
- }),
- (Val::Str(_), n) => bail!(ValueIndexMustBeTypeGot(
- ValType::Str,
- ValType::Num,
- n.value_type(),
- )),
- #[cfg(feature = "exp-null-coaelse")]
- (Val::Null, _) if part.null_coaelse => return Ok(Val::Null),
- (v, _) => bail!(CantIndexInto(v.value_type())),
- };
- }
- Ok(indexable)
- })?,
- LocalExpr(bindings, returned) => {
- let fctx = Context::new_future();
- let mut ctx = ContextBuilder::extend(ctx);
- for b in bindings {
- evaluate_dest(b, fctx.clone(), &mut ctx)?;
- }
- let ctx = ctx.build().into_future(fctx);
- evaluate(ctx, returned)?
- }
- Arr(items) => {
- if items.is_empty() {
- Val::arr(())
- } else {
- Val::Arr(ArrValue::expr(ctx, items.clone()))
- }
- }
- ArrComp(expr, comp_specs) => Val::Arr(evaluate_arr_comp(ctx, expr, comp_specs)?),
- Obj(body) => Val::Obj(evaluate_object(None, ctx, body)?),
- ObjExtend(a, b) => {
- let base = evaluate(ctx.clone(), a)?;
- match base {
- Val::Obj(base_obj) => Val::Obj(evaluate_object(Some(base_obj), ctx, b)?),
- _ => bail!("ObjExtend lhs should be an object value"),
- }
- }
- Apply(value, args, tailstrict) => ensure_sufficient_stack(|| {
- evaluate_apply(ctx, value, args, CallLocation::new(&args.span), *tailstrict)
- })?,
- Function(params, body) => {
- evaluate_method(ctx, "anonymous".into(), params.clone(), body.clone())
- }
- AssertExpr(assert) => {
- evaluate_assert(ctx.clone(), &assert.assert)?;
- evaluate(ctx, &assert.rest)?
- }
- ErrorStmt(s, e) => in_frame(
- CallLocation::new(s),
- || "error statement".to_owned(),
- || bail!(RuntimeError(evaluate(ctx, e)?.to_string()?,)),
- )?,
- IfElse(if_else) => {
- if in_frame(
- CallLocation::new(&if_else.cond.span),
- || "if condition".to_owned(),
- || bool::from_untyped(evaluate(ctx.clone(), &if_else.cond.cond)?),
- )? {
- evaluate(ctx, &if_else.cond_then)?
- } else {
- match &if_else.cond_else {
- Some(v) => evaluate(ctx, v)?,
- None => Val::Null,
- }
+ impl<B: Unbound<Bound = Context>> ObjectAssertion for ObjectAssert<B> {
+ fn run(&self, sup_this: SupThis) -> Result<()> {
+ let ctx = self.uctx.bind(sup_this)?;
+ for assert in &*self.asserts {
+ evaluate_assert(ctx.clone(), assert)?;
}
+ Ok(())
}
- Slice(slice) => {
- fn parse_idx<T: Typed + FromUntyped>(
- ctx: Context,
- expr: Option<&Spanned<Expr>>,
- desc: &'static str,
- ) -> Result<Option<T>> {
- if let Some(value) = expr {
- Ok(in_frame(
- CallLocation::new(&value.span),
- || format!("slice {desc}"),
- || <Option<T>>::from_untyped(evaluate(ctx, value)?),
- )?)
- } else {
- Ok(None)
- }
+ }
+ ObjectAssert { uctx, asserts }
+}
+fn evaluate_object_assertions_static(
+ ctx: Context,
+ asserts: Rc<Vec<LAssertStmt>>,
+) -> impl ObjectAssertion {
+ #[derive(Trace)]
+ struct ObjectAssert {
+ ctx: Context,
+ asserts: Rc<Vec<LAssertStmt>>,
+ }
+ impl ObjectAssertion for ObjectAssert {
+ fn run(&self, _sup_this: SupThis) -> Result<()> {
+ for assert in &*self.asserts {
+ evaluate_assert(self.ctx.clone(), assert)?;
}
-
- let indexable = evaluate(ctx.clone(), &slice.value)?;
-
- let start = parse_idx(ctx.clone(), slice.slice.start.as_ref(), "start")?;
- let end = parse_idx(ctx.clone(), slice.slice.end.as_ref(), "end")?;
- let step = parse_idx(ctx, slice.slice.step.as_ref(), "step")?;
-
- IndexableVal::into_untyped(indexable.into_indexable()?.slice(start, end, step)?)?
+ Ok(())
}
- Import(kind, path) => {
- let Expr::Str(path) = &**path else {
- bail!("computed imports are not supported")
- };
- with_state(|s| {
- let span = &kind.span;
- let resolved_path = s.resolve_from(span.0.source_path(), path)?;
- Ok(match &**kind {
- ImportKind::Normal => in_frame(
- CallLocation::new(span),
- || format!("import {:?}", path.clone()),
- || s.import_resolved(resolved_path),
- )?,
- ImportKind::Str => Val::string(s.import_resolved_str(resolved_path)?),
- ImportKind::Bin => Val::arr(s.import_resolved_bin(resolved_path)?),
- }) as Result<Val>
- })?
- }
- })
+ }
+ ObjectAssert { ctx, asserts }
}
crates/jrsonnet-evaluator/src/evaluate/operator.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/evaluate/operator.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/operator.rs
@@ -1,16 +1,17 @@
use std::cmp::Ordering;
-use jrsonnet_ir::{BinaryOpType, Expr, UnaryOpType};
+use jrsonnet_ir::{BinaryOpType, UnaryOpType};
use crate::{
- Context, Result, Val,
+ analyze::LExpr,
arr::ArrValue,
- bail,
+ bail, error,
error::ErrorKind::*,
- evaluate,
+ evaluate::evaluate,
stdlib::std_format,
typed::IntoUntyped as _,
- val::{StrValue, equals},
+ val::{equals, StrValue},
+ Context, Result, Val,
};
pub fn evaluate_unary_op(op: UnaryOpType, b: &Val) -> Result<Val> {
@@ -39,7 +40,9 @@
(o, Str(a)) => Val::string(format!("{}{a}", o.clone().to_string()?)),
(Obj(v1), Obj(v2)) => Obj(v2.extend_from(v1.clone())),
- (Arr(a), Arr(b)) => Val::Arr(ArrValue::extended(a.clone(), b.clone())),
+ (Arr(a), Arr(b)) => Val::Arr(
+ ArrValue::extended(a.clone(), b.clone()).ok_or_else(|| error!("array is too large"))?,
+ ),
(Num(v1), Num(v2)) => Val::try_num(v1.get() + v2.get())?,
@@ -158,19 +161,27 @@
pub fn evaluate_binary_op_special(
ctx: Context,
- a: &Expr,
+ a: &LExpr,
op: BinaryOpType,
- b: &Expr,
+ b: &LExpr,
) -> Result<Val> {
use BinaryOpType::*;
use Val::*;
+
Ok(match (evaluate(ctx.clone(), a)?, op, b) {
- (Bool(true), Or, _o) => Val::Bool(true),
- (Bool(false), And, _o) => Val::Bool(false),
+ (Bool(true), Or, _) => Val::Bool(true),
+ (Bool(false), And, _) => Val::Bool(false),
#[cfg(feature = "exp-null-coaelse")]
(Null, NullCoaelse, eb) => evaluate(ctx, eb)?,
#[cfg(feature = "exp-null-coaelse")]
- (a, NullCoaelse, _o) => a,
+ (a, NullCoaelse, _) => a,
+ (a, In, LExpr::Super) => {
+ let sup_this = ctx.try_sup_this()?;
+ if !sup_this.has_super() {
+ return Ok(Val::Bool(false));
+ }
+ return Ok(Val::Bool(sup_this.field_in_super(a.to_string()?)));
+ }
(a, op, eb) => evaluate_binary_op_normal(&a, op, &evaluate(ctx, eb)?)?,
})
}
crates/jrsonnet-evaluator/src/function/builtin.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/function/builtin.rs
+++ b/crates/jrsonnet-evaluator/src/function/builtin.rs
@@ -19,6 +19,23 @@
};
}
+#[macro_export]
+macro_rules! names {
+ ($($name:ident: $val:literal),* $(,)?) => {
+ struct Names {
+ $($name: $crate::IStr,)*
+ }
+ thread_local! {
+ static NAMES: Names = Names {
+ $($name: $crate::IStr::from($val)),*
+ };
+ }
+ $(pub fn $name() -> $crate::IStr {
+ NAMES.with(|n| n.$name.clone())
+ })*
+ }
+}
+
cc_dyn!(
#[derive(Clone)]
BuiltinFunc,
crates/jrsonnet-evaluator/src/function/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/function/mod.rs
+++ b/crates/jrsonnet-evaluator/src/function/mod.rs
@@ -3,22 +3,24 @@
use educe::Educe;
use jrsonnet_gcmodule::{Cc, Trace};
use jrsonnet_interner::IStr;
-use jrsonnet_ir::{Destruct, Expr, ExprParams, Span};
+use jrsonnet_ir::Span;
pub use jrsonnet_macros::builtin;
use self::{
builtin::Builtin,
- parse::parse_default_function_call,
- prepared::{PreparedCall, parse_prepared_builtin_call, parse_prepared_function_call},
+ prepared::{parse_prepared_builtin_call, PreparedCall},
};
use crate::{
- Context, Result, Thunk, Val, evaluate, evaluate_trivial, function::builtin::BuiltinFunc,
+ analyze::{LDestruct, LExpr, LFunction},
+ evaluate::{destructure::destruct, ensure_sufficient_stack, evaluate, evaluate_trivial},
+ function::builtin::BuiltinFunc,
+ Context, ContextBuilder, Result, Thunk, Val,
};
pub mod builtin;
mod native;
mod parse;
-mod prepared;
+pub(crate) mod prepared;
pub use jrsonnet_ir::function::*;
pub use native::NativeFn;
@@ -66,19 +68,63 @@
/// context will contain `a`.
pub ctx: Context,
- /// Function parameter definition
- pub params: ExprParams,
- /// Function body
- pub body: Rc<Expr>,
+ #[educe(PartialEq(method = Rc::ptr_eq))]
+ pub func: Rc<LFunction>,
}
+
impl FuncDesc {
- /// Create body context, but fill arguments without defaults with lazy error
- pub fn default_body_context(&self) -> Result<Context> {
- parse_default_function_call(self.ctx.clone(), &self.params)
+ pub fn signature(&self) -> FunctionSignature {
+ self.func.signature.clone()
}
+ pub fn call(
+ &self,
+ unnamed: &[Thunk<Val>],
+ named: &[Thunk<Val>],
+ prepared: &PreparedCall,
+ ) -> Result<Val> {
+ let has_defaults = !prepared.defaults().is_empty();
+ let mut builder = ContextBuilder::extend(self.ctx.clone(), self.func.params.len());
+
+ let fctx = Context::new_future();
+ for (param_idx, thunk) in unnamed.iter().enumerate() {
+ destruct(
+ &self.func.params[param_idx].destruct,
+ thunk.clone(),
+ fctx.clone(),
+ &mut builder,
+ );
+ }
+
+ for &(param_idx, arg_idx) in prepared.named() {
+ destruct(
+ &self.func.params[param_idx].destruct,
+ named[arg_idx].clone(),
+ fctx.clone(),
+ &mut builder,
+ );
+ }
+
+ if has_defaults {
+ for ¶m_idx in prepared.defaults() {
+ let param = &self.func.params[param_idx];
+ if let Some(default_expr) = ¶m.default {
+ let default_expr = default_expr.clone();
+ let fctxc = fctx.clone();
+ let thunk = Thunk!(move || {
+ let ctx = fctxc.unwrap();
+ evaluate(ctx, &default_expr)
+ });
+ destruct(¶m.destruct, thunk, fctx.clone(), &mut builder);
+ }
+ }
+ };
+ let ctx = builder.build().into_future(fctx);
+ ensure_sufficient_stack(|| evaluate(ctx, &self.func.body))
+ }
+
pub fn evaluate_trivial(&self) -> Option<Val> {
- evaluate_trivial(&self.body)
+ evaluate_trivial(&self.func.body)
}
}
@@ -115,12 +161,12 @@
pub fn params(&self) -> FunctionSignature {
match self {
Self::Builtin(i) => i.params(),
- Self::Normal(p) => p.params.signature.clone(),
+ Self::Normal(p) => p.signature(),
}
}
/// Amount of non-default required arguments
- pub fn params_len(&self) -> usize {
- self.params().iter().filter(|p| !p.has_default()).count()
+ pub fn params_len(&self) -> u32 {
+ self.params().iter().filter(|p| !p.has_default()).count() as u32
}
/// Function name, as defined in code.
pub fn name(&self) -> IStr {
@@ -139,16 +185,7 @@
_tailstrict: bool,
) -> Result<Val> {
match self {
- FuncVal::Normal(func) => {
- let body_ctx = parse_prepared_function_call(
- func.ctx.clone(),
- prepared,
- &func.params,
- unnamed,
- named,
- )?;
- evaluate(body_ctx, &func.body)
- }
+ FuncVal::Normal(func) => func.call(unnamed, named, prepared),
FuncVal::Builtin(b) => {
let args = parse_prepared_builtin_call(prepared, b.params(), unnamed, named);
b.call(loc, &args)
@@ -156,7 +193,7 @@
}
}
- /// Is this function an indentity function.
+ /// Is this function an identity function.
///
/// Currently only works for builtin `std.id`, aka `Self::Id` value, and `function(x) x`.
///
@@ -165,21 +202,19 @@
match self {
Self::Builtin(b) => b.as_any().downcast_ref::<builtin_id>().is_some(),
Self::Normal(desc) => {
- if desc.params.len() != 1 {
+ if desc.func.params.len() != 1 {
return false;
}
- let param = &desc.params.exprs[0];
+ let param = &desc.func.params[0];
if param.default.is_some() {
return false;
}
-
- #[allow(clippy::infallible_destructuring_match)]
- let id = match ¶m.destruct {
- Destruct::Full(id) => id,
- #[cfg(feature = "exp-destruct")]
- _ => return false,
+ #[allow(irrefutable_let_patterns, reason = "refutable with exp-destruct")]
+ let LDestruct::Full(id) = ¶m.destruct
+ else {
+ return false;
};
- matches!(&*desc.body, Expr::Var(v) if &**v == id)
+ matches!(&*desc.func.body, LExpr::Local(v) if v == id)
}
}
}
crates/jrsonnet-evaluator/src/function/parse.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/function/parse.rs
+++ b/crates/jrsonnet-evaluator/src/function/parse.rs
@@ -1,49 +1,39 @@
-use jrsonnet_ir::ExprParams;
+use std::rc::Rc;
use crate::{
- Context, ContextBuilder, Thunk,
- destructure::destruct,
- error::{ErrorKind::*, Result},
- evaluate_named_param,
+ analyze::LFunction,
+ evaluate::{destructure::destruct, evaluate},
+ Context, ContextBuilder, Result, Thunk,
};
-/// Creates Context, which has all argument default values applied
-/// and with unbound values causing error to be returned
-pub fn parse_default_function_call(body_ctx: Context, params: &ExprParams) -> Result<Context> {
+/// Creates Context with all argument default values applied
+/// and with unbound values causing error to be returned.
+pub fn parse_default_function_call(body_ctx: Context, func: &Rc<LFunction>) -> Result<Context> {
let fctx = Context::new_future();
-
- let mut ctx = ContextBuilder::extend(body_ctx);
+ let mut builder = ContextBuilder::extend(body_ctx, func.params.len());
- for param in params.exprs.iter() {
- if let Some(v) = ¶m.default {
- destruct(
- ¶m.destruct.clone(),
- {
- let ctx = fctx.clone();
- let name = param.destruct.name();
- let value = v.clone();
- Thunk!(move || evaluate_named_param(ctx.unwrap(), &value, name))
- },
- fctx.clone(),
- &mut ctx,
- )?;
+ for param in &func.params {
+ if let Some(default_expr) = ¶m.default {
+ let default_expr = default_expr.clone();
+ let fctxc = fctx.clone();
+ let thunk = Thunk!(move || {
+ let ctx = fctxc.unwrap();
+ evaluate(ctx, &default_expr)
+ });
+ destruct(¶m.destruct, thunk, fctx.clone(), &mut builder);
} else {
- destruct(
- ¶m.destruct,
- {
- let param_name = param.destruct.name();
- let params = params.clone();
- Thunk!(move || Err(FunctionParameterNotBoundInCall(
- param_name,
- params.signature
- )
- .into()))
- },
- fctx.clone(),
- &mut ctx,
- )?;
+ let name = param.name.clone().unwrap_or_else(|| "<param>".into());
+ let thunk = Thunk::errored(
+ crate::error::ErrorKind::FunctionParameterNotBoundInCall(
+ jrsonnet_ir::function::ParamName::Named(name),
+ jrsonnet_ir::function::FunctionSignature::empty(),
+ )
+ .into(),
+ );
+ destruct(¶m.destruct, thunk, fctx.clone(), &mut builder);
}
}
- Ok(ctx.build().into_future(fctx))
+ let ctx = builder.build().into_future(fctx);
+ Ok(ctx)
}
crates/jrsonnet-evaluator/src/function/prepared.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/function/prepared.rs
+++ b/crates/jrsonnet-evaluator/src/function/prepared.rs
@@ -1,13 +1,13 @@
use std::rc::Rc;
use jrsonnet_gcmodule::{Acyclic, Trace};
-use jrsonnet_ir::{ExprParams, IStr, function::FunctionSignature};
+use jrsonnet_ir::{IStr, function::FunctionSignature};
use rustc_hash::FxHashSet;
use super::{CallLocation, FuncVal};
use crate::{
- Context, ContextBuilder, Pending, Result, Thunk, Val, bail, destructure::destruct,
- error::ErrorKind::*, evaluate_named_param,
+ Result, Thunk, Val, bail,
+ error::ErrorKind::*,
};
#[derive(Debug, Trace, Clone)]
@@ -42,6 +42,15 @@
defaults: Vec<usize>,
}
+impl PreparedCall {
+ pub fn named(&self) -> &[(usize, usize)] {
+ &self.named
+ }
+ pub fn defaults(&self) -> &[usize] {
+ &self.defaults
+ }
+}
+
pub fn prepare_call(
params: FunctionSignature,
unnamed: usize,
@@ -51,6 +60,25 @@
bail!(TooManyArgsFunctionHas(params.len(), params))
}
+ // Fast path: positional-only (no named args). Avoids HashMap entirely.
+ if named.is_empty() {
+ let mut defaults = Vec::new();
+ for (param_id, param) in params.iter().enumerate().skip(unnamed) {
+ if param.has_default() {
+ defaults.push(param_id);
+ } else {
+ bail!(FunctionParameterNotBoundInCall(
+ param.name().clone(),
+ params.clone(),
+ ))
+ }
+ }
+ return Ok(PreparedCall {
+ named: Vec::new(),
+ defaults,
+ });
+ }
+
let expected_defaults = (params.len() - unnamed).saturating_sub(named.len());
let mut ops = PreparedCall {
named: Vec::with_capacity(named.len()),
@@ -110,63 +138,6 @@
}
Ok(ops)
-}
-pub fn parse_prepared_function_call(
- body_ctx: Context,
- prepared: &PreparedCall,
- params: &ExprParams,
- unnamed: &[Thunk<Val>],
- named: &[Thunk<Val>],
-) -> Result<Context> {
- let mut ctx = ContextBuilder::extend(body_ctx);
-
- let destruct_ctx = Pending::new();
-
- for (param_idx, unnamed) in unnamed.iter().enumerate() {
- destruct(
- ¶ms.exprs[param_idx].destruct,
- unnamed.clone(),
- destruct_ctx.clone(),
- &mut ctx,
- )?;
- }
-
- for (param_idx, arg_idx) in prepared.named.iter().copied() {
- destruct(
- ¶ms.exprs[param_idx].destruct,
- named[arg_idx].clone(),
- destruct_ctx.clone(),
- &mut ctx,
- )?;
- }
-
- if prepared.defaults.is_empty() {
- let body_ctx = ctx.build().into_future(destruct_ctx);
- Ok(body_ctx)
- } else {
- let fctx = Context::new_future();
- let mut ctx = ctx.commit();
- for param_idx in prepared.defaults.iter().copied() {
- // let param = params.0.rc_idx(param_idx);
- destruct(
- ¶ms.exprs[param_idx].destruct,
- {
- let ctx = fctx.clone();
- let params = params.clone();
- Thunk!(move || {
- let param = ¶ms.exprs[param_idx];
- let name = param.destruct.name();
- let value = param.default.as_ref().expect("default exists");
- evaluate_named_param(ctx.unwrap(), value, name)
- })
- },
- fctx.clone(),
- &mut ctx,
- )?;
- }
-
- Ok(ctx.build().into_future(fctx).into_future(destruct_ctx))
- }
}
pub fn parse_prepared_builtin_call(
prepared: &PreparedCall,
crates/jrsonnet-evaluator/src/integrations/serde.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/integrations/serde.rs
+++ b/crates/jrsonnet-evaluator/src/integrations/serde.rs
@@ -3,16 +3,16 @@
use jrsonnet_interner::{IBytes, IStr};
use jrsonnet_ir::NumValue;
use serde::{
- Deserialize, Serialize, Serializer,
de::{self, Visitor},
ser::{
Error, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple,
SerializeTupleStruct, SerializeTupleVariant,
},
+ Deserialize, Serialize, Serializer,
};
use crate::{
- Error as JrError, ObjValue, ObjValueBuilder, Result, Val, in_description_frame, runtime_error,
+ in_description_frame, runtime_error, Error as JrError, ObjValue, ObjValueBuilder, Result, Val,
};
impl<'de> Deserialize<'de> for Val {
@@ -182,7 +182,7 @@
#[cfg(feature = "exp-bigint")]
Self::BigInt(b) => b.serialize(serializer),
Self::Arr(arr) => {
- let mut seq = serializer.serialize_seq(Some(arr.len()))?;
+ let mut seq = serializer.serialize_seq(Some(arr.len() as usize))?;
for (i, element) in arr.iter().enumerate() {
let mut serde_error = None;
in_description_frame(
@@ -203,7 +203,7 @@
seq.end()
}
Self::Obj(obj) => {
- let mut map = serializer.serialize_map(Some(obj.len()))?;
+ let mut map = serializer.serialize_map(Some(obj.len() as usize))?;
for (field, value) in obj.iter(
#[cfg(feature = "exp-preserve-order")]
true,
crates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/lib.rs
+++ b/crates/jrsonnet-evaluator/src/lib.rs
@@ -36,14 +36,13 @@
pub use ctx::*;
pub use dynamic::*;
pub use error::{Error, ErrorKind::*, Result, ResultExt};
-pub use evaluate::*;
+pub use evaluate::ensure_sufficient_stack;
use function::CallLocation;
pub use import::*;
-use jrsonnet_gcmodule::{Cc, Trace, cc_dyn};
+use jrsonnet_gcmodule::{cc_dyn, Cc, Trace};
pub use jrsonnet_interner::{IBytes, IStr};
-pub use jrsonnet_ir as parser;
-pub use jrsonnet_ir::NumValue;
-use jrsonnet_ir::{Expr, Source, SourcePath};
+use jrsonnet_ir::Expr;
+pub use jrsonnet_ir::{NumValue, Source, SourcePath, Span};
#[doc(hidden)]
pub use jrsonnet_macros;
@@ -58,6 +57,7 @@
pub use tla::apply_tla;
pub use val::{Thunk, Val};
+pub mod analyze;
use crate::gc::WithCapacityExt as _;
#[allow(clippy::needless_return)]
@@ -87,7 +87,7 @@
jrsonnet_ir_parser::parse(code, &jrsonnet_ir_parser::ParserSettings { source }).map_err(|e| {
SyntaxError {
message: e.message,
- location: (e.location.0, e.location.1),
+ location: e.location,
}
})
}
@@ -165,7 +165,7 @@
pub trait ContextInitializer {
/// For composability: extend builder. May panic if this initialization is not supported,
/// and the context may only be created via `initialize`.
- fn populate(&self, for_file: Source, builder: &mut ContextBuilder);
+ fn populate(&self, for_file: Source, builder: &mut InitialContextBuilder);
/// Allows upcasting from abstract to concrete context initializer.
/// jrsonnet by itself doesn't use this method, it is allowed for it to panic.
fn as_any(&self) -> &dyn Any;
@@ -174,7 +174,7 @@
where
T: ContextInitializer,
{
- fn populate(&self, for_file: Source, builder: &mut ContextBuilder) {
+ fn populate(&self, for_file: Source, builder: &mut InitialContextBuilder) {
(*self).populate(for_file, builder);
}
@@ -185,7 +185,7 @@
/// Context initializer which adds nothing.
impl ContextInitializer for () {
- fn populate(&self, _for_file: Source, _builder: &mut ContextBuilder) {}
+ fn populate(&self, _for_file: Source, _builder: &mut InitialContextBuilder) {}
fn as_any(&self) -> &dyn Any {
self
}
@@ -195,7 +195,7 @@
where
T: ContextInitializer + 'static,
{
- fn populate(&self, for_file: Source, builder: &mut ContextBuilder) {
+ fn populate(&self, for_file: Source, builder: &mut InitialContextBuilder) {
if let Some(ctx) = self {
ctx.populate(for_file, builder);
}
@@ -210,7 +210,7 @@
($($gen:ident)*) => {
#[allow(non_snake_case)]
impl<$($gen: ContextInitializer + Trace,)*> ContextInitializer for ($($gen,)*) {
- fn populate(&self, for_file: Source, builder: &mut ContextBuilder) {
+ fn populate(&self, for_file: Source, builder: &mut InitialContextBuilder) {
let ($($gen,)*) = self;
$($gen.populate(for_file.clone(), builder);)*
}
@@ -408,7 +408,12 @@
file.evaluating = true;
// Dropping file cache guard here, as evaluation may use this map too
drop(file_cache);
- let res = evaluate(self.create_default_context(file_name), &parsed);
+ let (ctx, externals) = self.create_default_context(file_name.clone()).build();
+ let report = analyze::analyze_root(&parsed, externals);
+ if report.errored {
+ return Err(StaticAnalysisError(report.diagnostics_list).into());
+ }
+ let res = evaluate::evaluate(ctx.build(), &report.lir);
let mut file_cache = self.file_cache();
let mut file = file_cache.entry(path);
@@ -438,7 +443,7 @@
}
/// Creates context with all passed global variables
- pub fn create_default_context(&self, source: Source) -> Context {
+ pub fn create_default_context(&self, source: Source) -> InitialContextBuilder {
self.create_default_context_with(source, &())
}
@@ -447,13 +452,13 @@
&self,
source: Source,
context_initializer: &dyn ContextInitializer,
- ) -> Context {
+ ) -> InitialContextBuilder {
let default_initializer = self.context_initializer();
- let mut builder = ContextBuilder::new();
+ let mut builder = InitialContextBuilder::new();
default_initializer.populate(source.clone(), &mut builder);
context_initializer.populate(source, &mut builder);
- builder.build()
+ builder
}
}
@@ -487,7 +492,7 @@
#[derive(Trace)]
pub struct InitialUnderscore(pub Thunk<Val>);
impl ContextInitializer for InitialUnderscore {
- fn populate(&self, _for_file: Source, builder: &mut ContextBuilder) {
+ fn populate(&self, _for_file: Source, builder: &mut InitialContextBuilder) {
builder.bind("_", self.0.clone());
}
@@ -515,10 +520,14 @@
path: source.clone(),
error: Box::new(e),
})?;
- evaluate(
- self.create_default_context_with(source, context_initializer),
- &parsed,
- )
+ let (ctx, externals) = self
+ .create_default_context_with(source.clone(), context_initializer)
+ .build();
+ let report = analyze::analyze_root(&parsed, externals);
+ if report.errored {
+ return Err(StaticAnalysisError(report.diagnostics_list).into());
+ }
+ evaluate::evaluate(ctx.build(), &report.lir)
}
}
crates/jrsonnet-evaluator/src/obj/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/obj/mod.rs
+++ b/crates/jrsonnet-evaluator/src/obj/mod.rs
@@ -11,8 +11,8 @@
};
use educe::Educe;
-use im_rc::{Vector, vector};
-use jrsonnet_gcmodule::{Acyclic, Cc, Trace, Weak, cc_dyn};
+use im_rc::{vector, Vector};
+use jrsonnet_gcmodule::{cc_dyn, Acyclic, Cc, Trace, Weak};
use jrsonnet_interner::IStr;
use jrsonnet_ir::Span;
use rustc_hash::{FxHashMap, FxHashSet};
@@ -23,13 +23,13 @@
pub use oop::ObjValueBuilder;
use crate::{
- CcUnbound, MaybeUnbound, Result, Thunk, Unbound, Val,
arr::{PickObjectKeyValues, PickObjectValues},
bail,
- error::{ErrorKind::*, suggest_object_fields},
+ error::{suggest_object_fields, ErrorKind::*},
+ evaluate::operator::evaluate_add_op,
identity_hash,
- operator::evaluate_add_op,
val::{ArrValue, ThunkValue},
+ CcUnbound, MaybeUnbound, Result, Thunk, Unbound, Val,
};
#[cfg(not(feature = "exp-preserve-order"))]
@@ -400,6 +400,15 @@
this: ObjValue,
}
impl SupThis {
+ /// Create a `SupThis` for a freshly constructed object (no super).
+ pub fn new(this: ObjValue) -> Self {
+ Self {
+ sup: CoreIdx {
+ idx: this.0.cores.len(),
+ },
+ this,
+ }
+ }
pub fn has_super(&self) -> bool {
self.sup.super_exists()
}
@@ -501,11 +510,11 @@
// }
/// Returns amount of visible object fields
/// If object only contains hidden fields - may return zero.
- pub fn len(&self) -> usize {
+ pub fn len(&self) -> u32 {
self.fields_visibility()
.values()
.filter(|d| d.visible())
- .count()
+ .count() as u32
}
/// For each field, calls callback.
/// If callback returns false - ends iteration prematurely.
crates/jrsonnet-evaluator/src/trace/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/trace/mod.rs
+++ b/crates/jrsonnet-evaluator/src/trace/mod.rs
@@ -10,7 +10,7 @@
#[cfg(feature = "explaining-traces")]
use jrsonnet_ir::Span;
-use crate::{Error, error::ErrorKind};
+use crate::{error::ErrorKind, Error};
/// The way paths should be displayed
#[derive(Clone, Trace)]
@@ -122,7 +122,7 @@
|| path.source_path().to_string(),
|r| self.resolver.resolve(r),
);
- let mut offset = error.location.0 as usize;
+ let mut offset = error.location.1 as usize;
let is_eof = if offset >= path.code().len() {
offset = path.code().len().saturating_sub(1);
true
@@ -259,25 +259,64 @@
struct ResetData {
loc: Span,
}
- use hi_doc::{Formatting, SnippetBuilder, Text, source_to_ansi};
+ use hi_doc::{source_to_ansi, Formatting, SnippetBuilder, Text};
write!(out, "{}", error.error())?;
if let ErrorKind::ImportSyntaxError { path, error } = error.error() {
writeln!(out)?;
- let mut offset = error.location;
- // To inclusive range
- if offset.1 > offset.0 {
- offset.1 -= 1;
- }
let mut builder = SnippetBuilder::new(path.code());
builder
.error(Text::fragment("syntax error", Formatting::default()))
- .range(offset.0 as usize..=offset.1 as usize)
+ .range(error.location.range())
.build();
let source = builder.build();
let ansi = source_to_ansi(&source);
write!(out, "{ansi}")?;
}
+ if let ErrorKind::StaticAnalysisError(diagnostics) = error.error() {
+ use crate::analyze::DiagLevel;
+ let mut builder: Option<SnippetBuilder> = None;
+ let mut current_src: Option<&str> = None;
+ let flush =
+ |builder: Option<SnippetBuilder>, out: &mut dyn std::fmt::Write| -> Result<(), std::fmt::Error> {
+ if let Some(b) = builder {
+ let ansi = source_to_ansi(&b.build());
+ write!(out, "\n{}", ansi.trim_end())?;
+ }
+ Ok(())
+ };
+ for diag in diagnostics {
+ if let Some(span) = &diag.span {
+ let src = span.0.code();
+ if current_src != Some(src) {
+ flush(builder.take(), out)?;
+ builder = Some(SnippetBuilder::new(src));
+ current_src = Some(src);
+ }
+ let b = builder.as_mut().unwrap();
+ let ab = match diag.level {
+ DiagLevel::Error => b.error(Text::fragment(
+ diag.message.clone(),
+ Formatting::default(),
+ )),
+ DiagLevel::Warning => b.warning(Text::fragment(
+ diag.message.clone(),
+ Formatting::default(),
+ )),
+ };
+ ab.range(span.range()).build();
+ } else {
+ flush(builder.take(), out)?;
+ current_src = None;
+ let prefix = match diag.level {
+ DiagLevel::Error => "error",
+ DiagLevel::Warning => "warning",
+ };
+ write!(out, "\n{prefix}: {}", diag.message)?;
+ }
+ }
+ flush(builder, out)?;
+ }
let trace = &error.trace();
let snippet_builder: RefCell<Option<SnippetBuilder>> = RefCell::new(None);
let mut last_location: Option<Span> = None;
crates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/typed/conversions.rs
+++ b/crates/jrsonnet-evaluator/src/typed/conversions.rs
@@ -637,7 +637,7 @@
}
<Self as Typed>::TYPE.check(&value)?;
// Any::downcast_ref::<ByteArray>(&a);
- let mut out = Vec::with_capacity(a.len());
+ let mut out = Vec::with_capacity(a.len() as usize);
for e in a.iter() {
let r = e?;
out.push(u8::from_untyped(r)?);
crates/jrsonnet-interner/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-interner/src/lib.rs
+++ b/crates/jrsonnet-interner/src/lib.rs
@@ -171,6 +171,7 @@
let mut pool = pool.borrow_mut();
if pool.remove(inner).is_none() {
+ // DOC(string-pooling)
// On some platforms (i.e i686-windows), try_with will not fail after TLS
// destructor is called, but instead re-initialize the TLS with the empty pool.
// Allow non-pooled Drop in this case.
crates/jrsonnet-macros/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-macros/src/lib.rs
+++ b/crates/jrsonnet-macros/src/lib.rs
@@ -3,13 +3,14 @@
use proc_macro2::TokenStream;
use quote::{quote, quote_spanned};
use syn::{
- Attribute, DeriveInput, Error, Expr, ExprClosure, FnArg, GenericArgument, Ident, ItemFn,
- LitStr, Meta, Pat, Path, PathArguments, Result, ReturnType, Token, Type, parenthesized,
+ parenthesized,
parse::{Parse, ParseStream},
parse_macro_input,
punctuated::Punctuated,
spanned::Spanned,
token::Comma,
+ Attribute, DeriveInput, Error, Expr, ExprClosure, FnArg, GenericArgument, Ident, ItemFn,
+ LitStr, Meta, Pat, Path, PathArguments, Result, ReturnType, Token, Type,
};
use self::typed::{derive_from_untyped_inner, derive_into_untyped_inner, derive_typed_inner};
@@ -402,7 +403,7 @@
State, Val,
function::{builtin::Builtin, FunctionSignature, ParamParse, ParamName, ParamDefault, CallLocation},
Result, Context, typed::{Typed, FromUntyped, IntoUntypedResult},
- parser::Span, params, Thunk,
+ Span, params, Thunk,
};
params!(
#(#params_desc)*
crates/jrsonnet-stdlib/src/arrays.rsdiffbeforeafterboth--- a/crates/jrsonnet-stdlib/src/arrays.rs
+++ b/crates/jrsonnet-stdlib/src/arrays.rs
@@ -1,11 +1,12 @@
#![allow(non_snake_case)]
use jrsonnet_evaluator::{
- Either, IStr, ObjValue, ObjValueBuilder, Result, ResultExt, Thunk, Val, bail,
- function::{FuncVal, NativeFn, builtin},
+ bail, error,
+ function::{builtin, NativeFn},
runtime_error,
- typed::{BoundedI32, BoundedUsize, Either2, FromUntyped},
- val::{ArrValue, IndexableVal, equals},
+ typed::{BoundedUsize, Either2, FromUntyped},
+ val::{equals, ArrValue, IndexableVal},
+ Either, IStr, ObjValue, ObjValueBuilder, Result, ResultExt, Thunk, Val,
};
pub fn eval_on_empty(on_empty: Option<Thunk<Val>>) -> Result<Val> {
@@ -17,32 +18,28 @@
}
#[builtin]
-pub fn builtin_make_array(
- // Can't use usize because range_exclusive is over i32
- sz: BoundedI32<0, { i32::MAX }>,
- func: FuncVal,
-) -> Result<ArrValue> {
- if *sz == 0 {
+pub fn builtin_make_array(sz: u32, func: NativeFn!((u32,) -> Val)) -> Result<ArrValue> {
+ if sz == 0 {
return Ok(ArrValue::empty());
}
- func.evaluate_trivial().map_or_else(
- // TODO: Different mapped array impl avoiding allocating unnecessary vals
- || Ok(ArrValue::range_exclusive(0, *sz).map(FromUntyped::from_untyped(Val::Func(func))?)),
- |trivial| {
- #[expect(clippy::cast_sign_loss, reason = "sz is bounded to be larger than 0")]
- let mut out = Vec::with_capacity(*sz as usize);
- for _ in 0..*sz {
- out.push(trivial.clone());
+ // Try eager evaluation: call func(i) immediately for each element.
+ 'eager: {
+ let mut out = Vec::with_capacity(sz as usize);
+ for i in 0..sz {
+ match func.call(i) {
+ Ok(v) => out.push(v),
+ Err(_) => break 'eager,
}
- Ok(ArrValue::new(out))
- },
- )
+ }
+ return Ok(ArrValue::new(out));
+ }
+ Ok(ArrValue::make(sz, func))
}
#[builtin]
-pub fn builtin_repeat(what: Either![IStr, ArrValue], count: usize) -> Result<Val> {
+pub fn builtin_repeat(what: Either![IStr, ArrValue], count: u32) -> Result<Val> {
Ok(match what {
- Either2::A(s) => Val::string(s.repeat(count)),
+ Either2::A(s) => Val::string(s.repeat(count as usize)),
Either2::B(arr) => Val::Arr(
ArrValue::repeated(arr, count)
.ok_or_else(|| runtime_error!("repeated length overflow"))?,
@@ -210,14 +207,14 @@
let item = item?.clone();
if let Val::Arr(items) = item {
if !first {
- out.reserve(joiner_items.len());
+ out.reserve(joiner_items.len() as usize);
// TODO: extend
for item in joiner_items.iter() {
out.push(item?);
}
}
first = false;
- out.reserve(items.len());
+ out.reserve(items.len() as usize);
for item in items.iter() {
out.push(item?);
}
@@ -256,7 +253,8 @@
pub fn builtin_lines(arr: ArrValue) -> Result<IndexableVal> {
builtin_join(
IndexableVal::Str("\n".into()),
- ArrValue::extended(arr, ArrValue::new(vec![Val::string("")])),
+ ArrValue::extended(arr, ArrValue::new(vec![Val::string("")]))
+ .ok_or_else(|| error!("array is too large"))?,
)
}
@@ -380,7 +378,7 @@
let newArrLeft = arr.clone().slice(None, Some(at), None);
let newArrRight = arr.slice(Some(at + 1), None, None);
- Ok(ArrValue::extended(newArrLeft, newArrRight))
+ Ok(ArrValue::extended(newArrLeft, newArrRight).ok_or_else(|| error!("array is too large"))?)
}
#[builtin]
@@ -399,20 +397,22 @@
}
#[builtin]
-pub fn builtin_flatten_arrays(arrs: Vec<ArrValue>) -> ArrValue {
- pub fn flatten_inner(values: &[ArrValue]) -> ArrValue {
+pub fn builtin_flatten_arrays(arrs: Vec<ArrValue>) -> Result<ArrValue> {
+ pub fn flatten_inner(values: &[ArrValue]) -> Result<ArrValue> {
if values.len() == 1 {
- return values[0].clone();
+ return Ok(values[0].clone());
} else if values.len() == 2 {
- return ArrValue::extended(values[0].clone(), values[1].clone());
+ return ArrValue::extended(values[0].clone(), values[1].clone())
+ .ok_or_else(|| error!("array is too large"));
}
let (a, b) = values.split_at(values.len() / 2);
- ArrValue::extended(flatten_inner(a), flatten_inner(b))
+ ArrValue::extended(flatten_inner(a)?, flatten_inner(b)?)
+ .ok_or_else(|| error!("array is too large"))
}
if arrs.is_empty() {
- return ArrValue::empty();
+ return Ok(ArrValue::empty());
} else if arrs.len() == 1 {
- return arrs.into_iter().next().expect("single");
+ return Ok(arrs.into_iter().next().expect("single"));
}
flatten_inner(&arrs)
}
crates/jrsonnet-stdlib/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-stdlib/src/lib.rs
+++ b/crates/jrsonnet-stdlib/src/lib.rs
@@ -12,15 +12,9 @@
pub use encoding::*;
pub use hash::*;
use jrsonnet_evaluator::{
- ContextBuilder, IStr, NumValue, ObjValue, ObjValueBuilder, Thunk, Val,
- error::Result,
- function::{CallLocation, FuncVal, builtin_id},
- tla::TlaArg,
- trace::PathResolver,
- typed::SerializeTypedObj as _,
+ IStr, InitialContextBuilder, NumValue, ObjValue, ObjValueBuilder, Source, Thunk, Val, error::Result, function::{CallLocation, FuncVal, builtin_id}, tla::TlaArg, trace::PathResolver, typed::SerializeTypedObj as _
};
use jrsonnet_gcmodule::{Acyclic, Cc, Trace};
-use jrsonnet_ir::Source;
use jrsonnet_macros::{IntoUntyped, Typed};
pub use manifest::*;
pub use math::*;
@@ -544,7 +538,7 @@
}
}
impl jrsonnet_evaluator::ContextInitializer for ContextInitializer {
- fn populate(&self, source: Source, builder: &mut ContextBuilder) {
+ fn populate(&self, source: Source, builder: &mut InitialContextBuilder) {
let mut std = ObjValueBuilder::new();
std.with_super(self.stdlib_obj.clone());
std.field("thisFile").hide().value({
crates/jrsonnet-stdlib/src/misc.rsdiffbeforeafterboth--- a/crates/jrsonnet-stdlib/src/misc.rs
+++ b/crates/jrsonnet-stdlib/src/misc.rs
@@ -1,22 +1,23 @@
use std::{cell::RefCell, collections::BTreeSet};
use jrsonnet_evaluator::{
- Either, IStr, ObjValue, ObjValueBuilder, ResultExt, Thunk, Val, bail,
+ bail,
error::{ErrorKind::*, Result},
- function::{CallLocation, FuncVal, builtin},
+ function::{builtin, CallLocation, FuncVal},
manifest::JsonFormat,
typed::{Either2, Either4},
- val::{ArrValue, equals},
+ val::{equals, ArrValue},
+ Either, IStr, ObjValue, ObjValueBuilder, ResultExt, Thunk, Val,
};
use jrsonnet_gcmodule::Cc;
use crate::Settings;
#[builtin]
-pub fn builtin_length(x: Either![IStr, ArrValue, ObjValue, FuncVal]) -> usize {
+pub fn builtin_length(x: Either![IStr, ArrValue, ObjValue, FuncVal]) -> u32 {
use Either4::*;
match x {
- A(x) => x.chars().count(),
+ A(x) => x.chars().count() as u32,
B(x) => x.len(),
C(x) => x.len(),
D(f) => f.params_len(),
@@ -102,7 +103,7 @@
} else if b.len() == a.len() {
return equals(&Val::Arr(a), &Val::Arr(b));
}
- for (a, b) in a.iter().take(b.len()).zip(b.iter()) {
+ for (a, b) in a.iter().take(b.len() as usize).zip(b.iter()) {
let a = a?;
let b = b?;
if !equals(&a, &b)? {
@@ -127,7 +128,7 @@
return equals(&Val::Arr(a), &Val::Arr(b));
}
let a_len = a.len();
- for (a, b) in a.iter().skip(a_len - b.len()).zip(b.iter()) {
+ for (a, b) in a.iter().skip((a_len - b.len()) as usize).zip(b.iter()) {
let a = a?;
let b = b?;
if !equals(&a, &b)? {
tests/tests/builtin.rsdiffbeforeafterboth--- a/tests/tests/builtin.rs
+++ b/tests/tests/builtin.rs
@@ -1,11 +1,7 @@
mod common;
use jrsonnet_evaluator::{
- ContextBuilder, ContextInitializer, FileImportResolver, Result, State, Thunk, Val,
- function::{CallLocation, FuncVal, builtin, builtin::Builtin},
- parser::Source,
- trace::PathResolver,
- typed::FromUntyped,
+ ContextInitializer, FileImportResolver, InitialContextBuilder, Result, Source, State, Thunk, Val, function::{CallLocation, FuncVal, builtin, builtin::{Builtin}}, trace::PathResolver, typed::FromUntyped
};
use jrsonnet_gcmodule::Trace;
use jrsonnet_stdlib::ContextInitializer as StdContextInitializer;
@@ -31,7 +27,7 @@
#[derive(Trace)]
struct NativeAddContextInitializer;
impl ContextInitializer for NativeAddContextInitializer {
- fn populate(&self, _for_file: Source, builder: &mut ContextBuilder) {
+ fn populate(&self, _for_file: Source, builder: &mut InitialContextBuilder) {
builder.bind("nativeAdd", Thunk::evaluated(Val::function(native_add {})));
}
@@ -76,7 +72,7 @@
#[derive(Trace)]
struct CurryAddContextInitializer;
impl ContextInitializer for CurryAddContextInitializer {
- fn populate(&self, _for_file: Source, builder: &mut ContextBuilder) {
+ fn populate(&self, _for_file: Source, builder: &mut InitialContextBuilder) {
builder.bind("curryAdd", Thunk::evaluated(Val::function(curry_add {})));
}
tests/tests/common.rsdiffbeforeafterboth--- a/tests/tests/common.rs
+++ b/tests/tests/common.rs
@@ -1,8 +1,5 @@
use jrsonnet_evaluator::{
- ContextBuilder, ContextInitializer as ContextInitializerT, ObjValueBuilder, Result, Thunk, Val,
- bail,
- function::{FuncVal, builtin},
- parser::Source,
+ ContextBuilder, ContextInitializer as ContextInitializerT, InitialContextBuilder, ObjValueBuilder, Result, Thunk, Val, bail, function::{FuncVal, builtin}, Source
};
use jrsonnet_gcmodule::Trace;
@@ -68,7 +65,7 @@
#[allow(dead_code)]
pub struct ContextInitializer;
impl ContextInitializerT for ContextInitializer {
- fn populate(&self, _for_file: Source, builder: &mut ContextBuilder) {
+ fn populate(&self, _for_file: Source, builder: &mut InitialContextBuilder) {
let mut bobj = ObjValueBuilder::new();
bobj.method("assertThrow", assert_throw {});
bobj.method("paramNames", param_names {});
tests/tests/cpp_test_suite.rsdiffbeforeafterboth--- a/tests/tests/cpp_test_suite.rs
+++ b/tests/tests/cpp_test_suite.rs
@@ -9,9 +9,11 @@
gc::WithCapacityExt as _,
manifest::JsonFormat,
rustc_hash::FxHashMap,
+ stack::limit_stack_depth,
tla::TlaArg,
trace::{CompactFormat, PathResolver, TraceFormat},
};
+use jrsonnet_gcmodule::ObjectSpace;
use jrsonnet_stdlib::ContextInitializer;
mod common;
use common::ContextInitializer as TestContextInitializer;
@@ -179,6 +181,12 @@
continue;
}
+ let _stack = if entry.path().file_stem().is_some_and(|e| e == "recursive_function" || e == "tailstrict"|| e == "tailstrict5") {
+ Some(limit_stack_depth(100_000))
+ } else {
+ None
+ };
+
if entry
.path()
.file_name()
@@ -188,7 +196,7 @@
continue;
}
- println!("test: {}", entry.path().display());
+ eprintln!("test: {}", entry.path().display());
let result = run(&entry.path(), &root);
@@ -212,25 +220,10 @@
if let Some(golden_path) = read_file(&golden_override)? {
golden = Some(golden_path);
}
-
- // ir-parser has its own override layer
- #[cfg(feature = "ir-parser")]
- let ir_parser_override_path = {
- let p = root_tests
- .join(format!("{root_dir}_golden_override_ir_parser"))
- .join(golden_path.file_name().expect("file has basename"));
- if let Some(golden_path) = read_file(&p)? {
- golden = Some(golden_path);
- }
- p
- };
// Otherwise assume test should just not fail and return true.
let golden = golden.unwrap_or_else(|| "true".to_owned());
- #[cfg(feature = "ir-parser")]
- let update_golden_path = &ir_parser_override_path;
- #[cfg(not(feature = "ir-parser"))]
let update_golden_path = &golden_override;
match (serde_json::from_str::<serde_json::Value>(&result), serde_json::from_str::<serde_json::Value>(&golden)) {
@@ -270,8 +263,11 @@
}
}
}
+ println!("done!");
}
}
+ jrsonnet_gcmodule::with_thread_object_space(ObjectSpace::leak);
+
Ok(())
}
tests/tests/snapshots/golden__golden@issue172.jsonnet.snapdiffbeforeafterboth--- a/tests/tests/snapshots/golden__golden@issue172.jsonnet.snap
+++ b/tests/tests/snapshots/golden__golden@issue172.jsonnet.snap
@@ -3,7 +3,4 @@
expression: result
input_file: tests/golden/issue172.jsonnet
---
-local is not defined: b
- issue172.jsonnet:1:45-47: local <b> access
- issue172.jsonnet:1:4-10: field <value> access
- elem <0> evaluation
+static analysis errors: undefined local: b
tests/tests/snapshots/golden__golden@issue23.jsonnet.snapdiffbeforeafterboth--- a/tests/tests/snapshots/golden__golden@issue23.jsonnet.snap
+++ b/tests/tests/snapshots/golden__golden@issue23.jsonnet.snap
@@ -4,4 +4,4 @@
input_file: tests/golden/issue23.jsonnet
---
infinite recursion detected
- issue23.jsonnet:1:1-8: import "issue23.jsonnet"
+ issue23.jsonnet:1:1-8: import
tests/tests/snapshots/golden__golden@missing_binding.jsonnet.snapdiffbeforeafterboth--- a/tests/tests/snapshots/golden__golden@missing_binding.jsonnet.snap
+++ b/tests/tests/snapshots/golden__golden@missing_binding.jsonnet.snap
@@ -3,6 +3,5 @@
expression: result
input_file: tests/golden/missing_binding.jsonnet
---
-local is not defined: sta
+static analysis errors: undefined local: sta
There is a local with similar name present: std
- missing_binding.jsonnet:1:1-5: local <sta> access