From b06f547d26056a4ca8efb8fdb3aef6172ccd97dd Mon Sep 17 00:00:00 2001 From: James Carl Date: Thu, 5 Mar 2026 18:52:28 -0500 Subject: [PATCH 01/71] Add custom version of Boolmesh with Geo support --- Cargo.lock | 400 ++++++++++++++++++++++++++++++++++++++++- interpreter/Cargo.toml | 3 +- 2 files changed, 399 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b591dc9..73bcbb9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -113,6 +119,27 @@ dependencies = [ "yansi", ] +[[package]] +name = "as-slice" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0" +dependencies = [ + "generic-array 0.12.4", + "generic-array 0.13.3", + "generic-array 0.14.7", + "stable_deref_trait", +] + +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + [[package]] name = "autocfg" version = "1.5.0" @@ -140,14 +167,15 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] name = "boolmesh" version = "0.1.9" -source = "git+https://github.com/IamTheCarl/boolmesh.git?branch=serde#76b3783817e1e9782e3efd814ca939c869f45a7f" +source = "git+https://github.com/IamTheCarl/boolmesh.git?branch=command-cad#5cf00cd83345f979948b0cc3fbaea3bff0fdc361" dependencies = [ + "geo", "glam 0.30.10", "rayon", "serde", @@ -340,6 +368,12 @@ dependencies = [ "libc", ] +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + [[package]] name = "crokey" version = "1.4.0" @@ -456,7 +490,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ - "generic-array", + "generic-array 0.14.7", "typenum", ] @@ -561,6 +595,16 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" +[[package]] +name = "earcutr" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79127ed59a85d7687c409e9978547cffb7dc79675355ed22da6b66fd5f6ead01" +dependencies = [ + "itertools 0.11.0", + "num-traits", +] + [[package]] name = "either" version = "1.15.0" @@ -689,6 +733,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "float_next_after" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bf7cc16383c4b8d58b9905a8509f02926ce3058053c056376248d958c9df1e8" + [[package]] name = "fnv" version = "1.0.7" @@ -710,6 +760,24 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309" +dependencies = [ + "typenum", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -720,6 +788,53 @@ dependencies = [ "version_check", ] +[[package]] +name = "geo" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f3901269ec6d4f6068d3f09e5f02f995bd076398dcd1dfec407cd230b02d11b" +dependencies = [ + "earcutr", + "float_next_after", + "geo-types", + "geographiclib-rs", + "i_overlay", + "log", + "num-traits", + "rand", + "robust", + "rstar 0.12.2", + "serde", + "sif-itree", + "spade", +] + +[[package]] +name = "geo-types" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24f8647af4005fa11da47cd56252c6ef030be8fa97bdbf355e7dfb6348f0a82c" +dependencies = [ + "approx", + "num-traits", + "rayon", + "rstar 0.10.0", + "rstar 0.11.0", + "rstar 0.12.2", + "rstar 0.8.4", + "rstar 0.9.3", + "serde", +] + +[[package]] +name = "geographiclib-rs" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5a7f08910fd98737a6eda7568e7c5e645093e073328eeef49758cfe8b0489c7" +dependencies = [ + "libm", +] + [[package]] name = "gethostname" version = "1.1.0" @@ -730,6 +845,17 @@ dependencies = [ "windows-link", ] +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "getrandom" version = "0.3.4" @@ -869,6 +995,33 @@ dependencies = [ "serde_core", ] +[[package]] +name = "hash32" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4041af86e63ac4298ce40e5cca669066e75b6f1aa3390fe2561ffa5e1d9f4cc" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + [[package]] name = "hashable-map" version = "0.4.0" @@ -884,6 +1037,8 @@ version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ + "allocator-api2", + "equivalent", "foldhash", ] @@ -893,6 +1048,41 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +[[package]] +name = "heapless" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634bd4d29cbf24424d0a4bfcbf80c6960129dc24424752a7d1d1390607023422" +dependencies = [ + "as-slice", + "generic-array 0.14.7", + "hash32 0.1.1", + "stable_deref_trait", +] + +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32 0.2.1", + "rustc_version", + "spin", + "stable_deref_trait", +] + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32 0.3.1", + "stable_deref_trait", +] + [[package]] name = "heck" version = "0.5.0" @@ -905,6 +1095,49 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "i_float" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "010025c2c532c8d82e42d0b8bb5184afa449fa6f06c709ea9adcb16c49ae405b" +dependencies = [ + "libm", +] + +[[package]] +name = "i_key_sort" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9190f86706ca38ac8add223b2aed8b1330002b5cdbbce28fb58b10914d38fc27" + +[[package]] +name = "i_overlay" +version = "4.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413183068e6e0289e18d7d0a1f661b81546e6918d5453a44570b9ab30cbed1b3" +dependencies = [ + "i_float", + "i_key_sort", + "i_shape", + "i_tree", + "rayon", +] + +[[package]] +name = "i_shape" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ea154b742f7d43dae2897fcd5ead86bc7b5eefcedd305a7ebf9f69d44d61082" +dependencies = [ + "i_float", +] + +[[package]] +name = "i_tree" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35e6d558e6d4c7b82bc51d9c771e7a927862a161a7d87bf2b0541450e0e20915" + [[package]] name = "iana-time-zone" version = "0.1.65" @@ -1065,6 +1298,7 @@ dependencies = [ "enum_dispatch", "enum_downcast", "file-guard", + "geo", "hashable-map", "hex", "imstr", @@ -1106,6 +1340,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.13.0" @@ -1227,6 +1470,12 @@ dependencies = [ "windows-link", ] +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + [[package]] name = "libssh2-sys" version = "0.3.1" @@ -1464,6 +1713,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -1617,6 +1867,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pdqselect" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec91767ecc0a0bbe558ce8c9da33c068066c57ecc8bb8477ef8c1ad3ef77c27" + [[package]] name = "percent-encoding" version = "2.3.2" @@ -1691,6 +1947,15 @@ dependencies = [ "zerovec", ] +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + [[package]] name = "pretty_assertions" version = "1.4.1" @@ -1772,6 +2037,18 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", "rand_core", ] @@ -1780,6 +2057,9 @@ name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", +] [[package]] name = "rawpointer" @@ -1867,6 +2147,73 @@ version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" +[[package]] +name = "robust" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e27ee8bb91ca0adcf0ecb116293afa12d393f9c2b9b9cd54d33e8078fe19839" + +[[package]] +name = "rstar" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a45c0e8804d37e4d97e55c6f258bc9ad9c5ee7b07437009dd152d764949a27c" +dependencies = [ + "heapless 0.6.1", + "num-traits", + "pdqselect", + "serde", + "smallvec", +] + +[[package]] +name = "rstar" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b40f1bfe5acdab44bc63e6699c28b74f75ec43afb59f3eda01e145aff86a25fa" +dependencies = [ + "heapless 0.7.17", + "num-traits", + "serde", + "smallvec", +] + +[[package]] +name = "rstar" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f39465655a1e3d8ae79c6d9e007f4953bfc5d55297602df9dc38f9ae9f1359a" +dependencies = [ + "heapless 0.7.17", + "num-traits", + "serde", + "smallvec", +] + +[[package]] +name = "rstar" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73111312eb7a2287d229f06c00ff35b51ddee180f017ab6dec1f69d62ac098d6" +dependencies = [ + "heapless 0.7.17", + "num-traits", + "serde", + "smallvec", +] + +[[package]] +name = "rstar" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "421400d13ccfd26dfa5858199c30a5d76f9c54e0dba7575273025b43c5175dbb" +dependencies = [ + "heapless 0.8.0", + "num-traits", + "serde", + "smallvec", +] + [[package]] name = "rustc-stable-hash" version = "0.1.2" @@ -2004,6 +2351,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "sif-itree" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7f45b8998ced5134fb1d75732c77842a3e888f19c1ff98481822e8fbfbf930b" + [[package]] name = "signal-hook" version = "0.3.18" @@ -2066,6 +2419,27 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +[[package]] +name = "spade" +version = "2.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb313e1c8afee5b5647e00ee0fe6855e3d529eb863a0fdae1d60006c4d1e9990" +dependencies = [ + "hashbrown 0.15.5", + "num-traits", + "robust", + "smallvec", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -3060,6 +3434,26 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zerocopy" +version = "0.8.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a789c6e490b576db9f7e6b6d661bcc9799f7c0ac8352f56ea20193b2681532e5" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "zerofrom" version = "0.1.6" diff --git a/interpreter/Cargo.toml b/interpreter/Cargo.toml index c6a0fe3..4aee18b 100644 --- a/interpreter/Cargo.toml +++ b/interpreter/Cargo.toml @@ -29,10 +29,11 @@ sha2 = "0.10.9" serde = { version = "1.0.228", features = ["derive"] } hex = "0.4.3" # boolmesh = { version = "0.1.7", features = ["rayon"] } -boolmesh = { git = "https://github.com/IamTheCarl/boolmesh.git", branch = "serde", features = ["rayon", "serde"] } +boolmesh = { git = "https://github.com/IamTheCarl/boolmesh.git", branch = "command-cad", features = ["rayon", "serde"] } stl_io = "0.10.0" itertools = "0.14.0" thiserror = "2.0.18" +geo = { version = "0.32.0", features = ["serde"] } [build-dependencies] type-sitter-gen = "0.8" From 4b9a65b322b38b93d057edea5ec0b26642c47b63 Mon Sep 17 00:00:00 2001 From: James Carl Date: Thu, 5 Mar 2026 21:14:42 -0500 Subject: [PATCH 02/71] Rename mesh3d library to mush library --- examples/cooling_plate.ccm | 2 +- examples/modeling/mesh.ccm | 6 ++++++ examples/modeling/mesh3d.ccm | 6 ------ interpreter/src/execution/standard_environment.rs | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) create mode 100644 examples/modeling/mesh.ccm delete mode 100644 examples/modeling/mesh3d.ccm diff --git a/examples/cooling_plate.ccm b/examples/cooling_plate.ccm index a0110b9..c3b134b 100644 --- a/examples/cooling_plate.ccm +++ b/examples/cooling_plate.ccm @@ -12,7 +12,7 @@ let # We need 3cm of cooling surface for each watt this produces cooling_fin_size = nominal_power_output(main_body = 15cm) / 1W * 3cm; in - std.mesh3d.cylinder( + std.mesh.cylinder( diameter = cooling_fin_size, height = 1cm, sectors = 360u, diff --git a/examples/modeling/mesh.ccm b/examples/modeling/mesh.ccm new file mode 100644 index 0000000..3850654 --- /dev/null +++ b/examples/modeling/mesh.ccm @@ -0,0 +1,6 @@ +[ + std.mesh.icosphere(subdivions = 5u, diameter = 2cm)::to_stl(name="my_sphere"), + (std.mesh.icosphere(subdivions = 5u, diameter = 2cm) | std.mesh.cube(size = <(2cm, 2cm, 2cm)>) + <(1cm, 0cm, 0cm)>)::to_stl(name="my_cube_sphere_or"), + (std.mesh.icosphere(subdivions = 5u, diameter = 2cm) & std.mesh.cube(size = <(2cm, 2cm, 2cm)>) + <(1cm, 0cm, 0cm)>)::to_stl(name="my_cube_sphere_and"), + (std.mesh.icosphere(subdivions = 5u, diameter = 2cm) ^ std.mesh.cube(size = <(2cm, 2cm, 2cm)>) + <(1cm, 0cm, 0cm)>)::to_stl(name="my_cube_sphere_xor") +] diff --git a/examples/modeling/mesh3d.ccm b/examples/modeling/mesh3d.ccm deleted file mode 100644 index b0cbb9c..0000000 --- a/examples/modeling/mesh3d.ccm +++ /dev/null @@ -1,6 +0,0 @@ -[ - std.mesh3d.icosphere(subdivions = 5u, diameter = 2cm)::to_stl(name="my_sphere"), - (std.mesh3d.icosphere(subdivions = 5u, diameter = 2cm) | std.mesh3d.cube(size = <(2cm, 2cm, 2cm)>) + <(1cm, 0cm, 0cm)>)::to_stl(name="my_cube_sphere_or"), - (std.mesh3d.icosphere(subdivions = 5u, diameter = 2cm) & std.mesh3d.cube(size = <(2cm, 2cm, 2cm)>) + <(1cm, 0cm, 0cm)>)::to_stl(name="my_cube_sphere_and"), - (std.mesh3d.icosphere(subdivions = 5u, diameter = 2cm) ^ std.mesh3d.cube(size = <(2cm, 2cm, 2cm)>) + <(1cm, 0cm, 0cm)>)::to_stl(name="my_cube_sphere_xor") -] diff --git a/interpreter/src/execution/standard_environment.rs b/interpreter/src/execution/standard_environment.rs index 4bceef8..35a6a9c 100644 --- a/interpreter/src/execution/standard_environment.rs +++ b/interpreter/src/execution/standard_environment.rs @@ -87,7 +87,7 @@ fn build_std(context: &ExecutionContext) -> Dictionary { build_dimension_types(context, ValueType::Vector4).into(), ), ("consts".into(), build_consts(context).into()), - ("mesh3d".into(), build_mesh_3d(context).into()), + ("mesh".into(), build_mesh_3d(context).into()), ("import".into(), BuiltinFunction::new::().into()), ("range".into(), build_range(context).into()), ]); From 73b499666da030e19449b49606c4a33e02281a82 Mon Sep 17 00:00:00 2001 From: James Carl Date: Mon, 9 Mar 2026 22:45:12 -0400 Subject: [PATCH 03/71] Add transform types --- .../src/execution/standard_environment.rs | 13 +- interpreter/src/execution/values/closure.rs | 1 + interpreter/src/execution/values/mod.rs | 6 +- interpreter/src/execution/values/transform.rs | 358 ++++++++++++++++++ .../src/execution/values/value_type.rs | 40 ++ interpreter/src/execution/values/vector.rs | 83 +++- 6 files changed, 494 insertions(+), 7 deletions(-) create mode 100644 interpreter/src/execution/values/transform.rs diff --git a/interpreter/src/execution/standard_environment.rs b/interpreter/src/execution/standard_environment.rs index 35a6a9c..179c86b 100644 --- a/interpreter/src/execution/standard_environment.rs +++ b/interpreter/src/execution/standard_environment.rs @@ -20,6 +20,7 @@ use std::{collections::HashMap, path::Path, sync::Mutex}; use common_data_types::{Dimension, Float}; use imstr::ImString; +use nalgebra::{Matrix3, Matrix4}; use tempfile::TempDir; use crate::{ @@ -34,7 +35,7 @@ use crate::{ }, ExecutionContext, }, - values::BuiltinFunction, + values::{BuiltinFunction, Transform2d, Transform3d}, }; use super::values::{Dictionary, Value, ValueType}; @@ -127,6 +128,14 @@ fn build_consts(context: &ExecutionContext) -> Dictionary { "SIntBits".into(), UnsignedInteger::from(i64::BITS as u64).into(), ), + ( + "Transform2d".into(), + Transform2d::new(Matrix3::identity()).into(), + ), + ( + "Transform3d".into(), + Transform3d::new(Matrix4::identity()).into(), + ), ]); Dictionary::new(context, types) } @@ -142,6 +151,8 @@ fn build_types(context: &ExecutionContext) -> Dictionary { ("String".into(), ValueType::String.into()), ("ValueType".into(), ValueType::ValueType.into()), ("ManifoldMesh".into(), ValueType::ManifoldMesh3D.into()), + ("Transform2d".into(), ValueType::Transform2d.into()), + ("Transform3d".into(), ValueType::Transform3d.into()), // TODO we need File types. // TODO we'll need a function to build custom function signature types. // ("Function".into(), ValueType::Closure(Arc)), diff --git a/interpreter/src/execution/values/closure.rs b/interpreter/src/execution/values/closure.rs index 24eefd5..60455fe 100644 --- a/interpreter/src/execution/values/closure.rs +++ b/interpreter/src/execution/values/closure.rs @@ -57,6 +57,7 @@ impl BuiltinCallableDatabase { super::manifold_mesh::register_methods_and_functions(&mut database); crate::execution::register_methods_and_functions(&mut database); super::iterators::register_methods(&mut database); + super::transform::register_methods(&mut database); database } diff --git a/interpreter/src/execution/values/mod.rs b/interpreter/src/execution/values/mod.rs index 7aacd16..9e8bbac 100644 --- a/interpreter/src/execution/values/mod.rs +++ b/interpreter/src/execution/values/mod.rs @@ -65,6 +65,9 @@ pub use constraint_set::ConstraintSet; mod iterators; pub mod manifold_mesh; +mod transform; +pub use transform::{Transform2d, Transform3d}; + mod value_type; pub use value_type::{StructDefinition, StructMember, ValueType}; @@ -292,7 +295,8 @@ pub enum Value { ConstraintSet, ManifoldMesh3D, ValueIterator, - // Quaternion, + Transform2d, + Transform3d, } impl StaticTypeName for Value { diff --git a/interpreter/src/execution/values/transform.rs b/interpreter/src/execution/values/transform.rs new file mode 100644 index 0000000..1b62bba --- /dev/null +++ b/interpreter/src/execution/values/transform.rs @@ -0,0 +1,358 @@ +/* + * Copyright 2026 James Carl + * AGPL-3.0-only or AGPL-3.0-or-later + * + * This file is part of Command Cad. + * + * Command CAD is free software: you can redistribute it and/or modify it under the terms of + * the GNU Affero General Public License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License along with this + * program. If not, see . + */ + +use std::borrow::Cow; + +use common_data_types::RawFloat; +use enum_downcast::{AsVariant, IntoVariant}; +use nalgebra::{Matrix3, Matrix4, Rotation2, Rotation3, Translation2, Translation3, Unit}; + +use crate::{ + build_method, + execution::errors::Raise as _, + values::{ + scalar::Angle, + vector::{Length2, Length3, Zero2, Zero3}, + BuiltinCallableDatabase, BuiltinFunction, MissingAttributeError, Object, StaticType, + StaticTypeName, Style, Value, ValueType, Vector2, Vector3, + }, + ExecutionContext, ExecutionResult, +}; + +type Float = RawFloat; + +pub type Transform2d = Transform>; +pub type Transform3d = Transform>; + +#[derive(Debug, Hash, Clone, Copy, PartialEq)] +pub struct Transform(pub T); + +impl Transform { + pub fn new(inner: T) -> Self { + Self(inner) + } +} + +impl Eq for Transform where I: PartialEq {} + +impl Object for Transform +where + I: TransformInternalType, + Self: StaticTypeName + Into, + Value: IntoVariant + AsVariant, +{ + fn get_type(&self, _context: &ExecutionContext) -> ValueType { + I::get_type() + } + + fn format( + &self, + _context: &ExecutionContext, + f: &mut dyn std::fmt::Write, + _style: Style, + _precision: Option, + ) -> std::fmt::Result { + write!(f, "{}", self.type_name()) + } + + fn unary_minus(self, _context: &ExecutionContext) -> ExecutionResult { + Ok(Self(self.0.invert()).into()) + } + + fn eq(self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { + let rhs: Self = rhs.downcast_for_binary_op(context)?; + Ok(self == rhs) + } + + fn get_attribute(&self, context: &ExecutionContext, attribute: &str) -> ExecutionResult { + match attribute { + "rotate" => Ok(BuiltinFunction::new::< + <::MethodSet as methods::MethodSet>::Rotate, + >() + .into()), + "translate" => Ok(BuiltinFunction::new::< + <::MethodSet as methods::MethodSet>::Translate, + >() + .into()), + "scale" => Ok(BuiltinFunction::new::< + <::MethodSet as methods::MethodSet>::Scale, + >() + .into()), + _ => Err(MissingAttributeError { + name: attribute.into(), + } + .to_error(context)), + } + } +} + +impl StaticTypeName for Transform +where + I: StaticTypeName, +{ + fn static_type_name() -> Cow<'static, str> { + I::static_type_name() + } +} + +impl StaticType for Transform +where + I: StaticType, +{ + fn static_type() -> ValueType { + I::static_type() + } +} + +mod methods { + pub trait MethodSet { + type Rotate; + type Translate; + type Scale; + } + + macro_rules! build_method_set { + ($name:ident) => { + paste::paste! { + pub struct [<$name Rotate>]; + pub struct [<$name Translate>]; + pub struct [<$name Scale>]; + + pub struct [<$name MethodSet>]; + impl MethodSet for [<$name MethodSet>] { + type Rotate = [<$name Rotate>]; + type Translate = [<$name Translate>]; + type Scale = [<$name Scale>]; + } + } + }; + } + + build_method_set!(Transform2d); + build_method_set!(Transform3d); +} + +pub fn register_methods(database: &mut BuiltinCallableDatabase) { + // Transform2d + build_method!( + database, + ::Rotate, "Transform2d::rotate", ( + context: &ExecutionContext, + this: Transform2d, + angle: Angle) -> Transform2d + { + let rotation = Rotation2::new(*angle.value); + Ok(Transform(this.0 * rotation.to_homogeneous())) + } + ); + build_method!( + database, + ::Translate, "Transform2d::translate", ( + context: &ExecutionContext, + this: Transform2d, + offset: Length2) -> Transform2d + { + let offset: Vector2 = offset.into(); + let offset = offset.raw_value(); + + let translation = Translation2::from(offset); + Ok(Transform(this.0 * translation.to_homogeneous())) + } + ); + build_method!( + database, + ::Scale, "Transform2d::scale", ( + context: &ExecutionContext, + this: Transform2d, + scale: Zero2) -> Transform2d + { + let scale: Vector2 = scale.into(); + let scale = scale.raw_value(); + + Ok(Transform(this.0 * Matrix3::new_nonuniform_scaling(&scale))) + } + ); + + // Transform3d + build_method!( + database, + ::Rotate, "Transform3d::rotate", ( + context: &ExecutionContext, + this: Transform3d, + axis: Zero3, + angle: Angle) -> Transform3d + { + let axis: Vector3 = axis.into(); + let axis = axis.raw_value(); + let axis = Unit::new_normalize(axis); + + let rotation = Rotation3::from_axis_angle(&axis, *angle.value); + Ok(Transform(this.0 * rotation.to_homogeneous())) + } + ); + build_method!( + database, + ::Translate, "Transform3d::translate", ( + context: &ExecutionContext, + this: Transform3d, + offset: Length3) -> Transform3d + { + let offset: Vector3 = offset.into(); + let offset = offset.raw_value(); + + let translation = Translation3::from(offset); + Ok(Transform(this.0 * translation.to_homogeneous())) + } + ); + build_method!( + database, + ::Scale, "Transform3d::scale", ( + context: &ExecutionContext, + this: Transform3d, + scale: Zero3) -> Transform3d + { + let scale: Vector3 = scale.into(); + let scale = scale.raw_value(); + + Ok(Transform(this.0 * Matrix4::new_nonuniform_scaling(&scale))) + } + ); +} + +pub(crate) trait TransformInternalType: + Copy + PartialEq + StaticTypeName + StaticType + 'static +{ + type MethodSet: methods::MethodSet; + + fn get_type() -> ValueType; + fn invert(&self) -> Self; +} + +impl TransformInternalType for Matrix3 { + type MethodSet = methods::Transform2dMethodSet; + + fn get_type() -> ValueType { + ValueType::Transform2d + } + + fn invert(&self) -> Self { + self.try_inverse().expect("Matrix wasn't square") + } +} + +impl StaticTypeName for Matrix3 { + fn static_type_name() -> Cow<'static, str> { + "Transform2d".into() + } +} + +impl StaticType for Matrix3 { + fn static_type() -> ValueType { + ValueType::Transform2d + } +} + +impl TransformInternalType for Matrix4 { + type MethodSet = methods::Transform3dMethodSet; + + fn get_type() -> ValueType { + ValueType::Transform3d + } + + fn invert(&self) -> Self { + self.try_inverse().expect("Matrix wasn't square") + } +} + +impl StaticTypeName for Matrix4 { + fn static_type_name() -> Cow<'static, str> { + "Transform3d".into() + } +} + +impl StaticType for Matrix4 { + fn static_type() -> ValueType { + ValueType::Transform3d + } +} + +#[cfg(test)] +mod test { + use crate::execution::{test_run, values::Boolean}; + use pretty_assertions::assert_eq; + + #[test] + fn identity_transform2d() { + let product = + test_run("<(1m, 2m)>::transform(t = std.consts.Transform2d) == <(1m, 2m)>").unwrap(); + assert_eq!(product, Boolean(true).into()); + } + + #[test] + fn identity_transform3d() { + let product = + test_run("<(1m, 2m, 3m)>::transform(t = std.consts.Transform3d) == <(1m, 2m, 3m)>") + .unwrap(); + assert_eq!(product, Boolean(true).into()); + } + + #[test] + fn translate2d() { + let product = + test_run("<(1m, 2m)>::transform(t = std.consts.Transform2d::translate(offset = <(2m, 4m)>)) == <(3m, 6m)>").unwrap(); + assert_eq!(product, Boolean(true).into()); + } + + #[test] + fn translate3d() { + let product = + test_run("<(1m, 2m, 3m)>::transform(t = std.consts.Transform3d::translate(offset = <(2m, 4m, 6m)>)) == <(3m, 6m, 9m)>") + .unwrap(); + assert_eq!(product, Boolean(true).into()); + } + + #[test] + fn rotate2d() { + let product = + test_run("let rotated = <(0m, 1m)>::transform(t = std.consts.Transform2d::rotate(angle = 90deg)); x = (rotated.x + 1m)::abs() < 0.0001m; y = rotated.y::abs() < 0.0001m; in x && y").unwrap(); + assert_eq!(product, Boolean(true).into()); + } + + #[test] + fn rotate3d() { + let product = + test_run("let rotated = <(0m, 1m, 0m)>::transform(t = std.consts.Transform3d::rotate(axis = <(0, 0, 1)>, angle = 90deg)); x = (rotated.x + 1m)::abs() < 0.0001m; y = rotated.y::abs() < 0.0001m; z = rotated.z::abs() < 0.0001m; in x && y && z") + .unwrap(); + assert_eq!(product, Boolean(true).into()); + } + + #[test] + fn scale2d() { + let product = + test_run("<(1m, 2m)>::transform(t = std.consts.Transform2d::scale(scale = <(3, 4)>)) == <(3m, 8m)>").unwrap(); + assert_eq!(product, Boolean(true).into()); + } + + #[test] + fn scale3d() { + let product = + test_run("<(1m, 2m, 3m)>::transform(t = std.consts.Transform3d::scale(scale = <(3, 4, 5)>)) == <(3m, 8m, 15m)>") + .unwrap(); + assert_eq!(product, Boolean(true).into()); + } +} diff --git a/interpreter/src/execution/values/value_type.rs b/interpreter/src/execution/values/value_type.rs index 5a80d91..6536b11 100644 --- a/interpreter/src/execution/values/value_type.rs +++ b/interpreter/src/execution/values/value_type.rs @@ -63,6 +63,8 @@ pub enum ValueType { ConstraintSet(Arc>), ManifoldMesh3D, Iterator, + Transform2d, + Transform3d, } impl From for ValueType { @@ -97,6 +99,8 @@ impl ValueType { Self::Any => "Any".into(), Self::ManifoldMesh3D => "ManifoldMesh3D".into(), Self::Iterator => "Iterator".into(), + Self::Transform2d => "Transform2d".into(), + Self::Transform3d => "Transform3d".into(), _ => format!("{}", self).into(), } } @@ -868,6 +872,42 @@ mod test { ); } + #[test] + fn type_transform2d() { + ValueType::Transform2d + .check_other_qualifies(&ValueType::Transform2d) + .unwrap(); + + let error = ValueType::Transform2d + .check_other_qualifies(&ValueType::TypeNone) + .unwrap_err(); + assert_eq!( + error, + TypeQualificationError::This { + expected: ValueType::Transform2d, + got: ValueType::TypeNone + } + ); + } + + #[test] + fn type_transform3d() { + ValueType::Transform3d + .check_other_qualifies(&ValueType::Transform3d) + .unwrap(); + + let error = ValueType::Transform3d + .check_other_qualifies(&ValueType::TypeNone) + .unwrap_err(); + assert_eq!( + error, + TypeQualificationError::This { + expected: ValueType::Transform3d, + got: ValueType::TypeNone + } + ); + } + #[test] fn combined_type() { let value_type = test_run("std.types.None | std.types.UInt").unwrap(); diff --git a/interpreter/src/execution/values/vector.rs b/interpreter/src/execution/values/vector.rs index 9cfa12f..5b6c7d4 100644 --- a/interpreter/src/execution/values/vector.rs +++ b/interpreter/src/execution/values/vector.rs @@ -1,6 +1,6 @@ -use common_data_types::Dimension; +use common_data_types::{Dimension, RawFloat}; use enum_downcast::{AsVariant, IntoVariant}; -use nalgebra::{Dim, RawStorage}; +use nalgebra::{Dim, Matrix3, Matrix4, Point2, Point3, RawStorage}; use crate::{ build_closure_type, build_method, @@ -15,7 +15,7 @@ use crate::{ }, ExecutionContext, }, - values::scalar::ResultIsNan, + values::{scalar::ResultIsNan, transform::TransformInternalType}, }; use std::{ @@ -24,7 +24,7 @@ use std::{ ops::{Add, Div, Mul, Neg, Sub}, }; -type Float = f64; +type Float = RawFloat; pub type Vector2 = Vector>; pub type Vector3 = Vector>; @@ -264,6 +264,7 @@ mod methods { use crate::{ build_method, execution::values::{BuiltinCallableDatabase, Dictionary}, + values::{transform::Transform, DowncastError}, }; pub trait MethodSet { @@ -277,6 +278,7 @@ mod methods { type Angle; type Map; type Fold; + type Transform; } macro_rules! build_method_set { @@ -292,6 +294,7 @@ mod methods { pub struct [<$name Angle>]; pub struct [<$name Map>]; pub struct [<$name Fold>]; + pub struct [<$name Transform>]; pub struct [<$name MethodSet>]; impl MethodSet for [<$name MethodSet>] { @@ -305,6 +308,7 @@ mod methods { type Angle = [<$name Angle>]; type Map = [<$name Map>]; type Fold = [<$name Fold>]; + type Transform = [<$name Transform>]; } } }; @@ -507,11 +511,49 @@ mod methods { } ); } + pub fn register_transform_methods( + database: &mut BuiltinCallableDatabase, + dimension: usize, + ) where + I: VectorInternalType + TransformableVector, + Vector: StaticTypeName + Into, + Value: IntoVariant> + + AsVariant> + + IntoVariant> + + AsVariant>, + M: MethodSet + 'static, + { + build_method!( + database, + M::Transform, format!("Vector{dimension}::transform"), ( + context: &ExecutionContext, + this: Vector, + t: Transform) -> Vector + { + if this.dimension != Dimension::length() { + return Err(DowncastError{ expected: "Length vector".into(), got: this.type_name() }.to_error(context)); + } + + + let value = this.raw_value().transform(&t.0); + Ok(Vector { + dimension: Dimension::length(), + value, + }) + } + ); + } } pub fn register_methods(database: &mut BuiltinCallableDatabase) { methods::register_methods::, methods::Vector2MethodSet>(database, 2); + methods::register_transform_methods::, methods::Vector2MethodSet>( + database, 2, + ); methods::register_methods::, methods::Vector3MethodSet>(database, 3); + methods::register_transform_methods::, methods::Vector3MethodSet>( + database, 3, + ); methods::register_methods::, methods::Vector4MethodSet>(database, 4); build_method!( @@ -598,6 +640,12 @@ where } } +trait TransformableVector: VectorInternalType { + type TransformInternalType: TransformInternalType; + + fn transform(&self, transform: &Self::TransformInternalType) -> Self; +} + #[derive(Debug, Eq, PartialEq)] pub struct MissmatchedComponentDimensionsError; @@ -673,6 +721,9 @@ impl VectorInternalType for nalgebra::Vector2 { } .into(), )), + "transform" => Ok(Some( + BuiltinFunction::new::().into(), + )), _ => Ok(None), } } @@ -713,6 +764,15 @@ impl VectorInternalType for nalgebra::Vector2 { self.iter().copied() } } + +impl TransformableVector for nalgebra::Vector2 { + type TransformInternalType = Matrix3; + + fn transform(&self, transform: &Self::TransformInternalType) -> Self { + transform.transform_point(&Point2 { coords: *self }).coords + } +} + impl StaticTypeName for nalgebra::Vector2 { fn static_type_name() -> Cow<'static, str> { "Vector2".into() @@ -801,6 +861,9 @@ impl VectorInternalType for nalgebra::Vector3 { .into(), )), "cross" => Ok(Some(BuiltinFunction::new::().into())), + "transform" => Ok(Some( + BuiltinFunction::new::().into(), + )), _ => Ok(None), } } @@ -841,6 +904,15 @@ impl VectorInternalType for nalgebra::Vector3 { self.iter().copied() } } + +impl TransformableVector for nalgebra::Vector3 { + type TransformInternalType = Matrix4; + + fn transform(&self, transform: &Self::TransformInternalType) -> Self { + transform.transform_point(&Point3 { coords: *self }).coords + } +} + impl StaticTypeName for nalgebra::Vector3 { fn static_type_name() -> Cow<'static, str> { "Vector3".into() @@ -1055,7 +1127,8 @@ macro_rules! build_vector_type { }; } -build_vector_type!(Zero3: Vector3 = Dimension::length()); +build_vector_type!(Zero2: Vector2 = Dimension::zero()); +build_vector_type!(Zero3: Vector3 = Dimension::zero()); build_vector_type!(Length2: Vector2 = Dimension::length()); build_vector_type!(Length3: Vector3 = Dimension::length()); From 29cc0a5d89145d8b2331c3d386b5735e6a727c77 Mon Sep 17 00:00:00 2001 From: James Carl Date: Mon, 9 Mar 2026 22:56:26 -0400 Subject: [PATCH 04/71] Improve syntax for vectors --- examples/language/vectors.ccm | 8 +- examples/modeling/mesh.ccm | 6 +- interpreter/src/compile/expressions.rs | 6 +- interpreter/src/execution/values/scalar.rs | 2 +- interpreter/src/execution/values/transform.rs | 20 +- interpreter/src/execution/values/vector.rs | 191 +- tree-sitter-command-cad-model/grammar.js | 6 +- .../src/grammar.json | 12 +- .../src/node-types.json | 16 +- tree-sitter-command-cad-model/src/parser.c | 12881 +++++----------- .../test/corpus/precedence.txt | 2 +- .../test/corpus/primitives.txt | 6 +- 12 files changed, 4329 insertions(+), 8827 deletions(-) diff --git a/examples/language/vectors.ccm b/examples/language/vectors.ccm index ce0ae6a..3ce76ee 100644 --- a/examples/language/vectors.ccm +++ b/examples/language/vectors.ccm @@ -1,6 +1,6 @@ [ - <(1, 2)>, <(1, 2, 3)>, <(1, 2, 3, 4)>, # Three different sizes of vector are available - <(1m, 2m, 3m)>, # Vectors can have units - <(1, 2, 3)> * 1m, # Arithmetic operations on the vector are applied to the vector's components. - [<(1, 2, 3)>, <(4, 5, 6)>, <(7, 8, 9)>, <(10, 11, 12)>] * 1mm # Use this with a list to mass-apply a unit + {1, 2}, {1, 2, 3}, {1, 2, 3, 4}, # Three different sizes of vector are available + {1m, 2m, 3m}, # Vectors can have units + {1, 2, 3} * 1m, # Arithmetic operations on the vector are applied to the vector's components. + [{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}] * 1mm # Use this with a list to mass-apply a unit ] diff --git a/examples/modeling/mesh.ccm b/examples/modeling/mesh.ccm index 3850654..6b23c76 100644 --- a/examples/modeling/mesh.ccm +++ b/examples/modeling/mesh.ccm @@ -1,6 +1,6 @@ [ std.mesh.icosphere(subdivions = 5u, diameter = 2cm)::to_stl(name="my_sphere"), - (std.mesh.icosphere(subdivions = 5u, diameter = 2cm) | std.mesh.cube(size = <(2cm, 2cm, 2cm)>) + <(1cm, 0cm, 0cm)>)::to_stl(name="my_cube_sphere_or"), - (std.mesh.icosphere(subdivions = 5u, diameter = 2cm) & std.mesh.cube(size = <(2cm, 2cm, 2cm)>) + <(1cm, 0cm, 0cm)>)::to_stl(name="my_cube_sphere_and"), - (std.mesh.icosphere(subdivions = 5u, diameter = 2cm) ^ std.mesh.cube(size = <(2cm, 2cm, 2cm)>) + <(1cm, 0cm, 0cm)>)::to_stl(name="my_cube_sphere_xor") + (std.mesh.icosphere(subdivions = 5u, diameter = 2cm) | std.mesh.cube(size = {2cm, 2cm, 2cm}) + {1cm, 0cm, 0cm})::to_stl(name="my_cube_sphere_or"), + (std.mesh.icosphere(subdivions = 5u, diameter = 2cm) & std.mesh.cube(size = {2cm, 2cm, 2cm}) + {1cm, 0cm, 0cm})::to_stl(name="my_cube_sphere_and"), + (std.mesh.icosphere(subdivions = 5u, diameter = 2cm) ^ std.mesh.cube(size = {2cm, 2cm, 2cm}) + {1cm, 0cm, 0cm})::to_stl(name="my_cube_sphere_xor") ] diff --git a/interpreter/src/compile/expressions.rs b/interpreter/src/compile/expressions.rs index be0e045..334d535 100644 --- a/interpreter/src/compile/expressions.rs +++ b/interpreter/src/compile/expressions.rs @@ -2371,7 +2371,7 @@ mod test { #[test] fn vector2() { - let root = full_compile("<(1.0, 2.0)>"); + let root = full_compile("{1.0, 2.0}"); let vector = root.node.as_vector2().unwrap(); let x = &vector.node.x; let x_scalar = x.node.as_scalar().unwrap(); @@ -2413,7 +2413,7 @@ mod test { #[test] fn vector3() { - let root = full_compile("<(1.0, 2.0, 3.0)>"); + let root = full_compile("{1.0, 2.0, 3.0}"); let vector = root.node.as_vector3().unwrap(); let x = &vector.node.x; let x_scalar = x.node.as_scalar().unwrap(); @@ -2467,7 +2467,7 @@ mod test { #[test] fn vector4() { - let root = full_compile("<(1.0, 2.0, 3.0, 4.0)>"); + let root = full_compile("{1.0, 2.0, 3.0, 4.0}"); let vector = root.node.as_vector4().unwrap(); let x = &vector.node.x; let x_scalar = x.node.as_scalar().unwrap(); diff --git a/interpreter/src/execution/values/scalar.rs b/interpreter/src/execution/values/scalar.rs index 7765359..be9e63c 100644 --- a/interpreter/src/execution/values/scalar.rs +++ b/interpreter/src/execution/values/scalar.rs @@ -1292,7 +1292,7 @@ mod test { #[test] fn cossin() { - let product = test_run("let angle = 45deg; in (angle::cossin() - <(angle::cos(), angle::sin())>)::norm() < 0.0000000001").unwrap(); + let product = test_run("let angle = 45deg; in (angle::cossin() - {angle::cos(), angle::sin()})::norm() < 0.0000000001").unwrap(); assert_eq!(product, Boolean(true).into()); } diff --git a/interpreter/src/execution/values/transform.rs b/interpreter/src/execution/values/transform.rs index 1b62bba..15d130d 100644 --- a/interpreter/src/execution/values/transform.rs +++ b/interpreter/src/execution/values/transform.rs @@ -299,14 +299,14 @@ mod test { #[test] fn identity_transform2d() { let product = - test_run("<(1m, 2m)>::transform(t = std.consts.Transform2d) == <(1m, 2m)>").unwrap(); + test_run("{1m, 2m}::transform(t = std.consts.Transform2d) == {1m, 2m}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn identity_transform3d() { let product = - test_run("<(1m, 2m, 3m)>::transform(t = std.consts.Transform3d) == <(1m, 2m, 3m)>") + test_run("{1m, 2m, 3m}::transform(t = std.consts.Transform3d) == {1m, 2m, 3m}") .unwrap(); assert_eq!(product, Boolean(true).into()); } @@ -314,14 +314,14 @@ mod test { #[test] fn translate2d() { let product = - test_run("<(1m, 2m)>::transform(t = std.consts.Transform2d::translate(offset = <(2m, 4m)>)) == <(3m, 6m)>").unwrap(); + test_run("{1m, 2m}::transform(t = std.consts.Transform2d::translate(offset = {2m, 4m})) == {3m, 6m}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn translate3d() { let product = - test_run("<(1m, 2m, 3m)>::transform(t = std.consts.Transform3d::translate(offset = <(2m, 4m, 6m)>)) == <(3m, 6m, 9m)>") + test_run("{1m, 2m, 3m}::transform(t = std.consts.Transform3d::translate(offset = {2m, 4m, 6m})) == {3m, 6m, 9m}") .unwrap(); assert_eq!(product, Boolean(true).into()); } @@ -329,29 +329,31 @@ mod test { #[test] fn rotate2d() { let product = - test_run("let rotated = <(0m, 1m)>::transform(t = std.consts.Transform2d::rotate(angle = 90deg)); x = (rotated.x + 1m)::abs() < 0.0001m; y = rotated.y::abs() < 0.0001m; in x && y").unwrap(); + test_run("let rotated = {0m, 1m}::transform(t = std.consts.Transform2d::rotate(angle = 90deg)); x = (rotated.x + 1m)::abs() < 0.0001m; y = rotated.y::abs() < 0.0001m; in x && y").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn rotate3d() { let product = - test_run("let rotated = <(0m, 1m, 0m)>::transform(t = std.consts.Transform3d::rotate(axis = <(0, 0, 1)>, angle = 90deg)); x = (rotated.x + 1m)::abs() < 0.0001m; y = rotated.y::abs() < 0.0001m; z = rotated.z::abs() < 0.0001m; in x && y && z") + test_run("let rotated = {0m, 1m, 0m}::transform(t = std.consts.Transform3d::rotate(axis = {0, 0, 1}, angle = 90deg)); x = (rotated.x + 1m)::abs() < 0.0001m; y = rotated.y::abs() < 0.0001m; z = rotated.z::abs() < 0.0001m; in x && y && z") .unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn scale2d() { - let product = - test_run("<(1m, 2m)>::transform(t = std.consts.Transform2d::scale(scale = <(3, 4)>)) == <(3m, 8m)>").unwrap(); + let product = test_run( + "{1m, 2m}::transform(t = std.consts.Transform2d::scale(scale = {3, 4})) == {3m, 8m}", + ) + .unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn scale3d() { let product = - test_run("<(1m, 2m, 3m)>::transform(t = std.consts.Transform3d::scale(scale = <(3, 4, 5)>)) == <(3m, 8m, 15m)>") + test_run("{1m, 2m, 3m}::transform(t = std.consts.Transform3d::scale(scale = {3, 4, 5})) == {3m, 8m, 15m}") .unwrap(); assert_eq!(product, Boolean(true).into()); } diff --git a/interpreter/src/execution/values/vector.rs b/interpreter/src/execution/values/vector.rs index 5b6c7d4..dd2e1a2 100644 --- a/interpreter/src/execution/values/vector.rs +++ b/interpreter/src/execution/values/vector.rs @@ -57,7 +57,7 @@ where ) -> std::fmt::Result { let mut components = self.value.iter().peekable(); - write!(f, "<(")?; + write!(f, "{{")?; while let Some(value) = components.next() { let c = Scalar { @@ -72,7 +72,7 @@ where } } - write!(f, ")>")?; + write!(f, "}}")?; Ok(()) } @@ -1142,7 +1142,7 @@ mod test { #[test] fn construct_vector2() { test_context([], |context| { - let product = test_run("<(1m, 2m)>").unwrap(); + let product = test_run("{1m, 2m}").unwrap(); assert_eq!( product, Vector2::new(context, Dimension::length(), [1.0, 2.0]) @@ -1150,7 +1150,7 @@ mod test { .into() ); - let product = test_run("<(-1m, -2m)>").unwrap(); + let product = test_run("{-1m, -2m}").unwrap(); assert_eq!( product, Vector2::new(context, Dimension::length(), [-1.0, -2.0]) @@ -1163,7 +1163,7 @@ mod test { #[test] fn construct_vector3() { test_context([], |context| { - let product = test_run("<(1m, 2m, 3m)>").unwrap(); + let product = test_run("{1m, 2m, 3m}").unwrap(); assert_eq!( product, Vector3::new(context, Dimension::length(), [1.0, 2.0, 3.0]) @@ -1171,7 +1171,7 @@ mod test { .into() ); - let product = test_run("<(-1m, -2m, -3m)>").unwrap(); + let product = test_run("{-1m, -2m, -3m}").unwrap(); assert_eq!( product, Vector3::new(context, Dimension::length(), [-1.0, -2.0, -3.0]) @@ -1184,7 +1184,7 @@ mod test { #[test] fn construct_vector4() { test_context([], |context| { - let product = test_run("<(1m, 2m, 3m, 4m)>").unwrap(); + let product = test_run("{1m, 2m, 3m, 4m}").unwrap(); assert_eq!( product, Vector4::new(context, Dimension::length(), [1.0, 2.0, 3.0, 4.0]) @@ -1192,7 +1192,7 @@ mod test { .into() ); - let product = test_run("<(-1m, -2m, -3m, -4m)>").unwrap(); + let product = test_run("{-1m, -2m, -3m, -4m}").unwrap(); assert_eq!( product, Vector4::new(context, Dimension::length(), [-1.0, -2.0, -3.0, -4.0]) @@ -1204,13 +1204,13 @@ mod test { #[test] fn missmatched_dimensions_vector2() { - let error = test_run("<(1deg, 2m)>").unwrap_err(); + let error = test_run("{1deg, 2m}").unwrap_err(); let error = error.ty.as_any(); error .downcast_ref::() .unwrap(); - let error = test_run("<(1m, 2deg)>").unwrap_err(); + let error = test_run("{1m, 2deg}").unwrap_err(); let error = error.ty.as_any(); error .downcast_ref::() @@ -1219,19 +1219,19 @@ mod test { #[test] fn missmatched_dimensions_vector3() { - let error = test_run("<(1deg, 2m, 3m)>").unwrap_err(); + let error = test_run("{1deg, 2m, 3m}").unwrap_err(); let error = error.ty.as_any(); error .downcast_ref::() .unwrap(); - let error = test_run("<(1m, 2deg, 3m)>").unwrap_err(); + let error = test_run("{1m, 2deg, 3m}").unwrap_err(); let error = error.ty.as_any(); error .downcast_ref::() .unwrap(); - let error = test_run("<(1m, 2m, 3deg)>").unwrap_err(); + let error = test_run("{1m, 2m, 3deg}").unwrap_err(); let error = error.ty.as_any(); error .downcast_ref::() @@ -1240,25 +1240,25 @@ mod test { #[test] fn missmatched_dimensions_vector4() { - let error = test_run("<(1deg, 2m, 3m, 4m)>").unwrap_err(); + let error = test_run("{1deg, 2m, 3m, 4m}").unwrap_err(); let error = error.ty.as_any(); error .downcast_ref::() .unwrap(); - let error = test_run("<(1m, 2deg, 3m, 4m)>").unwrap_err(); + let error = test_run("{1m, 2deg, 3m, 4m}").unwrap_err(); let error = error.ty.as_any(); error .downcast_ref::() .unwrap(); - let error = test_run("<(1m, 2m, 3deg, 4m)>").unwrap_err(); + let error = test_run("{1m, 2m, 3deg, 4m}").unwrap_err(); let error = error.ty.as_any(); error .downcast_ref::() .unwrap(); - let error = test_run("<(1m, 2m, 3m, 4deg)>").unwrap_err(); + let error = test_run("{1m, 2m, 3m, 4deg}").unwrap_err(); let error = error.ty.as_any(); error .downcast_ref::() @@ -1267,7 +1267,7 @@ mod test { #[test] fn construccomponent_access_vector2() { - let product = test_run("let vec = <(1m, 2m)>; in vec.x").unwrap(); + let product = test_run("let vec = {1m, 2m}; in vec.x").unwrap(); assert_eq!( product, Scalar { @@ -1277,7 +1277,7 @@ mod test { .into() ); - let product = test_run("let vec = <(1m, 2m)>; in vec.y").unwrap(); + let product = test_run("let vec = {1m, 2m}; in vec.y").unwrap(); assert_eq!( product, Scalar { @@ -1290,7 +1290,7 @@ mod test { #[test] fn construccomponent_access_vector3() { - let product = test_run("let vec = <(1m, 2m, 3m)>; in vec.x").unwrap(); + let product = test_run("let vec = {1m, 2m, 3m}; in vec.x").unwrap(); assert_eq!( product, Scalar { @@ -1300,7 +1300,7 @@ mod test { .into() ); - let product = test_run("let vec = <(1m, 2m, 3m)>; in vec.y").unwrap(); + let product = test_run("let vec = {1m, 2m, 3m}; in vec.y").unwrap(); assert_eq!( product, Scalar { @@ -1310,7 +1310,7 @@ mod test { .into() ); - let product = test_run("let vec = <(1m, 2m, 3m)>; in vec.z").unwrap(); + let product = test_run("let vec = {1m, 2m, 3m}; in vec.z").unwrap(); assert_eq!( product, Scalar { @@ -1323,7 +1323,7 @@ mod test { #[test] fn construccomponent_access_vector4() { - let product = test_run("let vec = <(1m, 2m, 3m, 4m)>; in vec.x").unwrap(); + let product = test_run("let vec = {1m, 2m, 3m, 4m}; in vec.x").unwrap(); assert_eq!( product, Scalar { @@ -1333,7 +1333,7 @@ mod test { .into() ); - let product = test_run("let vec = <(1m, 2m, 3m, 4m)>; in vec.y").unwrap(); + let product = test_run("let vec = {1m, 2m, 3m, 4m}; in vec.y").unwrap(); assert_eq!( product, Scalar { @@ -1343,7 +1343,7 @@ mod test { .into() ); - let product = test_run("let vec = <(1m, 2m, 3m, 4m)>; in vec.z").unwrap(); + let product = test_run("let vec = {1m, 2m, 3m, 4m}; in vec.z").unwrap(); assert_eq!( product, Scalar { @@ -1353,7 +1353,7 @@ mod test { .into() ); - let product = test_run("let vec = <(1m, 2m, 3m, 4m)>; in vec.w").unwrap(); + let product = test_run("let vec = {1m, 2m, 3m, 4m}; in vec.w").unwrap(); assert_eq!( product, Scalar { @@ -1366,309 +1366,310 @@ mod test { #[test] fn compare_vector2() { - let product = test_run("<(1m, 2m)> == <(1m, 2m)>").unwrap(); + let product = test_run("{1m, 2m} == {1m, 2m}").unwrap(); assert_eq!(product, Boolean(true).into()); - let product = test_run("<(1m, 2m)> != <(1m, 2m)>").unwrap(); + let product = test_run("{1m, 2m} != {1m, 2m}").unwrap(); assert_eq!(product, Boolean(false).into()); - let product = test_run("<(2m, 2m)> == <(1m, 2m)>").unwrap(); + let product = test_run("{2m, 2m} == {1m, 2m}").unwrap(); assert_eq!(product, Boolean(false).into()); - let product = test_run("<(2m, 2m)> != <(1m, 2m)>").unwrap(); + let product = test_run("{2m, 2m} != {1m, 2m}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn compare_vector3() { - let product = test_run("<(1m, 2m, 3m)> == <(1m, 2m, 3m)>").unwrap(); + let product = test_run("{1m, 2m, 3m} == {1m, 2m, 3m}").unwrap(); assert_eq!(product, Boolean(true).into()); - let product = test_run("<(1m, 2m, 3m)> != <(1m, 2m, 3m)>").unwrap(); + let product = test_run("{1m, 2m, 3m} != {1m, 2m, 3m}").unwrap(); assert_eq!(product, Boolean(false).into()); - let product = test_run("<(2m, 2m, 3m)> == <(1m, 2m, 3m)>").unwrap(); + let product = test_run("{2m, 2m, 3m} == {1m, 2m, 3m}").unwrap(); assert_eq!(product, Boolean(false).into()); - let product = test_run("<(2m, 2m, 3m)> != <(1m, 2m, 3m)>").unwrap(); + let product = test_run("{2m, 2m, 3m} != {1m, 2m, 3m}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn compare_vector4() { - let product = test_run("<(1m, 2m, 3m, 4m)> == <(1m, 2m, 3m, 4m)>").unwrap(); + let product = test_run("{1m, 2m, 3m, 4m} == {1m, 2m, 3m, 4m}").unwrap(); assert_eq!(product, Boolean(true).into()); - let product = test_run("<(1m, 2m, 3m, 4m)> != <(1m, 2m, 3m, 4m)>").unwrap(); + let product = test_run("{1m, 2m, 3m, 4m} != {1m, 2m, 3m, 4m}").unwrap(); assert_eq!(product, Boolean(false).into()); - let product = test_run("<(2m, 2m, 3m, 4m)> == <(1m, 2m, 3m, 4m)>").unwrap(); + let product = test_run("{2m, 2m, 3m, 4m} == {1m, 2m, 3m, 4m}").unwrap(); assert_eq!(product, Boolean(false).into()); - let product = test_run("<(2m, 2m, 3m, 4m)> != <(1m, 2m, 3m, 4m)>").unwrap(); + let product = test_run("{2m, 2m, 3m, 4m} != {1m, 2m, 3m, 4m}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn add_vector2() { - let product = test_run("<(1m, 2m)> + <(2m, 3m)> == <(3m, 5m)>").unwrap(); + let product = test_run("{1m, 2m} + {2m, 3m} == {3m, 5m}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn add_vector3() { - let product = test_run("<(1m, 2m, 3m)> + <(2m, 3m, 4m)> == <(3m, 5m, 7m)>").unwrap(); + let product = test_run("{1m, 2m, 3m} + {2m, 3m, 4m} == {3m, 5m, 7m}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn add_vector4() { - let product = - test_run("<(1m, 2m, 3m, 4m)> + <(2m, 3m, 4m, 5m)> == <(3m, 5m, 7m, 9m)>").unwrap(); + let product = test_run("{1m, 2m, 3m, 4m} + {2m, 3m, 4m, 5m} == {3m, 5m, 7m, 9m}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn sub_vector2() { - let product = test_run("<(1m, 2m)> - <(2m, 3m)> == <(-1m, -1m)>").unwrap(); + let product = test_run("{1m, 2m} - {2m, 3m} == {-1m, -1m}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn sub_vector3() { - let product = test_run("<(1m, 2m, 3m)> - <(2m, 3m, 4m)> == <(-1m, -1m, -1m)>").unwrap(); + let product = test_run("{1m, 2m, 3m} - {2m, 3m, 4m} == {-1m, -1m, -1m}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn sub_vector4() { let product = - test_run("<(1m, 2m, 3m, 4m)> - <(2m, 3m, 4m, 5m)> == <(-1m, -1m, -1m, -1m)>").unwrap(); + test_run("{1m, 2m, 3m, 4m} - {2m, 3m, 4m, 5m} == {-1m, -1m, -1m, -1m}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn multiply_vector2() { - let product = test_run("<(1m, 2m)> * 2.0 == <(2m, 4m)>").unwrap(); + let product = test_run("{1m, 2m} * 2.0 == {2m, 4m}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn multiply_vector3() { - let product = test_run("<(1m, 2m, 3m)> * 2.0 == <(2m, 4m, 6m)>").unwrap(); + let product = test_run("{1m, 2m, 3m} * 2.0 == {2m, 4m, 6m}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn multiply_vector4() { - let product = test_run("<(1m, 2m, 3m, 4m)> * 2.0 == <(2m, 4m, 6m, 8m)>").unwrap(); + let product = test_run("{1m, 2m, 3m, 4m} * 2.0 == {2m, 4m, 6m, 8m}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn divide_vector2() { - let product = test_run("<(2m, 4m)> / 2.0 == <(1m, 2m)>").unwrap(); + let product = test_run("{2m, 4m} / 2.0 == {1m, 2m}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn divide_vector3() { - let product = test_run("<(2m, 4m, 6m)> / 2.0 == <(1m, 2m, 3m)>").unwrap(); + let product = test_run("{2m, 4m, 6m} / 2.0 == {1m, 2m, 3m}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn divide_vector4() { - let product = test_run("<(2m, 4m, 6m, 8m)> / 2.0 == <(1m, 2m, 3m, 4m)>").unwrap(); + let product = test_run("{2m, 4m, 6m, 8m} / 2.0 == {1m, 2m, 3m, 4m}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn abs_vector2() { - let product = test_run("<(-1m, -2m)>::abs() == <(1m, 2m)>").unwrap(); + let product = test_run("{-1m, -2m}::abs() == {1m, 2m}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn abs_vector3() { - let product = test_run("<(-1m, -2m, -3m)>::abs() == <(1m, 2m, 3m)>").unwrap(); + let product = test_run("{-1m, -2m, -3m}::abs() == {1m, 2m, 3m}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn abs_vector4() { - let product = test_run("<(-1m, -2m, -3m, -4m)>::abs() == <(1m, 2m, 3m, 4m)>").unwrap(); + let product = test_run("{-1m, -2m, -3m, -4m}::abs() == {1m, 2m, 3m, 4m}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn add_scalar_vector2() { - let product = test_run("<(1m, 2m)>::add_scalar(value = 1m) == <(2m, 3m)>").unwrap(); + let product = test_run("{1m, 2m}::add_scalar(value = 1m) == {2m, 3m}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn add_scalar_vector3() { - let product = test_run("<(1m, 2m, 3m)>::add_scalar(value = 1m) == <(2m, 3m, 4m)>").unwrap(); + let product = test_run("{1m, 2m, 3m}::add_scalar(value = 1m) == {2m, 3m, 4m}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn add_scalar_vector4() { let product = - test_run("<(1m, 2m, 3m, 4m)>::add_scalar(value = 1m) == <(2m, 3m, 4m, 5m)>").unwrap(); + test_run("{1m, 2m, 3m, 4m}::add_scalar(value = 1m) == {2m, 3m, 4m, 5m}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn amax_vector2() { - let product = test_run("<(1m, 2m)>::amax() == 2m").unwrap(); + let product = test_run("{1m, 2m}::amax() == 2m").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn amax_vector3() { - let product = test_run("<(1m, 2m, 3m)>::amax() == 3m").unwrap(); + let product = test_run("{1m, 2m, 3m}::amax() == 3m").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn amax_vector4() { - let product = test_run("<(1m, 2m, 3m, 4m)>::amax() == 4m").unwrap(); + let product = test_run("{1m, 2m, 3m, 4m}::amax() == 4m").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn dot_vector2() { - let product = test_run("<(1m, 0m)>::dot(rhs = <(0.5m, 10m)>) == 0.5m").unwrap(); + let product = test_run("{1m, 0m}::dot(rhs = {0.5m, 10m}) == 0.5m").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn dot_vector3() { - let product = test_run("<(1m, 0m, 0m)>::dot(rhs = <(0.5m, 10m, 10m)>) == 0.5m").unwrap(); + let product = test_run("{1m, 0m, 0m}::dot(rhs = {0.5m, 10m, 10m}) == 0.5m").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn dot_vector4() { let product = - test_run("<(1m, 0m, 0m, 0m)>::dot(rhs = <(0.5m, 10m, 10m, 10m)>) == 0.5m").unwrap(); + test_run("{1m, 0m, 0m, 0m}::dot(rhs = {0.5m, 10m, 10m, 10m}) == 0.5m").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn norm_vector2() { - let product = test_run("<(1m, 0m)>::norm() == 1m").unwrap(); + let product = test_run("{1m, 0m}::norm() == 1m").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn norm_vector3() { - let product = test_run("<(1m, 0m, 0m)>::norm() == 1m").unwrap(); + let product = test_run("{1m, 0m, 0m}::norm() == 1m").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn norm_vector4() { - let product = test_run("<(1m, 0m, 0m, 0m)>::norm() == 1m").unwrap(); + let product = test_run("{1m, 0m, 0m, 0m}::norm() == 1m").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn length_vector2() { - let product = test_run("<(1m, 0m)>::length() == 1m").unwrap(); + let product = test_run("{1m, 0m}::length() == 1m").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn length_vector3() { - let product = test_run("<(1m, 0m, 0m)>::length() == 1m").unwrap(); + let product = test_run("{1m, 0m, 0m}::length() == 1m").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn length_vector4() { - let product = test_run("<(1m, 0m, 0m, 0m)>::length() == 1m").unwrap(); + let product = test_run("{1m, 0m, 0m, 0m}::length() == 1m").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn normalize_vector2() { - let product = test_run("<(5m, 0m)>::normalize() == <(1, 0)>").unwrap(); + let product = test_run("{5m, 0m}::normalize() == {1, 0}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn normalize_vector3() { - let product = test_run("<(5m, 0m, 0m)>::normalize() == <(1, 0, 0)>").unwrap(); + let product = test_run("{5m, 0m, 0m}::normalize() == {1, 0, 0}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn normalize_vector4() { - let product = test_run("<(5m, 0m, 0m, 0m)>::normalize() == <(1, 0, 0, 0)>").unwrap(); + let product = test_run("{5m, 0m, 0m, 0m}::normalize() == {1, 0, 0, 0}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn normalize_zero_vector2() { - let error = test_run("<(0m, 0m)>::normalize()").unwrap_err(); + let error = test_run("{0m, 0m}::normalize()").unwrap_err(); let error = error.ty.as_any(); error.downcast_ref::().unwrap(); } #[test] fn normalize_zero_vector3() { - let error = test_run("<(0m, 0m, 0m)>::normalize()").unwrap_err(); + let error = test_run("{0m, 0m, 0m}::normalize()").unwrap_err(); let error = error.ty.as_any(); error.downcast_ref::().unwrap(); } #[test] fn normalize_zero_vector4() { - let error = test_run("<(0m, 0m, 0m, 0m)>::normalize()").unwrap_err(); + let error = test_run("{0m, 0m, 0m, 0m}::normalize()").unwrap_err(); let error = error.ty.as_any(); error.downcast_ref::().unwrap(); } #[test] fn cross_vector3() { - let product = - test_run("<(1m, 0m, 0m)>::cross(rhs = <(0m, 1m, 0m)>) == <(0m, 0m, 1m)>").unwrap(); + let product = test_run("{1m, 0m, 0m}::cross(rhs = {0m, 1m, 0m}) == {0m, 0m, 1m}").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn angle_vector2() { - let product = test_run("<(1m, 0m)>::angle(other = <(0m, 1m)>) - 90deg < 0.001deg").unwrap(); + let product = test_run("{1m, 0m}::angle(other = {0m, 1m}) - 90deg < 0.001deg").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn angle_vector3() { let product = - test_run("<(1m, 0m, 0m)>::angle(other = <(0m, 1m, 0m)>) - 90deg < 0.001deg").unwrap(); + test_run("{1m, 0m, 0m}::angle(other = {0m, 1m, 0m}) - 90deg < 0.001deg").unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn angle_vector4() { let product = - test_run("<(1m, 0m, 0m, 0m)>::angle(other = <(0m, 1m, 0m, 0m)>) - 90deg < 0.001deg") + test_run("{1m, 0m, 0m, 0m}::angle(other = {0m, 1m, 0m, 0m}) - 90deg < 0.001deg") .unwrap(); assert_eq!(product, Boolean(true).into()); } #[test] fn apply_vector2() { - let product = test_run("<(0m, 1m)>::apply(f = (c: std.scalar.Length) -> std.scalar.Length: c + 1m) == <(1m, 2m)>").unwrap(); + let product = test_run( + "{0m, 1m}::apply(f = (c: std.scalar.Length) -> std.scalar.Length: c + 1m) == {1m, 2m}", + ) + .unwrap(); assert_eq!(product, Boolean(true).into()); - let product = test_run("<(0m, 1m)>::apply(f = (c: std.scalar.Length) -> std.scalar.Area: c * 1m) == <(0 'm^2', 1 'm^2')>").unwrap(); + let product = test_run("{0m, 1m}::apply(f = (c: std.scalar.Length) -> std.scalar.Area: c * 1m) == {0 'm^2', 1 'm^2'}").unwrap(); assert_eq!(product, Boolean(true).into()); - let error = test_run("<(0m, 1m)>::apply(f = (c: std.scalar.Length) -> std.scalar.Any: if c == 0m then 1m else 1 'm^2')").unwrap_err(); + let error = test_run("{0m, 1m}::apply(f = (c: std.scalar.Length) -> std.scalar.Any: if c == 0m then 1m else 1 'm^2')").unwrap_err(); let error = error.ty.as_any(); error .downcast_ref::() @@ -1677,13 +1678,13 @@ mod test { #[test] fn apply_vector3() { - let product = test_run("<(0m, 1m, 2m)>::apply(f = (c: std.scalar.Length) -> std.scalar.Length: c + 1m) == <(1m, 2m, 3m)>").unwrap(); + let product = test_run("{0m, 1m, 2m}::apply(f = (c: std.scalar.Length) -> std.scalar.Length: c + 1m) == {1m, 2m, 3m}").unwrap(); assert_eq!(product, Boolean(true).into()); - let product = test_run("<(0m, 1m, 2m)>::apply(f = (c: std.scalar.Length) -> std.scalar.Area: c * 1m) == <(0 'm^2', 1 'm^2', 2 'm^2')>").unwrap(); + let product = test_run("{0m, 1m, 2m}::apply(f = (c: std.scalar.Length) -> std.scalar.Area: c * 1m) == {0 'm^2', 1 'm^2', 2 'm^2'}").unwrap(); assert_eq!(product, Boolean(true).into()); - let error =test_run("<(0m, 1m, 1m)>::apply(f = (c: std.scalar.Length) -> std.scalar.Any: if c == 0m then 1m else 1 'm^2')").unwrap_err(); + let error =test_run("{0m, 1m, 1m}::apply(f = (c: std.scalar.Length) -> std.scalar.Any: if c == 0m then 1m else 1 'm^2')").unwrap_err(); let error = error.ty.as_any(); error .downcast_ref::() @@ -1692,13 +1693,13 @@ mod test { #[test] fn apply_vector4() { - let product = test_run("<(0m, 1m, 2m, 3m)>::apply(f = (c: std.scalar.Length) -> std.scalar.Length: c + 1m) == <(1m, 2m, 3m, 4m)>").unwrap(); + let product = test_run("{0m, 1m, 2m, 3m}::apply(f = (c: std.scalar.Length) -> std.scalar.Length: c + 1m) == {1m, 2m, 3m, 4m}").unwrap(); assert_eq!(product, Boolean(true).into()); - let product = test_run("<(0m, 1m, 2m, 3m)>::apply(f = (c: std.scalar.Length) -> std.scalar.Area: c * 1m) == <(0 'm^2', 1 'm^2', 2 'm^2', 3 'm^2')>").unwrap(); + let product = test_run("{0m, 1m, 2m, 3m}::apply(f = (c: std.scalar.Length) -> std.scalar.Area: c * 1m) == {0 'm^2', 1 'm^2', 2 'm^2', 3 'm^2'}").unwrap(); assert_eq!(product, Boolean(true).into()); - let error = test_run("<(0m, 1m, 1m, 1m)>::apply(f = (c: std.scalar.Length) -> std.scalar.Any: if c == 0m then 1m else 1 'm^2')").unwrap_err(); + let error = test_run("{0m, 1m, 1m, 1m}::apply(f = (c: std.scalar.Length) -> std.scalar.Any: if c == 0m then 1m else 1 'm^2')").unwrap_err(); let error = error.ty.as_any(); error .downcast_ref::() @@ -1707,7 +1708,7 @@ mod test { #[test] fn fold_vector2() { - let product = test_run("<(1m, 2m)>::fold(init = 0m, f = (previous: std.scalar.Length, c: std.scalar.Length) -> std.scalar.Length: previous + c)").unwrap(); + let product = test_run("{1m, 2m}::fold(init = 0m, f = (previous: std.scalar.Length, c: std.scalar.Length) -> std.scalar.Length: previous + c)").unwrap(); assert_eq!( product, Scalar { @@ -1720,7 +1721,7 @@ mod test { #[test] fn fold_vector3() { - let product = test_run("<(1m, 2m, 3m)>::fold(init = 0m, f = (previous: std.scalar.Length, c: std.scalar.Length) -> std.scalar.Length: previous + c)").unwrap(); + let product = test_run("{1m, 2m, 3m}::fold(init = 0m, f = (previous: std.scalar.Length, c: std.scalar.Length) -> std.scalar.Length: previous + c)").unwrap(); assert_eq!( product, Scalar { @@ -1733,7 +1734,7 @@ mod test { #[test] fn fold_vector4() { - let product = test_run("<(1m, 2m, 3m, 4m)>::fold(init = 0m, f = (previous: std.scalar.Length, c: std.scalar.Length) -> std.scalar.Length: previous + c)").unwrap(); + let product = test_run("{1m, 2m, 3m, 4m}::fold(init = 0m, f = (previous: std.scalar.Length, c: std.scalar.Length) -> std.scalar.Length: previous + c)").unwrap(); assert_eq!( product, Scalar { @@ -1747,19 +1748,19 @@ mod test { #[test] fn format() { let product = test_run( - "\"{a} {b} {c:.2}\"::format(a = <(1, 2)>, b = <(1m, 2m)>, c = <(1.234, 2.345)>) == \"<(1, 2)> <(1m, 2m)> <(1.23, 2.34)>\"", + "\"{a} {b} {c:.2}\"::format(a = {1, 2}, b = {1m, 2m}, c = {1.234, 2.345}) == \"{1, 2} {1m, 2m} {1.23, 2.34}\"", ) .unwrap(); assert_eq!(product, Boolean(true).into()); let product = test_run( - "\"{a} {b} {c:.2}\"::format(a = <(1, 2, 3)>, b = <(1m, 2m, 3m)>, c = <(1.234, 2.345, 3.456)>) == \"<(1, 2, 3)> <(1m, 2m, 3m)> <(1.23, 2.34, 3.46)>\"", + "\"{a} {b} {c:.2}\"::format(a = {1, 2, 3}, b = {1m, 2m, 3m}, c = {1.234, 2.345, 3.456}) == \"{1, 2, 3} {1m, 2m, 3m} {1.23, 2.34, 3.46}\"", ) .unwrap(); assert_eq!(product, Boolean(true).into()); let product = test_run( - "\"{a} {b} {c:.2}\"::format(a = <(1, 2, 3, 4)>, b = <(1m, 2m, 3m, 4m)>, c = <(1.234, 2.345, 3.456, 4.567)>) == \"<(1, 2, 3, 4)> <(1m, 2m, 3m, 4m)> <(1.23, 2.34, 3.46, 4.57)>\"", + "\"{a} {b} {c:.2}\"::format(a = {1, 2, 3, 4}, b = {1m, 2m, 3m, 4m}, c = {1.234, 2.345, 3.456, 4.567}) == \"{1, 2, 3, 4} {1m, 2m, 3m, 4m} {1.23, 2.34, 3.46, 4.57}\"", ) .unwrap(); assert_eq!(product, Boolean(true).into()); diff --git a/tree-sitter-command-cad-model/grammar.js b/tree-sitter-command-cad-model/grammar.js index a8f9bf8..df33404 100644 --- a/tree-sitter-command-cad-model/grammar.js +++ b/tree-sitter-command-cad-model/grammar.js @@ -116,9 +116,9 @@ module.exports = grammar({ _unit: $ => choice($.identifier, $.unit_quote), scalar: $ => prec.left(PREC.unit, seq($._float, field('unit', optional($._unit)))), - vector2: $ => seq('<(', field('x', $.expression), ',', field('y', $.expression), ')>'), - vector3: $ => seq('<(', field('x', $.expression), ',', field('y', $.expression), ',', field('z', $.expression), ')>'), - vector4: $ => seq('<(', field('x', $.expression), ',', field('y', $.expression), ',', field('z', $.expression), ',', field('w', $.expression), ')>'), + vector2: $ => seq('{', field('x', $.expression), ',', field('y', $.expression), '}'), + vector3: $ => seq('{', field('x', $.expression), ',', field('y', $.expression), ',', field('z', $.expression), '}'), + vector4: $ => seq('{', field('x', $.expression), ',', field('y', $.expression), ',', field('z', $.expression), ',', field('w', $.expression), '}'), true: $ => 'true', false: $ => 'false', diff --git a/tree-sitter-command-cad-model/src/grammar.json b/tree-sitter-command-cad-model/src/grammar.json index f9cd538..eb7377c 100644 --- a/tree-sitter-command-cad-model/src/grammar.json +++ b/tree-sitter-command-cad-model/src/grammar.json @@ -254,7 +254,7 @@ "members": [ { "type": "STRING", - "value": "<(" + "value": "{" }, { "type": "FIELD", @@ -278,7 +278,7 @@ }, { "type": "STRING", - "value": ")>" + "value": "}" } ] }, @@ -287,7 +287,7 @@ "members": [ { "type": "STRING", - "value": "<(" + "value": "{" }, { "type": "FIELD", @@ -323,7 +323,7 @@ }, { "type": "STRING", - "value": ")>" + "value": "}" } ] }, @@ -332,7 +332,7 @@ "members": [ { "type": "STRING", - "value": "<(" + "value": "{" }, { "type": "FIELD", @@ -380,7 +380,7 @@ }, { "type": "STRING", - "value": ")>" + "value": "}" } ] }, diff --git a/tree-sitter-command-cad-model/src/node-types.json b/tree-sitter-command-cad-model/src/node-types.json index ce4d974..6571f57 100644 --- a/tree-sitter-command-cad-model/src/node-types.json +++ b/tree-sitter-command-cad-model/src/node-types.json @@ -1157,10 +1157,6 @@ "type": ")", "named": false }, - { - "type": ")>", - "named": false - }, { "type": "*", "named": false @@ -1209,10 +1205,6 @@ "type": "<", "named": false }, - { - "type": "<(", - "named": false - }, { "type": "<<", "named": false @@ -1318,6 +1310,10 @@ "type": "varadic_dots", "named": true }, + { + "type": "{", + "named": false + }, { "type": "|", "named": false @@ -1325,5 +1321,9 @@ { "type": "||", "named": false + }, + { + "type": "}", + "named": false } ] \ No newline at end of file diff --git a/tree-sitter-command-cad-model/src/parser.c b/tree-sitter-command-cad-model/src/parser.c index 919ee9f..8c6f4a1 100644 --- a/tree-sitter-command-cad-model/src/parser.c +++ b/tree-sitter-command-cad-model/src/parser.c @@ -7,8 +7,8 @@ #endif #define LANGUAGE_VERSION 15 -#define STATE_COUNT 322 -#define LARGE_STATE_COUNT 4 +#define STATE_COUNT 219 +#define LARGE_STATE_COUNT 3 #define SYMBOL_COUNT 105 #define ALIAS_COUNT 0 #define TOKEN_COUNT 58 @@ -35,9 +35,9 @@ enum ts_symbol_identifiers { aux_sym_unsigned_integer_token1 = 13, sym_unit_quote = 14, anon_sym_DOT = 15, - anon_sym_LT_LPAREN = 16, + anon_sym_LBRACE = 16, anon_sym_COMMA = 17, - anon_sym_RPAREN_GT = 18, + anon_sym_RBRACE = 18, sym_true = 19, sym_false = 20, anon_sym_COLON_COLON = 21, @@ -143,9 +143,9 @@ static const char * const ts_symbol_names[] = { [aux_sym_unsigned_integer_token1] = "unsigned_integer_token1", [sym_unit_quote] = "unit_quote", [anon_sym_DOT] = ".", - [anon_sym_LT_LPAREN] = "<(", + [anon_sym_LBRACE] = "{", [anon_sym_COMMA] = ",", - [anon_sym_RPAREN_GT] = ")>", + [anon_sym_RBRACE] = "}", [sym_true] = "true", [sym_false] = "false", [anon_sym_COLON_COLON] = "::", @@ -251,9 +251,9 @@ static const TSSymbol ts_symbol_map[] = { [aux_sym_unsigned_integer_token1] = aux_sym_unsigned_integer_token1, [sym_unit_quote] = sym_unit_quote, [anon_sym_DOT] = anon_sym_DOT, - [anon_sym_LT_LPAREN] = anon_sym_LT_LPAREN, + [anon_sym_LBRACE] = anon_sym_LBRACE, [anon_sym_COMMA] = anon_sym_COMMA, - [anon_sym_RPAREN_GT] = anon_sym_RPAREN_GT, + [anon_sym_RBRACE] = anon_sym_RBRACE, [sym_true] = sym_true, [sym_false] = sym_false, [anon_sym_COLON_COLON] = anon_sym_COLON_COLON, @@ -407,7 +407,7 @@ static const TSSymbolMetadata ts_symbol_metadata[] = { .visible = true, .named = false, }, - [anon_sym_LT_LPAREN] = { + [anon_sym_LBRACE] = { .visible = true, .named = false, }, @@ -415,7 +415,7 @@ static const TSSymbolMetadata ts_symbol_metadata[] = { .visible = true, .named = false, }, - [anon_sym_RPAREN_GT] = { + [anon_sym_RBRACE] = { .visible = true, .named = false, }, @@ -974,19 +974,19 @@ static const TSStateId ts_primary_state_ids[STATE_COUNT] = { [0] = 0, [1] = 1, [2] = 2, - [3] = 2, + [3] = 3, [4] = 4, [5] = 5, - [6] = 5, - [7] = 4, + [6] = 6, + [7] = 7, [8] = 8, [9] = 9, [10] = 10, [11] = 11, [12] = 12, - [13] = 13, + [13] = 6, [14] = 14, - [15] = 9, + [15] = 15, [16] = 16, [17] = 17, [18] = 18, @@ -1004,51 +1004,51 @@ static const TSStateId ts_primary_state_ids[STATE_COUNT] = { [30] = 30, [31] = 31, [32] = 32, - [33] = 33, - [34] = 34, - [35] = 35, + [33] = 27, + [34] = 8, + [35] = 9, [36] = 10, [37] = 11, [38] = 12, - [39] = 13, + [39] = 7, [40] = 14, - [41] = 16, - [42] = 17, - [43] = 18, - [44] = 19, - [45] = 24, - [46] = 46, - [47] = 31, - [48] = 33, - [49] = 34, - [50] = 35, - [51] = 10, - [52] = 11, - [53] = 12, - [54] = 13, - [55] = 14, - [56] = 9, - [57] = 16, - [58] = 17, - [59] = 18, - [60] = 19, - [61] = 24, - [62] = 29, - [63] = 31, - [64] = 34, - [65] = 33, - [66] = 35, - [67] = 20, - [68] = 21, - [69] = 22, - [70] = 30, - [71] = 32, - [72] = 20, - [73] = 22, - [74] = 46, - [75] = 27, - [76] = 27, - [77] = 29, + [41] = 15, + [42] = 16, + [43] = 17, + [44] = 18, + [45] = 19, + [46] = 24, + [47] = 29, + [48] = 31, + [49] = 20, + [50] = 22, + [51] = 51, + [52] = 52, + [53] = 53, + [54] = 54, + [55] = 55, + [56] = 56, + [57] = 57, + [58] = 58, + [59] = 59, + [60] = 60, + [61] = 61, + [62] = 62, + [63] = 63, + [64] = 64, + [65] = 65, + [66] = 66, + [67] = 67, + [68] = 68, + [69] = 69, + [70] = 70, + [71] = 71, + [72] = 72, + [73] = 73, + [74] = 74, + [75] = 75, + [76] = 76, + [77] = 77, [78] = 78, [79] = 79, [80] = 80, @@ -1069,20 +1069,20 @@ static const TSStateId ts_primary_state_ids[STATE_COUNT] = { [95] = 95, [96] = 96, [97] = 97, - [98] = 98, - [99] = 99, + [98] = 52, + [99] = 53, [100] = 100, [101] = 101, - [102] = 102, - [103] = 103, - [104] = 104, + [102] = 55, + [103] = 56, + [104] = 54, [105] = 105, [106] = 106, [107] = 107, [108] = 108, [109] = 109, [110] = 110, - [111] = 111, + [111] = 63, [112] = 112, [113] = 113, [114] = 114, @@ -1090,209 +1090,106 @@ static const TSStateId ts_primary_state_ids[STATE_COUNT] = { [116] = 116, [117] = 117, [118] = 118, - [119] = 119, - [120] = 120, - [121] = 121, - [122] = 122, - [123] = 123, - [124] = 79, - [125] = 78, - [126] = 79, - [127] = 127, - [128] = 81, - [129] = 80, - [130] = 78, - [131] = 131, - [132] = 82, - [133] = 133, - [134] = 98, - [135] = 99, - [136] = 100, - [137] = 101, - [138] = 102, - [139] = 104, - [140] = 140, - [141] = 80, - [142] = 114, - [143] = 115, - [144] = 133, - [145] = 112, - [146] = 122, + [119] = 65, + [120] = 85, + [121] = 87, + [122] = 88, + [123] = 89, + [124] = 90, + [125] = 91, + [126] = 93, + [127] = 94, + [128] = 95, + [129] = 64, + [130] = 130, + [131] = 74, + [132] = 75, + [133] = 70, + [134] = 134, + [135] = 116, + [136] = 134, + [137] = 67, + [138] = 112, + [139] = 139, + [140] = 55, + [141] = 56, + [142] = 53, + [143] = 143, + [144] = 144, + [145] = 145, + [146] = 146, [147] = 147, - [148] = 83, - [149] = 97, + [148] = 148, + [149] = 146, [150] = 150, - [151] = 151, - [152] = 140, - [153] = 84, - [154] = 154, - [155] = 85, - [156] = 82, - [157] = 81, - [158] = 86, - [159] = 87, - [160] = 116, - [161] = 154, - [162] = 92, - [163] = 94, - [164] = 95, - [165] = 96, - [166] = 150, + [151] = 54, + [152] = 147, + [153] = 153, + [154] = 150, + [155] = 155, + [156] = 156, + [157] = 157, + [158] = 158, + [159] = 60, + [160] = 160, + [161] = 161, + [162] = 161, + [163] = 160, + [164] = 164, + [165] = 165, + [166] = 166, [167] = 167, - [168] = 120, - [169] = 121, - [170] = 110, + [168] = 168, + [169] = 169, + [170] = 170, [171] = 171, - [172] = 90, - [173] = 116, - [174] = 89, + [172] = 170, + [173] = 171, + [174] = 174, [175] = 175, - [176] = 93, - [177] = 123, + [176] = 176, + [177] = 177, [178] = 178, - [179] = 91, - [180] = 92, - [181] = 94, - [182] = 95, - [183] = 96, - [184] = 97, - [185] = 98, - [186] = 99, - [187] = 100, - [188] = 101, - [189] = 102, - [190] = 103, - [191] = 104, - [192] = 105, - [193] = 167, - [194] = 107, - [195] = 108, + [179] = 179, + [180] = 180, + [181] = 181, + [182] = 182, + [183] = 183, + [184] = 184, + [185] = 185, + [186] = 186, + [187] = 187, + [188] = 188, + [189] = 189, + [190] = 190, + [191] = 191, + [192] = 192, + [193] = 193, + [194] = 194, + [195] = 186, [196] = 196, - [197] = 111, - [198] = 113, - [199] = 114, - [200] = 115, - [201] = 117, - [202] = 118, - [203] = 119, - [204] = 88, + [197] = 197, + [198] = 186, + [199] = 199, + [200] = 200, + [201] = 201, + [202] = 202, + [203] = 203, + [204] = 204, [205] = 205, [206] = 206, - [207] = 122, - [208] = 175, - [209] = 178, - [210] = 167, + [207] = 207, + [208] = 208, + [209] = 209, + [210] = 210, [211] = 211, - [212] = 178, - [213] = 211, - [214] = 109, - [215] = 106, - [216] = 112, + [212] = 212, + [213] = 213, + [214] = 214, + [215] = 215, + [216] = 216, [217] = 217, - [218] = 171, - [219] = 171, - [220] = 217, - [221] = 221, - [222] = 78, - [223] = 80, - [224] = 82, - [225] = 225, - [226] = 226, - [227] = 227, - [228] = 228, - [229] = 229, - [230] = 229, - [231] = 231, - [232] = 232, - [233] = 233, - [234] = 234, - [235] = 226, - [236] = 232, - [237] = 237, - [238] = 81, - [239] = 239, - [240] = 228, - [241] = 234, - [242] = 242, - [243] = 242, - [244] = 244, - [245] = 88, - [246] = 246, - [247] = 246, - [248] = 244, - [249] = 249, - [250] = 250, - [251] = 251, - [252] = 252, - [253] = 252, - [254] = 251, - [255] = 255, - [256] = 256, - [257] = 257, - [258] = 256, - [259] = 257, - [260] = 257, - [261] = 256, - [262] = 262, - [263] = 263, - [264] = 264, - [265] = 265, - [266] = 266, - [267] = 267, - [268] = 267, - [269] = 269, - [270] = 270, - [271] = 269, - [272] = 266, - [273] = 273, - [274] = 265, - [275] = 273, - [276] = 270, - [277] = 277, - [278] = 278, - [279] = 279, - [280] = 280, - [281] = 281, - [282] = 282, - [283] = 283, - [284] = 284, - [285] = 285, - [286] = 286, - [287] = 287, - [288] = 279, - [289] = 289, - [290] = 290, - [291] = 279, - [292] = 279, - [293] = 293, - [294] = 294, - [295] = 295, - [296] = 296, - [297] = 281, - [298] = 295, - [299] = 299, - [300] = 300, - [301] = 301, - [302] = 302, - [303] = 303, - [304] = 304, - [305] = 305, - [306] = 306, - [307] = 307, - [308] = 308, - [309] = 302, - [310] = 310, - [311] = 311, - [312] = 312, - [313] = 313, - [314] = 310, - [315] = 300, - [316] = 312, - [317] = 317, - [318] = 318, - [319] = 319, - [320] = 301, - [321] = 321, + [218] = 218, }; static bool ts_lex(TSLexer *lexer, TSStateId state) { @@ -1300,580 +1197,556 @@ static bool ts_lex(TSLexer *lexer, TSStateId state) { eof = lexer->eof(lexer); switch (state) { case 0: - if (eof) ADVANCE(23); + if (eof) ADVANCE(21); ADVANCE_MAP( - '!', 54, - '"', 5, - '#', 24, - '&', 62, - '\'', 7, - '(', 82, - ')', 83, - '*', 57, - '+', 52, - ',', 47, - '-', 51, - '.', 45, - '/', 58, - '0', 33, - '1', 35, - ':', 81, - ';', 80, - '<', 72, - '=', 79, - '>', 66, - '[', 84, - ']', 85, - '^', 64, - 't', 28, - '|', 63, + '!', 52, + '"', 4, + '#', 22, + '&', 60, + '\'', 6, + '(', 80, + ')', 81, + '*', 55, + '+', 50, + ',', 45, + '-', 49, + '.', 43, + '/', 56, + '0', 31, + '1', 33, + ':', 79, + ';', 78, + '<', 70, + '=', 77, + '>', 64, + '[', 82, + ']', 83, + '^', 62, + 't', 26, + '{', 44, + '|', 61, + '}', 46, ); if (('\t' <= lookahead && lookahead <= '\r') || - lookahead == ' ') ADVANCE(25); - if (('2' <= lookahead && lookahead <= '9')) ADVANCE(36); + lookahead == ' ') ADVANCE(23); + if (('2' <= lookahead && lookahead <= '9')) ADVANCE(34); if (('A' <= lookahead && lookahead <= 'Z') || lookahead == '_' || - ('a' <= lookahead && lookahead <= 'z')) ADVANCE(30); + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(28); END_STATE(); case 1: ADVANCE_MAP( - '!', 53, - '"', 5, - '#', 24, - '(', 82, - ')', 83, - '*', 56, - '+', 52, - '-', 50, - '.', 10, - '/', 58, - '0', 34, - ':', 12, - '<', 9, - '>', 18, - '[', 84, - ']', 85, + '!', 51, + '"', 4, + '#', 22, + '(', 80, + ')', 81, + '*', 54, + '+', 50, + '-', 48, + '.', 8, + '/', 56, + '0', 32, + ':', 10, + '<', 12, + '>', 16, + '[', 82, + ']', 83, + '{', 44, ); if (('\t' <= lookahead && lookahead <= '\r') || - lookahead == ' ') ADVANCE(25); - if (('1' <= lookahead && lookahead <= '9')) ADVANCE(36); + lookahead == ' ') ADVANCE(23); + if (('1' <= lookahead && lookahead <= '9')) ADVANCE(34); if (('A' <= lookahead && lookahead <= 'Z') || lookahead == '_' || - ('a' <= lookahead && lookahead <= 'z')) ADVANCE(30); + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(28); END_STATE(); case 2: ADVANCE_MAP( - '!', 14, - '#', 24, - '&', 62, - '\'', 7, - '(', 82, - ')', 17, - '*', 57, - '+', 52, - ',', 47, - '-', 51, - '.', 44, - '/', 58, - ':', 12, - '<', 72, - '=', 15, - '>', 67, - '^', 64, - '|', 63, + '!', 13, + '#', 22, + '\'', 6, + '*', 54, + '+', 50, + '-', 48, + '.', 42, + '/', 56, + ':', 10, + '<', 71, + '=', 14, + '>', 63, ); if (('\t' <= lookahead && lookahead <= '\r') || - lookahead == ' ') ADVANCE(25); + lookahead == ' ') ADVANCE(23); if (('A' <= lookahead && lookahead <= 'Z') || lookahead == '_' || - ('a' <= lookahead && lookahead <= 'z')) ADVANCE(30); + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(28); END_STATE(); case 3: ADVANCE_MAP( - '!', 14, - '#', 24, - '\'', 7, - '*', 56, - '+', 52, - '-', 50, - '.', 44, - '/', 58, - ':', 12, - '<', 73, - '=', 15, - '>', 65, - ); - if (('\t' <= lookahead && lookahead <= '\r') || - lookahead == ' ') ADVANCE(25); - if (('A' <= lookahead && lookahead <= 'Z') || - lookahead == '_' || - ('a' <= lookahead && lookahead <= 'z')) ADVANCE(30); - END_STATE(); - case 4: - ADVANCE_MAP( - '!', 14, - '#', 24, - ')', 83, - '*', 56, - '+', 52, - '-', 50, - '/', 58, - ':', 12, - '<', 73, - '=', 15, - '>', 68, + '!', 13, + '#', 22, + ')', 81, + '*', 54, + '+', 50, + '-', 48, + '/', 56, + ':', 10, + '<', 71, + '=', 14, + '>', 66, ); if (('\t' <= lookahead && lookahead <= '\r') || - lookahead == ' ') ADVANCE(25); + lookahead == ' ') ADVANCE(23); if (('0' <= lookahead && lookahead <= '9') || ('A' <= lookahead && lookahead <= 'F') || - ('a' <= lookahead && lookahead <= 'f')) ADVANCE(39); + ('a' <= lookahead && lookahead <= 'f')) ADVANCE(37); + END_STATE(); + case 4: + if (lookahead == '"') ADVANCE(29); + if (lookahead == '\\') ADVANCE(5); + if (lookahead != 0) ADVANCE(4); END_STATE(); case 5: - if (lookahead == '"') ADVANCE(31); - if (lookahead == '\\') ADVANCE(6); - if (lookahead != 0) ADVANCE(5); + if (lookahead == '"') ADVANCE(30); + if (lookahead == '\\') ADVANCE(5); + if (lookahead != 0) ADVANCE(4); END_STATE(); case 6: - if (lookahead == '"') ADVANCE(32); - if (lookahead == '\\') ADVANCE(6); - if (lookahead != 0) ADVANCE(5); + if (lookahead == '\'') ADVANCE(40); + if (lookahead == '\\') ADVANCE(7); + if (lookahead != 0) ADVANCE(6); END_STATE(); case 7: - if (lookahead == '\'') ADVANCE(42); - if (lookahead == '\\') ADVANCE(8); - if (lookahead != 0) ADVANCE(7); + if (lookahead == '\'') ADVANCE(41); + if (lookahead == '\\') ADVANCE(7); + if (lookahead != 0) ADVANCE(6); END_STATE(); case 8: - if (lookahead == '\'') ADVANCE(43); - if (lookahead == '\\') ADVANCE(8); - if (lookahead != 0) ADVANCE(7); + if (lookahead == '.') ADVANCE(9); END_STATE(); case 9: - if (lookahead == '(') ADVANCE(46); - if (lookahead == '<') ADVANCE(13); + if (lookahead == '.') ADVANCE(84); END_STATE(); case 10: - if (lookahead == '.') ADVANCE(11); + if (lookahead == ':') ADVANCE(47); END_STATE(); case 11: - if (lookahead == '.') ADVANCE(86); + if (lookahead == '<') ADVANCE(86); END_STATE(); case 12: - if (lookahead == ':') ADVANCE(49); + if (lookahead == '<') ADVANCE(11); END_STATE(); case 13: - if (lookahead == '<') ADVANCE(88); + if (lookahead == '=') ADVANCE(72); END_STATE(); case 14: - if (lookahead == '=') ADVANCE(74); + if (lookahead == '=') ADVANCE(68); END_STATE(); case 15: - if (lookahead == '=') ADVANCE(70); + if (lookahead == '>') ADVANCE(87); END_STATE(); case 16: - if (lookahead == '>') ADVANCE(89); + if (lookahead == '>') ADVANCE(15); END_STATE(); case 17: - if (lookahead == '>') ADVANCE(48); - END_STATE(); - case 18: - if (lookahead == '>') ADVANCE(16); - END_STATE(); - case 19: - if (eof) ADVANCE(23); + if (eof) ADVANCE(21); ADVANCE_MAP( - '!', 14, - '#', 24, - '&', 62, - '\'', 7, - '(', 82, - ')', 83, - '*', 57, - '+', 52, - ',', 47, - '-', 51, - '.', 44, - '/', 58, - ':', 81, - ';', 80, - '<', 72, - '=', 79, - '>', 67, - ']', 85, - '^', 64, - 't', 28, - '|', 63, + '!', 13, + '#', 22, + '&', 60, + '\'', 6, + '(', 80, + ')', 81, + '*', 55, + '+', 50, + ',', 45, + '-', 49, + '.', 42, + '/', 56, + ':', 79, + ';', 78, + '<', 70, + '=', 77, + '>', 65, + ']', 83, + '^', 62, + 't', 26, + '|', 61, + '}', 46, ); if (('\t' <= lookahead && lookahead <= '\r') || - lookahead == ' ') ADVANCE(25); + lookahead == ' ') ADVANCE(23); if (('A' <= lookahead && lookahead <= 'Z') || lookahead == '_' || - ('a' <= lookahead && lookahead <= 'z')) ADVANCE(30); + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(28); END_STATE(); - case 20: - if (eof) ADVANCE(23); + case 18: + if (eof) ADVANCE(21); ADVANCE_MAP( - '!', 14, - '#', 24, - '&', 62, - '\'', 7, - '(', 82, - ')', 83, - '*', 57, - '+', 52, - ',', 47, - '-', 51, - '.', 44, - '/', 58, - ':', 81, - ';', 80, - '<', 72, - '=', 79, - '>', 67, - ']', 85, - '^', 64, - '|', 63, - '0', 41, - '1', 41, + '!', 13, + '#', 22, + '&', 60, + '\'', 6, + '(', 80, + ')', 81, + '*', 55, + '+', 50, + ',', 45, + '-', 49, + '.', 42, + '/', 56, + ':', 79, + ';', 78, + '<', 70, + '=', 77, + '>', 65, + ']', 83, + '^', 62, + '|', 61, + '}', 46, ); if (('\t' <= lookahead && lookahead <= '\r') || - lookahead == ' ') ADVANCE(25); + lookahead == ' ') ADVANCE(23); + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(34); if (('A' <= lookahead && lookahead <= 'Z') || lookahead == '_' || - ('a' <= lookahead && lookahead <= 'z')) ADVANCE(30); + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(28); END_STATE(); - case 21: - if (eof) ADVANCE(23); + case 19: + if (eof) ADVANCE(21); ADVANCE_MAP( - '!', 14, - '#', 24, - '&', 62, - '\'', 7, - '(', 82, - ')', 83, - '*', 57, - '+', 52, - ',', 47, - '-', 50, - '.', 44, - '/', 58, - ':', 81, - ';', 80, - '<', 72, - '=', 79, - '>', 66, - ']', 85, - '^', 64, - '|', 63, + '!', 13, + '#', 22, + '&', 60, + '\'', 6, + '(', 80, + ')', 81, + '*', 55, + '+', 50, + ',', 45, + '-', 48, + '.', 42, + '/', 56, + ':', 79, + ';', 78, + '<', 70, + '=', 77, + '>', 64, + ']', 83, + '^', 62, + '|', 61, + '}', 46, + '0', 39, + '1', 39, ); if (('\t' <= lookahead && lookahead <= '\r') || - lookahead == ' ') ADVANCE(25); - if (('0' <= lookahead && lookahead <= '9')) ADVANCE(36); + lookahead == ' ') ADVANCE(23); if (('A' <= lookahead && lookahead <= 'Z') || lookahead == '_' || - ('a' <= lookahead && lookahead <= 'z')) ADVANCE(30); + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(28); END_STATE(); - case 22: - if (eof) ADVANCE(23); + case 20: + if (eof) ADVANCE(21); ADVANCE_MAP( - '!', 14, - '#', 24, - '&', 62, - '(', 82, - ')', 83, - '*', 57, - '+', 52, - ',', 47, - '-', 50, - '.', 44, - '/', 58, - ':', 81, - ';', 80, - '<', 72, - '=', 79, - '>', 66, - ']', 85, - '^', 64, - 't', 28, - '|', 63, + '!', 13, + '#', 22, + '&', 60, + '(', 80, + ')', 81, + '*', 55, + '+', 50, + ',', 45, + '-', 48, + '.', 42, + '/', 56, + ':', 79, + ';', 78, + '<', 70, + '=', 77, + '>', 64, + ']', 83, + '^', 62, + 't', 26, + '|', 61, + '}', 46, ); if (('\t' <= lookahead && lookahead <= '\r') || - lookahead == ' ') ADVANCE(25); + lookahead == ' ') ADVANCE(23); if (('A' <= lookahead && lookahead <= 'Z') || lookahead == '_' || - ('a' <= lookahead && lookahead <= 'z')) ADVANCE(30); + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(28); END_STATE(); - case 23: + case 21: ACCEPT_TOKEN(ts_builtin_sym_end); END_STATE(); - case 24: + case 22: ACCEPT_TOKEN(sym_comment); if (lookahead != 0 && - lookahead != '\n') ADVANCE(24); + lookahead != '\n') ADVANCE(22); END_STATE(); - case 25: + case 23: ACCEPT_TOKEN(sym__whitespace); END_STATE(); - case 26: + case 24: ACCEPT_TOKEN(sym_identifier); - if (lookahead == ' ') ADVANCE(78); + if (lookahead == ' ') ADVANCE(76); if (('0' <= lookahead && lookahead <= '9') || ('A' <= lookahead && lookahead <= 'Z') || lookahead == '_' || - ('a' <= lookahead && lookahead <= 'z')) ADVANCE(30); + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(28); END_STATE(); - case 27: + case 25: ACCEPT_TOKEN(sym_identifier); - if (lookahead == 'e') ADVANCE(29); + if (lookahead == 'e') ADVANCE(27); if (('0' <= lookahead && lookahead <= '9') || ('A' <= lookahead && lookahead <= 'Z') || lookahead == '_' || - ('a' <= lookahead && lookahead <= 'z')) ADVANCE(30); + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(28); END_STATE(); - case 28: + case 26: ACCEPT_TOKEN(sym_identifier); - if (lookahead == 'h') ADVANCE(27); + if (lookahead == 'h') ADVANCE(25); if (('0' <= lookahead && lookahead <= '9') || ('A' <= lookahead && lookahead <= 'Z') || lookahead == '_' || - ('a' <= lookahead && lookahead <= 'z')) ADVANCE(30); + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(28); END_STATE(); - case 29: + case 27: ACCEPT_TOKEN(sym_identifier); - if (lookahead == 'n') ADVANCE(26); + if (lookahead == 'n') ADVANCE(24); if (('0' <= lookahead && lookahead <= '9') || ('A' <= lookahead && lookahead <= 'Z') || lookahead == '_' || - ('a' <= lookahead && lookahead <= 'z')) ADVANCE(30); + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(28); END_STATE(); - case 30: + case 28: ACCEPT_TOKEN(sym_identifier); if (('0' <= lookahead && lookahead <= '9') || ('A' <= lookahead && lookahead <= 'Z') || lookahead == '_' || - ('a' <= lookahead && lookahead <= 'z')) ADVANCE(30); + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(28); END_STATE(); - case 31: + case 29: ACCEPT_TOKEN(sym_string); END_STATE(); - case 32: + case 30: ACCEPT_TOKEN(sym_string); - if (lookahead == '"') ADVANCE(31); - if (lookahead == '\\') ADVANCE(6); - if (lookahead != 0) ADVANCE(5); + if (lookahead == '"') ADVANCE(29); + if (lookahead == '\\') ADVANCE(5); + if (lookahead != 0) ADVANCE(4); END_STATE(); - case 33: + case 31: ACCEPT_TOKEN(aux_sym_base_ten_token1); - if (lookahead == 'b') ADVANCE(40); - if (lookahead == 'o') ADVANCE(37); - if (lookahead == 'x') ADVANCE(38); + if (lookahead == 'b') ADVANCE(38); + if (lookahead == 'o') ADVANCE(35); + if (lookahead == 'x') ADVANCE(36); if (lookahead == '0' || - lookahead == '1') ADVANCE(35); - if (('2' <= lookahead && lookahead <= '9')) ADVANCE(36); + lookahead == '1') ADVANCE(33); + if (('2' <= lookahead && lookahead <= '9')) ADVANCE(34); END_STATE(); - case 34: + case 32: ACCEPT_TOKEN(aux_sym_base_ten_token1); - if (lookahead == 'b') ADVANCE(40); - if (lookahead == 'o') ADVANCE(37); - if (lookahead == 'x') ADVANCE(38); - if (('0' <= lookahead && lookahead <= '9')) ADVANCE(36); + if (lookahead == 'b') ADVANCE(38); + if (lookahead == 'o') ADVANCE(35); + if (lookahead == 'x') ADVANCE(36); + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(34); END_STATE(); - case 35: + case 33: ACCEPT_TOKEN(aux_sym_base_ten_token1); if (lookahead == '0' || - lookahead == '1') ADVANCE(35); - if (('2' <= lookahead && lookahead <= '9')) ADVANCE(36); + lookahead == '1') ADVANCE(33); + if (('2' <= lookahead && lookahead <= '9')) ADVANCE(34); END_STATE(); - case 36: + case 34: ACCEPT_TOKEN(aux_sym_base_ten_token1); - if (('0' <= lookahead && lookahead <= '9')) ADVANCE(36); + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(34); END_STATE(); - case 37: + case 35: ACCEPT_TOKEN(aux_sym_octal_token1); END_STATE(); - case 38: + case 36: ACCEPT_TOKEN(aux_sym_hex_token1); END_STATE(); - case 39: + case 37: ACCEPT_TOKEN(aux_sym_hex_token2); if (('0' <= lookahead && lookahead <= '9') || ('A' <= lookahead && lookahead <= 'F') || - ('a' <= lookahead && lookahead <= 'f')) ADVANCE(39); + ('a' <= lookahead && lookahead <= 'f')) ADVANCE(37); END_STATE(); - case 40: + case 38: ACCEPT_TOKEN(aux_sym_binary_token1); END_STATE(); - case 41: + case 39: ACCEPT_TOKEN(aux_sym_binary_token2); if (lookahead == '0' || - lookahead == '1') ADVANCE(41); + lookahead == '1') ADVANCE(39); END_STATE(); - case 42: + case 40: ACCEPT_TOKEN(sym_unit_quote); END_STATE(); - case 43: + case 41: ACCEPT_TOKEN(sym_unit_quote); - if (lookahead == '\'') ADVANCE(42); - if (lookahead == '\\') ADVANCE(8); - if (lookahead != 0) ADVANCE(7); + if (lookahead == '\'') ADVANCE(40); + if (lookahead == '\\') ADVANCE(7); + if (lookahead != 0) ADVANCE(6); END_STATE(); - case 44: + case 42: ACCEPT_TOKEN(anon_sym_DOT); END_STATE(); - case 45: + case 43: ACCEPT_TOKEN(anon_sym_DOT); - if (lookahead == '.') ADVANCE(11); + if (lookahead == '.') ADVANCE(9); + END_STATE(); + case 44: + ACCEPT_TOKEN(anon_sym_LBRACE); + END_STATE(); + case 45: + ACCEPT_TOKEN(anon_sym_COMMA); END_STATE(); case 46: - ACCEPT_TOKEN(anon_sym_LT_LPAREN); + ACCEPT_TOKEN(anon_sym_RBRACE); END_STATE(); case 47: - ACCEPT_TOKEN(anon_sym_COMMA); + ACCEPT_TOKEN(anon_sym_COLON_COLON); END_STATE(); case 48: - ACCEPT_TOKEN(anon_sym_RPAREN_GT); + ACCEPT_TOKEN(anon_sym_DASH); END_STATE(); case 49: - ACCEPT_TOKEN(anon_sym_COLON_COLON); + ACCEPT_TOKEN(anon_sym_DASH); + if (lookahead == '>') ADVANCE(85); END_STATE(); case 50: - ACCEPT_TOKEN(anon_sym_DASH); + ACCEPT_TOKEN(anon_sym_PLUS); END_STATE(); case 51: - ACCEPT_TOKEN(anon_sym_DASH); - if (lookahead == '>') ADVANCE(87); + ACCEPT_TOKEN(anon_sym_BANG); END_STATE(); case 52: - ACCEPT_TOKEN(anon_sym_PLUS); + ACCEPT_TOKEN(anon_sym_BANG); + if (lookahead == '=') ADVANCE(72); END_STATE(); case 53: - ACCEPT_TOKEN(anon_sym_BANG); + ACCEPT_TOKEN(anon_sym_STAR_STAR); END_STATE(); case 54: - ACCEPT_TOKEN(anon_sym_BANG); - if (lookahead == '=') ADVANCE(74); + ACCEPT_TOKEN(anon_sym_STAR); END_STATE(); case 55: - ACCEPT_TOKEN(anon_sym_STAR_STAR); + ACCEPT_TOKEN(anon_sym_STAR); + if (lookahead == '*') ADVANCE(53); END_STATE(); case 56: - ACCEPT_TOKEN(anon_sym_STAR); + ACCEPT_TOKEN(anon_sym_SLASH); END_STATE(); case 57: - ACCEPT_TOKEN(anon_sym_STAR); - if (lookahead == '*') ADVANCE(55); + ACCEPT_TOKEN(anon_sym_LT_LT); END_STATE(); case 58: - ACCEPT_TOKEN(anon_sym_SLASH); + ACCEPT_TOKEN(anon_sym_GT_GT); END_STATE(); case 59: - ACCEPT_TOKEN(anon_sym_LT_LT); + ACCEPT_TOKEN(anon_sym_GT_GT); + if (lookahead == '>') ADVANCE(87); END_STATE(); case 60: - ACCEPT_TOKEN(anon_sym_GT_GT); + ACCEPT_TOKEN(anon_sym_AMP); + if (lookahead == '&') ADVANCE(73); END_STATE(); case 61: - ACCEPT_TOKEN(anon_sym_GT_GT); - if (lookahead == '>') ADVANCE(89); + ACCEPT_TOKEN(anon_sym_PIPE); + if (lookahead == '|') ADVANCE(74); END_STATE(); case 62: - ACCEPT_TOKEN(anon_sym_AMP); - if (lookahead == '&') ADVANCE(75); + ACCEPT_TOKEN(anon_sym_CARET); + if (lookahead == '^') ADVANCE(75); END_STATE(); case 63: - ACCEPT_TOKEN(anon_sym_PIPE); - if (lookahead == '|') ADVANCE(76); + ACCEPT_TOKEN(anon_sym_GT); + if (lookahead == '=') ADVANCE(67); END_STATE(); case 64: - ACCEPT_TOKEN(anon_sym_CARET); - if (lookahead == '^') ADVANCE(77); + ACCEPT_TOKEN(anon_sym_GT); + if (lookahead == '=') ADVANCE(67); + if (lookahead == '>') ADVANCE(59); END_STATE(); case 65: ACCEPT_TOKEN(anon_sym_GT); - if (lookahead == '=') ADVANCE(69); + if (lookahead == '=') ADVANCE(67); + if (lookahead == '>') ADVANCE(58); END_STATE(); case 66: ACCEPT_TOKEN(anon_sym_GT); - if (lookahead == '=') ADVANCE(69); - if (lookahead == '>') ADVANCE(61); + if (lookahead == '=') ADVANCE(67); + if (lookahead == '>') ADVANCE(15); END_STATE(); case 67: - ACCEPT_TOKEN(anon_sym_GT); - if (lookahead == '=') ADVANCE(69); - if (lookahead == '>') ADVANCE(60); - END_STATE(); - case 68: - ACCEPT_TOKEN(anon_sym_GT); - if (lookahead == '=') ADVANCE(69); - if (lookahead == '>') ADVANCE(16); - END_STATE(); - case 69: ACCEPT_TOKEN(anon_sym_GT_EQ); END_STATE(); - case 70: + case 68: ACCEPT_TOKEN(anon_sym_EQ_EQ); END_STATE(); - case 71: + case 69: ACCEPT_TOKEN(anon_sym_LT_EQ); END_STATE(); - case 72: + case 70: ACCEPT_TOKEN(anon_sym_LT); - if (lookahead == '<') ADVANCE(59); - if (lookahead == '=') ADVANCE(71); + if (lookahead == '<') ADVANCE(57); + if (lookahead == '=') ADVANCE(69); END_STATE(); - case 73: + case 71: ACCEPT_TOKEN(anon_sym_LT); - if (lookahead == '=') ADVANCE(71); + if (lookahead == '=') ADVANCE(69); END_STATE(); - case 74: + case 72: ACCEPT_TOKEN(anon_sym_BANG_EQ); END_STATE(); - case 75: + case 73: ACCEPT_TOKEN(anon_sym_AMP_AMP); END_STATE(); - case 76: + case 74: ACCEPT_TOKEN(anon_sym_PIPE_PIPE); END_STATE(); - case 77: + case 75: ACCEPT_TOKEN(anon_sym_CARET_CARET); END_STATE(); - case 78: + case 76: ACCEPT_TOKEN(anon_sym_then); END_STATE(); - case 79: + case 77: ACCEPT_TOKEN(anon_sym_EQ); - if (lookahead == '=') ADVANCE(70); + if (lookahead == '=') ADVANCE(68); END_STATE(); - case 80: + case 78: ACCEPT_TOKEN(anon_sym_SEMI); END_STATE(); - case 81: + case 79: ACCEPT_TOKEN(anon_sym_COLON); - if (lookahead == ':') ADVANCE(49); + if (lookahead == ':') ADVANCE(47); END_STATE(); - case 82: + case 80: ACCEPT_TOKEN(anon_sym_LPAREN); END_STATE(); - case 83: + case 81: ACCEPT_TOKEN(anon_sym_RPAREN); END_STATE(); - case 84: + case 82: ACCEPT_TOKEN(anon_sym_LBRACK); END_STATE(); - case 85: + case 83: ACCEPT_TOKEN(anon_sym_RBRACK); END_STATE(); - case 86: + case 84: ACCEPT_TOKEN(sym_varadic_dots); END_STATE(); - case 87: + case 85: ACCEPT_TOKEN(anon_sym_DASH_GT); END_STATE(); - case 88: + case 86: ACCEPT_TOKEN(anon_sym_LT_LT_LT); END_STATE(); - case 89: + case 87: ACCEPT_TOKEN(anon_sym_GT_GT_GT); END_STATE(); default: @@ -2033,276 +1906,173 @@ static const TSLexerMode ts_lex_modes[STATE_COUNT] = { [49] = {.lex_state = 1}, [50] = {.lex_state = 1}, [51] = {.lex_state = 1}, - [52] = {.lex_state = 1}, - [53] = {.lex_state = 1}, - [54] = {.lex_state = 1}, - [55] = {.lex_state = 1}, - [56] = {.lex_state = 1}, - [57] = {.lex_state = 1}, - [58] = {.lex_state = 1}, - [59] = {.lex_state = 1}, - [60] = {.lex_state = 1}, - [61] = {.lex_state = 1}, - [62] = {.lex_state = 1}, - [63] = {.lex_state = 1}, - [64] = {.lex_state = 1}, - [65] = {.lex_state = 1}, - [66] = {.lex_state = 1}, - [67] = {.lex_state = 1}, - [68] = {.lex_state = 1}, - [69] = {.lex_state = 1}, - [70] = {.lex_state = 1}, - [71] = {.lex_state = 1}, - [72] = {.lex_state = 1}, - [73] = {.lex_state = 1}, - [74] = {.lex_state = 1}, - [75] = {.lex_state = 1}, - [76] = {.lex_state = 1}, - [77] = {.lex_state = 1}, - [78] = {.lex_state = 21}, - [79] = {.lex_state = 20}, - [80] = {.lex_state = 21}, - [81] = {.lex_state = 21}, - [82] = {.lex_state = 21}, - [83] = {.lex_state = 19}, - [84] = {.lex_state = 19}, - [85] = {.lex_state = 19}, - [86] = {.lex_state = 19}, - [87] = {.lex_state = 19}, - [88] = {.lex_state = 22}, - [89] = {.lex_state = 19}, - [90] = {.lex_state = 19}, - [91] = {.lex_state = 19}, - [92] = {.lex_state = 20}, - [93] = {.lex_state = 19}, - [94] = {.lex_state = 20}, - [95] = {.lex_state = 20}, - [96] = {.lex_state = 20}, - [97] = {.lex_state = 20}, - [98] = {.lex_state = 20}, - [99] = {.lex_state = 20}, - [100] = {.lex_state = 20}, - [101] = {.lex_state = 20}, - [102] = {.lex_state = 20}, - [103] = {.lex_state = 19}, - [104] = {.lex_state = 20}, - [105] = {.lex_state = 19}, - [106] = {.lex_state = 19}, - [107] = {.lex_state = 19}, - [108] = {.lex_state = 19}, - [109] = {.lex_state = 19}, - [110] = {.lex_state = 19}, - [111] = {.lex_state = 19}, - [112] = {.lex_state = 20}, - [113] = {.lex_state = 19}, - [114] = {.lex_state = 20}, - [115] = {.lex_state = 20}, - [116] = {.lex_state = 20}, - [117] = {.lex_state = 19}, - [118] = {.lex_state = 19}, - [119] = {.lex_state = 19}, - [120] = {.lex_state = 19}, - [121] = {.lex_state = 19}, - [122] = {.lex_state = 20}, - [123] = {.lex_state = 19}, - [124] = {.lex_state = 2}, - [125] = {.lex_state = 2}, - [126] = {.lex_state = 19}, - [127] = {.lex_state = 20}, - [128] = {.lex_state = 2}, - [129] = {.lex_state = 2}, - [130] = {.lex_state = 19}, - [131] = {.lex_state = 20}, - [132] = {.lex_state = 2}, - [133] = {.lex_state = 2}, - [134] = {.lex_state = 2}, - [135] = {.lex_state = 2}, - [136] = {.lex_state = 2}, - [137] = {.lex_state = 2}, - [138] = {.lex_state = 2}, - [139] = {.lex_state = 2}, - [140] = {.lex_state = 20}, - [141] = {.lex_state = 19}, + [52] = {.lex_state = 18}, + [53] = {.lex_state = 19}, + [54] = {.lex_state = 19}, + [55] = {.lex_state = 19}, + [56] = {.lex_state = 19}, + [57] = {.lex_state = 17}, + [58] = {.lex_state = 17}, + [59] = {.lex_state = 17}, + [60] = {.lex_state = 20}, + [61] = {.lex_state = 17}, + [62] = {.lex_state = 17}, + [63] = {.lex_state = 18}, + [64] = {.lex_state = 18}, + [65] = {.lex_state = 18}, + [66] = {.lex_state = 17}, + [67] = {.lex_state = 18}, + [68] = {.lex_state = 17}, + [69] = {.lex_state = 17}, + [70] = {.lex_state = 18}, + [71] = {.lex_state = 17}, + [72] = {.lex_state = 17}, + [73] = {.lex_state = 17}, + [74] = {.lex_state = 18}, + [75] = {.lex_state = 18}, + [76] = {.lex_state = 17}, + [77] = {.lex_state = 17}, + [78] = {.lex_state = 17}, + [79] = {.lex_state = 17}, + [80] = {.lex_state = 17}, + [81] = {.lex_state = 17}, + [82] = {.lex_state = 17}, + [83] = {.lex_state = 17}, + [84] = {.lex_state = 17}, + [85] = {.lex_state = 18}, + [86] = {.lex_state = 17}, + [87] = {.lex_state = 18}, + [88] = {.lex_state = 18}, + [89] = {.lex_state = 18}, + [90] = {.lex_state = 18}, + [91] = {.lex_state = 18}, + [92] = {.lex_state = 17}, + [93] = {.lex_state = 18}, + [94] = {.lex_state = 18}, + [95] = {.lex_state = 18}, + [96] = {.lex_state = 17}, + [97] = {.lex_state = 17}, + [98] = {.lex_state = 17}, + [99] = {.lex_state = 17}, + [100] = {.lex_state = 18}, + [101] = {.lex_state = 18}, + [102] = {.lex_state = 17}, + [103] = {.lex_state = 17}, + [104] = {.lex_state = 17}, + [105] = {.lex_state = 18}, + [106] = {.lex_state = 18}, + [107] = {.lex_state = 18}, + [108] = {.lex_state = 18}, + [109] = {.lex_state = 18}, + [110] = {.lex_state = 18}, + [111] = {.lex_state = 17}, + [112] = {.lex_state = 17}, + [113] = {.lex_state = 18}, + [114] = {.lex_state = 18}, + [115] = {.lex_state = 18}, + [116] = {.lex_state = 18}, + [117] = {.lex_state = 18}, + [118] = {.lex_state = 18}, + [119] = {.lex_state = 17}, + [120] = {.lex_state = 17}, + [121] = {.lex_state = 17}, + [122] = {.lex_state = 17}, + [123] = {.lex_state = 17}, + [124] = {.lex_state = 17}, + [125] = {.lex_state = 17}, + [126] = {.lex_state = 17}, + [127] = {.lex_state = 17}, + [128] = {.lex_state = 17}, + [129] = {.lex_state = 17}, + [130] = {.lex_state = 18}, + [131] = {.lex_state = 17}, + [132] = {.lex_state = 17}, + [133] = {.lex_state = 17}, + [134] = {.lex_state = 18}, + [135] = {.lex_state = 18}, + [136] = {.lex_state = 18}, + [137] = {.lex_state = 17}, + [138] = {.lex_state = 17}, + [139] = {.lex_state = 1}, + [140] = {.lex_state = 2}, + [141] = {.lex_state = 2}, [142] = {.lex_state = 2}, - [143] = {.lex_state = 2}, - [144] = {.lex_state = 2}, - [145] = {.lex_state = 2}, - [146] = {.lex_state = 2}, - [147] = {.lex_state = 20}, - [148] = {.lex_state = 2}, - [149] = {.lex_state = 2}, - [150] = {.lex_state = 20}, - [151] = {.lex_state = 20}, - [152] = {.lex_state = 20}, - [153] = {.lex_state = 2}, - [154] = {.lex_state = 2}, - [155] = {.lex_state = 2}, - [156] = {.lex_state = 19}, - [157] = {.lex_state = 19}, + [143] = {.lex_state = 3}, + [144] = {.lex_state = 3}, + [145] = {.lex_state = 18}, + [146] = {.lex_state = 18}, + [147] = {.lex_state = 18}, + [148] = {.lex_state = 18}, + [149] = {.lex_state = 18}, + [150] = {.lex_state = 18}, + [151] = {.lex_state = 2}, + [152] = {.lex_state = 18}, + [153] = {.lex_state = 18}, + [154] = {.lex_state = 18}, + [155] = {.lex_state = 3}, + [156] = {.lex_state = 3}, + [157] = {.lex_state = 18}, [158] = {.lex_state = 2}, [159] = {.lex_state = 2}, [160] = {.lex_state = 2}, [161] = {.lex_state = 2}, - [162] = {.lex_state = 2}, - [163] = {.lex_state = 2}, - [164] = {.lex_state = 2}, - [165] = {.lex_state = 2}, - [166] = {.lex_state = 20}, - [167] = {.lex_state = 20}, - [168] = {.lex_state = 2}, - [169] = {.lex_state = 2}, - [170] = {.lex_state = 2}, - [171] = {.lex_state = 19}, - [172] = {.lex_state = 2}, - [173] = {.lex_state = 19}, - [174] = {.lex_state = 2}, - [175] = {.lex_state = 20}, - [176] = {.lex_state = 2}, - [177] = {.lex_state = 2}, - [178] = {.lex_state = 20}, - [179] = {.lex_state = 2}, - [180] = {.lex_state = 19}, - [181] = {.lex_state = 19}, - [182] = {.lex_state = 19}, - [183] = {.lex_state = 19}, - [184] = {.lex_state = 19}, - [185] = {.lex_state = 19}, - [186] = {.lex_state = 19}, - [187] = {.lex_state = 19}, - [188] = {.lex_state = 19}, - [189] = {.lex_state = 19}, - [190] = {.lex_state = 2}, - [191] = {.lex_state = 19}, - [192] = {.lex_state = 2}, - [193] = {.lex_state = 20}, - [194] = {.lex_state = 2}, - [195] = {.lex_state = 2}, - [196] = {.lex_state = 20}, - [197] = {.lex_state = 2}, - [198] = {.lex_state = 2}, - [199] = {.lex_state = 19}, - [200] = {.lex_state = 19}, - [201] = {.lex_state = 2}, - [202] = {.lex_state = 2}, - [203] = {.lex_state = 2}, - [204] = {.lex_state = 2}, - [205] = {.lex_state = 20}, - [206] = {.lex_state = 20}, - [207] = {.lex_state = 19}, - [208] = {.lex_state = 20}, - [209] = {.lex_state = 20}, - [210] = {.lex_state = 20}, - [211] = {.lex_state = 2}, - [212] = {.lex_state = 20}, - [213] = {.lex_state = 2}, - [214] = {.lex_state = 2}, - [215] = {.lex_state = 2}, - [216] = {.lex_state = 19}, - [217] = {.lex_state = 20}, - [218] = {.lex_state = 19}, - [219] = {.lex_state = 19}, - [220] = {.lex_state = 20}, - [221] = {.lex_state = 1}, - [222] = {.lex_state = 3}, - [223] = {.lex_state = 3}, - [224] = {.lex_state = 3}, - [225] = {.lex_state = 21}, - [226] = {.lex_state = 21}, - [227] = {.lex_state = 4}, - [228] = {.lex_state = 21}, - [229] = {.lex_state = 21}, - [230] = {.lex_state = 21}, - [231] = {.lex_state = 4}, - [232] = {.lex_state = 21}, - [233] = {.lex_state = 4}, - [234] = {.lex_state = 21}, - [235] = {.lex_state = 21}, - [236] = {.lex_state = 21}, - [237] = {.lex_state = 4}, - [238] = {.lex_state = 3}, - [239] = {.lex_state = 21}, - [240] = {.lex_state = 21}, - [241] = {.lex_state = 21}, - [242] = {.lex_state = 3}, - [243] = {.lex_state = 3}, - [244] = {.lex_state = 3}, - [245] = {.lex_state = 3}, - [246] = {.lex_state = 3}, - [247] = {.lex_state = 1}, - [248] = {.lex_state = 1}, - [249] = {.lex_state = 0}, - [250] = {.lex_state = 0}, - [251] = {.lex_state = 1}, - [252] = {.lex_state = 1}, - [253] = {.lex_state = 1}, - [254] = {.lex_state = 1}, - [255] = {.lex_state = 1}, - [256] = {.lex_state = 1}, - [257] = {.lex_state = 1}, - [258] = {.lex_state = 1}, - [259] = {.lex_state = 1}, - [260] = {.lex_state = 1}, - [261] = {.lex_state = 1}, - [262] = {.lex_state = 1}, - [263] = {.lex_state = 1}, - [264] = {.lex_state = 0}, - [265] = {.lex_state = 1}, - [266] = {.lex_state = 0}, - [267] = {.lex_state = 1}, - [268] = {.lex_state = 1}, - [269] = {.lex_state = 1}, - [270] = {.lex_state = 1}, - [271] = {.lex_state = 1}, - [272] = {.lex_state = 0}, - [273] = {.lex_state = 0}, - [274] = {.lex_state = 1}, - [275] = {.lex_state = 0}, - [276] = {.lex_state = 1}, - [277] = {.lex_state = 0}, - [278] = {.lex_state = 1}, - [279] = {.lex_state = 21}, - [280] = {.lex_state = 1}, - [281] = {.lex_state = 0}, - [282] = {.lex_state = 1}, - [283] = {.lex_state = 0}, - [284] = {.lex_state = 1}, - [285] = {.lex_state = 1}, - [286] = {.lex_state = 0}, - [287] = {.lex_state = 0}, - [288] = {.lex_state = 21}, - [289] = {.lex_state = 0}, - [290] = {.lex_state = 0}, - [291] = {.lex_state = 21}, - [292] = {.lex_state = 21}, - [293] = {.lex_state = 1}, - [294] = {.lex_state = 0}, - [295] = {.lex_state = 1}, - [296] = {.lex_state = 1}, - [297] = {.lex_state = 0}, - [298] = {.lex_state = 1}, - [299] = {.lex_state = 1}, - [300] = {.lex_state = 0}, - [301] = {.lex_state = 0}, - [302] = {.lex_state = 1}, - [303] = {.lex_state = 4}, - [304] = {.lex_state = 20}, - [305] = {.lex_state = 21}, - [306] = {.lex_state = 1}, - [307] = {.lex_state = 0}, - [308] = {.lex_state = 0}, - [309] = {.lex_state = 1}, - [310] = {.lex_state = 0}, - [311] = {.lex_state = 0}, - [312] = {.lex_state = 1}, - [313] = {.lex_state = 0}, - [314] = {.lex_state = 0}, - [315] = {.lex_state = 0}, - [316] = {.lex_state = 1}, - [317] = {.lex_state = 1}, - [318] = {.lex_state = 0}, - [319] = {.lex_state = 0}, - [320] = {.lex_state = 0}, - [321] = {.lex_state = 0}, + [162] = {.lex_state = 1}, + [163] = {.lex_state = 1}, + [164] = {.lex_state = 1}, + [165] = {.lex_state = 0}, + [166] = {.lex_state = 0}, + [167] = {.lex_state = 1}, + [168] = {.lex_state = 1}, + [169] = {.lex_state = 1}, + [170] = {.lex_state = 1}, + [171] = {.lex_state = 1}, + [172] = {.lex_state = 1}, + [173] = {.lex_state = 1}, + [174] = {.lex_state = 0}, + [175] = {.lex_state = 1}, + [176] = {.lex_state = 0}, + [177] = {.lex_state = 1}, + [178] = {.lex_state = 0}, + [179] = {.lex_state = 1}, + [180] = {.lex_state = 1}, + [181] = {.lex_state = 0}, + [182] = {.lex_state = 1}, + [183] = {.lex_state = 1}, + [184] = {.lex_state = 1}, + [185] = {.lex_state = 0}, + [186] = {.lex_state = 18}, + [187] = {.lex_state = 1}, + [188] = {.lex_state = 0}, + [189] = {.lex_state = 1}, + [190] = {.lex_state = 0}, + [191] = {.lex_state = 1}, + [192] = {.lex_state = 1}, + [193] = {.lex_state = 0}, + [194] = {.lex_state = 1}, + [195] = {.lex_state = 18}, + [196] = {.lex_state = 1}, + [197] = {.lex_state = 0}, + [198] = {.lex_state = 18}, + [199] = {.lex_state = 0}, + [200] = {.lex_state = 1}, + [201] = {.lex_state = 0}, + [202] = {.lex_state = 1}, + [203] = {.lex_state = 1}, + [204] = {.lex_state = 3}, + [205] = {.lex_state = 19}, + [206] = {.lex_state = 0}, + [207] = {.lex_state = 0}, + [208] = {.lex_state = 0}, + [209] = {.lex_state = 0}, + [210] = {.lex_state = 18}, + [211] = {.lex_state = 0}, + [212] = {.lex_state = 0}, + [213] = {.lex_state = 0}, + [214] = {.lex_state = 0}, + [215] = {.lex_state = 1}, + [216] = {.lex_state = 1}, + [217] = {.lex_state = 0}, + [218] = {.lex_state = 0}, }; static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = { @@ -2322,7 +2092,9 @@ static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = { [aux_sym_unsigned_integer_token1] = ACTIONS(1), [sym_unit_quote] = ACTIONS(1), [anon_sym_DOT] = ACTIONS(1), + [anon_sym_LBRACE] = ACTIONS(1), [anon_sym_COMMA] = ACTIONS(1), + [anon_sym_RBRACE] = ACTIONS(1), [sym_true] = ACTIONS(1), [sym_false] = ACTIONS(1), [anon_sym_COLON_COLON] = ACTIONS(1), @@ -2363,35 +2135,35 @@ static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = { [anon_sym_GT_GT_GT] = ACTIONS(1), }, [STATE(1)] = { - [sym_source_file] = STATE(319), - [sym_base_ten] = STATE(284), - [sym_octal] = STATE(284), - [sym_hex] = STATE(284), - [sym_binary] = STATE(284), - [sym_integer] = STATE(298), - [sym_signed_integer] = STATE(109), - [sym_unsigned_integer] = STATE(109), - [sym_number] = STATE(80), - [sym__float] = STATE(78), - [sym_scalar] = STATE(109), - [sym_vector2] = STATE(109), - [sym_vector3] = STATE(109), - [sym_vector4] = STATE(109), - [sym_boolean] = STATE(109), - [sym_function_call] = STATE(109), - [sym_method_call] = STATE(109), - [sym_expression] = STATE(206), - [sym_unary_expression] = STATE(109), - [sym_binary_expression] = STATE(109), - [sym_if] = STATE(109), - [sym_let_in] = STATE(109), - [sym_member_access] = STATE(109), - [sym_parenthesis] = STATE(109), - [sym_list] = STATE(109), - [sym_struct_definition] = STATE(112), - [sym_dictionary_construction] = STATE(109), - [sym_closure_definition] = STATE(109), - [sym_constraint_set] = STATE(109), + [sym_source_file] = STATE(212), + [sym_base_ten] = STATE(200), + [sym_octal] = STATE(200), + [sym_hex] = STATE(200), + [sym_binary] = STATE(200), + [sym_integer] = STATE(189), + [sym_signed_integer] = STATE(92), + [sym_unsigned_integer] = STATE(92), + [sym_number] = STATE(55), + [sym__float] = STATE(53), + [sym_scalar] = STATE(92), + [sym_vector2] = STATE(92), + [sym_vector3] = STATE(92), + [sym_vector4] = STATE(92), + [sym_boolean] = STATE(92), + [sym_function_call] = STATE(92), + [sym_method_call] = STATE(92), + [sym_expression] = STATE(114), + [sym_unary_expression] = STATE(92), + [sym_binary_expression] = STATE(92), + [sym_if] = STATE(92), + [sym_let_in] = STATE(92), + [sym_member_access] = STATE(92), + [sym_parenthesis] = STATE(92), + [sym_list] = STATE(92), + [sym_struct_definition] = STATE(67), + [sym_dictionary_construction] = STATE(92), + [sym_closure_definition] = STATE(92), + [sym_constraint_set] = STATE(92), [sym_identifier] = ACTIONS(5), [sym_comment] = ACTIONS(3), [sym__whitespace] = ACTIONS(3), @@ -2401,7 +2173,7 @@ static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = { [aux_sym_octal_token1] = ACTIONS(11), [aux_sym_hex_token1] = ACTIONS(13), [aux_sym_binary_token1] = ACTIONS(15), - [anon_sym_LT_LPAREN] = ACTIONS(17), + [anon_sym_LBRACE] = ACTIONS(17), [sym_true] = ACTIONS(19), [sym_false] = ACTIONS(19), [anon_sym_DASH] = ACTIONS(21), @@ -2414,38 +2186,38 @@ static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = { [anon_sym_LT_LT_LT] = ACTIONS(31), }, [STATE(2)] = { - [sym_base_ten] = STATE(284), - [sym_octal] = STATE(284), - [sym_hex] = STATE(284), - [sym_binary] = STATE(284), - [sym_integer] = STATE(298), - [sym_signed_integer] = STATE(109), - [sym_unsigned_integer] = STATE(109), - [sym_number] = STATE(80), - [sym__float] = STATE(78), - [sym_scalar] = STATE(109), - [sym_vector2] = STATE(109), - [sym_vector3] = STATE(109), - [sym_vector4] = STATE(109), - [sym_boolean] = STATE(109), - [sym_function_call] = STATE(109), - [sym_method_call] = STATE(109), - [sym_expression] = STATE(175), - [sym_unary_expression] = STATE(109), - [sym_binary_expression] = STATE(109), - [sym_if] = STATE(109), - [sym_let_in] = STATE(109), - [sym_member_access] = STATE(109), - [sym_parenthesis] = STATE(109), - [sym_list] = STATE(109), - [sym_struct_member] = STATE(283), - [sym__struct_final_element] = STATE(310), - [sym_struct_definition] = STATE(112), - [sym_dictionary_member_assignment] = STATE(273), - [sym_dictionary_construction] = STATE(109), - [sym_closure_definition] = STATE(109), - [sym_constraint_set] = STATE(109), - [aux_sym_struct_definition_repeat1] = STATE(252), + [sym_base_ten] = STATE(200), + [sym_octal] = STATE(200), + [sym_hex] = STATE(200), + [sym_binary] = STATE(200), + [sym_integer] = STATE(189), + [sym_signed_integer] = STATE(92), + [sym_unsigned_integer] = STATE(92), + [sym_number] = STATE(55), + [sym__float] = STATE(53), + [sym_scalar] = STATE(92), + [sym_vector2] = STATE(92), + [sym_vector3] = STATE(92), + [sym_vector4] = STATE(92), + [sym_boolean] = STATE(92), + [sym_function_call] = STATE(92), + [sym_method_call] = STATE(92), + [sym_expression] = STATE(130), + [sym_unary_expression] = STATE(92), + [sym_binary_expression] = STATE(92), + [sym_if] = STATE(92), + [sym_let_in] = STATE(92), + [sym_member_access] = STATE(92), + [sym_parenthesis] = STATE(92), + [sym_list] = STATE(92), + [sym_struct_member] = STATE(199), + [sym__struct_final_element] = STATE(218), + [sym_struct_definition] = STATE(67), + [sym_dictionary_member_assignment] = STATE(174), + [sym_dictionary_construction] = STATE(92), + [sym_closure_definition] = STATE(92), + [sym_constraint_set] = STATE(92), + [aux_sym_struct_definition_repeat1] = STATE(164), [sym_identifier] = ACTIONS(33), [sym_comment] = ACTIONS(3), [sym__whitespace] = ACTIONS(3), @@ -2455,7 +2227,7 @@ static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = { [aux_sym_octal_token1] = ACTIONS(11), [aux_sym_hex_token1] = ACTIONS(13), [aux_sym_binary_token1] = ACTIONS(15), - [anon_sym_LT_LPAREN] = ACTIONS(17), + [anon_sym_LBRACE] = ACTIONS(17), [sym_true] = ACTIONS(19), [sym_false] = ACTIONS(19), [anon_sym_DASH] = ACTIONS(21), @@ -2469,62 +2241,6 @@ static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = { [sym_varadic_dots] = ACTIONS(37), [anon_sym_LT_LT_LT] = ACTIONS(31), }, - [STATE(3)] = { - [sym_base_ten] = STATE(284), - [sym_octal] = STATE(284), - [sym_hex] = STATE(284), - [sym_binary] = STATE(284), - [sym_integer] = STATE(298), - [sym_signed_integer] = STATE(109), - [sym_unsigned_integer] = STATE(109), - [sym_number] = STATE(80), - [sym__float] = STATE(78), - [sym_scalar] = STATE(109), - [sym_vector2] = STATE(109), - [sym_vector3] = STATE(109), - [sym_vector4] = STATE(109), - [sym_boolean] = STATE(109), - [sym_function_call] = STATE(109), - [sym_method_call] = STATE(109), - [sym_expression] = STATE(208), - [sym_unary_expression] = STATE(109), - [sym_binary_expression] = STATE(109), - [sym_if] = STATE(109), - [sym_let_in] = STATE(109), - [sym_member_access] = STATE(109), - [sym_parenthesis] = STATE(109), - [sym_list] = STATE(109), - [sym_struct_member] = STATE(283), - [sym__struct_final_element] = STATE(314), - [sym_struct_definition] = STATE(112), - [sym_dictionary_member_assignment] = STATE(275), - [sym_dictionary_construction] = STATE(109), - [sym_closure_definition] = STATE(109), - [sym_constraint_set] = STATE(109), - [aux_sym_struct_definition_repeat1] = STATE(253), - [sym_identifier] = ACTIONS(33), - [sym_comment] = ACTIONS(3), - [sym__whitespace] = ACTIONS(3), - [sym_string] = ACTIONS(7), - [sym_self] = ACTIONS(5), - [aux_sym_base_ten_token1] = ACTIONS(9), - [aux_sym_octal_token1] = ACTIONS(11), - [aux_sym_hex_token1] = ACTIONS(13), - [aux_sym_binary_token1] = ACTIONS(15), - [anon_sym_LT_LPAREN] = ACTIONS(17), - [sym_true] = ACTIONS(19), - [sym_false] = ACTIONS(19), - [anon_sym_DASH] = ACTIONS(21), - [anon_sym_PLUS] = ACTIONS(21), - [anon_sym_BANG] = ACTIONS(21), - [anon_sym_if] = ACTIONS(23), - [anon_sym_let] = ACTIONS(25), - [anon_sym_LPAREN] = ACTIONS(27), - [anon_sym_RPAREN] = ACTIONS(39), - [anon_sym_LBRACK] = ACTIONS(29), - [sym_varadic_dots] = ACTIONS(37), - [anon_sym_LT_LT_LT] = ACTIONS(31), - }, }; static const uint16_t ts_small_parse_table[] = { @@ -2540,7 +2256,7 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(23), 1, anon_sym_if, ACTIONS(25), 1, @@ -2551,19 +2267,19 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(41), 1, + ACTIONS(39), 1, anon_sym_RBRACK, - STATE(8), 1, + STATE(4), 1, aux_sym_list_repeat1, - STATE(78), 1, + STATE(53), 1, sym__float, - STATE(80), 1, + STATE(55), 1, sym_number, - STATE(112), 1, + STATE(67), 1, sym_struct_definition, - STATE(140), 1, + STATE(106), 1, sym_expression, - STATE(298), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -2578,12 +2294,12 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -2615,7 +2331,7 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(23), 1, anon_sym_if, ACTIONS(25), 1, @@ -2626,19 +2342,19 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(43), 1, + ACTIONS(41), 1, anon_sym_RBRACK, - STATE(4), 1, + STATE(5), 1, aux_sym_list_repeat1, - STATE(78), 1, + STATE(53), 1, sym__float, - STATE(80), 1, + STATE(55), 1, sym_number, - STATE(112), 1, + STATE(67), 1, sym_struct_definition, - STATE(166), 1, + STATE(107), 1, sym_expression, - STATE(298), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -2653,12 +2369,12 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -2679,61 +2395,61 @@ static const uint16_t ts_small_parse_table[] = { sym_closure_definition, sym_constraint_set, [198] = 24, - ACTIONS(7), 1, + ACTIONS(46), 1, sym_string, - ACTIONS(9), 1, + ACTIONS(49), 1, aux_sym_base_ten_token1, - ACTIONS(11), 1, + ACTIONS(52), 1, aux_sym_octal_token1, - ACTIONS(13), 1, + ACTIONS(55), 1, aux_sym_hex_token1, - ACTIONS(15), 1, + ACTIONS(58), 1, aux_sym_binary_token1, - ACTIONS(17), 1, - anon_sym_LT_LPAREN, - ACTIONS(23), 1, + ACTIONS(61), 1, + anon_sym_LBRACE, + ACTIONS(70), 1, anon_sym_if, - ACTIONS(25), 1, + ACTIONS(73), 1, anon_sym_let, - ACTIONS(27), 1, + ACTIONS(76), 1, anon_sym_LPAREN, - ACTIONS(29), 1, + ACTIONS(79), 1, anon_sym_LBRACK, - ACTIONS(31), 1, - anon_sym_LT_LT_LT, - ACTIONS(45), 1, + ACTIONS(82), 1, anon_sym_RBRACK, - STATE(7), 1, + ACTIONS(84), 1, + anon_sym_LT_LT_LT, + STATE(5), 1, aux_sym_list_repeat1, - STATE(78), 1, + STATE(53), 1, sym__float, - STATE(80), 1, + STATE(55), 1, sym_number, - STATE(112), 1, + STATE(67), 1, sym_struct_definition, - STATE(150), 1, + STATE(113), 1, sym_expression, - STATE(298), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(5), 2, + ACTIONS(43), 2, sym_identifier, sym_self, - ACTIONS(19), 2, + ACTIONS(64), 2, sym_true, sym_false, - ACTIONS(21), 3, + ACTIONS(67), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -2753,11 +2469,9 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [297] = 24, + [297] = 22, ACTIONS(7), 1, sym_string, - ACTIONS(9), 1, - aux_sym_base_ten_token1, ACTIONS(11), 1, aux_sym_octal_token1, ACTIONS(13), 1, @@ -2765,30 +2479,28 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, - ACTIONS(23), 1, - anon_sym_if, - ACTIONS(25), 1, - anon_sym_let, + anon_sym_LBRACE, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(47), 1, - anon_sym_RBRACK, - STATE(8), 1, - aux_sym_list_repeat1, - STATE(78), 1, + ACTIONS(87), 1, + aux_sym_base_ten_token1, + ACTIONS(91), 1, + anon_sym_if, + ACTIONS(93), 1, + anon_sym_let, + STATE(99), 1, sym__float, - STATE(80), 1, + STATE(102), 1, sym_number, - STATE(112), 1, - sym_struct_definition, - STATE(152), 1, + STATE(123), 1, sym_expression, - STATE(298), 1, + STATE(137), 1, + sym_struct_definition, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -2799,16 +2511,16 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(21), 3, + ACTIONS(89), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -2828,62 +2540,58 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [396] = 24, - ACTIONS(52), 1, + [390] = 22, + ACTIONS(7), 1, sym_string, - ACTIONS(55), 1, - aux_sym_base_ten_token1, - ACTIONS(58), 1, + ACTIONS(11), 1, aux_sym_octal_token1, - ACTIONS(61), 1, + ACTIONS(13), 1, aux_sym_hex_token1, - ACTIONS(64), 1, + ACTIONS(15), 1, aux_sym_binary_token1, - ACTIONS(67), 1, - anon_sym_LT_LPAREN, - ACTIONS(76), 1, - anon_sym_if, - ACTIONS(79), 1, - anon_sym_let, - ACTIONS(82), 1, + ACTIONS(17), 1, + anon_sym_LBRACE, + ACTIONS(27), 1, anon_sym_LPAREN, - ACTIONS(85), 1, + ACTIONS(29), 1, anon_sym_LBRACK, - ACTIONS(88), 1, - anon_sym_RBRACK, - ACTIONS(90), 1, + ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(8), 1, - aux_sym_list_repeat1, - STATE(78), 1, + ACTIONS(87), 1, + aux_sym_base_ten_token1, + ACTIONS(91), 1, + anon_sym_if, + ACTIONS(93), 1, + anon_sym_let, + STATE(99), 1, sym__float, - STATE(80), 1, + STATE(102), 1, sym_number, STATE(112), 1, - sym_struct_definition, - STATE(205), 1, sym_expression, - STATE(298), 1, + STATE(137), 1, + sym_struct_definition, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(49), 2, + ACTIONS(5), 2, sym_identifier, sym_self, - ACTIONS(70), 2, + ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(73), 3, + ACTIONS(89), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -2903,9 +2611,11 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [495] = 22, + [483] = 22, ACTIONS(7), 1, sym_string, + ACTIONS(9), 1, + aux_sym_base_ten_token1, ACTIONS(11), 1, aux_sym_octal_token1, ACTIONS(13), 1, @@ -2913,28 +2623,26 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, + ACTIONS(23), 1, + anon_sym_if, + ACTIONS(25), 1, + anon_sym_let, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(93), 1, - aux_sym_base_ten_token1, - ACTIONS(97), 1, - anon_sym_if, - ACTIONS(99), 1, - anon_sym_let, - STATE(130), 1, + STATE(53), 1, sym__float, - STATE(141), 1, + STATE(55), 1, sym_number, - STATE(185), 1, + STATE(65), 1, sym_expression, - STATE(216), 1, + STATE(67), 1, sym_struct_definition, - STATE(298), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -2945,16 +2653,16 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(95), 3, + ACTIONS(21), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -2974,7 +2682,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [588] = 22, + [576] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -2986,7 +2694,7 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(23), 1, anon_sym_if, ACTIONS(25), 1, @@ -2997,15 +2705,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(78), 1, + STATE(53), 1, sym__float, - STATE(80), 1, + STATE(55), 1, sym_number, - STATE(86), 1, - sym_expression, - STATE(112), 1, + STATE(67), 1, sym_struct_definition, - STATE(298), 1, + STATE(85), 1, + sym_expression, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3020,12 +2728,12 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -3045,7 +2753,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [681] = 22, + [669] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3057,7 +2765,7 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(23), 1, anon_sym_if, ACTIONS(25), 1, @@ -3068,15 +2776,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(78), 1, + STATE(53), 1, sym__float, - STATE(80), 1, + STATE(55), 1, sym_number, - STATE(94), 1, + STATE(59), 1, sym_expression, - STATE(112), 1, + STATE(67), 1, sym_struct_definition, - STATE(298), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3091,12 +2799,12 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -3116,7 +2824,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [774] = 22, + [762] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3128,7 +2836,7 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(23), 1, anon_sym_if, ACTIONS(25), 1, @@ -3139,15 +2847,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(78), 1, + STATE(53), 1, sym__float, - STATE(80), 1, + STATE(55), 1, sym_number, - STATE(95), 1, - sym_expression, - STATE(112), 1, + STATE(67), 1, sym_struct_definition, - STATE(298), 1, + STATE(87), 1, + sym_expression, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3162,12 +2870,12 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -3187,7 +2895,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [867] = 22, + [855] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3199,7 +2907,7 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(23), 1, anon_sym_if, ACTIONS(25), 1, @@ -3210,15 +2918,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(78), 1, + STATE(53), 1, sym__float, - STATE(80), 1, + STATE(55), 1, sym_number, - STATE(96), 1, - sym_expression, - STATE(112), 1, + STATE(67), 1, sym_struct_definition, - STATE(298), 1, + STATE(88), 1, + sym_expression, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3233,12 +2941,12 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -3258,7 +2966,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [960] = 22, + [948] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3270,7 +2978,7 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(23), 1, anon_sym_if, ACTIONS(25), 1, @@ -3281,15 +2989,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(78), 1, + STATE(53), 1, sym__float, - STATE(80), 1, + STATE(55), 1, sym_number, - STATE(97), 1, - sym_expression, - STATE(112), 1, + STATE(67), 1, sym_struct_definition, - STATE(298), 1, + STATE(89), 1, + sym_expression, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3304,12 +3012,12 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -3329,7 +3037,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [1053] = 22, + [1041] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3341,7 +3049,7 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(23), 1, anon_sym_if, ACTIONS(25), 1, @@ -3352,15 +3060,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(78), 1, + STATE(53), 1, sym__float, - STATE(80), 1, + STATE(55), 1, sym_number, - STATE(98), 1, - sym_expression, - STATE(112), 1, + STATE(67), 1, sym_struct_definition, - STATE(298), 1, + STATE(90), 1, + sym_expression, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3375,12 +3083,12 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -3400,7 +3108,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [1146] = 22, + [1134] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3412,7 +3120,7 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(23), 1, anon_sym_if, ACTIONS(25), 1, @@ -3423,15 +3131,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(78), 1, + STATE(53), 1, sym__float, - STATE(80), 1, + STATE(55), 1, sym_number, - STATE(99), 1, - sym_expression, - STATE(112), 1, + STATE(67), 1, sym_struct_definition, - STATE(298), 1, + STATE(91), 1, + sym_expression, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3446,12 +3154,12 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -3471,7 +3179,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [1239] = 22, + [1227] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3483,7 +3191,7 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(23), 1, anon_sym_if, ACTIONS(25), 1, @@ -3494,15 +3202,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(78), 1, + STATE(53), 1, sym__float, - STATE(80), 1, + STATE(55), 1, sym_number, - STATE(100), 1, + STATE(63), 1, sym_expression, - STATE(112), 1, + STATE(67), 1, sym_struct_definition, - STATE(298), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3517,12 +3225,12 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -3542,7 +3250,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [1332] = 22, + [1320] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3554,7 +3262,7 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(23), 1, anon_sym_if, ACTIONS(25), 1, @@ -3565,15 +3273,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(78), 1, + STATE(53), 1, sym__float, - STATE(80), 1, + STATE(55), 1, sym_number, - STATE(101), 1, - sym_expression, - STATE(112), 1, + STATE(67), 1, sym_struct_definition, - STATE(298), 1, + STATE(93), 1, + sym_expression, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3588,12 +3296,12 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -3613,7 +3321,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [1425] = 22, + [1413] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3625,7 +3333,7 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(23), 1, anon_sym_if, ACTIONS(25), 1, @@ -3636,15 +3344,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(78), 1, + STATE(53), 1, sym__float, - STATE(80), 1, + STATE(55), 1, sym_number, - STATE(102), 1, - sym_expression, - STATE(112), 1, + STATE(67), 1, sym_struct_definition, - STATE(298), 1, + STATE(94), 1, + sym_expression, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3659,12 +3367,12 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -3684,7 +3392,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [1518] = 22, + [1506] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3696,7 +3404,7 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(23), 1, anon_sym_if, ACTIONS(25), 1, @@ -3707,15 +3415,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(78), 1, + STATE(53), 1, sym__float, - STATE(80), 1, + STATE(55), 1, sym_number, - STATE(112), 1, + STATE(67), 1, sym_struct_definition, - STATE(178), 1, + STATE(95), 1, sym_expression, - STATE(298), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3730,12 +3438,12 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -3755,58 +3463,58 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [1611] = 22, + [1599] = 22, + ACTIONS(7), 1, + sym_string, + ACTIONS(9), 1, + aux_sym_base_ten_token1, ACTIONS(11), 1, aux_sym_octal_token1, ACTIONS(13), 1, aux_sym_hex_token1, ACTIONS(15), 1, aux_sym_binary_token1, - ACTIONS(103), 1, - sym_string, - ACTIONS(105), 1, - aux_sym_base_ten_token1, - ACTIONS(107), 1, - anon_sym_LT_LPAREN, - ACTIONS(113), 1, + ACTIONS(17), 1, + anon_sym_LBRACE, + ACTIONS(23), 1, anon_sym_if, - ACTIONS(115), 1, + ACTIONS(25), 1, anon_sym_let, - ACTIONS(117), 1, + ACTIONS(27), 1, anon_sym_LPAREN, - ACTIONS(119), 1, + ACTIONS(29), 1, anon_sym_LBRACK, - ACTIONS(121), 1, + ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(125), 1, + STATE(53), 1, sym__float, - STATE(129), 1, + STATE(55), 1, sym_number, - STATE(144), 1, - sym_expression, - STATE(145), 1, + STATE(67), 1, sym_struct_definition, - STATE(295), 1, + STATE(136), 1, + sym_expression, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(101), 2, + ACTIONS(5), 2, sym_identifier, sym_self, - ACTIONS(109), 2, + ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(111), 3, + ACTIONS(21), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(214), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -3826,7 +3534,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [1704] = 22, + [1692] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3838,7 +3546,7 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(23), 1, anon_sym_if, ACTIONS(25), 1, @@ -3849,15 +3557,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(78), 1, + STATE(53), 1, sym__float, - STATE(80), 1, + STATE(55), 1, sym_number, - STATE(112), 1, + STATE(67), 1, sym_struct_definition, - STATE(193), 1, + STATE(108), 1, sym_expression, - STATE(298), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3872,12 +3580,12 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -3897,7 +3605,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [1797] = 22, + [1785] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3909,7 +3617,7 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(23), 1, anon_sym_if, ACTIONS(25), 1, @@ -3920,15 +3628,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(78), 1, + STATE(53), 1, sym__float, - STATE(80), 1, + STATE(55), 1, sym_number, - STATE(112), 1, + STATE(67), 1, sym_struct_definition, - STATE(196), 1, + STATE(116), 1, sym_expression, - STATE(298), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3943,12 +3651,12 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -3968,7 +3676,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [1890] = 22, + [1878] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3980,7 +3688,7 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(23), 1, anon_sym_if, ACTIONS(25), 1, @@ -3991,15 +3699,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(78), 1, + STATE(53), 1, sym__float, - STATE(80), 1, + STATE(55), 1, sym_number, - STATE(104), 1, - sym_expression, - STATE(112), 1, + STATE(67), 1, sym_struct_definition, - STATE(298), 1, + STATE(118), 1, + sym_expression, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4014,12 +3722,12 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -4039,7 +3747,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [1983] = 22, + [1971] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -4051,7 +3759,7 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(23), 1, anon_sym_if, ACTIONS(25), 1, @@ -4062,15 +3770,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(78), 1, + STATE(53), 1, sym__float, - STATE(80), 1, + STATE(55), 1, sym_number, - STATE(112), 1, - sym_struct_definition, - STATE(151), 1, + STATE(64), 1, sym_expression, - STATE(298), 1, + STATE(67), 1, + sym_struct_definition, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4085,12 +3793,12 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -4110,7 +3818,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [2076] = 22, + [2064] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -4122,7 +3830,7 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(23), 1, anon_sym_if, ACTIONS(25), 1, @@ -4133,15 +3841,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(78), 1, + STATE(53), 1, sym__float, - STATE(80), 1, + STATE(55), 1, sym_number, - STATE(112), 1, + STATE(67), 1, sym_struct_definition, - STATE(127), 1, + STATE(109), 1, sym_expression, - STATE(298), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4156,12 +3864,12 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -4181,9 +3889,11 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [2169] = 22, + [2157] = 22, ACTIONS(7), 1, sym_string, + ACTIONS(9), 1, + aux_sym_base_ten_token1, ACTIONS(11), 1, aux_sym_octal_token1, ACTIONS(13), 1, @@ -4191,28 +3901,26 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, + ACTIONS(23), 1, + anon_sym_if, + ACTIONS(25), 1, + anon_sym_let, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(93), 1, - aux_sym_base_ten_token1, - ACTIONS(97), 1, - anon_sym_if, - ACTIONS(99), 1, - anon_sym_let, - STATE(130), 1, + STATE(53), 1, sym__float, - STATE(141), 1, + STATE(55), 1, sym_number, - STATE(171), 1, - sym_expression, - STATE(216), 1, + STATE(67), 1, sym_struct_definition, - STATE(298), 1, + STATE(100), 1, + sym_expression, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4223,16 +3931,16 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(95), 3, + ACTIONS(21), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -4252,7 +3960,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [2262] = 22, + [2250] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -4264,7 +3972,7 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(23), 1, anon_sym_if, ACTIONS(25), 1, @@ -4275,15 +3983,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(78), 1, + STATE(53), 1, sym__float, - STATE(80), 1, + STATE(55), 1, sym_number, - STATE(112), 1, + STATE(67), 1, sym_struct_definition, - STATE(147), 1, + STATE(70), 1, sym_expression, - STATE(298), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4298,12 +4006,12 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -4323,7 +4031,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [2355] = 22, + [2343] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -4335,7 +4043,7 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(23), 1, anon_sym_if, ACTIONS(25), 1, @@ -4346,15 +4054,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(78), 1, + STATE(53), 1, sym__float, - STATE(80), 1, + STATE(55), 1, sym_number, - STATE(112), 1, + STATE(67), 1, sym_struct_definition, - STATE(114), 1, + STATE(105), 1, sym_expression, - STATE(298), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4369,12 +4077,12 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -4394,58 +4102,58 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [2448] = 22, + [2436] = 22, + ACTIONS(7), 1, + sym_string, + ACTIONS(9), 1, + aux_sym_base_ten_token1, ACTIONS(11), 1, aux_sym_octal_token1, ACTIONS(13), 1, aux_sym_hex_token1, ACTIONS(15), 1, aux_sym_binary_token1, - ACTIONS(103), 1, - sym_string, - ACTIONS(105), 1, - aux_sym_base_ten_token1, - ACTIONS(107), 1, - anon_sym_LT_LPAREN, - ACTIONS(113), 1, + ACTIONS(17), 1, + anon_sym_LBRACE, + ACTIONS(23), 1, anon_sym_if, - ACTIONS(115), 1, + ACTIONS(25), 1, anon_sym_let, - ACTIONS(117), 1, + ACTIONS(27), 1, anon_sym_LPAREN, - ACTIONS(119), 1, + ACTIONS(29), 1, anon_sym_LBRACK, - ACTIONS(121), 1, + ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(125), 1, + STATE(53), 1, sym__float, - STATE(129), 1, + STATE(55), 1, sym_number, - STATE(145), 1, + STATE(67), 1, sym_struct_definition, - STATE(161), 1, + STATE(74), 1, sym_expression, - STATE(295), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(101), 2, + ACTIONS(5), 2, sym_identifier, sym_self, - ACTIONS(109), 2, + ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(111), 3, + ACTIONS(21), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(214), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -4465,7 +4173,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [2541] = 22, + [2529] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -4477,7 +4185,7 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(23), 1, anon_sym_if, ACTIONS(25), 1, @@ -4488,15 +4196,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(78), 1, + STATE(53), 1, sym__float, - STATE(80), 1, + STATE(55), 1, sym_number, - STATE(112), 1, + STATE(67), 1, sym_struct_definition, - STATE(115), 1, + STATE(110), 1, sym_expression, - STATE(298), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4511,12 +4219,12 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -4536,58 +4244,58 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [2634] = 22, + [2622] = 22, + ACTIONS(7), 1, + sym_string, + ACTIONS(9), 1, + aux_sym_base_ten_token1, ACTIONS(11), 1, aux_sym_octal_token1, ACTIONS(13), 1, aux_sym_hex_token1, ACTIONS(15), 1, aux_sym_binary_token1, - ACTIONS(103), 1, - sym_string, - ACTIONS(105), 1, - aux_sym_base_ten_token1, - ACTIONS(107), 1, - anon_sym_LT_LPAREN, - ACTIONS(113), 1, + ACTIONS(17), 1, + anon_sym_LBRACE, + ACTIONS(23), 1, anon_sym_if, - ACTIONS(115), 1, + ACTIONS(25), 1, anon_sym_let, - ACTIONS(117), 1, + ACTIONS(27), 1, anon_sym_LPAREN, - ACTIONS(119), 1, + ACTIONS(29), 1, anon_sym_LBRACK, - ACTIONS(121), 1, + ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(125), 1, + STATE(53), 1, sym__float, - STATE(129), 1, + STATE(55), 1, sym_number, - STATE(145), 1, + STATE(67), 1, sym_struct_definition, - STATE(213), 1, + STATE(75), 1, sym_expression, - STATE(295), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(101), 2, + ACTIONS(5), 2, sym_identifier, sym_self, - ACTIONS(109), 2, + ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(111), 3, + ACTIONS(21), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(214), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -4607,9 +4315,11 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [2727] = 22, + [2715] = 22, ACTIONS(7), 1, sym_string, + ACTIONS(9), 1, + aux_sym_base_ten_token1, ACTIONS(11), 1, aux_sym_octal_token1, ACTIONS(13), 1, @@ -4617,28 +4327,26 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, + ACTIONS(23), 1, + anon_sym_if, + ACTIONS(25), 1, + anon_sym_let, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(93), 1, - aux_sym_base_ten_token1, - ACTIONS(97), 1, - anon_sym_if, - ACTIONS(99), 1, - anon_sym_let, - STATE(130), 1, + STATE(53), 1, sym__float, - STATE(141), 1, + STATE(55), 1, sym_number, - STATE(207), 1, - sym_expression, - STATE(216), 1, + STATE(67), 1, sym_struct_definition, - STATE(298), 1, + STATE(115), 1, + sym_expression, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4649,16 +4357,16 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(95), 3, + ACTIONS(21), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -4678,7 +4386,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [2820] = 22, + [2808] = 22, ACTIONS(7), 1, sym_string, ACTIONS(11), 1, @@ -4688,28 +4396,28 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(93), 1, + ACTIONS(87), 1, aux_sym_base_ten_token1, - ACTIONS(97), 1, + ACTIONS(91), 1, anon_sym_if, - ACTIONS(99), 1, + ACTIONS(93), 1, anon_sym_let, - STATE(130), 1, + STATE(99), 1, sym__float, - STATE(141), 1, + STATE(102), 1, sym_number, - STATE(173), 1, + STATE(133), 1, sym_expression, - STATE(216), 1, + STATE(137), 1, sym_struct_definition, - STATE(298), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4720,16 +4428,16 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(95), 3, + ACTIONS(89), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -4749,7 +4457,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [2913] = 22, + [2901] = 22, ACTIONS(7), 1, sym_string, ACTIONS(11), 1, @@ -4759,28 +4467,28 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(93), 1, + ACTIONS(87), 1, aux_sym_base_ten_token1, - ACTIONS(97), 1, + ACTIONS(91), 1, anon_sym_if, - ACTIONS(99), 1, + ACTIONS(93), 1, anon_sym_let, - STATE(130), 1, + STATE(99), 1, sym__float, - STATE(141), 1, + STATE(102), 1, sym_number, - STATE(180), 1, + STATE(119), 1, sym_expression, - STATE(216), 1, + STATE(137), 1, sym_struct_definition, - STATE(298), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4791,16 +4499,16 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(95), 3, + ACTIONS(89), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -4820,7 +4528,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [3006] = 22, + [2994] = 22, ACTIONS(7), 1, sym_string, ACTIONS(11), 1, @@ -4830,28 +4538,28 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(93), 1, + ACTIONS(87), 1, aux_sym_base_ten_token1, - ACTIONS(97), 1, + ACTIONS(91), 1, anon_sym_if, - ACTIONS(99), 1, + ACTIONS(93), 1, anon_sym_let, - STATE(86), 1, - sym_expression, - STATE(130), 1, + STATE(99), 1, sym__float, - STATE(141), 1, + STATE(102), 1, sym_number, - STATE(216), 1, + STATE(120), 1, + sym_expression, + STATE(137), 1, sym_struct_definition, - STATE(298), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4862,16 +4570,16 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(95), 3, + ACTIONS(89), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -4891,7 +4599,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [3099] = 22, + [3087] = 22, ACTIONS(7), 1, sym_string, ACTIONS(11), 1, @@ -4901,28 +4609,28 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(93), 1, + ACTIONS(87), 1, aux_sym_base_ten_token1, - ACTIONS(97), 1, + ACTIONS(91), 1, anon_sym_if, - ACTIONS(99), 1, + ACTIONS(93), 1, anon_sym_let, - STATE(130), 1, + STATE(59), 1, + sym_expression, + STATE(99), 1, sym__float, - STATE(141), 1, + STATE(102), 1, sym_number, - STATE(181), 1, - sym_expression, - STATE(216), 1, + STATE(137), 1, sym_struct_definition, - STATE(298), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4933,16 +4641,16 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(95), 3, + ACTIONS(89), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -4962,7 +4670,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [3192] = 22, + [3180] = 22, ACTIONS(7), 1, sym_string, ACTIONS(11), 1, @@ -4972,28 +4680,28 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(93), 1, + ACTIONS(87), 1, aux_sym_base_ten_token1, - ACTIONS(97), 1, + ACTIONS(91), 1, anon_sym_if, - ACTIONS(99), 1, + ACTIONS(93), 1, anon_sym_let, - STATE(130), 1, + STATE(99), 1, sym__float, - STATE(141), 1, + STATE(102), 1, sym_number, - STATE(182), 1, + STATE(121), 1, sym_expression, - STATE(216), 1, + STATE(137), 1, sym_struct_definition, - STATE(298), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -5004,16 +4712,16 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(95), 3, + ACTIONS(89), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -5033,7 +4741,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [3285] = 22, + [3273] = 22, ACTIONS(7), 1, sym_string, ACTIONS(11), 1, @@ -5043,28 +4751,28 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(93), 1, + ACTIONS(87), 1, aux_sym_base_ten_token1, - ACTIONS(97), 1, + ACTIONS(91), 1, anon_sym_if, - ACTIONS(99), 1, + ACTIONS(93), 1, anon_sym_let, - STATE(130), 1, + STATE(99), 1, sym__float, - STATE(141), 1, + STATE(102), 1, sym_number, - STATE(183), 1, + STATE(122), 1, sym_expression, - STATE(216), 1, + STATE(137), 1, sym_struct_definition, - STATE(298), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -5075,16 +4783,16 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(95), 3, + ACTIONS(89), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -5104,7 +4812,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [3378] = 22, + [3366] = 22, ACTIONS(7), 1, sym_string, ACTIONS(11), 1, @@ -5114,28 +4822,28 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(93), 1, + ACTIONS(87), 1, aux_sym_base_ten_token1, - ACTIONS(97), 1, + ACTIONS(91), 1, anon_sym_if, - ACTIONS(99), 1, + ACTIONS(93), 1, anon_sym_let, - STATE(130), 1, + STATE(99), 1, sym__float, - STATE(141), 1, + STATE(102), 1, sym_number, - STATE(184), 1, - sym_expression, - STATE(216), 1, + STATE(137), 1, sym_struct_definition, - STATE(298), 1, + STATE(138), 1, + sym_expression, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -5146,16 +4854,16 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(95), 3, + ACTIONS(89), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -5175,7 +4883,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [3471] = 22, + [3459] = 22, ACTIONS(7), 1, sym_string, ACTIONS(11), 1, @@ -5185,28 +4893,28 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(93), 1, + ACTIONS(87), 1, aux_sym_base_ten_token1, - ACTIONS(97), 1, + ACTIONS(91), 1, anon_sym_if, - ACTIONS(99), 1, + ACTIONS(93), 1, anon_sym_let, - STATE(130), 1, + STATE(99), 1, sym__float, - STATE(141), 1, + STATE(102), 1, sym_number, - STATE(186), 1, + STATE(124), 1, sym_expression, - STATE(216), 1, + STATE(137), 1, sym_struct_definition, - STATE(298), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -5217,16 +4925,16 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(95), 3, + ACTIONS(89), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -5246,7 +4954,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [3564] = 22, + [3552] = 22, ACTIONS(7), 1, sym_string, ACTIONS(11), 1, @@ -5256,28 +4964,28 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(93), 1, + ACTIONS(87), 1, aux_sym_base_ten_token1, - ACTIONS(97), 1, + ACTIONS(91), 1, anon_sym_if, - ACTIONS(99), 1, + ACTIONS(93), 1, anon_sym_let, - STATE(130), 1, + STATE(99), 1, sym__float, - STATE(141), 1, + STATE(102), 1, sym_number, - STATE(187), 1, + STATE(125), 1, sym_expression, - STATE(216), 1, + STATE(137), 1, sym_struct_definition, - STATE(298), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -5288,16 +4996,16 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(95), 3, + ACTIONS(89), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -5317,7 +5025,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [3657] = 22, + [3645] = 22, ACTIONS(7), 1, sym_string, ACTIONS(11), 1, @@ -5327,28 +5035,28 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(93), 1, + ACTIONS(87), 1, aux_sym_base_ten_token1, - ACTIONS(97), 1, + ACTIONS(91), 1, anon_sym_if, - ACTIONS(99), 1, + ACTIONS(93), 1, anon_sym_let, - STATE(130), 1, + STATE(99), 1, sym__float, - STATE(141), 1, + STATE(102), 1, sym_number, - STATE(188), 1, + STATE(111), 1, sym_expression, - STATE(216), 1, + STATE(137), 1, sym_struct_definition, - STATE(298), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -5359,16 +5067,16 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(95), 3, + ACTIONS(89), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -5388,7 +5096,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [3750] = 22, + [3738] = 22, ACTIONS(7), 1, sym_string, ACTIONS(11), 1, @@ -5398,28 +5106,28 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(93), 1, + ACTIONS(87), 1, aux_sym_base_ten_token1, - ACTIONS(97), 1, + ACTIONS(91), 1, anon_sym_if, - ACTIONS(99), 1, + ACTIONS(93), 1, anon_sym_let, - STATE(130), 1, + STATE(99), 1, sym__float, - STATE(141), 1, + STATE(102), 1, sym_number, - STATE(189), 1, + STATE(126), 1, sym_expression, - STATE(216), 1, + STATE(137), 1, sym_struct_definition, - STATE(298), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -5430,16 +5138,16 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(95), 3, + ACTIONS(89), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -5459,7 +5167,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [3843] = 22, + [3831] = 22, ACTIONS(7), 1, sym_string, ACTIONS(11), 1, @@ -5469,28 +5177,28 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(93), 1, + ACTIONS(87), 1, aux_sym_base_ten_token1, - ACTIONS(97), 1, + ACTIONS(91), 1, anon_sym_if, - ACTIONS(99), 1, + ACTIONS(93), 1, anon_sym_let, - STATE(130), 1, + STATE(99), 1, sym__float, - STATE(141), 1, + STATE(102), 1, sym_number, - STATE(191), 1, + STATE(127), 1, sym_expression, - STATE(216), 1, + STATE(137), 1, sym_struct_definition, - STATE(298), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -5501,16 +5209,16 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(95), 3, + ACTIONS(89), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -5530,11 +5238,9 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [3936] = 22, + [3924] = 22, ACTIONS(7), 1, sym_string, - ACTIONS(9), 1, - aux_sym_base_ten_token1, ACTIONS(11), 1, aux_sym_octal_token1, ACTIONS(13), 1, @@ -5542,26 +5248,28 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, - ACTIONS(23), 1, - anon_sym_if, - ACTIONS(25), 1, - anon_sym_let, + anon_sym_LBRACE, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(78), 1, + ACTIONS(87), 1, + aux_sym_base_ten_token1, + ACTIONS(91), 1, + anon_sym_if, + ACTIONS(93), 1, + anon_sym_let, + STATE(99), 1, sym__float, - STATE(80), 1, + STATE(102), 1, sym_number, - STATE(112), 1, - sym_struct_definition, - STATE(220), 1, + STATE(128), 1, sym_expression, - STATE(298), 1, + STATE(137), 1, + sym_struct_definition, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -5572,16 +5280,16 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(21), 3, + ACTIONS(89), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -5601,7 +5309,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [4029] = 22, + [4017] = 22, ACTIONS(7), 1, sym_string, ACTIONS(11), 1, @@ -5611,28 +5319,28 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(15), 1, aux_sym_binary_token1, ACTIONS(17), 1, - anon_sym_LT_LPAREN, + anon_sym_LBRACE, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(93), 1, + ACTIONS(87), 1, aux_sym_base_ten_token1, - ACTIONS(97), 1, + ACTIONS(91), 1, anon_sym_if, - ACTIONS(99), 1, + ACTIONS(93), 1, anon_sym_let, - STATE(130), 1, + STATE(99), 1, sym__float, - STATE(141), 1, + STATE(102), 1, sym_number, - STATE(200), 1, + STATE(129), 1, sym_expression, - STATE(216), 1, + STATE(137), 1, sym_struct_definition, - STATE(298), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -5643,16 +5351,16 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(95), 3, + ACTIONS(89), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(109), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -5672,58 +5380,58 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [4122] = 22, + [4110] = 22, + ACTIONS(7), 1, + sym_string, ACTIONS(11), 1, aux_sym_octal_token1, ACTIONS(13), 1, aux_sym_hex_token1, ACTIONS(15), 1, aux_sym_binary_token1, - ACTIONS(103), 1, - sym_string, - ACTIONS(105), 1, - aux_sym_base_ten_token1, - ACTIONS(107), 1, - anon_sym_LT_LPAREN, - ACTIONS(113), 1, - anon_sym_if, - ACTIONS(115), 1, - anon_sym_let, - ACTIONS(117), 1, + ACTIONS(17), 1, + anon_sym_LBRACE, + ACTIONS(27), 1, anon_sym_LPAREN, - ACTIONS(119), 1, + ACTIONS(29), 1, anon_sym_LBRACK, - ACTIONS(121), 1, + ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(125), 1, + ACTIONS(87), 1, + aux_sym_base_ten_token1, + ACTIONS(91), 1, + anon_sym_if, + ACTIONS(93), 1, + anon_sym_let, + STATE(99), 1, sym__float, - STATE(129), 1, + STATE(102), 1, sym_number, - STATE(145), 1, - sym_struct_definition, - STATE(146), 1, + STATE(131), 1, sym_expression, - STATE(295), 1, + STATE(137), 1, + sym_struct_definition, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(101), 2, + ACTIONS(5), 2, sym_identifier, sym_self, - ACTIONS(109), 2, + ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(111), 3, + ACTIONS(89), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(214), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -5743,58 +5451,58 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [4215] = 22, + [4203] = 22, + ACTIONS(7), 1, + sym_string, ACTIONS(11), 1, aux_sym_octal_token1, ACTIONS(13), 1, aux_sym_hex_token1, ACTIONS(15), 1, aux_sym_binary_token1, - ACTIONS(103), 1, - sym_string, - ACTIONS(105), 1, - aux_sym_base_ten_token1, - ACTIONS(107), 1, - anon_sym_LT_LPAREN, - ACTIONS(113), 1, - anon_sym_if, - ACTIONS(115), 1, - anon_sym_let, - ACTIONS(117), 1, + ACTIONS(17), 1, + anon_sym_LBRACE, + ACTIONS(27), 1, anon_sym_LPAREN, - ACTIONS(119), 1, + ACTIONS(29), 1, anon_sym_LBRACK, - ACTIONS(121), 1, + ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(125), 1, + ACTIONS(87), 1, + aux_sym_base_ten_token1, + ACTIONS(91), 1, + anon_sym_if, + ACTIONS(93), 1, + anon_sym_let, + STATE(99), 1, sym__float, - STATE(129), 1, + STATE(102), 1, sym_number, - STATE(145), 1, - sym_struct_definition, - STATE(160), 1, + STATE(132), 1, sym_expression, - STATE(295), 1, + STATE(137), 1, + sym_struct_definition, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(101), 2, + ACTIONS(5), 2, sym_identifier, sym_self, - ACTIONS(109), 2, + ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(111), 3, + ACTIONS(89), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(214), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -5814,58 +5522,58 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [4308] = 22, + [4296] = 22, + ACTIONS(7), 1, + sym_string, + ACTIONS(9), 1, + aux_sym_base_ten_token1, ACTIONS(11), 1, aux_sym_octal_token1, ACTIONS(13), 1, aux_sym_hex_token1, ACTIONS(15), 1, aux_sym_binary_token1, - ACTIONS(103), 1, - sym_string, - ACTIONS(105), 1, - aux_sym_base_ten_token1, - ACTIONS(107), 1, - anon_sym_LT_LPAREN, - ACTIONS(113), 1, + ACTIONS(17), 1, + anon_sym_LBRACE, + ACTIONS(23), 1, anon_sym_if, - ACTIONS(115), 1, + ACTIONS(25), 1, anon_sym_let, - ACTIONS(117), 1, + ACTIONS(27), 1, anon_sym_LPAREN, - ACTIONS(119), 1, + ACTIONS(29), 1, anon_sym_LBRACK, - ACTIONS(121), 1, + ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(125), 1, + STATE(53), 1, sym__float, - STATE(129), 1, + STATE(55), 1, sym_number, - STATE(145), 1, + STATE(67), 1, sym_struct_definition, - STATE(162), 1, + STATE(134), 1, sym_expression, - STATE(295), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(101), 2, + ACTIONS(5), 2, sym_identifier, sym_self, - ACTIONS(109), 2, + ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(111), 3, + ACTIONS(21), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(214), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -5885,58 +5593,58 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [4401] = 22, + [4389] = 22, + ACTIONS(7), 1, + sym_string, + ACTIONS(9), 1, + aux_sym_base_ten_token1, ACTIONS(11), 1, aux_sym_octal_token1, ACTIONS(13), 1, aux_sym_hex_token1, ACTIONS(15), 1, aux_sym_binary_token1, - ACTIONS(103), 1, - sym_string, - ACTIONS(105), 1, - aux_sym_base_ten_token1, - ACTIONS(107), 1, - anon_sym_LT_LPAREN, - ACTIONS(113), 1, + ACTIONS(17), 1, + anon_sym_LBRACE, + ACTIONS(23), 1, anon_sym_if, - ACTIONS(115), 1, + ACTIONS(25), 1, anon_sym_let, - ACTIONS(117), 1, + ACTIONS(27), 1, anon_sym_LPAREN, - ACTIONS(119), 1, + ACTIONS(29), 1, anon_sym_LBRACK, - ACTIONS(121), 1, + ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(125), 1, + STATE(53), 1, sym__float, - STATE(129), 1, + STATE(55), 1, sym_number, - STATE(145), 1, + STATE(67), 1, sym_struct_definition, - STATE(158), 1, + STATE(135), 1, sym_expression, - STATE(295), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(101), 2, + ACTIONS(5), 2, sym_identifier, sym_self, - ACTIONS(109), 2, + ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(111), 3, + ACTIONS(21), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(214), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -5956,58 +5664,58 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [4494] = 22, + [4482] = 22, + ACTIONS(7), 1, + sym_string, + ACTIONS(9), 1, + aux_sym_base_ten_token1, ACTIONS(11), 1, aux_sym_octal_token1, ACTIONS(13), 1, aux_sym_hex_token1, ACTIONS(15), 1, aux_sym_binary_token1, - ACTIONS(103), 1, - sym_string, - ACTIONS(105), 1, - aux_sym_base_ten_token1, - ACTIONS(107), 1, - anon_sym_LT_LPAREN, - ACTIONS(113), 1, + ACTIONS(17), 1, + anon_sym_LBRACE, + ACTIONS(23), 1, anon_sym_if, - ACTIONS(115), 1, + ACTIONS(25), 1, anon_sym_let, - ACTIONS(117), 1, + ACTIONS(27), 1, anon_sym_LPAREN, - ACTIONS(119), 1, + ACTIONS(29), 1, anon_sym_LBRACK, - ACTIONS(121), 1, + ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(125), 1, + STATE(53), 1, sym__float, - STATE(129), 1, + STATE(55), 1, sym_number, - STATE(145), 1, + STATE(67), 1, sym_struct_definition, - STATE(163), 1, + STATE(117), 1, sym_expression, - STATE(295), 1, + STATE(189), 1, sym_integer, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(101), 2, + ACTIONS(5), 2, sym_identifier, sym_self, - ACTIONS(109), 2, + ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(111), 3, + ACTIONS(21), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(284), 4, + STATE(200), 4, sym_base_ten, sym_octal, sym_hex, sym_binary, - STATE(214), 19, + STATE(92), 19, sym_signed_integer, sym_unsigned_integer, sym_scalar, @@ -6027,3760 +5735,31 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [4587] = 22, - ACTIONS(11), 1, - aux_sym_octal_token1, - ACTIONS(13), 1, - aux_sym_hex_token1, - ACTIONS(15), 1, - aux_sym_binary_token1, - ACTIONS(103), 1, - sym_string, - ACTIONS(105), 1, - aux_sym_base_ten_token1, - ACTIONS(107), 1, - anon_sym_LT_LPAREN, - ACTIONS(113), 1, - anon_sym_if, - ACTIONS(115), 1, - anon_sym_let, - ACTIONS(117), 1, - anon_sym_LPAREN, - ACTIONS(119), 1, - anon_sym_LBRACK, - ACTIONS(121), 1, - anon_sym_LT_LT_LT, - STATE(125), 1, - sym__float, - STATE(129), 1, - sym_number, - STATE(145), 1, - sym_struct_definition, - STATE(164), 1, - sym_expression, - STATE(295), 1, - sym_integer, + [4575] = 4, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(101), 2, + ACTIONS(99), 2, + aux_sym_signed_integer_token1, + aux_sym_unsigned_integer_token1, + ACTIONS(97), 10, sym_identifier, - sym_self, - ACTIONS(109), 2, - sym_true, - sym_false, - ACTIONS(111), 3, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_BANG, - STATE(284), 4, - sym_base_ten, - sym_octal, - sym_hex, - sym_binary, - STATE(214), 19, - sym_signed_integer, - sym_unsigned_integer, - sym_scalar, - sym_vector2, - sym_vector3, - sym_vector4, - sym_boolean, - sym_function_call, - sym_method_call, - sym_unary_expression, - sym_binary_expression, - sym_if, - sym_let_in, - sym_member_access, - sym_parenthesis, - sym_list, - sym_dictionary_construction, - sym_closure_definition, - sym_constraint_set, - [4680] = 22, - ACTIONS(11), 1, - aux_sym_octal_token1, - ACTIONS(13), 1, - aux_sym_hex_token1, - ACTIONS(15), 1, - aux_sym_binary_token1, - ACTIONS(103), 1, - sym_string, - ACTIONS(105), 1, - aux_sym_base_ten_token1, - ACTIONS(107), 1, - anon_sym_LT_LPAREN, - ACTIONS(113), 1, - anon_sym_if, - ACTIONS(115), 1, - anon_sym_let, - ACTIONS(117), 1, - anon_sym_LPAREN, - ACTIONS(119), 1, - anon_sym_LBRACK, - ACTIONS(121), 1, - anon_sym_LT_LT_LT, - STATE(125), 1, - sym__float, - STATE(129), 1, - sym_number, - STATE(145), 1, - sym_struct_definition, - STATE(165), 1, - sym_expression, - STATE(295), 1, - sym_integer, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(101), 2, - sym_identifier, - sym_self, - ACTIONS(109), 2, - sym_true, - sym_false, - ACTIONS(111), 3, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_BANG, - STATE(284), 4, - sym_base_ten, - sym_octal, - sym_hex, - sym_binary, - STATE(214), 19, - sym_signed_integer, - sym_unsigned_integer, - sym_scalar, - sym_vector2, - sym_vector3, - sym_vector4, - sym_boolean, - sym_function_call, - sym_method_call, - sym_unary_expression, - sym_binary_expression, - sym_if, - sym_let_in, - sym_member_access, - sym_parenthesis, - sym_list, - sym_dictionary_construction, - sym_closure_definition, - sym_constraint_set, - [4773] = 22, - ACTIONS(11), 1, - aux_sym_octal_token1, - ACTIONS(13), 1, - aux_sym_hex_token1, - ACTIONS(15), 1, - aux_sym_binary_token1, - ACTIONS(103), 1, - sym_string, - ACTIONS(105), 1, - aux_sym_base_ten_token1, - ACTIONS(107), 1, - anon_sym_LT_LPAREN, - ACTIONS(113), 1, - anon_sym_if, - ACTIONS(115), 1, - anon_sym_let, - ACTIONS(117), 1, - anon_sym_LPAREN, - ACTIONS(119), 1, - anon_sym_LBRACK, - ACTIONS(121), 1, - anon_sym_LT_LT_LT, - STATE(125), 1, - sym__float, - STATE(129), 1, - sym_number, - STATE(145), 1, - sym_struct_definition, - STATE(149), 1, - sym_expression, - STATE(295), 1, - sym_integer, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(101), 2, - sym_identifier, - sym_self, - ACTIONS(109), 2, - sym_true, - sym_false, - ACTIONS(111), 3, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_BANG, - STATE(284), 4, - sym_base_ten, - sym_octal, - sym_hex, - sym_binary, - STATE(214), 19, - sym_signed_integer, - sym_unsigned_integer, - sym_scalar, - sym_vector2, - sym_vector3, - sym_vector4, - sym_boolean, - sym_function_call, - sym_method_call, - sym_unary_expression, - sym_binary_expression, - sym_if, - sym_let_in, - sym_member_access, - sym_parenthesis, - sym_list, - sym_dictionary_construction, - sym_closure_definition, - sym_constraint_set, - [4866] = 22, - ACTIONS(11), 1, - aux_sym_octal_token1, - ACTIONS(13), 1, - aux_sym_hex_token1, - ACTIONS(15), 1, - aux_sym_binary_token1, - ACTIONS(103), 1, - sym_string, - ACTIONS(105), 1, - aux_sym_base_ten_token1, - ACTIONS(107), 1, - anon_sym_LT_LPAREN, - ACTIONS(113), 1, - anon_sym_if, - ACTIONS(115), 1, - anon_sym_let, - ACTIONS(117), 1, - anon_sym_LPAREN, - ACTIONS(119), 1, - anon_sym_LBRACK, - ACTIONS(121), 1, - anon_sym_LT_LT_LT, - STATE(125), 1, - sym__float, - STATE(129), 1, - sym_number, - STATE(134), 1, - sym_expression, - STATE(145), 1, - sym_struct_definition, - STATE(295), 1, - sym_integer, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(101), 2, - sym_identifier, - sym_self, - ACTIONS(109), 2, - sym_true, - sym_false, - ACTIONS(111), 3, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_BANG, - STATE(284), 4, - sym_base_ten, - sym_octal, - sym_hex, - sym_binary, - STATE(214), 19, - sym_signed_integer, - sym_unsigned_integer, - sym_scalar, - sym_vector2, - sym_vector3, - sym_vector4, - sym_boolean, - sym_function_call, - sym_method_call, - sym_unary_expression, - sym_binary_expression, - sym_if, - sym_let_in, - sym_member_access, - sym_parenthesis, - sym_list, - sym_dictionary_construction, - sym_closure_definition, - sym_constraint_set, - [4959] = 22, - ACTIONS(11), 1, - aux_sym_octal_token1, - ACTIONS(13), 1, - aux_sym_hex_token1, - ACTIONS(15), 1, - aux_sym_binary_token1, - ACTIONS(103), 1, - sym_string, - ACTIONS(105), 1, - aux_sym_base_ten_token1, - ACTIONS(107), 1, - anon_sym_LT_LPAREN, - ACTIONS(113), 1, - anon_sym_if, - ACTIONS(115), 1, - anon_sym_let, - ACTIONS(117), 1, - anon_sym_LPAREN, - ACTIONS(119), 1, - anon_sym_LBRACK, - ACTIONS(121), 1, - anon_sym_LT_LT_LT, - STATE(125), 1, - sym__float, - STATE(129), 1, - sym_number, - STATE(135), 1, - sym_expression, - STATE(145), 1, - sym_struct_definition, - STATE(295), 1, - sym_integer, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(101), 2, - sym_identifier, - sym_self, - ACTIONS(109), 2, - sym_true, - sym_false, - ACTIONS(111), 3, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_BANG, - STATE(284), 4, - sym_base_ten, - sym_octal, - sym_hex, - sym_binary, - STATE(214), 19, - sym_signed_integer, - sym_unsigned_integer, - sym_scalar, - sym_vector2, - sym_vector3, - sym_vector4, - sym_boolean, - sym_function_call, - sym_method_call, - sym_unary_expression, - sym_binary_expression, - sym_if, - sym_let_in, - sym_member_access, - sym_parenthesis, - sym_list, - sym_dictionary_construction, - sym_closure_definition, - sym_constraint_set, - [5052] = 22, - ACTIONS(11), 1, - aux_sym_octal_token1, - ACTIONS(13), 1, - aux_sym_hex_token1, - ACTIONS(15), 1, - aux_sym_binary_token1, - ACTIONS(103), 1, - sym_string, - ACTIONS(105), 1, - aux_sym_base_ten_token1, - ACTIONS(107), 1, - anon_sym_LT_LPAREN, - ACTIONS(113), 1, - anon_sym_if, - ACTIONS(115), 1, - anon_sym_let, - ACTIONS(117), 1, - anon_sym_LPAREN, - ACTIONS(119), 1, - anon_sym_LBRACK, - ACTIONS(121), 1, - anon_sym_LT_LT_LT, - STATE(125), 1, - sym__float, - STATE(129), 1, - sym_number, - STATE(136), 1, - sym_expression, - STATE(145), 1, - sym_struct_definition, - STATE(295), 1, - sym_integer, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(101), 2, - sym_identifier, - sym_self, - ACTIONS(109), 2, - sym_true, - sym_false, - ACTIONS(111), 3, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_BANG, - STATE(284), 4, - sym_base_ten, - sym_octal, - sym_hex, - sym_binary, - STATE(214), 19, - sym_signed_integer, - sym_unsigned_integer, - sym_scalar, - sym_vector2, - sym_vector3, - sym_vector4, - sym_boolean, - sym_function_call, - sym_method_call, - sym_unary_expression, - sym_binary_expression, - sym_if, - sym_let_in, - sym_member_access, - sym_parenthesis, - sym_list, - sym_dictionary_construction, - sym_closure_definition, - sym_constraint_set, - [5145] = 22, - ACTIONS(11), 1, - aux_sym_octal_token1, - ACTIONS(13), 1, - aux_sym_hex_token1, - ACTIONS(15), 1, - aux_sym_binary_token1, - ACTIONS(103), 1, - sym_string, - ACTIONS(105), 1, - aux_sym_base_ten_token1, - ACTIONS(107), 1, - anon_sym_LT_LPAREN, - ACTIONS(113), 1, - anon_sym_if, - ACTIONS(115), 1, - anon_sym_let, - ACTIONS(117), 1, - anon_sym_LPAREN, - ACTIONS(119), 1, - anon_sym_LBRACK, - ACTIONS(121), 1, - anon_sym_LT_LT_LT, - STATE(125), 1, - sym__float, - STATE(129), 1, - sym_number, - STATE(137), 1, - sym_expression, - STATE(145), 1, - sym_struct_definition, - STATE(295), 1, - sym_integer, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(101), 2, - sym_identifier, - sym_self, - ACTIONS(109), 2, - sym_true, - sym_false, - ACTIONS(111), 3, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_BANG, - STATE(284), 4, - sym_base_ten, - sym_octal, - sym_hex, - sym_binary, - STATE(214), 19, - sym_signed_integer, - sym_unsigned_integer, - sym_scalar, - sym_vector2, - sym_vector3, - sym_vector4, - sym_boolean, - sym_function_call, - sym_method_call, - sym_unary_expression, - sym_binary_expression, - sym_if, - sym_let_in, - sym_member_access, - sym_parenthesis, - sym_list, - sym_dictionary_construction, - sym_closure_definition, - sym_constraint_set, - [5238] = 22, - ACTIONS(11), 1, - aux_sym_octal_token1, - ACTIONS(13), 1, - aux_sym_hex_token1, - ACTIONS(15), 1, - aux_sym_binary_token1, - ACTIONS(103), 1, - sym_string, - ACTIONS(105), 1, - aux_sym_base_ten_token1, - ACTIONS(107), 1, - anon_sym_LT_LPAREN, - ACTIONS(113), 1, - anon_sym_if, - ACTIONS(115), 1, - anon_sym_let, - ACTIONS(117), 1, - anon_sym_LPAREN, - ACTIONS(119), 1, - anon_sym_LBRACK, - ACTIONS(121), 1, - anon_sym_LT_LT_LT, - STATE(125), 1, - sym__float, - STATE(129), 1, - sym_number, - STATE(138), 1, - sym_expression, - STATE(145), 1, - sym_struct_definition, - STATE(295), 1, - sym_integer, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(101), 2, - sym_identifier, - sym_self, - ACTIONS(109), 2, - sym_true, - sym_false, - ACTIONS(111), 3, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_BANG, - STATE(284), 4, - sym_base_ten, - sym_octal, - sym_hex, - sym_binary, - STATE(214), 19, - sym_signed_integer, - sym_unsigned_integer, - sym_scalar, - sym_vector2, - sym_vector3, - sym_vector4, - sym_boolean, - sym_function_call, - sym_method_call, - sym_unary_expression, - sym_binary_expression, - sym_if, - sym_let_in, - sym_member_access, - sym_parenthesis, - sym_list, - sym_dictionary_construction, - sym_closure_definition, - sym_constraint_set, - [5331] = 22, - ACTIONS(11), 1, - aux_sym_octal_token1, - ACTIONS(13), 1, - aux_sym_hex_token1, - ACTIONS(15), 1, - aux_sym_binary_token1, - ACTIONS(103), 1, - sym_string, - ACTIONS(105), 1, - aux_sym_base_ten_token1, - ACTIONS(107), 1, - anon_sym_LT_LPAREN, - ACTIONS(113), 1, - anon_sym_if, - ACTIONS(115), 1, - anon_sym_let, - ACTIONS(117), 1, - anon_sym_LPAREN, - ACTIONS(119), 1, - anon_sym_LBRACK, - ACTIONS(121), 1, - anon_sym_LT_LT_LT, - STATE(125), 1, - sym__float, - STATE(129), 1, - sym_number, - STATE(139), 1, - sym_expression, - STATE(145), 1, - sym_struct_definition, - STATE(295), 1, - sym_integer, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(101), 2, - sym_identifier, - sym_self, - ACTIONS(109), 2, - sym_true, - sym_false, - ACTIONS(111), 3, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_BANG, - STATE(284), 4, - sym_base_ten, - sym_octal, - sym_hex, - sym_binary, - STATE(214), 19, - sym_signed_integer, - sym_unsigned_integer, - sym_scalar, - sym_vector2, - sym_vector3, - sym_vector4, - sym_boolean, - sym_function_call, - sym_method_call, - sym_unary_expression, - sym_binary_expression, - sym_if, - sym_let_in, - sym_member_access, - sym_parenthesis, - sym_list, - sym_dictionary_construction, - sym_closure_definition, - sym_constraint_set, - [5424] = 22, - ACTIONS(11), 1, - aux_sym_octal_token1, - ACTIONS(13), 1, - aux_sym_hex_token1, - ACTIONS(15), 1, - aux_sym_binary_token1, - ACTIONS(103), 1, - sym_string, - ACTIONS(105), 1, - aux_sym_base_ten_token1, - ACTIONS(107), 1, - anon_sym_LT_LPAREN, - ACTIONS(113), 1, - anon_sym_if, - ACTIONS(115), 1, - anon_sym_let, - ACTIONS(117), 1, - anon_sym_LPAREN, - ACTIONS(119), 1, - anon_sym_LBRACK, - ACTIONS(121), 1, - anon_sym_LT_LT_LT, - STATE(125), 1, - sym__float, - STATE(129), 1, - sym_number, - STATE(142), 1, - sym_expression, - STATE(145), 1, - sym_struct_definition, - STATE(295), 1, - sym_integer, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(101), 2, - sym_identifier, - sym_self, - ACTIONS(109), 2, - sym_true, - sym_false, - ACTIONS(111), 3, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_BANG, - STATE(284), 4, - sym_base_ten, - sym_octal, - sym_hex, - sym_binary, - STATE(214), 19, - sym_signed_integer, - sym_unsigned_integer, - sym_scalar, - sym_vector2, - sym_vector3, - sym_vector4, - sym_boolean, - sym_function_call, - sym_method_call, - sym_unary_expression, - sym_binary_expression, - sym_if, - sym_let_in, - sym_member_access, - sym_parenthesis, - sym_list, - sym_dictionary_construction, - sym_closure_definition, - sym_constraint_set, - [5517] = 22, - ACTIONS(11), 1, - aux_sym_octal_token1, - ACTIONS(13), 1, - aux_sym_hex_token1, - ACTIONS(15), 1, - aux_sym_binary_token1, - ACTIONS(103), 1, - sym_string, - ACTIONS(105), 1, - aux_sym_base_ten_token1, - ACTIONS(107), 1, - anon_sym_LT_LPAREN, - ACTIONS(113), 1, - anon_sym_if, - ACTIONS(115), 1, - anon_sym_let, - ACTIONS(117), 1, - anon_sym_LPAREN, - ACTIONS(119), 1, - anon_sym_LBRACK, - ACTIONS(121), 1, - anon_sym_LT_LT_LT, - STATE(125), 1, - sym__float, - STATE(129), 1, - sym_number, - STATE(143), 1, - sym_expression, - STATE(145), 1, - sym_struct_definition, - STATE(295), 1, - sym_integer, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(101), 2, - sym_identifier, - sym_self, - ACTIONS(109), 2, - sym_true, - sym_false, - ACTIONS(111), 3, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_BANG, - STATE(284), 4, - sym_base_ten, - sym_octal, - sym_hex, - sym_binary, - STATE(214), 19, - sym_signed_integer, - sym_unsigned_integer, - sym_scalar, - sym_vector2, - sym_vector3, - sym_vector4, - sym_boolean, - sym_function_call, - sym_method_call, - sym_unary_expression, - sym_binary_expression, - sym_if, - sym_let_in, - sym_member_access, - sym_parenthesis, - sym_list, - sym_dictionary_construction, - sym_closure_definition, - sym_constraint_set, - [5610] = 22, - ACTIONS(7), 1, - sym_string, - ACTIONS(9), 1, - aux_sym_base_ten_token1, - ACTIONS(11), 1, - aux_sym_octal_token1, - ACTIONS(13), 1, - aux_sym_hex_token1, - ACTIONS(15), 1, - aux_sym_binary_token1, - ACTIONS(17), 1, - anon_sym_LT_LPAREN, - ACTIONS(23), 1, - anon_sym_if, - ACTIONS(25), 1, - anon_sym_let, - ACTIONS(27), 1, - anon_sym_LPAREN, - ACTIONS(29), 1, - anon_sym_LBRACK, - ACTIONS(31), 1, - anon_sym_LT_LT_LT, - STATE(78), 1, - sym__float, - STATE(80), 1, - sym_number, - STATE(112), 1, - sym_struct_definition, - STATE(116), 1, - sym_expression, - STATE(298), 1, - sym_integer, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(5), 2, - sym_identifier, - sym_self, - ACTIONS(19), 2, - sym_true, - sym_false, - ACTIONS(21), 3, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_BANG, - STATE(284), 4, - sym_base_ten, - sym_octal, - sym_hex, - sym_binary, - STATE(109), 19, - sym_signed_integer, - sym_unsigned_integer, - sym_scalar, - sym_vector2, - sym_vector3, - sym_vector4, - sym_boolean, - sym_function_call, - sym_method_call, - sym_unary_expression, - sym_binary_expression, - sym_if, - sym_let_in, - sym_member_access, - sym_parenthesis, - sym_list, - sym_dictionary_construction, - sym_closure_definition, - sym_constraint_set, - [5703] = 22, - ACTIONS(7), 1, - sym_string, - ACTIONS(9), 1, - aux_sym_base_ten_token1, - ACTIONS(11), 1, - aux_sym_octal_token1, - ACTIONS(13), 1, - aux_sym_hex_token1, - ACTIONS(15), 1, - aux_sym_binary_token1, - ACTIONS(17), 1, - anon_sym_LT_LPAREN, - ACTIONS(23), 1, - anon_sym_if, - ACTIONS(25), 1, - anon_sym_let, - ACTIONS(27), 1, - anon_sym_LPAREN, - ACTIONS(29), 1, - anon_sym_LBRACK, - ACTIONS(31), 1, - anon_sym_LT_LT_LT, - STATE(78), 1, - sym__float, - STATE(80), 1, - sym_number, - STATE(112), 1, - sym_struct_definition, - STATE(122), 1, - sym_expression, - STATE(298), 1, - sym_integer, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(5), 2, - sym_identifier, - sym_self, - ACTIONS(19), 2, - sym_true, - sym_false, - ACTIONS(21), 3, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_BANG, - STATE(284), 4, - sym_base_ten, - sym_octal, - sym_hex, - sym_binary, - STATE(109), 19, - sym_signed_integer, - sym_unsigned_integer, - sym_scalar, - sym_vector2, - sym_vector3, - sym_vector4, - sym_boolean, - sym_function_call, - sym_method_call, - sym_unary_expression, - sym_binary_expression, - sym_if, - sym_let_in, - sym_member_access, - sym_parenthesis, - sym_list, - sym_dictionary_construction, - sym_closure_definition, - sym_constraint_set, - [5796] = 22, - ACTIONS(7), 1, - sym_string, - ACTIONS(9), 1, - aux_sym_base_ten_token1, - ACTIONS(11), 1, - aux_sym_octal_token1, - ACTIONS(13), 1, - aux_sym_hex_token1, - ACTIONS(15), 1, - aux_sym_binary_token1, - ACTIONS(17), 1, - anon_sym_LT_LPAREN, - ACTIONS(23), 1, - anon_sym_if, - ACTIONS(25), 1, - anon_sym_let, - ACTIONS(27), 1, - anon_sym_LPAREN, - ACTIONS(29), 1, - anon_sym_LBRACK, - ACTIONS(31), 1, - anon_sym_LT_LT_LT, - STATE(78), 1, - sym__float, - STATE(80), 1, - sym_number, - STATE(92), 1, - sym_expression, - STATE(112), 1, - sym_struct_definition, - STATE(298), 1, - sym_integer, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(5), 2, - sym_identifier, - sym_self, - ACTIONS(19), 2, - sym_true, - sym_false, - ACTIONS(21), 3, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_BANG, - STATE(284), 4, - sym_base_ten, - sym_octal, - sym_hex, - sym_binary, - STATE(109), 19, - sym_signed_integer, - sym_unsigned_integer, - sym_scalar, - sym_vector2, - sym_vector3, - sym_vector4, - sym_boolean, - sym_function_call, - sym_method_call, - sym_unary_expression, - sym_binary_expression, - sym_if, - sym_let_in, - sym_member_access, - sym_parenthesis, - sym_list, - sym_dictionary_construction, - sym_closure_definition, - sym_constraint_set, - [5889] = 22, - ACTIONS(7), 1, - sym_string, - ACTIONS(9), 1, - aux_sym_base_ten_token1, - ACTIONS(11), 1, - aux_sym_octal_token1, - ACTIONS(13), 1, - aux_sym_hex_token1, - ACTIONS(15), 1, - aux_sym_binary_token1, - ACTIONS(17), 1, - anon_sym_LT_LPAREN, - ACTIONS(23), 1, - anon_sym_if, - ACTIONS(25), 1, - anon_sym_let, - ACTIONS(27), 1, - anon_sym_LPAREN, - ACTIONS(29), 1, - anon_sym_LBRACK, - ACTIONS(31), 1, - anon_sym_LT_LT_LT, - STATE(78), 1, - sym__float, - STATE(80), 1, - sym_number, - STATE(112), 1, - sym_struct_definition, - STATE(209), 1, - sym_expression, - STATE(298), 1, - sym_integer, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(5), 2, - sym_identifier, - sym_self, - ACTIONS(19), 2, - sym_true, - sym_false, - ACTIONS(21), 3, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_BANG, - STATE(284), 4, - sym_base_ten, - sym_octal, - sym_hex, - sym_binary, - STATE(109), 19, - sym_signed_integer, - sym_unsigned_integer, - sym_scalar, - sym_vector2, - sym_vector3, - sym_vector4, - sym_boolean, - sym_function_call, - sym_method_call, - sym_unary_expression, - sym_binary_expression, - sym_if, - sym_let_in, - sym_member_access, - sym_parenthesis, - sym_list, - sym_dictionary_construction, - sym_closure_definition, - sym_constraint_set, - [5982] = 22, - ACTIONS(11), 1, - aux_sym_octal_token1, - ACTIONS(13), 1, - aux_sym_hex_token1, - ACTIONS(15), 1, - aux_sym_binary_token1, - ACTIONS(103), 1, - sym_string, - ACTIONS(105), 1, - aux_sym_base_ten_token1, - ACTIONS(107), 1, - anon_sym_LT_LPAREN, - ACTIONS(113), 1, - anon_sym_if, - ACTIONS(115), 1, - anon_sym_let, - ACTIONS(117), 1, - anon_sym_LPAREN, - ACTIONS(119), 1, - anon_sym_LBRACK, - ACTIONS(121), 1, - anon_sym_LT_LT_LT, - STATE(125), 1, - sym__float, - STATE(129), 1, - sym_number, - STATE(133), 1, - sym_expression, - STATE(145), 1, - sym_struct_definition, - STATE(295), 1, - sym_integer, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(101), 2, - sym_identifier, - sym_self, - ACTIONS(109), 2, - sym_true, - sym_false, - ACTIONS(111), 3, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_BANG, - STATE(284), 4, - sym_base_ten, - sym_octal, - sym_hex, - sym_binary, - STATE(214), 19, - sym_signed_integer, - sym_unsigned_integer, - sym_scalar, - sym_vector2, - sym_vector3, - sym_vector4, - sym_boolean, - sym_function_call, - sym_method_call, - sym_unary_expression, - sym_binary_expression, - sym_if, - sym_let_in, - sym_member_access, - sym_parenthesis, - sym_list, - sym_dictionary_construction, - sym_closure_definition, - sym_constraint_set, - [6075] = 22, - ACTIONS(7), 1, - sym_string, - ACTIONS(9), 1, - aux_sym_base_ten_token1, - ACTIONS(11), 1, - aux_sym_octal_token1, - ACTIONS(13), 1, - aux_sym_hex_token1, - ACTIONS(15), 1, - aux_sym_binary_token1, - ACTIONS(17), 1, - anon_sym_LT_LPAREN, - ACTIONS(23), 1, - anon_sym_if, - ACTIONS(25), 1, - anon_sym_let, - ACTIONS(27), 1, - anon_sym_LPAREN, - ACTIONS(29), 1, - anon_sym_LBRACK, - ACTIONS(31), 1, - anon_sym_LT_LT_LT, - STATE(78), 1, - sym__float, - STATE(80), 1, - sym_number, - STATE(112), 1, - sym_struct_definition, - STATE(210), 1, - sym_expression, - STATE(298), 1, - sym_integer, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(5), 2, - sym_identifier, - sym_self, - ACTIONS(19), 2, - sym_true, - sym_false, - ACTIONS(21), 3, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_BANG, - STATE(284), 4, - sym_base_ten, - sym_octal, - sym_hex, - sym_binary, - STATE(109), 19, - sym_signed_integer, - sym_unsigned_integer, - sym_scalar, - sym_vector2, - sym_vector3, - sym_vector4, - sym_boolean, - sym_function_call, - sym_method_call, - sym_unary_expression, - sym_binary_expression, - sym_if, - sym_let_in, - sym_member_access, - sym_parenthesis, - sym_list, - sym_dictionary_construction, - sym_closure_definition, - sym_constraint_set, - [6168] = 22, - ACTIONS(11), 1, - aux_sym_octal_token1, - ACTIONS(13), 1, - aux_sym_hex_token1, - ACTIONS(15), 1, - aux_sym_binary_token1, - ACTIONS(103), 1, - sym_string, - ACTIONS(105), 1, - aux_sym_base_ten_token1, - ACTIONS(107), 1, - anon_sym_LT_LPAREN, - ACTIONS(113), 1, - anon_sym_if, - ACTIONS(115), 1, - anon_sym_let, - ACTIONS(117), 1, - anon_sym_LPAREN, - ACTIONS(119), 1, - anon_sym_LBRACK, - ACTIONS(121), 1, - anon_sym_LT_LT_LT, - STATE(125), 1, - sym__float, - STATE(129), 1, - sym_number, - STATE(145), 1, - sym_struct_definition, - STATE(154), 1, - sym_expression, - STATE(295), 1, - sym_integer, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(101), 2, - sym_identifier, - sym_self, - ACTIONS(109), 2, - sym_true, - sym_false, - ACTIONS(111), 3, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_BANG, - STATE(284), 4, - sym_base_ten, - sym_octal, - sym_hex, - sym_binary, - STATE(214), 19, - sym_signed_integer, - sym_unsigned_integer, - sym_scalar, - sym_vector2, - sym_vector3, - sym_vector4, - sym_boolean, - sym_function_call, - sym_method_call, - sym_unary_expression, - sym_binary_expression, - sym_if, - sym_let_in, - sym_member_access, - sym_parenthesis, - sym_list, - sym_dictionary_construction, - sym_closure_definition, - sym_constraint_set, - [6261] = 22, - ACTIONS(11), 1, - aux_sym_octal_token1, - ACTIONS(13), 1, - aux_sym_hex_token1, - ACTIONS(15), 1, - aux_sym_binary_token1, - ACTIONS(103), 1, - sym_string, - ACTIONS(105), 1, - aux_sym_base_ten_token1, - ACTIONS(107), 1, - anon_sym_LT_LPAREN, - ACTIONS(113), 1, - anon_sym_if, - ACTIONS(115), 1, - anon_sym_let, - ACTIONS(117), 1, - anon_sym_LPAREN, - ACTIONS(119), 1, - anon_sym_LBRACK, - ACTIONS(121), 1, - anon_sym_LT_LT_LT, - STATE(125), 1, - sym__float, - STATE(129), 1, - sym_number, - STATE(145), 1, - sym_struct_definition, - STATE(211), 1, - sym_expression, - STATE(295), 1, - sym_integer, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(101), 2, - sym_identifier, - sym_self, - ACTIONS(109), 2, - sym_true, - sym_false, - ACTIONS(111), 3, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_BANG, - STATE(284), 4, - sym_base_ten, - sym_octal, - sym_hex, - sym_binary, - STATE(214), 19, - sym_signed_integer, - sym_unsigned_integer, - sym_scalar, - sym_vector2, - sym_vector3, - sym_vector4, - sym_boolean, - sym_function_call, - sym_method_call, - sym_unary_expression, - sym_binary_expression, - sym_if, - sym_let_in, - sym_member_access, - sym_parenthesis, - sym_list, - sym_dictionary_construction, - sym_closure_definition, - sym_constraint_set, - [6354] = 22, - ACTIONS(7), 1, - sym_string, - ACTIONS(9), 1, - aux_sym_base_ten_token1, - ACTIONS(11), 1, - aux_sym_octal_token1, - ACTIONS(13), 1, - aux_sym_hex_token1, - ACTIONS(15), 1, - aux_sym_binary_token1, - ACTIONS(17), 1, - anon_sym_LT_LPAREN, - ACTIONS(23), 1, - anon_sym_if, - ACTIONS(25), 1, - anon_sym_let, - ACTIONS(27), 1, - anon_sym_LPAREN, - ACTIONS(29), 1, - anon_sym_LBRACK, - ACTIONS(31), 1, - anon_sym_LT_LT_LT, - STATE(78), 1, - sym__float, - STATE(80), 1, - sym_number, - STATE(112), 1, - sym_struct_definition, - STATE(212), 1, - sym_expression, - STATE(298), 1, - sym_integer, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(5), 2, - sym_identifier, - sym_self, - ACTIONS(19), 2, - sym_true, - sym_false, - ACTIONS(21), 3, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_BANG, - STATE(284), 4, - sym_base_ten, - sym_octal, - sym_hex, - sym_binary, - STATE(109), 19, - sym_signed_integer, - sym_unsigned_integer, - sym_scalar, - sym_vector2, - sym_vector3, - sym_vector4, - sym_boolean, - sym_function_call, - sym_method_call, - sym_unary_expression, - sym_binary_expression, - sym_if, - sym_let_in, - sym_member_access, - sym_parenthesis, - sym_list, - sym_dictionary_construction, - sym_closure_definition, - sym_constraint_set, - [6447] = 22, - ACTIONS(7), 1, - sym_string, - ACTIONS(9), 1, - aux_sym_base_ten_token1, - ACTIONS(11), 1, - aux_sym_octal_token1, - ACTIONS(13), 1, - aux_sym_hex_token1, - ACTIONS(15), 1, - aux_sym_binary_token1, - ACTIONS(17), 1, - anon_sym_LT_LPAREN, - ACTIONS(23), 1, - anon_sym_if, - ACTIONS(25), 1, - anon_sym_let, - ACTIONS(27), 1, - anon_sym_LPAREN, - ACTIONS(29), 1, - anon_sym_LBRACK, - ACTIONS(31), 1, - anon_sym_LT_LT_LT, - STATE(78), 1, - sym__float, - STATE(80), 1, - sym_number, - STATE(112), 1, - sym_struct_definition, - STATE(167), 1, - sym_expression, - STATE(298), 1, - sym_integer, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(5), 2, - sym_identifier, - sym_self, - ACTIONS(19), 2, - sym_true, - sym_false, - ACTIONS(21), 3, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_BANG, - STATE(284), 4, - sym_base_ten, - sym_octal, - sym_hex, - sym_binary, - STATE(109), 19, - sym_signed_integer, - sym_unsigned_integer, - sym_scalar, - sym_vector2, - sym_vector3, - sym_vector4, - sym_boolean, - sym_function_call, - sym_method_call, - sym_unary_expression, - sym_binary_expression, - sym_if, - sym_let_in, - sym_member_access, - sym_parenthesis, - sym_list, - sym_dictionary_construction, - sym_closure_definition, - sym_constraint_set, - [6540] = 22, - ACTIONS(7), 1, - sym_string, - ACTIONS(9), 1, - aux_sym_base_ten_token1, - ACTIONS(11), 1, - aux_sym_octal_token1, - ACTIONS(13), 1, - aux_sym_hex_token1, - ACTIONS(15), 1, - aux_sym_binary_token1, - ACTIONS(17), 1, - anon_sym_LT_LPAREN, - ACTIONS(23), 1, - anon_sym_if, - ACTIONS(25), 1, - anon_sym_let, - ACTIONS(27), 1, - anon_sym_LPAREN, - ACTIONS(29), 1, - anon_sym_LBRACK, - ACTIONS(31), 1, - anon_sym_LT_LT_LT, - STATE(78), 1, - sym__float, - STATE(80), 1, - sym_number, - STATE(112), 1, - sym_struct_definition, - STATE(217), 1, - sym_expression, - STATE(298), 1, - sym_integer, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(5), 2, - sym_identifier, - sym_self, - ACTIONS(19), 2, - sym_true, - sym_false, - ACTIONS(21), 3, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_BANG, - STATE(284), 4, - sym_base_ten, - sym_octal, - sym_hex, - sym_binary, - STATE(109), 19, - sym_signed_integer, - sym_unsigned_integer, - sym_scalar, - sym_vector2, - sym_vector3, - sym_vector4, - sym_boolean, - sym_function_call, - sym_method_call, - sym_unary_expression, - sym_binary_expression, - sym_if, - sym_let_in, - sym_member_access, - sym_parenthesis, - sym_list, - sym_dictionary_construction, - sym_closure_definition, - sym_constraint_set, - [6633] = 22, - ACTIONS(7), 1, - sym_string, - ACTIONS(11), 1, - aux_sym_octal_token1, - ACTIONS(13), 1, - aux_sym_hex_token1, - ACTIONS(15), 1, - aux_sym_binary_token1, - ACTIONS(17), 1, - anon_sym_LT_LPAREN, - ACTIONS(27), 1, - anon_sym_LPAREN, - ACTIONS(29), 1, - anon_sym_LBRACK, - ACTIONS(31), 1, - anon_sym_LT_LT_LT, - ACTIONS(93), 1, - aux_sym_base_ten_token1, - ACTIONS(97), 1, - anon_sym_if, - ACTIONS(99), 1, - anon_sym_let, - STATE(130), 1, - sym__float, - STATE(141), 1, - sym_number, - STATE(216), 1, - sym_struct_definition, - STATE(218), 1, - sym_expression, - STATE(298), 1, - sym_integer, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(5), 2, - sym_identifier, - sym_self, - ACTIONS(19), 2, - sym_true, - sym_false, - ACTIONS(95), 3, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_BANG, - STATE(284), 4, - sym_base_ten, - sym_octal, - sym_hex, - sym_binary, - STATE(109), 19, - sym_signed_integer, - sym_unsigned_integer, - sym_scalar, - sym_vector2, - sym_vector3, - sym_vector4, - sym_boolean, - sym_function_call, - sym_method_call, - sym_unary_expression, - sym_binary_expression, - sym_if, - sym_let_in, - sym_member_access, - sym_parenthesis, - sym_list, - sym_dictionary_construction, - sym_closure_definition, - sym_constraint_set, - [6726] = 22, - ACTIONS(7), 1, - sym_string, - ACTIONS(11), 1, - aux_sym_octal_token1, - ACTIONS(13), 1, - aux_sym_hex_token1, - ACTIONS(15), 1, - aux_sym_binary_token1, - ACTIONS(17), 1, - anon_sym_LT_LPAREN, - ACTIONS(27), 1, - anon_sym_LPAREN, - ACTIONS(29), 1, - anon_sym_LBRACK, - ACTIONS(31), 1, - anon_sym_LT_LT_LT, - ACTIONS(93), 1, - aux_sym_base_ten_token1, - ACTIONS(97), 1, - anon_sym_if, - ACTIONS(99), 1, - anon_sym_let, - STATE(130), 1, - sym__float, - STATE(141), 1, - sym_number, - STATE(216), 1, - sym_struct_definition, - STATE(219), 1, - sym_expression, - STATE(298), 1, - sym_integer, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(5), 2, - sym_identifier, - sym_self, - ACTIONS(19), 2, - sym_true, - sym_false, - ACTIONS(95), 3, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_BANG, - STATE(284), 4, - sym_base_ten, - sym_octal, - sym_hex, - sym_binary, - STATE(109), 19, - sym_signed_integer, - sym_unsigned_integer, - sym_scalar, - sym_vector2, - sym_vector3, - sym_vector4, - sym_boolean, - sym_function_call, - sym_method_call, - sym_unary_expression, - sym_binary_expression, - sym_if, - sym_let_in, - sym_member_access, - sym_parenthesis, - sym_list, - sym_dictionary_construction, - sym_closure_definition, - sym_constraint_set, - [6819] = 22, - ACTIONS(7), 1, - sym_string, - ACTIONS(11), 1, - aux_sym_octal_token1, - ACTIONS(13), 1, - aux_sym_hex_token1, - ACTIONS(15), 1, - aux_sym_binary_token1, - ACTIONS(17), 1, - anon_sym_LT_LPAREN, - ACTIONS(27), 1, - anon_sym_LPAREN, - ACTIONS(29), 1, - anon_sym_LBRACK, - ACTIONS(31), 1, - anon_sym_LT_LT_LT, - ACTIONS(93), 1, - aux_sym_base_ten_token1, - ACTIONS(97), 1, - anon_sym_if, - ACTIONS(99), 1, - anon_sym_let, - STATE(130), 1, - sym__float, - STATE(141), 1, - sym_number, - STATE(199), 1, - sym_expression, - STATE(216), 1, - sym_struct_definition, - STATE(298), 1, - sym_integer, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(5), 2, - sym_identifier, - sym_self, - ACTIONS(19), 2, - sym_true, - sym_false, - ACTIONS(95), 3, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_BANG, - STATE(284), 4, - sym_base_ten, - sym_octal, - sym_hex, - sym_binary, - STATE(109), 19, - sym_signed_integer, - sym_unsigned_integer, - sym_scalar, - sym_vector2, - sym_vector3, - sym_vector4, - sym_boolean, - sym_function_call, - sym_method_call, - sym_unary_expression, - sym_binary_expression, - sym_if, - sym_let_in, - sym_member_access, - sym_parenthesis, - sym_list, - sym_dictionary_construction, - sym_closure_definition, - sym_constraint_set, - [6912] = 6, - ACTIONS(125), 1, - sym_identifier, - ACTIONS(127), 1, - sym_unit_quote, - STATE(88), 1, - sym__unit, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(129), 10, - anon_sym_STAR, - anon_sym_GT_GT, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_else, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(123), 21, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - anon_sym_GT_GT_GT, - [6961] = 4, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(135), 2, - aux_sym_signed_integer_token1, - aux_sym_unsigned_integer_token1, - ACTIONS(133), 10, - sym_identifier, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_else, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(131), 22, - ts_builtin_sym_end, - sym_unit_quote, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - [7006] = 4, - ACTIONS(141), 1, - anon_sym_DOT, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(139), 11, - sym_identifier, - anon_sym_STAR, - anon_sym_GT_GT, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_else, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(137), 21, - ts_builtin_sym_end, - sym_unit_quote, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - anon_sym_GT_GT_GT, - [7050] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(145), 11, - sym_identifier, - anon_sym_STAR, - anon_sym_GT_GT, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_else, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(143), 22, - ts_builtin_sym_end, - sym_unit_quote, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - anon_sym_GT_GT_GT, - [7092] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(133), 11, - sym_identifier, - anon_sym_STAR, - anon_sym_GT_GT, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_else, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(131), 22, - ts_builtin_sym_end, - sym_unit_quote, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - anon_sym_GT_GT_GT, - [7134] = 4, - ACTIONS(151), 1, - anon_sym_DASH_GT, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(149), 9, - anon_sym_DASH, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(147), 22, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - [7177] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(155), 9, - anon_sym_DASH, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(153), 23, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - anon_sym_DASH_GT, - [7218] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(159), 9, - anon_sym_DASH, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(157), 23, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - anon_sym_DASH_GT, - [7259] = 7, - ACTIONS(163), 1, - anon_sym_DOT, - ACTIONS(165), 1, - anon_sym_COLON_COLON, - ACTIONS(169), 1, - anon_sym_LPAREN, - STATE(90), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(167), 8, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(161), 20, - ts_builtin_sym_end, - anon_sym_COMMA, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, - anon_sym_RPAREN, - anon_sym_RBRACK, - [7308] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(173), 9, - anon_sym_DASH, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(171), 23, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - anon_sym_DASH_GT, - [7349] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(177), 9, - anon_sym_STAR, - anon_sym_GT_GT, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(175), 23, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - anon_sym_GT_GT_GT, - [7390] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(181), 8, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(179), 23, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - [7430] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(185), 8, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(183), 23, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - [7470] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(189), 8, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(187), 23, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - [7510] = 10, - ACTIONS(163), 1, - anon_sym_DOT, - ACTIONS(165), 1, - anon_sym_COLON_COLON, - ACTIONS(169), 1, - anon_sym_LPAREN, - ACTIONS(191), 1, - anon_sym_STAR_STAR, - ACTIONS(193), 1, - anon_sym_STAR, - ACTIONS(195), 1, - anon_sym_SLASH, - STATE(90), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(167), 7, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(161), 17, - ts_builtin_sym_end, - anon_sym_COMMA, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_else, - anon_sym_SEMI, - anon_sym_RPAREN, - anon_sym_RBRACK, - [7564] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(199), 8, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(197), 23, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - [7604] = 8, - ACTIONS(163), 1, - anon_sym_DOT, - ACTIONS(165), 1, - anon_sym_COLON_COLON, - ACTIONS(169), 1, - anon_sym_LPAREN, - ACTIONS(191), 1, - anon_sym_STAR_STAR, - STATE(90), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(167), 8, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(161), 18, - ts_builtin_sym_end, - anon_sym_COMMA, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_else, - anon_sym_SEMI, - anon_sym_RPAREN, - anon_sym_RBRACK, - [7654] = 11, - ACTIONS(163), 1, - anon_sym_DOT, - ACTIONS(165), 1, - anon_sym_COLON_COLON, - ACTIONS(169), 1, - anon_sym_LPAREN, - ACTIONS(191), 1, - anon_sym_STAR_STAR, - ACTIONS(193), 1, - anon_sym_STAR, - ACTIONS(195), 1, - anon_sym_SLASH, - STATE(90), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(201), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(167), 7, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(161), 15, - ts_builtin_sym_end, - anon_sym_COMMA, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_else, - anon_sym_SEMI, - anon_sym_RPAREN, - anon_sym_RBRACK, - [7710] = 12, - ACTIONS(163), 1, - anon_sym_DOT, - ACTIONS(165), 1, - anon_sym_COLON_COLON, - ACTIONS(169), 1, - anon_sym_LPAREN, - ACTIONS(191), 1, - anon_sym_STAR_STAR, - ACTIONS(193), 1, - anon_sym_STAR, - ACTIONS(195), 1, - anon_sym_SLASH, - STATE(90), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(201), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(203), 2, - anon_sym_LT_LT, - anon_sym_GT_GT, - ACTIONS(167), 7, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(161), 13, - ts_builtin_sym_end, - anon_sym_COMMA, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_else, - anon_sym_SEMI, - anon_sym_RPAREN, - anon_sym_RBRACK, - [7768] = 14, - ACTIONS(163), 1, - anon_sym_DOT, - ACTIONS(165), 1, - anon_sym_COLON_COLON, - ACTIONS(169), 1, - anon_sym_LPAREN, - ACTIONS(191), 1, - anon_sym_STAR_STAR, - ACTIONS(193), 1, - anon_sym_STAR, - ACTIONS(195), 1, - anon_sym_SLASH, - ACTIONS(205), 1, - anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - STATE(90), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(201), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(203), 2, - anon_sym_LT_LT, - anon_sym_GT_GT, - ACTIONS(167), 5, - anon_sym_PIPE, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(161), 13, - ts_builtin_sym_end, - anon_sym_COMMA, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_else, - anon_sym_SEMI, - anon_sym_RPAREN, - anon_sym_RBRACK, - [7830] = 13, - ACTIONS(163), 1, - anon_sym_DOT, - ACTIONS(165), 1, - anon_sym_COLON_COLON, - ACTIONS(169), 1, - anon_sym_LPAREN, - ACTIONS(191), 1, - anon_sym_STAR_STAR, - ACTIONS(193), 1, - anon_sym_STAR, - ACTIONS(195), 1, - anon_sym_SLASH, - ACTIONS(205), 1, - anon_sym_AMP, - STATE(90), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(201), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(203), 2, - anon_sym_LT_LT, - anon_sym_GT_GT, - ACTIONS(167), 6, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(161), 13, - ts_builtin_sym_end, - anon_sym_COMMA, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_else, - anon_sym_SEMI, - anon_sym_RPAREN, - anon_sym_RBRACK, - [7890] = 15, - ACTIONS(163), 1, - anon_sym_DOT, - ACTIONS(165), 1, - anon_sym_COLON_COLON, - ACTIONS(169), 1, - anon_sym_LPAREN, - ACTIONS(191), 1, - anon_sym_STAR_STAR, - ACTIONS(193), 1, - anon_sym_STAR, - ACTIONS(195), 1, - anon_sym_SLASH, - ACTIONS(205), 1, - anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, - anon_sym_PIPE, - STATE(90), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(201), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(203), 2, - anon_sym_LT_LT, - anon_sym_GT_GT, - ACTIONS(167), 4, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(161), 13, - ts_builtin_sym_end, - anon_sym_COMMA, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_else, - anon_sym_SEMI, - anon_sym_RPAREN, - anon_sym_RBRACK, - [7954] = 17, - ACTIONS(163), 1, - anon_sym_DOT, - ACTIONS(165), 1, - anon_sym_COLON_COLON, - ACTIONS(169), 1, - anon_sym_LPAREN, - ACTIONS(191), 1, - anon_sym_STAR_STAR, - ACTIONS(193), 1, - anon_sym_STAR, - ACTIONS(195), 1, - anon_sym_SLASH, - ACTIONS(205), 1, - anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, - anon_sym_PIPE, - STATE(90), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(167), 2, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(201), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(203), 2, - anon_sym_LT_LT, - anon_sym_GT_GT, - ACTIONS(211), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(213), 4, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - ACTIONS(161), 9, - ts_builtin_sym_end, - anon_sym_COMMA, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_else, - anon_sym_SEMI, - anon_sym_RPAREN, - anon_sym_RBRACK, - [8022] = 18, - ACTIONS(163), 1, - anon_sym_DOT, - ACTIONS(165), 1, - anon_sym_COLON_COLON, - ACTIONS(169), 1, - anon_sym_LPAREN, - ACTIONS(191), 1, - anon_sym_STAR_STAR, - ACTIONS(193), 1, - anon_sym_STAR, - ACTIONS(195), 1, - anon_sym_SLASH, - ACTIONS(205), 1, - anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, - anon_sym_PIPE, - ACTIONS(215), 1, - anon_sym_AMP_AMP, - STATE(90), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(167), 2, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(201), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(203), 2, - anon_sym_LT_LT, - anon_sym_GT_GT, - ACTIONS(211), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(213), 4, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - ACTIONS(161), 8, - ts_builtin_sym_end, - anon_sym_COMMA, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_else, - anon_sym_SEMI, - anon_sym_RPAREN, - anon_sym_RBRACK, - [8092] = 19, - ACTIONS(163), 1, - anon_sym_DOT, - ACTIONS(165), 1, - anon_sym_COLON_COLON, - ACTIONS(169), 1, - anon_sym_LPAREN, - ACTIONS(191), 1, - anon_sym_STAR_STAR, - ACTIONS(193), 1, - anon_sym_STAR, - ACTIONS(195), 1, - anon_sym_SLASH, - ACTIONS(205), 1, - anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, - anon_sym_PIPE, - ACTIONS(215), 1, - anon_sym_AMP_AMP, - ACTIONS(217), 1, - anon_sym_PIPE_PIPE, - STATE(90), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(167), 2, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(201), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(203), 2, - anon_sym_LT_LT, - anon_sym_GT_GT, - ACTIONS(211), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(213), 4, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - ACTIONS(161), 7, - ts_builtin_sym_end, - anon_sym_COMMA, - anon_sym_CARET_CARET, - anon_sym_else, - anon_sym_SEMI, - anon_sym_RPAREN, - anon_sym_RBRACK, - [8164] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(149), 8, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(147), 23, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - [8204] = 20, - ACTIONS(163), 1, - anon_sym_DOT, - ACTIONS(165), 1, - anon_sym_COLON_COLON, - ACTIONS(169), 1, - anon_sym_LPAREN, - ACTIONS(191), 1, - anon_sym_STAR_STAR, - ACTIONS(193), 1, - anon_sym_STAR, - ACTIONS(195), 1, - anon_sym_SLASH, - ACTIONS(205), 1, - anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, - anon_sym_PIPE, - ACTIONS(215), 1, - anon_sym_AMP_AMP, - ACTIONS(217), 1, - anon_sym_PIPE_PIPE, - ACTIONS(221), 1, - anon_sym_CARET_CARET, - STATE(90), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(201), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(203), 2, - anon_sym_LT_LT, - anon_sym_GT_GT, - ACTIONS(211), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(223), 2, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(213), 4, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - ACTIONS(219), 6, - ts_builtin_sym_end, - anon_sym_COMMA, - anon_sym_else, - anon_sym_SEMI, - anon_sym_RPAREN, - anon_sym_RBRACK, - [8278] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(227), 8, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(225), 23, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - [8318] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(231), 8, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(229), 23, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - [8358] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(235), 8, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(233), 23, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - [8398] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(239), 8, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(237), 23, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - [8438] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(243), 8, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(241), 23, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - [8478] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(247), 8, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(245), 23, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - [8518] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(251), 8, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(249), 23, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - [8558] = 4, - ACTIONS(253), 1, - anon_sym_DASH_GT, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(243), 9, - anon_sym_DASH, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(241), 21, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_else, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - [8600] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(257), 8, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(255), 23, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - [8640] = 20, - ACTIONS(163), 1, - anon_sym_DOT, - ACTIONS(165), 1, - anon_sym_COLON_COLON, - ACTIONS(169), 1, - anon_sym_LPAREN, - ACTIONS(191), 1, - anon_sym_STAR_STAR, - ACTIONS(193), 1, - anon_sym_STAR, - ACTIONS(195), 1, - anon_sym_SLASH, - ACTIONS(205), 1, - anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, - anon_sym_PIPE, - ACTIONS(215), 1, - anon_sym_AMP_AMP, - ACTIONS(217), 1, - anon_sym_PIPE_PIPE, - ACTIONS(221), 1, - anon_sym_CARET_CARET, - STATE(90), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(201), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(203), 2, - anon_sym_LT_LT, - anon_sym_GT_GT, - ACTIONS(211), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(261), 2, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(213), 4, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - ACTIONS(259), 6, - ts_builtin_sym_end, - anon_sym_COMMA, - anon_sym_else, - anon_sym_SEMI, - anon_sym_RPAREN, - anon_sym_RBRACK, - [8714] = 20, - ACTIONS(163), 1, - anon_sym_DOT, - ACTIONS(165), 1, - anon_sym_COLON_COLON, - ACTIONS(169), 1, - anon_sym_LPAREN, - ACTIONS(191), 1, - anon_sym_STAR_STAR, - ACTIONS(193), 1, - anon_sym_STAR, - ACTIONS(195), 1, - anon_sym_SLASH, - ACTIONS(205), 1, - anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, - anon_sym_PIPE, - ACTIONS(215), 1, - anon_sym_AMP_AMP, - ACTIONS(217), 1, - anon_sym_PIPE_PIPE, - ACTIONS(221), 1, - anon_sym_CARET_CARET, - STATE(90), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(201), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(203), 2, - anon_sym_LT_LT, - anon_sym_GT_GT, - ACTIONS(211), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(265), 2, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(213), 4, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - ACTIONS(263), 6, - ts_builtin_sym_end, - anon_sym_COMMA, - anon_sym_else, - anon_sym_SEMI, - anon_sym_RPAREN, - anon_sym_RBRACK, - [8788] = 20, - ACTIONS(163), 1, - anon_sym_DOT, - ACTIONS(165), 1, - anon_sym_COLON_COLON, - ACTIONS(169), 1, - anon_sym_LPAREN, - ACTIONS(191), 1, - anon_sym_STAR_STAR, - ACTIONS(193), 1, - anon_sym_STAR, - ACTIONS(195), 1, - anon_sym_SLASH, - ACTIONS(205), 1, - anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, - anon_sym_PIPE, - ACTIONS(215), 1, - anon_sym_AMP_AMP, - ACTIONS(217), 1, - anon_sym_PIPE_PIPE, - ACTIONS(221), 1, - anon_sym_CARET_CARET, - STATE(90), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(201), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(203), 2, - anon_sym_LT_LT, - anon_sym_GT_GT, - ACTIONS(211), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(269), 2, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(213), 4, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - ACTIONS(267), 6, - ts_builtin_sym_end, - anon_sym_COMMA, - anon_sym_else, - anon_sym_SEMI, - anon_sym_RPAREN, - anon_sym_RBRACK, - [8862] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(273), 8, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(271), 23, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - [8902] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(277), 8, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(275), 23, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - [8942] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(281), 8, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(279), 23, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - [8982] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(285), 8, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(283), 23, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - [9022] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(289), 8, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(287), 23, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - [9062] = 20, - ACTIONS(163), 1, - anon_sym_DOT, - ACTIONS(165), 1, - anon_sym_COLON_COLON, - ACTIONS(169), 1, - anon_sym_LPAREN, - ACTIONS(191), 1, - anon_sym_STAR_STAR, - ACTIONS(193), 1, - anon_sym_STAR, - ACTIONS(195), 1, - anon_sym_SLASH, - ACTIONS(205), 1, - anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, - anon_sym_PIPE, - ACTIONS(215), 1, - anon_sym_AMP_AMP, - ACTIONS(217), 1, - anon_sym_PIPE_PIPE, - ACTIONS(221), 1, - anon_sym_CARET_CARET, - STATE(90), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(201), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(203), 2, - anon_sym_LT_LT, - anon_sym_GT_GT, - ACTIONS(211), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(293), 2, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(213), 4, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - ACTIONS(291), 6, - ts_builtin_sym_end, - anon_sym_COMMA, - anon_sym_else, - anon_sym_SEMI, - anon_sym_RPAREN, - anon_sym_RBRACK, - [9136] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(297), 8, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(295), 23, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - [9176] = 4, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(135), 2, - aux_sym_signed_integer_token1, - aux_sym_unsigned_integer_token1, - ACTIONS(133), 7, - sym_identifier, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - ACTIONS(131), 19, - sym_unit_quote, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_RPAREN_GT, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_LPAREN, - [9215] = 5, - STATE(204), 1, - sym__unit, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(299), 2, - sym_identifier, - sym_unit_quote, - ACTIONS(129), 6, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - ACTIONS(123), 18, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_RPAREN_GT, - anon_sym_COLON_COLON, + anon_sym_STAR, + anon_sym_AMP, + anon_sym_PIPE, + anon_sym_CARET, + anon_sym_GT, + anon_sym_LT, + anon_sym_else, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(95), 23, + ts_builtin_sym_end, + sym_unit_quote, + anon_sym_DOT, + anon_sym_COMMA, + anon_sym_RBRACE, + anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, anon_sym_STAR_STAR, @@ -9794,114 +5773,42 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, + anon_sym_SEMI, anon_sym_LPAREN, - [9255] = 4, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(135), 2, - aux_sym_signed_integer_token1, - aux_sym_unsigned_integer_token1, - ACTIONS(133), 7, + anon_sym_RPAREN, + anon_sym_RBRACK, + [4621] = 6, + ACTIONS(103), 1, sym_identifier, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - ACTIONS(131), 18, + ACTIONS(105), 1, sym_unit_quote, - anon_sym_DOT, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_LPAREN, - [9293] = 20, - ACTIONS(163), 1, - anon_sym_DOT, - ACTIONS(165), 1, - anon_sym_COLON_COLON, - ACTIONS(169), 1, - anon_sym_LPAREN, - ACTIONS(191), 1, - anon_sym_STAR_STAR, - ACTIONS(193), 1, - anon_sym_STAR, - ACTIONS(195), 1, - anon_sym_SLASH, - ACTIONS(205), 1, - anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, - anon_sym_PIPE, - ACTIONS(215), 1, - anon_sym_AMP_AMP, - ACTIONS(217), 1, - anon_sym_PIPE_PIPE, - ACTIONS(221), 1, - anon_sym_CARET_CARET, - ACTIONS(303), 1, - anon_sym_EQ, - STATE(90), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(201), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(203), 2, - anon_sym_LT_LT, - anon_sym_GT_GT, - ACTIONS(211), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(301), 2, - anon_sym_COMMA, - anon_sym_RPAREN, - ACTIONS(213), 4, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - [9362] = 3, + STATE(60), 1, + sym__unit, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(145), 6, + ACTIONS(107), 10, anon_sym_STAR, + anon_sym_GT_GT, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(143), 20, - sym_identifier, - sym_unit_quote, + anon_sym_else, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(101), 22, + ts_builtin_sym_end, anon_sym_DOT, anon_sym_COMMA, - anon_sym_RPAREN_GT, + anon_sym_RBRACE, anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, anon_sym_STAR_STAR, anon_sym_SLASH, anon_sym_LT_LT, - anon_sym_GT_GT, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, @@ -9909,101 +5816,39 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, + anon_sym_SEMI, anon_sym_LPAREN, - [9397] = 4, - ACTIONS(305), 1, - anon_sym_DOT, + anon_sym_RPAREN, + anon_sym_RBRACK, + anon_sym_GT_GT_GT, + [4671] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(139), 6, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - ACTIONS(137), 19, - sym_identifier, - sym_unit_quote, - anon_sym_COMMA, - anon_sym_RPAREN_GT, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_LPAREN, - [9434] = 6, - ACTIONS(125), 1, + ACTIONS(111), 11, sym_identifier, - ACTIONS(127), 1, - sym_unit_quote, - STATE(88), 1, - sym__unit, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(129), 6, anon_sym_STAR, + anon_sym_GT_GT, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(123), 17, - anon_sym_DOT, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_LPAREN, - [9475] = 6, - ACTIONS(307), 1, + anon_sym_else, anon_sym_EQ, - ACTIONS(309), 1, anon_sym_COLON, - STATE(277), 1, - sym_declaration_type, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(243), 6, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - ACTIONS(241), 17, + ACTIONS(109), 23, + ts_builtin_sym_end, + sym_unit_quote, anon_sym_DOT, + anon_sym_COMMA, + anon_sym_RBRACE, anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, anon_sym_STAR_STAR, anon_sym_SLASH, anon_sym_LT_LT, - anon_sym_GT_GT, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, @@ -10011,165 +5856,80 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, + anon_sym_SEMI, anon_sym_LPAREN, anon_sym_RPAREN, - [9516] = 3, + anon_sym_RBRACK, + anon_sym_GT_GT_GT, + [4714] = 4, + ACTIONS(117), 1, + anon_sym_DOT, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(133), 6, + ACTIONS(115), 11, + sym_identifier, anon_sym_STAR, + anon_sym_GT_GT, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(131), 20, - sym_identifier, + anon_sym_else, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(113), 22, + ts_builtin_sym_end, sym_unit_quote, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_RPAREN_GT, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_LPAREN, - [9551] = 20, - ACTIONS(311), 1, - anon_sym_DOT, - ACTIONS(313), 1, anon_sym_COMMA, - ACTIONS(315), 1, - anon_sym_RPAREN_GT, - ACTIONS(317), 1, + anon_sym_RBRACE, anon_sym_COLON_COLON, - ACTIONS(321), 1, - anon_sym_STAR_STAR, - ACTIONS(323), 1, - anon_sym_STAR, - ACTIONS(325), 1, - anon_sym_SLASH, - ACTIONS(329), 1, - anon_sym_AMP, - ACTIONS(331), 1, - anon_sym_PIPE, - ACTIONS(333), 1, - anon_sym_CARET, - ACTIONS(339), 1, - anon_sym_AMP_AMP, - ACTIONS(341), 1, - anon_sym_PIPE_PIPE, - ACTIONS(343), 1, - anon_sym_CARET_CARET, - ACTIONS(345), 1, - anon_sym_LPAREN, - STATE(172), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(319), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(327), 2, - anon_sym_LT_LT, - anon_sym_GT_GT, - ACTIONS(335), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(337), 4, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - [9619] = 13, - ACTIONS(311), 1, - anon_sym_DOT, - ACTIONS(317), 1, - anon_sym_COLON_COLON, - ACTIONS(321), 1, anon_sym_STAR_STAR, - ACTIONS(323), 1, - anon_sym_STAR, - ACTIONS(325), 1, anon_sym_SLASH, - ACTIONS(329), 1, - anon_sym_AMP, - ACTIONS(345), 1, - anon_sym_LPAREN, - STATE(172), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(319), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(327), 2, anon_sym_LT_LT, - anon_sym_GT_GT, - ACTIONS(167), 4, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - ACTIONS(161), 9, - anon_sym_COMMA, - anon_sym_RPAREN_GT, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - [9673] = 15, - ACTIONS(311), 1, - anon_sym_DOT, - ACTIONS(317), 1, - anon_sym_COLON_COLON, - ACTIONS(321), 1, - anon_sym_STAR_STAR, - ACTIONS(323), 1, - anon_sym_STAR, - ACTIONS(325), 1, - anon_sym_SLASH, - ACTIONS(329), 1, - anon_sym_AMP, - ACTIONS(331), 1, - anon_sym_PIPE, - ACTIONS(333), 1, - anon_sym_CARET, - ACTIONS(345), 1, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_CARET_CARET, + anon_sym_SEMI, anon_sym_LPAREN, - STATE(172), 1, - sym_dictionary_construction, + anon_sym_RPAREN, + anon_sym_RBRACK, + anon_sym_GT_GT_GT, + [4759] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(167), 2, + ACTIONS(97), 11, + sym_identifier, + anon_sym_STAR, + anon_sym_GT_GT, + anon_sym_AMP, + anon_sym_PIPE, + anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(319), 2, + anon_sym_else, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(95), 23, + ts_builtin_sym_end, + sym_unit_quote, + anon_sym_DOT, + anon_sym_COMMA, + anon_sym_RBRACE, + anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(327), 2, + anon_sym_STAR_STAR, + anon_sym_SLASH, anon_sym_LT_LT, - anon_sym_GT_GT, - ACTIONS(161), 9, - anon_sym_COMMA, - anon_sym_RPAREN_GT, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, @@ -10177,254 +5937,231 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, - [9731] = 16, - ACTIONS(311), 1, - anon_sym_DOT, - ACTIONS(317), 1, - anon_sym_COLON_COLON, - ACTIONS(321), 1, - anon_sym_STAR_STAR, - ACTIONS(323), 1, - anon_sym_STAR, - ACTIONS(325), 1, - anon_sym_SLASH, - ACTIONS(329), 1, - anon_sym_AMP, - ACTIONS(331), 1, - anon_sym_PIPE, - ACTIONS(333), 1, - anon_sym_CARET, - ACTIONS(345), 1, + anon_sym_SEMI, anon_sym_LPAREN, - STATE(172), 1, - sym_dictionary_construction, + anon_sym_RPAREN, + anon_sym_RBRACK, + anon_sym_GT_GT_GT, + [4802] = 4, + ACTIONS(123), 1, + anon_sym_DASH_GT, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(319), 2, + ACTIONS(121), 9, anon_sym_DASH, + anon_sym_STAR, + anon_sym_AMP, + anon_sym_PIPE, + anon_sym_CARET, + anon_sym_GT, + anon_sym_LT, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(119), 23, + ts_builtin_sym_end, + anon_sym_DOT, + anon_sym_COMMA, + anon_sym_RBRACE, + anon_sym_COLON_COLON, anon_sym_PLUS, - ACTIONS(327), 2, + anon_sym_STAR_STAR, + anon_sym_SLASH, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(335), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(337), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - ACTIONS(161), 5, - anon_sym_COMMA, - anon_sym_RPAREN_GT, anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, - [9791] = 17, - ACTIONS(311), 1, - anon_sym_DOT, - ACTIONS(317), 1, - anon_sym_COLON_COLON, - ACTIONS(321), 1, - anon_sym_STAR_STAR, - ACTIONS(323), 1, - anon_sym_STAR, - ACTIONS(325), 1, - anon_sym_SLASH, - ACTIONS(329), 1, - anon_sym_AMP, - ACTIONS(331), 1, - anon_sym_PIPE, - ACTIONS(333), 1, - anon_sym_CARET, - ACTIONS(339), 1, - anon_sym_AMP_AMP, - ACTIONS(345), 1, + anon_sym_then, + anon_sym_else, + anon_sym_SEMI, anon_sym_LPAREN, - STATE(172), 1, - sym_dictionary_construction, + anon_sym_RPAREN, + anon_sym_RBRACK, + [4846] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(319), 2, + ACTIONS(127), 9, anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(327), 2, - anon_sym_LT_LT, - anon_sym_GT_GT, - ACTIONS(335), 2, + anon_sym_STAR, + anon_sym_AMP, + anon_sym_PIPE, + anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(161), 4, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(125), 24, + ts_builtin_sym_end, + anon_sym_DOT, anon_sym_COMMA, - anon_sym_RPAREN_GT, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - ACTIONS(337), 4, + anon_sym_RBRACE, + anon_sym_COLON_COLON, + anon_sym_PLUS, + anon_sym_STAR_STAR, + anon_sym_SLASH, + anon_sym_LT_LT, + anon_sym_GT_GT, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [9853] = 18, - ACTIONS(311), 1, - anon_sym_DOT, - ACTIONS(317), 1, - anon_sym_COLON_COLON, - ACTIONS(321), 1, - anon_sym_STAR_STAR, - ACTIONS(323), 1, - anon_sym_STAR, - ACTIONS(325), 1, - anon_sym_SLASH, - ACTIONS(329), 1, - anon_sym_AMP, - ACTIONS(331), 1, - anon_sym_PIPE, - ACTIONS(333), 1, - anon_sym_CARET, - ACTIONS(339), 1, anon_sym_AMP_AMP, - ACTIONS(341), 1, anon_sym_PIPE_PIPE, - ACTIONS(345), 1, + anon_sym_CARET_CARET, + anon_sym_then, + anon_sym_else, + anon_sym_SEMI, + anon_sym_LPAREN, + anon_sym_RPAREN, + anon_sym_RBRACK, + anon_sym_DASH_GT, + [4888] = 7, + ACTIONS(131), 1, + anon_sym_DOT, + ACTIONS(133), 1, + anon_sym_COLON_COLON, + ACTIONS(137), 1, anon_sym_LPAREN, - STATE(172), 1, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(319), 2, + ACTIONS(135), 8, + anon_sym_STAR, + anon_sym_AMP, + anon_sym_PIPE, + anon_sym_CARET, + anon_sym_GT, + anon_sym_LT, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(129), 21, + ts_builtin_sym_end, + anon_sym_COMMA, + anon_sym_RBRACE, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(327), 2, + anon_sym_STAR_STAR, + anon_sym_SLASH, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(335), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(161), 3, - anon_sym_COMMA, - anon_sym_RPAREN_GT, - anon_sym_CARET_CARET, - ACTIONS(337), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [9917] = 19, - ACTIONS(311), 1, - anon_sym_DOT, - ACTIONS(317), 1, - anon_sym_COLON_COLON, - ACTIONS(321), 1, - anon_sym_STAR_STAR, - ACTIONS(323), 1, - anon_sym_STAR, - ACTIONS(325), 1, - anon_sym_SLASH, - ACTIONS(329), 1, - anon_sym_AMP, - ACTIONS(331), 1, - anon_sym_PIPE, - ACTIONS(333), 1, - anon_sym_CARET, - ACTIONS(339), 1, anon_sym_AMP_AMP, - ACTIONS(341), 1, anon_sym_PIPE_PIPE, - ACTIONS(343), 1, anon_sym_CARET_CARET, - ACTIONS(345), 1, - anon_sym_LPAREN, - STATE(172), 1, - sym_dictionary_construction, + anon_sym_then, + anon_sym_else, + anon_sym_SEMI, + anon_sym_RPAREN, + anon_sym_RBRACK, + [4938] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(219), 2, + ACTIONS(141), 9, + anon_sym_STAR, + anon_sym_GT_GT, + anon_sym_AMP, + anon_sym_PIPE, + anon_sym_CARET, + anon_sym_GT, + anon_sym_LT, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(139), 24, + ts_builtin_sym_end, + anon_sym_DOT, anon_sym_COMMA, - anon_sym_RPAREN_GT, - ACTIONS(319), 2, + anon_sym_RBRACE, + anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(327), 2, + anon_sym_STAR_STAR, + anon_sym_SLASH, anon_sym_LT_LT, - anon_sym_GT_GT, - ACTIONS(335), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(337), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [9983] = 20, - ACTIONS(163), 1, - anon_sym_DOT, - ACTIONS(165), 1, - anon_sym_COLON_COLON, - ACTIONS(169), 1, - anon_sym_LPAREN, - ACTIONS(191), 1, - anon_sym_STAR_STAR, - ACTIONS(193), 1, - anon_sym_STAR, - ACTIONS(195), 1, - anon_sym_SLASH, - ACTIONS(205), 1, - anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, - anon_sym_PIPE, - ACTIONS(215), 1, anon_sym_AMP_AMP, - ACTIONS(217), 1, anon_sym_PIPE_PIPE, - ACTIONS(221), 1, anon_sym_CARET_CARET, - ACTIONS(347), 1, - anon_sym_COMMA, - ACTIONS(349), 1, + anon_sym_then, + anon_sym_else, + anon_sym_SEMI, + anon_sym_LPAREN, + anon_sym_RPAREN, anon_sym_RBRACK, - STATE(90), 1, - sym_dictionary_construction, + anon_sym_GT_GT_GT, + [4980] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(201), 2, + ACTIONS(145), 9, anon_sym_DASH, + anon_sym_STAR, + anon_sym_AMP, + anon_sym_PIPE, + anon_sym_CARET, + anon_sym_GT, + anon_sym_LT, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(143), 24, + ts_builtin_sym_end, + anon_sym_DOT, + anon_sym_COMMA, + anon_sym_RBRACE, + anon_sym_COLON_COLON, anon_sym_PLUS, - ACTIONS(203), 2, + anon_sym_STAR_STAR, + anon_sym_SLASH, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(211), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(213), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [10051] = 4, - ACTIONS(351), 1, - anon_sym_DOT, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_CARET_CARET, + anon_sym_then, + anon_sym_else, + anon_sym_SEMI, + anon_sym_LPAREN, + anon_sym_RPAREN, + anon_sym_RBRACK, + anon_sym_DASH_GT, + [5022] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(139), 7, - sym_identifier, + ACTIONS(149), 9, + anon_sym_DASH, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(137), 17, - sym_unit_quote, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(147), 24, + ts_builtin_sym_end, + anon_sym_DOT, + anon_sym_COMMA, + anon_sym_RBRACE, anon_sym_COLON_COLON, - anon_sym_DASH, anon_sym_PLUS, anon_sym_STAR_STAR, anon_sym_SLASH, @@ -10438,168 +6175,192 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, anon_sym_then, + anon_sym_else, + anon_sym_SEMI, anon_sym_LPAREN, - [10087] = 19, - ACTIONS(311), 1, + anon_sym_RPAREN, + anon_sym_RBRACK, + anon_sym_DASH_GT, + [5064] = 15, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(317), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(321), 1, + ACTIONS(137), 1, + anon_sym_LPAREN, + ACTIONS(153), 1, anon_sym_STAR_STAR, - ACTIONS(323), 1, + ACTIONS(155), 1, anon_sym_STAR, - ACTIONS(325), 1, + ACTIONS(157), 1, anon_sym_SLASH, - ACTIONS(329), 1, + ACTIONS(161), 1, anon_sym_AMP, - ACTIONS(331), 1, + ACTIONS(163), 1, anon_sym_PIPE, - ACTIONS(333), 1, + ACTIONS(165), 1, anon_sym_CARET, - ACTIONS(339), 1, - anon_sym_AMP_AMP, - ACTIONS(341), 1, - anon_sym_PIPE_PIPE, - ACTIONS(343), 1, - anon_sym_CARET_CARET, - ACTIONS(345), 1, - anon_sym_LPAREN, - STATE(172), 1, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(259), 2, - anon_sym_COMMA, - anon_sym_RPAREN_GT, - ACTIONS(319), 2, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(327), 2, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(335), 2, + ACTIONS(135), 4, anon_sym_GT, anon_sym_LT, - ACTIONS(337), 4, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(129), 14, + ts_builtin_sym_end, + anon_sym_COMMA, + anon_sym_RBRACE, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [10153] = 19, - ACTIONS(311), 1, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_CARET_CARET, + anon_sym_else, + anon_sym_SEMI, + anon_sym_RPAREN, + anon_sym_RBRACK, + [5129] = 20, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(317), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(321), 1, + ACTIONS(137), 1, + anon_sym_LPAREN, + ACTIONS(153), 1, anon_sym_STAR_STAR, - ACTIONS(323), 1, + ACTIONS(155), 1, anon_sym_STAR, - ACTIONS(325), 1, + ACTIONS(157), 1, anon_sym_SLASH, - ACTIONS(329), 1, + ACTIONS(161), 1, anon_sym_AMP, - ACTIONS(331), 1, + ACTIONS(163), 1, anon_sym_PIPE, - ACTIONS(333), 1, + ACTIONS(165), 1, anon_sym_CARET, - ACTIONS(339), 1, + ACTIONS(173), 1, anon_sym_AMP_AMP, - ACTIONS(341), 1, + ACTIONS(175), 1, anon_sym_PIPE_PIPE, - ACTIONS(343), 1, + ACTIONS(177), 1, anon_sym_CARET_CARET, - ACTIONS(345), 1, - anon_sym_LPAREN, - STATE(172), 1, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(263), 2, - anon_sym_COMMA, - anon_sym_RPAREN_GT, - ACTIONS(319), 2, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(327), 2, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(335), 2, + ACTIONS(169), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(337), 4, + ACTIONS(179), 2, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [10219] = 20, - ACTIONS(311), 1, + ACTIONS(167), 7, + ts_builtin_sym_end, + anon_sym_COMMA, + anon_sym_RBRACE, + anon_sym_else, + anon_sym_SEMI, + anon_sym_RPAREN, + anon_sym_RBRACK, + [5204] = 20, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(317), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(321), 1, + ACTIONS(137), 1, + anon_sym_LPAREN, + ACTIONS(153), 1, anon_sym_STAR_STAR, - ACTIONS(323), 1, + ACTIONS(155), 1, anon_sym_STAR, - ACTIONS(325), 1, + ACTIONS(157), 1, anon_sym_SLASH, - ACTIONS(329), 1, + ACTIONS(161), 1, anon_sym_AMP, - ACTIONS(331), 1, + ACTIONS(163), 1, anon_sym_PIPE, - ACTIONS(333), 1, + ACTIONS(165), 1, anon_sym_CARET, - ACTIONS(339), 1, + ACTIONS(173), 1, anon_sym_AMP_AMP, - ACTIONS(341), 1, + ACTIONS(175), 1, anon_sym_PIPE_PIPE, - ACTIONS(343), 1, + ACTIONS(177), 1, anon_sym_CARET_CARET, - ACTIONS(345), 1, - anon_sym_LPAREN, - ACTIONS(353), 1, - anon_sym_COMMA, - ACTIONS(355), 1, - anon_sym_RPAREN_GT, - STATE(172), 1, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(319), 2, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(327), 2, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(335), 2, + ACTIONS(169), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(337), 4, + ACTIONS(183), 2, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [10287] = 4, - ACTIONS(357), 1, - anon_sym_DASH_GT, + ACTIONS(181), 7, + ts_builtin_sym_end, + anon_sym_COMMA, + anon_sym_RBRACE, + anon_sym_else, + anon_sym_SEMI, + anon_sym_RPAREN, + anon_sym_RBRACK, + [5279] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(243), 7, - anon_sym_DASH, + ACTIONS(187), 8, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(241), 17, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(185), 24, + ts_builtin_sym_end, anon_sym_DOT, anon_sym_COMMA, - anon_sym_RPAREN_GT, + anon_sym_RBRACE, anon_sym_COLON_COLON, + anon_sym_DASH, anon_sym_PLUS, anon_sym_STAR_STAR, anon_sym_SLASH, @@ -10612,120 +6373,202 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, + anon_sym_then, + anon_sym_else, + anon_sym_SEMI, anon_sym_LPAREN, - [10323] = 19, - ACTIONS(311), 1, + anon_sym_RPAREN, + anon_sym_RBRACK, + [5320] = 4, + ACTIONS(193), 1, + anon_sym_DASH_GT, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(191), 9, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_AMP, + anon_sym_PIPE, + anon_sym_CARET, + anon_sym_GT, + anon_sym_LT, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(189), 22, + ts_builtin_sym_end, anon_sym_DOT, - ACTIONS(317), 1, + anon_sym_COMMA, + anon_sym_RBRACE, anon_sym_COLON_COLON, - ACTIONS(321), 1, + anon_sym_PLUS, anon_sym_STAR_STAR, - ACTIONS(323), 1, - anon_sym_STAR, - ACTIONS(325), 1, anon_sym_SLASH, - ACTIONS(329), 1, + anon_sym_LT_LT, + anon_sym_GT_GT, + anon_sym_GT_EQ, + anon_sym_EQ_EQ, + anon_sym_LT_EQ, + anon_sym_BANG_EQ, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_CARET_CARET, + anon_sym_else, + anon_sym_SEMI, + anon_sym_LPAREN, + anon_sym_RPAREN, + anon_sym_RBRACK, + [5363] = 3, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(197), 8, + anon_sym_STAR, anon_sym_AMP, - ACTIONS(331), 1, anon_sym_PIPE, - ACTIONS(333), 1, anon_sym_CARET, - ACTIONS(339), 1, + anon_sym_GT, + anon_sym_LT, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(195), 24, + ts_builtin_sym_end, + anon_sym_DOT, + anon_sym_COMMA, + anon_sym_RBRACE, + anon_sym_COLON_COLON, + anon_sym_DASH, + anon_sym_PLUS, + anon_sym_STAR_STAR, + anon_sym_SLASH, + anon_sym_LT_LT, + anon_sym_GT_GT, + anon_sym_GT_EQ, + anon_sym_EQ_EQ, + anon_sym_LT_EQ, + anon_sym_BANG_EQ, anon_sym_AMP_AMP, - ACTIONS(341), 1, anon_sym_PIPE_PIPE, - ACTIONS(343), 1, anon_sym_CARET_CARET, - ACTIONS(345), 1, + anon_sym_then, + anon_sym_else, + anon_sym_SEMI, anon_sym_LPAREN, - STATE(172), 1, - sym_dictionary_construction, + anon_sym_RPAREN, + anon_sym_RBRACK, + [5404] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(291), 2, + ACTIONS(201), 8, + anon_sym_STAR, + anon_sym_AMP, + anon_sym_PIPE, + anon_sym_CARET, + anon_sym_GT, + anon_sym_LT, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(199), 24, + ts_builtin_sym_end, + anon_sym_DOT, anon_sym_COMMA, - anon_sym_RPAREN_GT, - ACTIONS(319), 2, + anon_sym_RBRACE, + anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(327), 2, + anon_sym_STAR_STAR, + anon_sym_SLASH, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(335), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(337), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [10389] = 19, - ACTIONS(163), 1, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_CARET_CARET, + anon_sym_then, + anon_sym_else, + anon_sym_SEMI, + anon_sym_LPAREN, + anon_sym_RPAREN, + anon_sym_RBRACK, + [5445] = 20, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(191), 1, + ACTIONS(153), 1, anon_sym_STAR_STAR, - ACTIONS(193), 1, + ACTIONS(155), 1, anon_sym_STAR, - ACTIONS(195), 1, + ACTIONS(157), 1, anon_sym_SLASH, - ACTIONS(205), 1, + ACTIONS(161), 1, anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, + ACTIONS(163), 1, anon_sym_PIPE, - ACTIONS(215), 1, + ACTIONS(165), 1, + anon_sym_CARET, + ACTIONS(173), 1, anon_sym_AMP_AMP, - ACTIONS(217), 1, + ACTIONS(175), 1, anon_sym_PIPE_PIPE, - ACTIONS(221), 1, + ACTIONS(177), 1, anon_sym_CARET_CARET, - STATE(90), 1, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(201), 2, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(203), 2, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(211), 2, + ACTIONS(169), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(359), 2, - anon_sym_COMMA, - anon_sym_RPAREN, - ACTIONS(213), 4, + ACTIONS(205), 2, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [10455] = 4, - ACTIONS(151), 1, - anon_sym_DASH_GT, + ACTIONS(203), 7, + ts_builtin_sym_end, + anon_sym_COMMA, + anon_sym_RBRACE, + anon_sym_else, + anon_sym_SEMI, + anon_sym_RPAREN, + anon_sym_RBRACK, + [5520] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(149), 7, - anon_sym_DASH, + ACTIONS(209), 8, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(147), 17, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(207), 24, + ts_builtin_sym_end, anon_sym_DOT, anon_sym_COMMA, - anon_sym_RPAREN_GT, + anon_sym_RBRACE, anon_sym_COLON_COLON, + anon_sym_DASH, anon_sym_PLUS, anon_sym_STAR_STAR, anon_sym_SLASH, @@ -10738,42 +6581,37 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, + anon_sym_then, + anon_sym_else, + anon_sym_SEMI, anon_sym_LPAREN, - [10491] = 14, - ACTIONS(311), 1, - anon_sym_DOT, - ACTIONS(317), 1, - anon_sym_COLON_COLON, - ACTIONS(321), 1, - anon_sym_STAR_STAR, - ACTIONS(323), 1, - anon_sym_STAR, - ACTIONS(325), 1, - anon_sym_SLASH, - ACTIONS(329), 1, - anon_sym_AMP, - ACTIONS(333), 1, - anon_sym_CARET, - ACTIONS(345), 1, - anon_sym_LPAREN, - STATE(172), 1, - sym_dictionary_construction, + anon_sym_RPAREN, + anon_sym_RBRACK, + [5561] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(319), 2, + ACTIONS(213), 8, + anon_sym_STAR, + anon_sym_AMP, + anon_sym_PIPE, + anon_sym_CARET, + anon_sym_GT, + anon_sym_LT, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(211), 24, + ts_builtin_sym_end, + anon_sym_DOT, + anon_sym_COMMA, + anon_sym_RBRACE, + anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(327), 2, + anon_sym_STAR_STAR, + anon_sym_SLASH, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(167), 3, - anon_sym_PIPE, - anon_sym_GT, - anon_sym_LT, - ACTIONS(161), 9, - anon_sym_COMMA, - anon_sym_RPAREN_GT, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, @@ -10781,166 +6619,180 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, - [10547] = 20, - ACTIONS(47), 1, - anon_sym_RBRACK, - ACTIONS(163), 1, - anon_sym_DOT, - ACTIONS(165), 1, - anon_sym_COLON_COLON, - ACTIONS(169), 1, + anon_sym_then, + anon_sym_else, + anon_sym_SEMI, anon_sym_LPAREN, - ACTIONS(191), 1, - anon_sym_STAR_STAR, - ACTIONS(193), 1, + anon_sym_RPAREN, + anon_sym_RBRACK, + [5602] = 3, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(217), 8, anon_sym_STAR, - ACTIONS(195), 1, - anon_sym_SLASH, - ACTIONS(205), 1, anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, anon_sym_PIPE, - ACTIONS(215), 1, - anon_sym_AMP_AMP, - ACTIONS(217), 1, - anon_sym_PIPE_PIPE, - ACTIONS(221), 1, - anon_sym_CARET_CARET, - ACTIONS(347), 1, + anon_sym_CARET, + anon_sym_GT, + anon_sym_LT, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(215), 24, + ts_builtin_sym_end, + anon_sym_DOT, anon_sym_COMMA, - STATE(90), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(201), 2, + anon_sym_RBRACE, + anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(203), 2, + anon_sym_STAR_STAR, + anon_sym_SLASH, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(211), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(213), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [10615] = 19, - ACTIONS(163), 1, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_CARET_CARET, + anon_sym_then, + anon_sym_else, + anon_sym_SEMI, + anon_sym_LPAREN, + anon_sym_RPAREN, + anon_sym_RBRACK, + [5643] = 20, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(191), 1, + ACTIONS(153), 1, anon_sym_STAR_STAR, - ACTIONS(193), 1, + ACTIONS(155), 1, anon_sym_STAR, - ACTIONS(195), 1, + ACTIONS(157), 1, anon_sym_SLASH, - ACTIONS(205), 1, + ACTIONS(161), 1, anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, + ACTIONS(163), 1, anon_sym_PIPE, - ACTIONS(215), 1, + ACTIONS(165), 1, + anon_sym_CARET, + ACTIONS(173), 1, anon_sym_AMP_AMP, - ACTIONS(217), 1, + ACTIONS(175), 1, anon_sym_PIPE_PIPE, - ACTIONS(221), 1, + ACTIONS(177), 1, anon_sym_CARET_CARET, - STATE(90), 1, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(201), 2, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(203), 2, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(211), 2, + ACTIONS(169), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(361), 2, - anon_sym_COMMA, - anon_sym_RPAREN, - ACTIONS(213), 4, + ACTIONS(221), 2, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [10681] = 20, - ACTIONS(163), 1, + ACTIONS(219), 7, + ts_builtin_sym_end, + anon_sym_COMMA, + anon_sym_RBRACE, + anon_sym_else, + anon_sym_SEMI, + anon_sym_RPAREN, + anon_sym_RBRACK, + [5718] = 20, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(191), 1, + ACTIONS(153), 1, anon_sym_STAR_STAR, - ACTIONS(193), 1, + ACTIONS(155), 1, anon_sym_STAR, - ACTIONS(195), 1, + ACTIONS(157), 1, anon_sym_SLASH, - ACTIONS(205), 1, + ACTIONS(161), 1, anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, + ACTIONS(163), 1, anon_sym_PIPE, - ACTIONS(215), 1, + ACTIONS(165), 1, + anon_sym_CARET, + ACTIONS(173), 1, anon_sym_AMP_AMP, - ACTIONS(217), 1, + ACTIONS(175), 1, anon_sym_PIPE_PIPE, - ACTIONS(221), 1, + ACTIONS(177), 1, anon_sym_CARET_CARET, - ACTIONS(347), 1, - anon_sym_COMMA, - ACTIONS(363), 1, - anon_sym_RBRACK, - STATE(90), 1, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(201), 2, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(203), 2, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(211), 2, + ACTIONS(169), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(213), 4, + ACTIONS(225), 2, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [10749] = 3, + ACTIONS(223), 7, + ts_builtin_sym_end, + anon_sym_COMMA, + anon_sym_RBRACE, + anon_sym_else, + anon_sym_SEMI, + anon_sym_RPAREN, + anon_sym_RBRACK, + [5793] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(155), 7, - anon_sym_DASH, + ACTIONS(229), 8, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(153), 18, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(227), 24, + ts_builtin_sym_end, anon_sym_DOT, anon_sym_COMMA, - anon_sym_RPAREN_GT, + anon_sym_RBRACE, anon_sym_COLON_COLON, + anon_sym_DASH, anon_sym_PLUS, anon_sym_STAR_STAR, anon_sym_SLASH, @@ -10953,73 +6805,70 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, + anon_sym_then, + anon_sym_else, + anon_sym_SEMI, anon_sym_LPAREN, - anon_sym_DASH_GT, - [10783] = 20, - ACTIONS(311), 1, - anon_sym_DOT, - ACTIONS(317), 1, - anon_sym_COLON_COLON, - ACTIONS(321), 1, - anon_sym_STAR_STAR, - ACTIONS(323), 1, + anon_sym_RPAREN, + anon_sym_RBRACK, + [5834] = 3, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(233), 8, anon_sym_STAR, - ACTIONS(325), 1, - anon_sym_SLASH, - ACTIONS(329), 1, anon_sym_AMP, - ACTIONS(331), 1, anon_sym_PIPE, - ACTIONS(333), 1, anon_sym_CARET, - ACTIONS(339), 1, - anon_sym_AMP_AMP, - ACTIONS(341), 1, - anon_sym_PIPE_PIPE, - ACTIONS(343), 1, - anon_sym_CARET_CARET, - ACTIONS(345), 1, - anon_sym_LPAREN, - ACTIONS(365), 1, + anon_sym_GT, + anon_sym_LT, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(231), 24, + ts_builtin_sym_end, + anon_sym_DOT, anon_sym_COMMA, - ACTIONS(367), 1, - anon_sym_RPAREN_GT, - STATE(172), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(319), 2, + anon_sym_RBRACE, + anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(327), 2, + anon_sym_STAR_STAR, + anon_sym_SLASH, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(335), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(337), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [10851] = 3, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_CARET_CARET, + anon_sym_then, + anon_sym_else, + anon_sym_SEMI, + anon_sym_LPAREN, + anon_sym_RPAREN, + anon_sym_RBRACK, + [5875] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(159), 7, - anon_sym_DASH, + ACTIONS(237), 8, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(157), 18, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(235), 24, + ts_builtin_sym_end, anon_sym_DOT, anon_sym_COMMA, - anon_sym_RPAREN_GT, + anon_sym_RBRACE, anon_sym_COLON_COLON, + anon_sym_DASH, anon_sym_PLUS, anon_sym_STAR_STAR, anon_sym_SLASH, @@ -11032,23 +6881,30 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, + anon_sym_then, + anon_sym_else, + anon_sym_SEMI, anon_sym_LPAREN, - anon_sym_DASH_GT, - [10885] = 3, + anon_sym_RPAREN, + anon_sym_RBRACK, + [5916] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(133), 7, - sym_identifier, + ACTIONS(241), 8, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(131), 18, - sym_unit_quote, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(239), 24, + ts_builtin_sym_end, anon_sym_DOT, + anon_sym_COMMA, + anon_sym_RBRACE, anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, @@ -11064,22 +6920,29 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, anon_sym_then, + anon_sym_else, + anon_sym_SEMI, anon_sym_LPAREN, - [10919] = 3, + anon_sym_RPAREN, + anon_sym_RBRACK, + [5957] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(145), 7, - sym_identifier, + ACTIONS(245), 8, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(143), 18, - sym_unit_quote, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(243), 24, + ts_builtin_sym_end, anon_sym_DOT, + anon_sym_COMMA, + anon_sym_RBRACE, anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, @@ -11095,29 +6958,30 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, anon_sym_then, + anon_sym_else, + anon_sym_SEMI, anon_sym_LPAREN, - [10953] = 7, - ACTIONS(311), 1, - anon_sym_DOT, - ACTIONS(317), 1, - anon_sym_COLON_COLON, - ACTIONS(345), 1, - anon_sym_LPAREN, - STATE(172), 1, - sym_dictionary_construction, + anon_sym_RPAREN, + anon_sym_RBRACK, + [5998] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(167), 6, + ACTIONS(249), 8, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(161), 15, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(247), 24, + ts_builtin_sym_end, + anon_sym_DOT, anon_sym_COMMA, - anon_sym_RPAREN_GT, + anon_sym_RBRACE, + anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, anon_sym_STAR_STAR, @@ -11131,23 +6995,32 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, - [10995] = 3, + anon_sym_then, + anon_sym_else, + anon_sym_SEMI, + anon_sym_LPAREN, + anon_sym_RPAREN, + anon_sym_RBRACK, + [6039] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(173), 7, - anon_sym_DASH, + ACTIONS(253), 8, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(171), 18, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(251), 24, + ts_builtin_sym_end, anon_sym_DOT, anon_sym_COMMA, - anon_sym_RPAREN_GT, + anon_sym_RBRACE, anon_sym_COLON_COLON, + anon_sym_DASH, anon_sym_PLUS, anon_sym_STAR_STAR, anon_sym_SLASH, @@ -11160,132 +7033,156 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, + anon_sym_then, + anon_sym_else, + anon_sym_SEMI, anon_sym_LPAREN, - anon_sym_DASH_GT, - [11029] = 19, - ACTIONS(311), 1, - anon_sym_DOT, - ACTIONS(317), 1, - anon_sym_COLON_COLON, - ACTIONS(321), 1, - anon_sym_STAR_STAR, - ACTIONS(323), 1, + anon_sym_RPAREN, + anon_sym_RBRACK, + [6080] = 3, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(257), 8, anon_sym_STAR, - ACTIONS(325), 1, - anon_sym_SLASH, - ACTIONS(329), 1, anon_sym_AMP, - ACTIONS(331), 1, anon_sym_PIPE, - ACTIONS(333), 1, anon_sym_CARET, - ACTIONS(339), 1, + anon_sym_GT, + anon_sym_LT, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(255), 24, + ts_builtin_sym_end, + anon_sym_DOT, + anon_sym_COMMA, + anon_sym_RBRACE, + anon_sym_COLON_COLON, + anon_sym_DASH, + anon_sym_PLUS, + anon_sym_STAR_STAR, + anon_sym_SLASH, + anon_sym_LT_LT, + anon_sym_GT_GT, + anon_sym_GT_EQ, + anon_sym_EQ_EQ, + anon_sym_LT_EQ, + anon_sym_BANG_EQ, anon_sym_AMP_AMP, - ACTIONS(341), 1, anon_sym_PIPE_PIPE, - ACTIONS(343), 1, anon_sym_CARET_CARET, - ACTIONS(345), 1, + anon_sym_then, + anon_sym_else, + anon_sym_SEMI, anon_sym_LPAREN, - STATE(172), 1, - sym_dictionary_construction, + anon_sym_RPAREN, + anon_sym_RBRACK, + [6121] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(267), 2, + ACTIONS(261), 8, + anon_sym_STAR, + anon_sym_AMP, + anon_sym_PIPE, + anon_sym_CARET, + anon_sym_GT, + anon_sym_LT, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(259), 24, + ts_builtin_sym_end, + anon_sym_DOT, anon_sym_COMMA, - anon_sym_RPAREN_GT, - ACTIONS(319), 2, + anon_sym_RBRACE, + anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(327), 2, + anon_sym_STAR_STAR, + anon_sym_SLASH, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(335), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(337), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [11095] = 20, - ACTIONS(311), 1, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_CARET_CARET, + anon_sym_then, + anon_sym_else, + anon_sym_SEMI, + anon_sym_LPAREN, + anon_sym_RPAREN, + anon_sym_RBRACK, + [6162] = 10, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(317), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(321), 1, + ACTIONS(137), 1, + anon_sym_LPAREN, + ACTIONS(153), 1, anon_sym_STAR_STAR, - ACTIONS(323), 1, + ACTIONS(155), 1, anon_sym_STAR, - ACTIONS(325), 1, + ACTIONS(157), 1, anon_sym_SLASH, - ACTIONS(329), 1, - anon_sym_AMP, - ACTIONS(331), 1, - anon_sym_PIPE, - ACTIONS(333), 1, - anon_sym_CARET, - ACTIONS(339), 1, - anon_sym_AMP_AMP, - ACTIONS(341), 1, - anon_sym_PIPE_PIPE, - ACTIONS(343), 1, - anon_sym_CARET_CARET, - ACTIONS(345), 1, - anon_sym_LPAREN, - ACTIONS(369), 1, - anon_sym_COMMA, - ACTIONS(371), 1, - anon_sym_RPAREN_GT, - STATE(172), 1, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(319), 2, + ACTIONS(135), 7, + anon_sym_AMP, + anon_sym_PIPE, + anon_sym_CARET, + anon_sym_GT, + anon_sym_LT, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(129), 18, + ts_builtin_sym_end, + anon_sym_COMMA, + anon_sym_RBRACE, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(327), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(335), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(337), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [11163] = 10, - ACTIONS(311), 1, - anon_sym_DOT, - ACTIONS(317), 1, - anon_sym_COLON_COLON, - ACTIONS(321), 1, - anon_sym_STAR_STAR, - ACTIONS(323), 1, - anon_sym_STAR, - ACTIONS(325), 1, - anon_sym_SLASH, - ACTIONS(345), 1, - anon_sym_LPAREN, - STATE(172), 1, - sym_dictionary_construction, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_CARET_CARET, + anon_sym_else, + anon_sym_SEMI, + anon_sym_RPAREN, + anon_sym_RBRACK, + [6217] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(167), 5, + ACTIONS(265), 8, + anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(161), 13, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(263), 24, + ts_builtin_sym_end, + anon_sym_DOT, anon_sym_COMMA, - anon_sym_RPAREN_GT, + anon_sym_RBRACE, + anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, + anon_sym_STAR_STAR, + anon_sym_SLASH, anon_sym_LT_LT, anon_sym_GT_GT, anon_sym_GT_EQ, @@ -11295,30 +7192,39 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, - [11211] = 8, - ACTIONS(311), 1, + anon_sym_then, + anon_sym_else, + anon_sym_SEMI, + anon_sym_LPAREN, + anon_sym_RPAREN, + anon_sym_RBRACK, + [6258] = 8, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(317), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(321), 1, - anon_sym_STAR_STAR, - ACTIONS(345), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - STATE(172), 1, + ACTIONS(153), 1, + anon_sym_STAR_STAR, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(167), 6, + ACTIONS(135), 8, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(161), 14, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(129), 19, + ts_builtin_sym_end, anon_sym_COMMA, - anon_sym_RPAREN_GT, + anon_sym_RBRACE, anon_sym_DASH, anon_sym_PLUS, anon_sym_SLASH, @@ -11331,36 +7237,43 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, - [11255] = 11, - ACTIONS(311), 1, + anon_sym_else, + anon_sym_SEMI, + anon_sym_RPAREN, + anon_sym_RBRACK, + [6309] = 11, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(317), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(321), 1, + ACTIONS(137), 1, + anon_sym_LPAREN, + ACTIONS(153), 1, anon_sym_STAR_STAR, - ACTIONS(323), 1, + ACTIONS(155), 1, anon_sym_STAR, - ACTIONS(325), 1, + ACTIONS(157), 1, anon_sym_SLASH, - ACTIONS(345), 1, - anon_sym_LPAREN, - STATE(172), 1, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(319), 2, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(167), 5, + ACTIONS(135), 7, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(161), 11, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(129), 16, + ts_builtin_sym_end, anon_sym_COMMA, - anon_sym_RPAREN_GT, + anon_sym_RBRACE, anon_sym_LT_LT, anon_sym_GT_GT, anon_sym_GT_EQ, @@ -11370,39 +7283,46 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, - [11305] = 12, - ACTIONS(311), 1, + anon_sym_else, + anon_sym_SEMI, + anon_sym_RPAREN, + anon_sym_RBRACK, + [6366] = 12, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(317), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(321), 1, + ACTIONS(137), 1, + anon_sym_LPAREN, + ACTIONS(153), 1, anon_sym_STAR_STAR, - ACTIONS(323), 1, + ACTIONS(155), 1, anon_sym_STAR, - ACTIONS(325), 1, + ACTIONS(157), 1, anon_sym_SLASH, - ACTIONS(345), 1, - anon_sym_LPAREN, - STATE(172), 1, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(319), 2, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(327), 2, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(167), 5, + ACTIONS(135), 7, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(161), 9, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(129), 14, + ts_builtin_sym_end, anon_sym_COMMA, - anon_sym_RPAREN_GT, + anon_sym_RBRACE, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, @@ -11410,122 +7330,96 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, - [11357] = 20, - ACTIONS(41), 1, + anon_sym_else, + anon_sym_SEMI, + anon_sym_RPAREN, anon_sym_RBRACK, - ACTIONS(163), 1, + [6425] = 14, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(191), 1, + ACTIONS(153), 1, anon_sym_STAR_STAR, - ACTIONS(193), 1, + ACTIONS(155), 1, anon_sym_STAR, - ACTIONS(195), 1, + ACTIONS(157), 1, anon_sym_SLASH, - ACTIONS(205), 1, + ACTIONS(161), 1, anon_sym_AMP, - ACTIONS(207), 1, + ACTIONS(165), 1, anon_sym_CARET, - ACTIONS(209), 1, - anon_sym_PIPE, - ACTIONS(215), 1, - anon_sym_AMP_AMP, - ACTIONS(217), 1, - anon_sym_PIPE_PIPE, - ACTIONS(221), 1, - anon_sym_CARET_CARET, - ACTIONS(347), 1, - anon_sym_COMMA, - STATE(90), 1, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(201), 2, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(203), 2, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(211), 2, + ACTIONS(135), 5, + anon_sym_PIPE, anon_sym_GT, anon_sym_LT, - ACTIONS(213), 4, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(129), 14, + ts_builtin_sym_end, + anon_sym_COMMA, + anon_sym_RBRACE, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [11425] = 19, - ACTIONS(163), 1, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_CARET_CARET, + anon_sym_else, + anon_sym_SEMI, + anon_sym_RPAREN, + anon_sym_RBRACK, + [6488] = 13, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(191), 1, + ACTIONS(153), 1, anon_sym_STAR_STAR, - ACTIONS(193), 1, + ACTIONS(155), 1, anon_sym_STAR, - ACTIONS(195), 1, + ACTIONS(157), 1, anon_sym_SLASH, - ACTIONS(205), 1, + ACTIONS(161), 1, anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, - anon_sym_PIPE, - ACTIONS(215), 1, - anon_sym_AMP_AMP, - ACTIONS(217), 1, - anon_sym_PIPE_PIPE, - ACTIONS(221), 1, - anon_sym_CARET_CARET, - ACTIONS(373), 1, - anon_sym_else, - STATE(90), 1, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(201), 2, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(203), 2, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(211), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(213), 4, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - [11490] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(285), 6, - anon_sym_STAR, - anon_sym_AMP, + ACTIONS(135), 6, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(283), 18, - anon_sym_DOT, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(129), 14, + ts_builtin_sym_end, anon_sym_COMMA, - anon_sym_RPAREN_GT, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, + anon_sym_RBRACE, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, @@ -11533,22 +7427,28 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, - anon_sym_LPAREN, - [11523] = 3, + anon_sym_else, + anon_sym_SEMI, + anon_sym_RPAREN, + anon_sym_RBRACK, + [6549] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(289), 6, + ACTIONS(191), 8, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(287), 18, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(189), 24, + ts_builtin_sym_end, anon_sym_DOT, anon_sym_COMMA, - anon_sym_RPAREN_GT, + anon_sym_RBRACE, anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, @@ -11563,174 +7463,189 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, + anon_sym_then, + anon_sym_else, + anon_sym_SEMI, anon_sym_LPAREN, - [11556] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(247), 6, + anon_sym_RPAREN, + anon_sym_RBRACK, + [6590] = 17, + ACTIONS(131), 1, + anon_sym_DOT, + ACTIONS(133), 1, + anon_sym_COLON_COLON, + ACTIONS(137), 1, + anon_sym_LPAREN, + ACTIONS(153), 1, + anon_sym_STAR_STAR, + ACTIONS(155), 1, anon_sym_STAR, + ACTIONS(157), 1, + anon_sym_SLASH, + ACTIONS(161), 1, anon_sym_AMP, + ACTIONS(163), 1, anon_sym_PIPE, + ACTIONS(165), 1, anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - ACTIONS(245), 18, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_RPAREN_GT, - anon_sym_COLON_COLON, + STATE(80), 1, + sym_dictionary_construction, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(135), 2, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, + ACTIONS(169), 2, + anon_sym_GT, + anon_sym_LT, + ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, + ACTIONS(129), 10, + ts_builtin_sym_end, + anon_sym_COMMA, + anon_sym_RBRACE, anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, - anon_sym_LPAREN, - [11589] = 19, - ACTIONS(163), 1, + anon_sym_else, + anon_sym_SEMI, + anon_sym_RPAREN, + anon_sym_RBRACK, + [6659] = 18, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(377), 1, + ACTIONS(153), 1, anon_sym_STAR_STAR, - ACTIONS(379), 1, + ACTIONS(155), 1, anon_sym_STAR, - ACTIONS(381), 1, + ACTIONS(157), 1, anon_sym_SLASH, - ACTIONS(385), 1, + ACTIONS(161), 1, anon_sym_AMP, - ACTIONS(387), 1, + ACTIONS(163), 1, anon_sym_PIPE, - ACTIONS(389), 1, + ACTIONS(165), 1, anon_sym_CARET, - ACTIONS(395), 1, + ACTIONS(173), 1, anon_sym_AMP_AMP, - ACTIONS(397), 1, - anon_sym_PIPE_PIPE, - ACTIONS(399), 1, - anon_sym_CARET_CARET, - ACTIONS(401), 1, - anon_sym_then, - STATE(90), 1, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(375), 2, + ACTIONS(135), 2, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(383), 2, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(391), 2, + ACTIONS(169), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(393), 4, + ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [11654] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(185), 6, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - ACTIONS(183), 18, - anon_sym_DOT, + ACTIONS(129), 9, + ts_builtin_sym_end, anon_sym_COMMA, - anon_sym_RPAREN_GT, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, + anon_sym_RBRACE, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, - anon_sym_LPAREN, - [11687] = 19, - ACTIONS(163), 1, + anon_sym_else, + anon_sym_SEMI, + anon_sym_RPAREN, + anon_sym_RBRACK, + [6730] = 19, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(267), 1, - anon_sym_then, - ACTIONS(377), 1, + ACTIONS(153), 1, anon_sym_STAR_STAR, - ACTIONS(379), 1, + ACTIONS(155), 1, anon_sym_STAR, - ACTIONS(381), 1, + ACTIONS(157), 1, anon_sym_SLASH, - ACTIONS(385), 1, + ACTIONS(161), 1, anon_sym_AMP, - ACTIONS(387), 1, + ACTIONS(163), 1, anon_sym_PIPE, - ACTIONS(389), 1, + ACTIONS(165), 1, anon_sym_CARET, - ACTIONS(395), 1, + ACTIONS(173), 1, anon_sym_AMP_AMP, - ACTIONS(397), 1, + ACTIONS(175), 1, anon_sym_PIPE_PIPE, - ACTIONS(399), 1, - anon_sym_CARET_CARET, - STATE(90), 1, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(375), 2, + ACTIONS(135), 2, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(383), 2, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(391), 2, + ACTIONS(169), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(393), 4, + ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [11752] = 3, + ACTIONS(129), 8, + ts_builtin_sym_end, + anon_sym_COMMA, + anon_sym_RBRACE, + anon_sym_CARET_CARET, + anon_sym_else, + anon_sym_SEMI, + anon_sym_RPAREN, + anon_sym_RBRACK, + [6803] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(181), 6, + ACTIONS(121), 8, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(179), 18, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(119), 24, + ts_builtin_sym_end, anon_sym_DOT, anon_sym_COMMA, - anon_sym_RPAREN_GT, + anon_sym_RBRACE, anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, @@ -11745,68 +7660,68 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, + anon_sym_then, + anon_sym_else, + anon_sym_SEMI, anon_sym_LPAREN, - [11785] = 19, - ACTIONS(163), 1, - anon_sym_DOT, - ACTIONS(165), 1, - anon_sym_COLON_COLON, - ACTIONS(169), 1, - anon_sym_LPAREN, - ACTIONS(191), 1, - anon_sym_STAR_STAR, - ACTIONS(193), 1, - anon_sym_STAR, - ACTIONS(195), 1, - anon_sym_SLASH, - ACTIONS(205), 1, - anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, - anon_sym_PIPE, - ACTIONS(215), 1, - anon_sym_AMP_AMP, - ACTIONS(217), 1, - anon_sym_PIPE_PIPE, - ACTIONS(221), 1, - anon_sym_CARET_CARET, - ACTIONS(403), 1, anon_sym_RPAREN, - STATE(90), 1, - sym_dictionary_construction, + anon_sym_RBRACK, + [6844] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(201), 2, + ACTIONS(269), 8, + anon_sym_STAR, + anon_sym_AMP, + anon_sym_PIPE, + anon_sym_CARET, + anon_sym_GT, + anon_sym_LT, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(267), 24, + ts_builtin_sym_end, + anon_sym_DOT, + anon_sym_COMMA, + anon_sym_RBRACE, + anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(203), 2, + anon_sym_STAR_STAR, + anon_sym_SLASH, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(211), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(213), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [11850] = 3, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_CARET_CARET, + anon_sym_then, + anon_sym_else, + anon_sym_SEMI, + anon_sym_LPAREN, + anon_sym_RPAREN, + anon_sym_RBRACK, + [6885] = 4, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(199), 6, + ACTIONS(99), 2, + aux_sym_signed_integer_token1, + aux_sym_unsigned_integer_token1, + ACTIONS(97), 7, + sym_identifier, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(197), 18, + ACTIONS(95), 18, + sym_unit_quote, anon_sym_DOT, - anon_sym_COMMA, - anon_sym_RPAREN_GT, anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, @@ -11821,22 +7736,27 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, + anon_sym_then, anon_sym_LPAREN, - [11883] = 3, + [6923] = 6, + ACTIONS(103), 1, + sym_identifier, + ACTIONS(105), 1, + sym_unit_quote, + STATE(60), 1, + sym__unit, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(297), 6, + ACTIONS(107), 6, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(295), 18, + ACTIONS(101), 17, anon_sym_DOT, - anon_sym_COMMA, - anon_sym_RPAREN_GT, anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, @@ -11851,68 +7771,76 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, + anon_sym_then, anon_sym_LPAREN, - [11916] = 19, - ACTIONS(163), 1, + [6964] = 20, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(191), 1, + ACTIONS(153), 1, anon_sym_STAR_STAR, - ACTIONS(193), 1, + ACTIONS(155), 1, anon_sym_STAR, - ACTIONS(195), 1, + ACTIONS(157), 1, anon_sym_SLASH, - ACTIONS(205), 1, + ACTIONS(161), 1, anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, + ACTIONS(163), 1, anon_sym_PIPE, - ACTIONS(215), 1, + ACTIONS(165), 1, + anon_sym_CARET, + ACTIONS(173), 1, anon_sym_AMP_AMP, - ACTIONS(217), 1, + ACTIONS(175), 1, anon_sym_PIPE_PIPE, - ACTIONS(221), 1, + ACTIONS(177), 1, anon_sym_CARET_CARET, - ACTIONS(405), 1, - anon_sym_COLON, - STATE(90), 1, + ACTIONS(273), 1, + anon_sym_EQ, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(201), 2, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(203), 2, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(211), 2, + ACTIONS(169), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(213), 4, + ACTIONS(271), 2, + anon_sym_COMMA, + anon_sym_RPAREN, + ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [11981] = 3, + [7033] = 6, + ACTIONS(275), 1, + anon_sym_EQ, + ACTIONS(277), 1, + anon_sym_COLON, + STATE(178), 1, + sym_declaration_type, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(189), 6, + ACTIONS(191), 6, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(187), 18, + ACTIONS(189), 17, anon_sym_DOT, - anon_sym_COMMA, - anon_sym_RPAREN_GT, anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, @@ -11928,33 +7856,28 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, anon_sym_LPAREN, - [12014] = 10, - ACTIONS(163), 1, + anon_sym_RPAREN, + [7074] = 4, + ACTIONS(279), 1, anon_sym_DOT, - ACTIONS(165), 1, - anon_sym_COLON_COLON, - ACTIONS(169), 1, - anon_sym_LPAREN, - ACTIONS(377), 1, - anon_sym_STAR_STAR, - ACTIONS(379), 1, - anon_sym_STAR, - ACTIONS(381), 1, - anon_sym_SLASH, - STATE(90), 1, - sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(167), 5, + ACTIONS(115), 7, + sym_identifier, + anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(161), 12, + ACTIONS(113), 17, + sym_unit_quote, + anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, + anon_sym_STAR_STAR, + anon_sym_SLASH, anon_sym_LT_LT, anon_sym_GT_GT, anon_sym_GT_EQ, @@ -11965,30 +7888,26 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, anon_sym_then, - [12061] = 8, - ACTIONS(163), 1, - anon_sym_DOT, - ACTIONS(165), 1, - anon_sym_COLON_COLON, - ACTIONS(169), 1, anon_sym_LPAREN, - ACTIONS(377), 1, - anon_sym_STAR_STAR, - STATE(90), 1, - sym_dictionary_construction, + [7110] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(167), 6, + ACTIONS(97), 7, + sym_identifier, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(161), 13, + ACTIONS(95), 18, + sym_unit_quote, + anon_sym_DOT, + anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, + anon_sym_STAR_STAR, anon_sym_SLASH, anon_sym_LT_LT, anon_sym_GT_GT, @@ -12000,75 +7919,29 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, anon_sym_then, - [12104] = 11, - ACTIONS(163), 1, - anon_sym_DOT, - ACTIONS(165), 1, - anon_sym_COLON_COLON, - ACTIONS(169), 1, anon_sym_LPAREN, - ACTIONS(377), 1, - anon_sym_STAR_STAR, - ACTIONS(379), 1, - anon_sym_STAR, - ACTIONS(381), 1, - anon_sym_SLASH, - STATE(90), 1, - sym_dictionary_construction, + [7144] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(375), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(167), 5, + ACTIONS(111), 7, + sym_identifier, + anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(161), 10, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - [12153] = 12, - ACTIONS(163), 1, + ACTIONS(109), 18, + sym_unit_quote, anon_sym_DOT, - ACTIONS(165), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, - anon_sym_LPAREN, - ACTIONS(377), 1, - anon_sym_STAR_STAR, - ACTIONS(379), 1, - anon_sym_STAR, - ACTIONS(381), 1, - anon_sym_SLASH, - STATE(90), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(375), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(383), 2, + anon_sym_STAR_STAR, + anon_sym_SLASH, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(167), 5, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - ACTIONS(161), 8, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, @@ -12077,283 +7950,327 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, anon_sym_then, - [12204] = 14, - ACTIONS(163), 1, + anon_sym_LPAREN, + [7178] = 19, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(377), 1, + ACTIONS(153), 1, anon_sym_STAR_STAR, - ACTIONS(379), 1, + ACTIONS(155), 1, anon_sym_STAR, - ACTIONS(381), 1, + ACTIONS(157), 1, anon_sym_SLASH, - ACTIONS(385), 1, + ACTIONS(161), 1, anon_sym_AMP, - ACTIONS(389), 1, + ACTIONS(163), 1, + anon_sym_PIPE, + ACTIONS(165), 1, anon_sym_CARET, - STATE(90), 1, + ACTIONS(173), 1, + anon_sym_AMP_AMP, + ACTIONS(175), 1, + anon_sym_PIPE_PIPE, + ACTIONS(177), 1, + anon_sym_CARET_CARET, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(375), 2, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(383), 2, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(167), 3, - anon_sym_PIPE, + ACTIONS(169), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(161), 8, + ACTIONS(281), 2, + anon_sym_COMMA, + anon_sym_RPAREN, + ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - [12259] = 13, - ACTIONS(163), 1, + [7244] = 20, + ACTIONS(41), 1, + anon_sym_RBRACK, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(377), 1, + ACTIONS(153), 1, anon_sym_STAR_STAR, - ACTIONS(379), 1, + ACTIONS(155), 1, anon_sym_STAR, - ACTIONS(381), 1, + ACTIONS(157), 1, anon_sym_SLASH, - ACTIONS(385), 1, + ACTIONS(161), 1, anon_sym_AMP, - STATE(90), 1, + ACTIONS(163), 1, + anon_sym_PIPE, + ACTIONS(165), 1, + anon_sym_CARET, + ACTIONS(173), 1, + anon_sym_AMP_AMP, + ACTIONS(175), 1, + anon_sym_PIPE_PIPE, + ACTIONS(177), 1, + anon_sym_CARET_CARET, + ACTIONS(283), 1, + anon_sym_COMMA, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(375), 2, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(383), 2, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(167), 4, - anon_sym_PIPE, - anon_sym_CARET, + ACTIONS(169), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(161), 8, + ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - [12312] = 15, - ACTIONS(163), 1, + [7312] = 20, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(377), 1, + ACTIONS(153), 1, anon_sym_STAR_STAR, - ACTIONS(379), 1, + ACTIONS(155), 1, anon_sym_STAR, - ACTIONS(381), 1, + ACTIONS(157), 1, anon_sym_SLASH, - ACTIONS(385), 1, + ACTIONS(161), 1, anon_sym_AMP, - ACTIONS(387), 1, + ACTIONS(163), 1, anon_sym_PIPE, - ACTIONS(389), 1, + ACTIONS(165), 1, anon_sym_CARET, - STATE(90), 1, + ACTIONS(173), 1, + anon_sym_AMP_AMP, + ACTIONS(175), 1, + anon_sym_PIPE_PIPE, + ACTIONS(177), 1, + anon_sym_CARET_CARET, + ACTIONS(283), 1, + anon_sym_COMMA, + ACTIONS(285), 1, + anon_sym_RBRACK, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(167), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(375), 2, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(383), 2, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(161), 8, + ACTIONS(169), 2, + anon_sym_GT, + anon_sym_LT, + ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - [12369] = 16, - ACTIONS(163), 1, + [7380] = 20, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(377), 1, + ACTIONS(153), 1, anon_sym_STAR_STAR, - ACTIONS(379), 1, + ACTIONS(155), 1, anon_sym_STAR, - ACTIONS(381), 1, + ACTIONS(157), 1, anon_sym_SLASH, - ACTIONS(385), 1, + ACTIONS(161), 1, anon_sym_AMP, - ACTIONS(387), 1, + ACTIONS(163), 1, anon_sym_PIPE, - ACTIONS(389), 1, + ACTIONS(165), 1, anon_sym_CARET, - STATE(90), 1, + ACTIONS(173), 1, + anon_sym_AMP_AMP, + ACTIONS(175), 1, + anon_sym_PIPE_PIPE, + ACTIONS(177), 1, + anon_sym_CARET_CARET, + ACTIONS(287), 1, + anon_sym_COMMA, + ACTIONS(289), 1, + anon_sym_RBRACE, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(375), 2, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(383), 2, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(391), 2, + ACTIONS(169), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(161), 4, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - ACTIONS(393), 4, + ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [12428] = 17, - ACTIONS(163), 1, + [7448] = 19, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(377), 1, + ACTIONS(153), 1, anon_sym_STAR_STAR, - ACTIONS(379), 1, + ACTIONS(155), 1, anon_sym_STAR, - ACTIONS(381), 1, + ACTIONS(157), 1, anon_sym_SLASH, - ACTIONS(385), 1, + ACTIONS(161), 1, anon_sym_AMP, - ACTIONS(387), 1, + ACTIONS(163), 1, anon_sym_PIPE, - ACTIONS(389), 1, + ACTIONS(165), 1, anon_sym_CARET, - ACTIONS(395), 1, + ACTIONS(173), 1, anon_sym_AMP_AMP, - STATE(90), 1, + ACTIONS(175), 1, + anon_sym_PIPE_PIPE, + ACTIONS(177), 1, + anon_sym_CARET_CARET, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(375), 2, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(383), 2, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(391), 2, + ACTIONS(169), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(161), 3, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - ACTIONS(393), 4, + ACTIONS(291), 2, + anon_sym_COMMA, + anon_sym_RPAREN, + ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [12489] = 18, - ACTIONS(163), 1, + [7514] = 20, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(377), 1, + ACTIONS(153), 1, anon_sym_STAR_STAR, - ACTIONS(379), 1, + ACTIONS(155), 1, anon_sym_STAR, - ACTIONS(381), 1, + ACTIONS(157), 1, anon_sym_SLASH, - ACTIONS(385), 1, + ACTIONS(161), 1, anon_sym_AMP, - ACTIONS(387), 1, + ACTIONS(163), 1, anon_sym_PIPE, - ACTIONS(389), 1, + ACTIONS(165), 1, anon_sym_CARET, - ACTIONS(395), 1, + ACTIONS(173), 1, anon_sym_AMP_AMP, - ACTIONS(397), 1, + ACTIONS(175), 1, anon_sym_PIPE_PIPE, - STATE(90), 1, + ACTIONS(177), 1, + anon_sym_CARET_CARET, + ACTIONS(293), 1, + anon_sym_COMMA, + ACTIONS(295), 1, + anon_sym_RBRACE, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(161), 2, - anon_sym_CARET_CARET, - anon_sym_then, - ACTIONS(375), 2, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(383), 2, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(391), 2, + ACTIONS(169), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(393), 4, + ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [12552] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(149), 6, + [7582] = 15, + ACTIONS(131), 1, + anon_sym_DOT, + ACTIONS(133), 1, + anon_sym_COLON_COLON, + ACTIONS(137), 1, + anon_sym_LPAREN, + ACTIONS(299), 1, + anon_sym_STAR_STAR, + ACTIONS(301), 1, anon_sym_STAR, + ACTIONS(303), 1, + anon_sym_SLASH, + ACTIONS(307), 1, anon_sym_AMP, + ACTIONS(309), 1, anon_sym_PIPE, + ACTIONS(311), 1, anon_sym_CARET, + STATE(80), 1, + sym_dictionary_construction, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(135), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(147), 18, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_RPAREN_GT, - anon_sym_COLON_COLON, + ACTIONS(297), 2, anon_sym_DASH, anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, + ACTIONS(305), 2, anon_sym_LT_LT, anon_sym_GT_GT, + ACTIONS(129), 8, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, @@ -12361,407 +8278,402 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, - anon_sym_LPAREN, - [12585] = 19, - ACTIONS(163), 1, + anon_sym_then, + [7639] = 19, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(219), 1, - anon_sym_then, - ACTIONS(377), 1, + ACTIONS(299), 1, anon_sym_STAR_STAR, - ACTIONS(379), 1, + ACTIONS(301), 1, anon_sym_STAR, - ACTIONS(381), 1, + ACTIONS(303), 1, anon_sym_SLASH, - ACTIONS(385), 1, + ACTIONS(307), 1, anon_sym_AMP, - ACTIONS(387), 1, + ACTIONS(309), 1, anon_sym_PIPE, - ACTIONS(389), 1, + ACTIONS(311), 1, anon_sym_CARET, - ACTIONS(395), 1, + ACTIONS(317), 1, anon_sym_AMP_AMP, - ACTIONS(397), 1, + ACTIONS(319), 1, anon_sym_PIPE_PIPE, - ACTIONS(399), 1, + ACTIONS(321), 1, anon_sym_CARET_CARET, - STATE(90), 1, + ACTIONS(323), 1, + anon_sym_then, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(375), 2, + ACTIONS(297), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(383), 2, + ACTIONS(305), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(391), 2, + ACTIONS(313), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(393), 4, + ACTIONS(315), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [12650] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(227), 6, + [7704] = 19, + ACTIONS(131), 1, + anon_sym_DOT, + ACTIONS(133), 1, + anon_sym_COLON_COLON, + ACTIONS(137), 1, + anon_sym_LPAREN, + ACTIONS(153), 1, + anon_sym_STAR_STAR, + ACTIONS(155), 1, anon_sym_STAR, + ACTIONS(157), 1, + anon_sym_SLASH, + ACTIONS(161), 1, anon_sym_AMP, + ACTIONS(163), 1, anon_sym_PIPE, + ACTIONS(165), 1, anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - ACTIONS(225), 18, - anon_sym_DOT, + ACTIONS(173), 1, + anon_sym_AMP_AMP, + ACTIONS(175), 1, + anon_sym_PIPE_PIPE, + ACTIONS(177), 1, + anon_sym_CARET_CARET, + ACTIONS(283), 1, anon_sym_COMMA, - anon_sym_RPAREN_GT, - anon_sym_COLON_COLON, + STATE(80), 1, + sym_dictionary_construction, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, + ACTIONS(169), 2, + anon_sym_GT, + anon_sym_LT, + ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_LPAREN, - [12683] = 19, - ACTIONS(163), 1, + [7769] = 19, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(191), 1, + ACTIONS(153), 1, anon_sym_STAR_STAR, - ACTIONS(193), 1, + ACTIONS(155), 1, anon_sym_STAR, - ACTIONS(195), 1, + ACTIONS(157), 1, anon_sym_SLASH, - ACTIONS(205), 1, + ACTIONS(161), 1, anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, + ACTIONS(163), 1, anon_sym_PIPE, - ACTIONS(215), 1, + ACTIONS(165), 1, + anon_sym_CARET, + ACTIONS(173), 1, anon_sym_AMP_AMP, - ACTIONS(217), 1, + ACTIONS(175), 1, anon_sym_PIPE_PIPE, - ACTIONS(221), 1, + ACTIONS(177), 1, anon_sym_CARET_CARET, - ACTIONS(407), 1, - anon_sym_else, - STATE(90), 1, + ACTIONS(325), 1, + ts_builtin_sym_end, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(201), 2, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(203), 2, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(211), 2, + ACTIONS(169), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(213), 4, + ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [12748] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(235), 6, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - ACTIONS(233), 18, + [7834] = 19, + ACTIONS(131), 1, anon_sym_DOT, - anon_sym_COMMA, - anon_sym_RPAREN_GT, + ACTIONS(133), 1, anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, + ACTIONS(137), 1, + anon_sym_LPAREN, + ACTIONS(153), 1, anon_sym_STAR_STAR, + ACTIONS(155), 1, + anon_sym_STAR, + ACTIONS(157), 1, anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, + ACTIONS(161), 1, + anon_sym_AMP, + ACTIONS(163), 1, + anon_sym_PIPE, + ACTIONS(165), 1, + anon_sym_CARET, + ACTIONS(173), 1, anon_sym_AMP_AMP, + ACTIONS(175), 1, anon_sym_PIPE_PIPE, + ACTIONS(177), 1, anon_sym_CARET_CARET, - anon_sym_LPAREN, - [12781] = 3, + ACTIONS(327), 1, + anon_sym_RBRACE, + STATE(80), 1, + sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(239), 6, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - ACTIONS(237), 18, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_RPAREN_GT, - anon_sym_COLON_COLON, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, + ACTIONS(169), 2, + anon_sym_GT, + anon_sym_LT, + ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_LPAREN, - [12814] = 19, - ACTIONS(163), 1, + [7899] = 19, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(191), 1, + ACTIONS(153), 1, anon_sym_STAR_STAR, - ACTIONS(193), 1, + ACTIONS(155), 1, anon_sym_STAR, - ACTIONS(195), 1, + ACTIONS(157), 1, anon_sym_SLASH, - ACTIONS(205), 1, + ACTIONS(161), 1, anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, + ACTIONS(163), 1, anon_sym_PIPE, - ACTIONS(215), 1, + ACTIONS(165), 1, + anon_sym_CARET, + ACTIONS(173), 1, anon_sym_AMP_AMP, - ACTIONS(217), 1, + ACTIONS(175), 1, anon_sym_PIPE_PIPE, - ACTIONS(221), 1, + ACTIONS(177), 1, anon_sym_CARET_CARET, - ACTIONS(409), 1, - anon_sym_SEMI, - STATE(90), 1, + ACTIONS(329), 1, + anon_sym_else, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(201), 2, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(203), 2, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(211), 2, + ACTIONS(169), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(213), 4, + ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [12879] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(251), 6, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - ACTIONS(249), 18, + [7964] = 19, + ACTIONS(131), 1, anon_sym_DOT, - anon_sym_COMMA, - anon_sym_RPAREN_GT, + ACTIONS(133), 1, anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, + ACTIONS(137), 1, + anon_sym_LPAREN, + ACTIONS(153), 1, anon_sym_STAR_STAR, + ACTIONS(155), 1, + anon_sym_STAR, + ACTIONS(157), 1, anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, + ACTIONS(161), 1, + anon_sym_AMP, + ACTIONS(163), 1, + anon_sym_PIPE, + ACTIONS(165), 1, + anon_sym_CARET, + ACTIONS(173), 1, anon_sym_AMP_AMP, + ACTIONS(175), 1, anon_sym_PIPE_PIPE, + ACTIONS(177), 1, anon_sym_CARET_CARET, - anon_sym_LPAREN, - [12912] = 3, + ACTIONS(331), 1, + anon_sym_COMMA, + STATE(80), 1, + sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(257), 6, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - ACTIONS(255), 18, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_RPAREN_GT, - anon_sym_COLON_COLON, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, + ACTIONS(169), 2, + anon_sym_GT, + anon_sym_LT, + ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_LPAREN, - [12945] = 19, - ACTIONS(163), 1, + [8029] = 19, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(259), 1, - anon_sym_then, - ACTIONS(377), 1, + ACTIONS(153), 1, anon_sym_STAR_STAR, - ACTIONS(379), 1, + ACTIONS(155), 1, anon_sym_STAR, - ACTIONS(381), 1, + ACTIONS(157), 1, anon_sym_SLASH, - ACTIONS(385), 1, + ACTIONS(161), 1, anon_sym_AMP, - ACTIONS(387), 1, + ACTIONS(163), 1, anon_sym_PIPE, - ACTIONS(389), 1, + ACTIONS(165), 1, anon_sym_CARET, - ACTIONS(395), 1, + ACTIONS(173), 1, anon_sym_AMP_AMP, - ACTIONS(397), 1, + ACTIONS(175), 1, anon_sym_PIPE_PIPE, - ACTIONS(399), 1, + ACTIONS(177), 1, anon_sym_CARET_CARET, - STATE(90), 1, + ACTIONS(333), 1, + anon_sym_SEMI, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(375), 2, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(383), 2, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(391), 2, + ACTIONS(169), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(393), 4, + ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [13010] = 19, - ACTIONS(163), 1, + [8094] = 19, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(263), 1, + ACTIONS(181), 1, anon_sym_then, - ACTIONS(377), 1, + ACTIONS(299), 1, anon_sym_STAR_STAR, - ACTIONS(379), 1, + ACTIONS(301), 1, anon_sym_STAR, - ACTIONS(381), 1, + ACTIONS(303), 1, anon_sym_SLASH, - ACTIONS(385), 1, + ACTIONS(307), 1, anon_sym_AMP, - ACTIONS(387), 1, + ACTIONS(309), 1, anon_sym_PIPE, - ACTIONS(389), 1, + ACTIONS(311), 1, anon_sym_CARET, - ACTIONS(395), 1, + ACTIONS(317), 1, anon_sym_AMP_AMP, - ACTIONS(397), 1, + ACTIONS(319), 1, anon_sym_PIPE_PIPE, - ACTIONS(399), 1, + ACTIONS(321), 1, anon_sym_CARET_CARET, - STATE(90), 1, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(375), 2, + ACTIONS(297), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(383), 2, + ACTIONS(305), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(391), 2, + ACTIONS(313), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(393), 4, + ACTIONS(315), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [13075] = 3, + [8159] = 10, + ACTIONS(131), 1, + anon_sym_DOT, + ACTIONS(133), 1, + anon_sym_COLON_COLON, + ACTIONS(137), 1, + anon_sym_LPAREN, + ACTIONS(299), 1, + anon_sym_STAR_STAR, + ACTIONS(301), 1, + anon_sym_STAR, + ACTIONS(303), 1, + anon_sym_SLASH, + STATE(80), 1, + sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(273), 6, - anon_sym_STAR, + ACTIONS(135), 5, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(271), 18, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_RPAREN_GT, - anon_sym_COLON_COLON, + ACTIONS(129), 12, anon_sym_DASH, anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, anon_sym_LT_LT, anon_sym_GT_GT, anon_sym_GT_EQ, @@ -12771,26 +8683,31 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, + anon_sym_then, + [8206] = 8, + ACTIONS(131), 1, + anon_sym_DOT, + ACTIONS(133), 1, + anon_sym_COLON_COLON, + ACTIONS(137), 1, anon_sym_LPAREN, - [13108] = 3, + ACTIONS(299), 1, + anon_sym_STAR_STAR, + STATE(80), 1, + sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(277), 6, + ACTIONS(135), 6, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(275), 18, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_RPAREN_GT, - anon_sym_COLON_COLON, + ACTIONS(129), 13, anon_sym_DASH, anon_sym_PLUS, - anon_sym_STAR_STAR, anon_sym_SLASH, anon_sym_LT_LT, anon_sym_GT_GT, @@ -12801,27 +8718,35 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, + anon_sym_then, + [8249] = 11, + ACTIONS(131), 1, + anon_sym_DOT, + ACTIONS(133), 1, + anon_sym_COLON_COLON, + ACTIONS(137), 1, anon_sym_LPAREN, - [13141] = 3, + ACTIONS(299), 1, + anon_sym_STAR_STAR, + ACTIONS(301), 1, + anon_sym_STAR, + ACTIONS(303), 1, + anon_sym_SLASH, + STATE(80), 1, + sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(281), 6, - anon_sym_STAR, + ACTIONS(297), 2, + anon_sym_DASH, + anon_sym_PLUS, + ACTIONS(135), 5, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(279), 18, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_RPAREN_GT, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, + ACTIONS(129), 10, anon_sym_LT_LT, anon_sym_GT_GT, anon_sym_GT_EQ, @@ -12831,29 +8756,119 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, + anon_sym_then, + [8298] = 12, + ACTIONS(131), 1, + anon_sym_DOT, + ACTIONS(133), 1, + anon_sym_COLON_COLON, + ACTIONS(137), 1, anon_sym_LPAREN, - [13174] = 3, + ACTIONS(299), 1, + anon_sym_STAR_STAR, + ACTIONS(301), 1, + anon_sym_STAR, + ACTIONS(303), 1, + anon_sym_SLASH, + STATE(80), 1, + sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(177), 6, - anon_sym_STAR, + ACTIONS(297), 2, + anon_sym_DASH, + anon_sym_PLUS, + ACTIONS(305), 2, + anon_sym_LT_LT, + anon_sym_GT_GT, + ACTIONS(135), 5, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(175), 18, + ACTIONS(129), 8, + anon_sym_GT_EQ, + anon_sym_EQ_EQ, + anon_sym_LT_EQ, + anon_sym_BANG_EQ, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_CARET_CARET, + anon_sym_then, + [8349] = 14, + ACTIONS(131), 1, anon_sym_DOT, - anon_sym_COMMA, - anon_sym_RPAREN_GT, + ACTIONS(133), 1, anon_sym_COLON_COLON, + ACTIONS(137), 1, + anon_sym_LPAREN, + ACTIONS(299), 1, + anon_sym_STAR_STAR, + ACTIONS(301), 1, + anon_sym_STAR, + ACTIONS(303), 1, + anon_sym_SLASH, + ACTIONS(307), 1, + anon_sym_AMP, + ACTIONS(311), 1, + anon_sym_CARET, + STATE(80), 1, + sym_dictionary_construction, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(297), 2, anon_sym_DASH, anon_sym_PLUS, + ACTIONS(305), 2, + anon_sym_LT_LT, + anon_sym_GT_GT, + ACTIONS(135), 3, + anon_sym_PIPE, + anon_sym_GT, + anon_sym_LT, + ACTIONS(129), 8, + anon_sym_GT_EQ, + anon_sym_EQ_EQ, + anon_sym_LT_EQ, + anon_sym_BANG_EQ, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_CARET_CARET, + anon_sym_then, + [8404] = 13, + ACTIONS(131), 1, + anon_sym_DOT, + ACTIONS(133), 1, + anon_sym_COLON_COLON, + ACTIONS(137), 1, + anon_sym_LPAREN, + ACTIONS(299), 1, anon_sym_STAR_STAR, + ACTIONS(301), 1, + anon_sym_STAR, + ACTIONS(303), 1, anon_sym_SLASH, + ACTIONS(307), 1, + anon_sym_AMP, + STATE(80), 1, + sym_dictionary_construction, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(297), 2, + anon_sym_DASH, + anon_sym_PLUS, + ACTIONS(305), 2, anon_sym_LT_LT, anon_sym_GT_GT, + ACTIONS(135), 4, + anon_sym_PIPE, + anon_sym_CARET, + anon_sym_GT, + anon_sym_LT, + ACTIONS(129), 8, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, @@ -12861,488 +8876,514 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, - anon_sym_LPAREN, - [13207] = 19, - ACTIONS(163), 1, + anon_sym_then, + [8457] = 16, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(191), 1, + ACTIONS(299), 1, anon_sym_STAR_STAR, - ACTIONS(193), 1, + ACTIONS(301), 1, anon_sym_STAR, - ACTIONS(195), 1, + ACTIONS(303), 1, anon_sym_SLASH, - ACTIONS(205), 1, + ACTIONS(307), 1, anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, + ACTIONS(309), 1, anon_sym_PIPE, - ACTIONS(215), 1, + ACTIONS(311), 1, + anon_sym_CARET, + STATE(80), 1, + sym_dictionary_construction, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(297), 2, + anon_sym_DASH, + anon_sym_PLUS, + ACTIONS(305), 2, + anon_sym_LT_LT, + anon_sym_GT_GT, + ACTIONS(313), 2, + anon_sym_GT, + anon_sym_LT, + ACTIONS(129), 4, anon_sym_AMP_AMP, - ACTIONS(217), 1, anon_sym_PIPE_PIPE, - ACTIONS(221), 1, anon_sym_CARET_CARET, - ACTIONS(347), 1, - anon_sym_COMMA, - STATE(90), 1, + anon_sym_then, + ACTIONS(315), 4, + anon_sym_GT_EQ, + anon_sym_EQ_EQ, + anon_sym_LT_EQ, + anon_sym_BANG_EQ, + [8516] = 17, + ACTIONS(131), 1, + anon_sym_DOT, + ACTIONS(133), 1, + anon_sym_COLON_COLON, + ACTIONS(137), 1, + anon_sym_LPAREN, + ACTIONS(299), 1, + anon_sym_STAR_STAR, + ACTIONS(301), 1, + anon_sym_STAR, + ACTIONS(303), 1, + anon_sym_SLASH, + ACTIONS(307), 1, + anon_sym_AMP, + ACTIONS(309), 1, + anon_sym_PIPE, + ACTIONS(311), 1, + anon_sym_CARET, + ACTIONS(317), 1, + anon_sym_AMP_AMP, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(201), 2, + ACTIONS(297), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(203), 2, + ACTIONS(305), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(211), 2, + ACTIONS(313), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(213), 4, + ACTIONS(129), 3, + anon_sym_PIPE_PIPE, + anon_sym_CARET_CARET, + anon_sym_then, + ACTIONS(315), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [13272] = 19, - ACTIONS(163), 1, + [8577] = 18, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(191), 1, + ACTIONS(299), 1, anon_sym_STAR_STAR, - ACTIONS(193), 1, + ACTIONS(301), 1, anon_sym_STAR, - ACTIONS(195), 1, + ACTIONS(303), 1, anon_sym_SLASH, - ACTIONS(205), 1, + ACTIONS(307), 1, anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, + ACTIONS(309), 1, anon_sym_PIPE, - ACTIONS(215), 1, + ACTIONS(311), 1, + anon_sym_CARET, + ACTIONS(317), 1, anon_sym_AMP_AMP, - ACTIONS(217), 1, + ACTIONS(319), 1, anon_sym_PIPE_PIPE, - ACTIONS(221), 1, - anon_sym_CARET_CARET, - ACTIONS(411), 1, - ts_builtin_sym_end, - STATE(90), 1, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(201), 2, + ACTIONS(129), 2, + anon_sym_CARET_CARET, + anon_sym_then, + ACTIONS(297), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(203), 2, + ACTIONS(305), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(211), 2, + ACTIONS(313), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(213), 4, + ACTIONS(315), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [13337] = 19, - ACTIONS(163), 1, + [8640] = 19, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(291), 1, + ACTIONS(167), 1, anon_sym_then, - ACTIONS(377), 1, + ACTIONS(299), 1, anon_sym_STAR_STAR, - ACTIONS(379), 1, + ACTIONS(301), 1, anon_sym_STAR, - ACTIONS(381), 1, + ACTIONS(303), 1, anon_sym_SLASH, - ACTIONS(385), 1, + ACTIONS(307), 1, anon_sym_AMP, - ACTIONS(387), 1, + ACTIONS(309), 1, anon_sym_PIPE, - ACTIONS(389), 1, + ACTIONS(311), 1, anon_sym_CARET, - ACTIONS(395), 1, + ACTIONS(317), 1, anon_sym_AMP_AMP, - ACTIONS(397), 1, + ACTIONS(319), 1, anon_sym_PIPE_PIPE, - ACTIONS(399), 1, + ACTIONS(321), 1, anon_sym_CARET_CARET, - STATE(90), 1, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(375), 2, + ACTIONS(297), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(383), 2, + ACTIONS(305), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(391), 2, + ACTIONS(313), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(393), 4, + ACTIONS(315), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [13402] = 19, - ACTIONS(163), 1, + [8705] = 19, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(191), 1, + ACTIONS(153), 1, anon_sym_STAR_STAR, - ACTIONS(193), 1, + ACTIONS(155), 1, anon_sym_STAR, - ACTIONS(195), 1, + ACTIONS(157), 1, anon_sym_SLASH, - ACTIONS(205), 1, + ACTIONS(161), 1, anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, + ACTIONS(163), 1, anon_sym_PIPE, - ACTIONS(215), 1, + ACTIONS(165), 1, + anon_sym_CARET, + ACTIONS(173), 1, anon_sym_AMP_AMP, - ACTIONS(217), 1, + ACTIONS(175), 1, anon_sym_PIPE_PIPE, - ACTIONS(221), 1, + ACTIONS(177), 1, anon_sym_CARET_CARET, - ACTIONS(413), 1, + ACTIONS(335), 1, anon_sym_RPAREN, - STATE(90), 1, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(201), 2, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(203), 2, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(211), 2, + ACTIONS(169), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(213), 4, + ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [13467] = 19, - ACTIONS(163), 1, + [8770] = 19, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(191), 1, + ACTIONS(219), 1, + anon_sym_then, + ACTIONS(299), 1, anon_sym_STAR_STAR, - ACTIONS(193), 1, + ACTIONS(301), 1, anon_sym_STAR, - ACTIONS(195), 1, + ACTIONS(303), 1, anon_sym_SLASH, - ACTIONS(205), 1, + ACTIONS(307), 1, anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, + ACTIONS(309), 1, anon_sym_PIPE, - ACTIONS(215), 1, + ACTIONS(311), 1, + anon_sym_CARET, + ACTIONS(317), 1, anon_sym_AMP_AMP, - ACTIONS(217), 1, + ACTIONS(319), 1, anon_sym_PIPE_PIPE, - ACTIONS(221), 1, + ACTIONS(321), 1, anon_sym_CARET_CARET, - ACTIONS(415), 1, - anon_sym_COLON, - STATE(90), 1, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(201), 2, + ACTIONS(297), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(203), 2, + ACTIONS(305), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(211), 2, + ACTIONS(313), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(213), 4, + ACTIONS(315), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [13532] = 19, - ACTIONS(163), 1, + [8835] = 19, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(191), 1, + ACTIONS(223), 1, + anon_sym_then, + ACTIONS(299), 1, anon_sym_STAR_STAR, - ACTIONS(193), 1, + ACTIONS(301), 1, anon_sym_STAR, - ACTIONS(195), 1, + ACTIONS(303), 1, anon_sym_SLASH, - ACTIONS(205), 1, + ACTIONS(307), 1, anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, + ACTIONS(309), 1, anon_sym_PIPE, - ACTIONS(215), 1, + ACTIONS(311), 1, + anon_sym_CARET, + ACTIONS(317), 1, anon_sym_AMP_AMP, - ACTIONS(217), 1, + ACTIONS(319), 1, anon_sym_PIPE_PIPE, - ACTIONS(221), 1, + ACTIONS(321), 1, anon_sym_CARET_CARET, - ACTIONS(417), 1, - anon_sym_else, - STATE(90), 1, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(201), 2, + ACTIONS(297), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(203), 2, + ACTIONS(305), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(211), 2, + ACTIONS(313), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(213), 4, + ACTIONS(315), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [13597] = 19, - ACTIONS(311), 1, + [8900] = 19, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(317), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(321), 1, + ACTIONS(137), 1, + anon_sym_LPAREN, + ACTIONS(203), 1, + anon_sym_then, + ACTIONS(299), 1, anon_sym_STAR_STAR, - ACTIONS(323), 1, + ACTIONS(301), 1, anon_sym_STAR, - ACTIONS(325), 1, + ACTIONS(303), 1, anon_sym_SLASH, - ACTIONS(329), 1, + ACTIONS(307), 1, anon_sym_AMP, - ACTIONS(331), 1, + ACTIONS(309), 1, anon_sym_PIPE, - ACTIONS(333), 1, + ACTIONS(311), 1, anon_sym_CARET, - ACTIONS(339), 1, + ACTIONS(317), 1, anon_sym_AMP_AMP, - ACTIONS(341), 1, + ACTIONS(319), 1, anon_sym_PIPE_PIPE, - ACTIONS(343), 1, + ACTIONS(321), 1, anon_sym_CARET_CARET, - ACTIONS(345), 1, - anon_sym_LPAREN, - ACTIONS(419), 1, - anon_sym_RPAREN_GT, - STATE(172), 1, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(319), 2, + ACTIONS(297), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(327), 2, + ACTIONS(305), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(335), 2, + ACTIONS(313), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(337), 4, + ACTIONS(315), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [13662] = 19, - ACTIONS(163), 1, + [8965] = 19, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(191), 1, + ACTIONS(153), 1, anon_sym_STAR_STAR, - ACTIONS(193), 1, + ACTIONS(155), 1, anon_sym_STAR, - ACTIONS(195), 1, + ACTIONS(157), 1, anon_sym_SLASH, - ACTIONS(205), 1, + ACTIONS(161), 1, anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, + ACTIONS(163), 1, anon_sym_PIPE, - ACTIONS(215), 1, + ACTIONS(165), 1, + anon_sym_CARET, + ACTIONS(173), 1, anon_sym_AMP_AMP, - ACTIONS(217), 1, + ACTIONS(175), 1, anon_sym_PIPE_PIPE, - ACTIONS(221), 1, + ACTIONS(177), 1, anon_sym_CARET_CARET, - ACTIONS(421), 1, + ACTIONS(337), 1, anon_sym_COLON, - STATE(90), 1, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(201), 2, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(203), 2, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(211), 2, + ACTIONS(169), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(213), 4, + ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [13727] = 19, - ACTIONS(311), 1, + [9030] = 19, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(317), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(321), 1, + ACTIONS(137), 1, + anon_sym_LPAREN, + ACTIONS(153), 1, anon_sym_STAR_STAR, - ACTIONS(323), 1, + ACTIONS(155), 1, anon_sym_STAR, - ACTIONS(325), 1, + ACTIONS(157), 1, anon_sym_SLASH, - ACTIONS(329), 1, + ACTIONS(161), 1, anon_sym_AMP, - ACTIONS(331), 1, + ACTIONS(163), 1, anon_sym_PIPE, - ACTIONS(333), 1, + ACTIONS(165), 1, anon_sym_CARET, - ACTIONS(339), 1, + ACTIONS(173), 1, anon_sym_AMP_AMP, - ACTIONS(341), 1, + ACTIONS(175), 1, anon_sym_PIPE_PIPE, - ACTIONS(343), 1, + ACTIONS(177), 1, anon_sym_CARET_CARET, - ACTIONS(345), 1, - anon_sym_LPAREN, - ACTIONS(423), 1, - anon_sym_RPAREN_GT, - STATE(172), 1, + ACTIONS(339), 1, + anon_sym_else, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(319), 2, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(327), 2, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(335), 2, + ACTIONS(169), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(337), 4, + ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [13792] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(243), 6, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - ACTIONS(241), 18, + [9095] = 19, + ACTIONS(131), 1, anon_sym_DOT, - anon_sym_COMMA, - anon_sym_RPAREN_GT, + ACTIONS(133), 1, anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, + ACTIONS(137), 1, + anon_sym_LPAREN, + ACTIONS(153), 1, anon_sym_STAR_STAR, + ACTIONS(155), 1, + anon_sym_STAR, + ACTIONS(157), 1, anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, + ACTIONS(161), 1, + anon_sym_AMP, + ACTIONS(163), 1, + anon_sym_PIPE, + ACTIONS(165), 1, + anon_sym_CARET, + ACTIONS(173), 1, anon_sym_AMP_AMP, + ACTIONS(175), 1, anon_sym_PIPE_PIPE, + ACTIONS(177), 1, anon_sym_CARET_CARET, - anon_sym_LPAREN, - [13825] = 3, + ACTIONS(341), 1, + anon_sym_COLON, + STATE(80), 1, + sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(231), 6, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - ACTIONS(229), 18, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_RPAREN_GT, - anon_sym_COLON_COLON, + ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, + ACTIONS(159), 2, anon_sym_LT_LT, anon_sym_GT_GT, + ACTIONS(169), 2, + anon_sym_GT, + anon_sym_LT, + ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_LPAREN, - [13858] = 4, - ACTIONS(425), 1, + [9160] = 4, + ACTIONS(343), 1, anon_sym_DASH_GT, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(243), 7, + ACTIONS(191), 7, anon_sym_DASH, anon_sym_STAR, anon_sym_AMP, @@ -13350,7 +9391,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(241), 16, + ACTIONS(189), 16, anon_sym_DOT, anon_sym_COLON_COLON, anon_sym_PLUS, @@ -13367,228 +9408,131 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_CARET_CARET, anon_sym_then, anon_sym_LPAREN, - [13893] = 19, - ACTIONS(163), 1, + [9195] = 19, + ACTIONS(131), 1, anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(169), 1, + ACTIONS(137), 1, anon_sym_LPAREN, - ACTIONS(191), 1, + ACTIONS(299), 1, anon_sym_STAR_STAR, - ACTIONS(193), 1, + ACTIONS(301), 1, anon_sym_STAR, - ACTIONS(195), 1, + ACTIONS(303), 1, anon_sym_SLASH, - ACTIONS(205), 1, + ACTIONS(307), 1, anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, + ACTIONS(309), 1, anon_sym_PIPE, - ACTIONS(215), 1, + ACTIONS(311), 1, + anon_sym_CARET, + ACTIONS(317), 1, anon_sym_AMP_AMP, - ACTIONS(217), 1, + ACTIONS(319), 1, anon_sym_PIPE_PIPE, - ACTIONS(221), 1, + ACTIONS(321), 1, anon_sym_CARET_CARET, - ACTIONS(427), 1, - anon_sym_COMMA, - STATE(90), 1, + ACTIONS(345), 1, + anon_sym_then, + STATE(80), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(201), 2, + ACTIONS(297), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(203), 2, + ACTIONS(305), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(211), 2, + ACTIONS(313), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(213), 4, + ACTIONS(315), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [13958] = 19, - ACTIONS(163), 1, - anon_sym_DOT, - ACTIONS(165), 1, - anon_sym_COLON_COLON, - ACTIONS(169), 1, - anon_sym_LPAREN, - ACTIONS(377), 1, - anon_sym_STAR_STAR, - ACTIONS(379), 1, - anon_sym_STAR, - ACTIONS(381), 1, - anon_sym_SLASH, - ACTIONS(385), 1, - anon_sym_AMP, - ACTIONS(387), 1, - anon_sym_PIPE, - ACTIONS(389), 1, - anon_sym_CARET, - ACTIONS(395), 1, - anon_sym_AMP_AMP, - ACTIONS(397), 1, - anon_sym_PIPE_PIPE, - ACTIONS(399), 1, - anon_sym_CARET_CARET, - ACTIONS(429), 1, - anon_sym_then, - STATE(90), 1, - sym_dictionary_construction, + [9260] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(375), 2, + ACTIONS(347), 7, + sym_identifier, + sym_self, + aux_sym_base_ten_token1, + sym_true, + sym_false, + anon_sym_if, + anon_sym_let, + ACTIONS(82), 12, + sym_string, + aux_sym_octal_token1, + aux_sym_hex_token1, + aux_sym_binary_token1, + anon_sym_LBRACE, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(383), 2, - anon_sym_LT_LT, - anon_sym_GT_GT, - ACTIONS(391), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(393), 4, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - [14023] = 19, - ACTIONS(163), 1, - anon_sym_DOT, - ACTIONS(165), 1, - anon_sym_COLON_COLON, - ACTIONS(169), 1, + anon_sym_BANG, anon_sym_LPAREN, - ACTIONS(377), 1, - anon_sym_STAR_STAR, - ACTIONS(379), 1, - anon_sym_STAR, - ACTIONS(381), 1, - anon_sym_SLASH, - ACTIONS(385), 1, - anon_sym_AMP, - ACTIONS(387), 1, - anon_sym_PIPE, - ACTIONS(389), 1, - anon_sym_CARET, - ACTIONS(395), 1, - anon_sym_AMP_AMP, - ACTIONS(397), 1, - anon_sym_PIPE_PIPE, - ACTIONS(399), 1, - anon_sym_CARET_CARET, - ACTIONS(431), 1, - anon_sym_then, - STATE(90), 1, - sym_dictionary_construction, + anon_sym_LBRACK, + anon_sym_RBRACK, + anon_sym_LT_LT_LT, + [9288] = 4, + ACTIONS(349), 1, + anon_sym_DOT, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(375), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(383), 2, - anon_sym_LT_LT, - anon_sym_GT_GT, - ACTIONS(391), 2, + ACTIONS(115), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(393), 4, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - [14088] = 19, - ACTIONS(163), 1, - anon_sym_DOT, - ACTIONS(165), 1, + ACTIONS(113), 11, + sym_identifier, + sym_unit_quote, anon_sym_COLON_COLON, - ACTIONS(169), 1, - anon_sym_LPAREN, - ACTIONS(191), 1, - anon_sym_STAR_STAR, - ACTIONS(193), 1, - anon_sym_STAR, - ACTIONS(195), 1, - anon_sym_SLASH, - ACTIONS(205), 1, - anon_sym_AMP, - ACTIONS(207), 1, - anon_sym_CARET, - ACTIONS(209), 1, - anon_sym_PIPE, - ACTIONS(215), 1, - anon_sym_AMP_AMP, - ACTIONS(217), 1, - anon_sym_PIPE_PIPE, - ACTIONS(221), 1, - anon_sym_CARET_CARET, - ACTIONS(433), 1, - anon_sym_COMMA, - STATE(90), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(201), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(203), 2, - anon_sym_LT_LT, - anon_sym_GT_GT, - ACTIONS(211), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(213), 4, + anon_sym_STAR, + anon_sym_SLASH, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [14153] = 3, + [9313] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(435), 7, + ACTIONS(97), 2, + anon_sym_GT, + anon_sym_LT, + ACTIONS(95), 12, sym_identifier, - sym_self, - aux_sym_base_ten_token1, - sym_true, - sym_false, - anon_sym_if, - anon_sym_let, - ACTIONS(88), 12, - sym_string, - aux_sym_octal_token1, - aux_sym_hex_token1, - aux_sym_binary_token1, - anon_sym_LT_LPAREN, + sym_unit_quote, + anon_sym_DOT, + anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, - anon_sym_BANG, - anon_sym_LPAREN, - anon_sym_LBRACK, - anon_sym_RBRACK, - anon_sym_LT_LT_LT, - [14181] = 5, - STATE(245), 1, + anon_sym_STAR, + anon_sym_SLASH, + anon_sym_GT_EQ, + anon_sym_EQ_EQ, + anon_sym_LT_EQ, + anon_sym_BANG_EQ, + [9336] = 5, + STATE(159), 1, sym__unit, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(129), 2, + ACTIONS(107), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(437), 2, + ACTIONS(351), 2, sym_identifier, sym_unit_quote, - ACTIONS(123), 9, + ACTIONS(101), 9, anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, @@ -13598,18 +9542,14 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [14208] = 4, - ACTIONS(439), 1, - anon_sym_DOT, + [9363] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(139), 2, + ACTIONS(355), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(137), 11, - sym_identifier, - sym_unit_quote, + ACTIONS(353), 11, anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, @@ -13619,17 +9559,16 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [14233] = 3, + anon_sym_RPAREN, + anon_sym_GT_GT_GT, + [9385] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(133), 2, + ACTIONS(359), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(131), 12, - sym_identifier, - sym_unit_quote, - anon_sym_DOT, + ACTIONS(357), 11, anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, @@ -13639,203 +9578,168 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [14256] = 9, - ACTIONS(441), 1, + anon_sym_RPAREN, + anon_sym_GT_GT_GT, + [9407] = 9, + ACTIONS(361), 1, sym_identifier, - ACTIONS(443), 1, + ACTIONS(363), 1, aux_sym_base_ten_token1, - ACTIONS(447), 1, + ACTIONS(367), 1, anon_sym_LPAREN, - STATE(78), 1, - sym__float, - STATE(80), 1, + STATE(140), 1, sym_number, - STATE(249), 1, + STATE(142), 1, + sym__float, + STATE(158), 1, sym_constraint_set_expression, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(445), 2, + ACTIONS(365), 2, anon_sym_DASH, anon_sym_PLUS, - STATE(233), 5, + STATE(143), 5, sym_scalar, sym_constraint_set_parenthesis, sym_constraint_set_unary_expression, sym_constraint_set_binary_expression, sym_constraint_set_method_call, - [14290] = 9, - ACTIONS(441), 1, + [9441] = 9, + ACTIONS(361), 1, sym_identifier, - ACTIONS(443), 1, + ACTIONS(363), 1, aux_sym_base_ten_token1, - ACTIONS(447), 1, + ACTIONS(367), 1, anon_sym_LPAREN, - STATE(78), 1, - sym__float, - STATE(80), 1, + STATE(140), 1, sym_number, - STATE(254), 1, + STATE(142), 1, + sym__float, + STATE(160), 1, sym_constraint_set_expression, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(445), 2, + ACTIONS(365), 2, anon_sym_DASH, anon_sym_PLUS, - STATE(233), 5, + STATE(143), 5, sym_scalar, sym_constraint_set_parenthesis, sym_constraint_set_unary_expression, sym_constraint_set_binary_expression, sym_constraint_set_method_call, - [14324] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(451), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(449), 11, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR, - anon_sym_SLASH, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_RPAREN, - anon_sym_GT_GT_GT, - [14346] = 9, - ACTIONS(441), 1, + [9475] = 9, + ACTIONS(361), 1, sym_identifier, - ACTIONS(447), 1, - anon_sym_LPAREN, - ACTIONS(453), 1, + ACTIONS(363), 1, aux_sym_base_ten_token1, - STATE(222), 1, - sym__float, - STATE(223), 1, + ACTIONS(367), 1, + anon_sym_LPAREN, + STATE(140), 1, sym_number, - STATE(244), 1, + STATE(142), 1, + sym__float, + STATE(161), 1, sym_constraint_set_expression, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(455), 2, + ACTIONS(365), 2, anon_sym_DASH, anon_sym_PLUS, - STATE(233), 5, + STATE(143), 5, sym_scalar, sym_constraint_set_parenthesis, sym_constraint_set_unary_expression, sym_constraint_set_binary_expression, sym_constraint_set_method_call, - [14380] = 9, - ACTIONS(441), 1, + [9509] = 9, + ACTIONS(361), 1, sym_identifier, - ACTIONS(443), 1, - aux_sym_base_ten_token1, - ACTIONS(447), 1, + ACTIONS(367), 1, anon_sym_LPAREN, - STATE(78), 1, + ACTIONS(369), 1, + aux_sym_base_ten_token1, + STATE(53), 1, sym__float, - STATE(80), 1, + STATE(55), 1, sym_number, - STATE(231), 1, + STATE(166), 1, sym_constraint_set_expression, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(445), 2, + ACTIONS(371), 2, anon_sym_DASH, anon_sym_PLUS, - STATE(233), 5, + STATE(143), 5, sym_scalar, sym_constraint_set_parenthesis, sym_constraint_set_unary_expression, sym_constraint_set_binary_expression, sym_constraint_set_method_call, - [14414] = 9, - ACTIONS(441), 1, + [9543] = 9, + ACTIONS(361), 1, sym_identifier, - ACTIONS(447), 1, + ACTIONS(367), 1, anon_sym_LPAREN, - ACTIONS(453), 1, + ACTIONS(369), 1, aux_sym_base_ten_token1, - STATE(222), 1, + STATE(53), 1, sym__float, - STATE(223), 1, + STATE(55), 1, sym_number, - STATE(231), 1, + STATE(163), 1, sym_constraint_set_expression, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(455), 2, + ACTIONS(371), 2, anon_sym_DASH, anon_sym_PLUS, - STATE(233), 5, + STATE(143), 5, sym_scalar, sym_constraint_set_parenthesis, sym_constraint_set_unary_expression, sym_constraint_set_binary_expression, sym_constraint_set_method_call, - [14448] = 4, - ACTIONS(457), 1, - anon_sym_COLON_COLON, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(461), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(459), 10, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR, - anon_sym_SLASH, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_RPAREN, - anon_sym_GT_GT_GT, - [14472] = 9, - ACTIONS(441), 1, + [9577] = 9, + ACTIONS(361), 1, sym_identifier, - ACTIONS(443), 1, + ACTIONS(363), 1, aux_sym_base_ten_token1, - ACTIONS(447), 1, + ACTIONS(367), 1, anon_sym_LPAREN, - STATE(78), 1, - sym__float, - STATE(80), 1, + STATE(140), 1, sym_number, - STATE(247), 1, + STATE(142), 1, + sym__float, + STATE(156), 1, sym_constraint_set_expression, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(445), 2, + ACTIONS(365), 2, anon_sym_DASH, anon_sym_PLUS, - STATE(233), 5, + STATE(143), 5, sym_scalar, sym_constraint_set_parenthesis, sym_constraint_set_unary_expression, sym_constraint_set_binary_expression, sym_constraint_set_method_call, - [14506] = 3, + [9611] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(465), 2, + ACTIONS(111), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(463), 11, + ACTIONS(109), 11, + sym_identifier, + sym_unit_quote, anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, @@ -13845,91 +9749,89 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - anon_sym_RPAREN, - anon_sym_GT_GT_GT, - [14528] = 9, - ACTIONS(441), 1, + [9633] = 9, + ACTIONS(361), 1, sym_identifier, - ACTIONS(447), 1, + ACTIONS(367), 1, anon_sym_LPAREN, - ACTIONS(453), 1, + ACTIONS(369), 1, aux_sym_base_ten_token1, - STATE(222), 1, + STATE(53), 1, sym__float, - STATE(223), 1, + STATE(55), 1, sym_number, - STATE(243), 1, + STATE(162), 1, sym_constraint_set_expression, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(455), 2, + ACTIONS(371), 2, anon_sym_DASH, anon_sym_PLUS, - STATE(233), 5, + STATE(143), 5, sym_scalar, sym_constraint_set_parenthesis, sym_constraint_set_unary_expression, sym_constraint_set_binary_expression, sym_constraint_set_method_call, - [14562] = 9, - ACTIONS(441), 1, + [9667] = 9, + ACTIONS(361), 1, sym_identifier, - ACTIONS(443), 1, - aux_sym_base_ten_token1, - ACTIONS(447), 1, + ACTIONS(367), 1, anon_sym_LPAREN, - STATE(78), 1, + ACTIONS(369), 1, + aux_sym_base_ten_token1, + STATE(53), 1, sym__float, - STATE(80), 1, + STATE(55), 1, sym_number, - STATE(251), 1, + STATE(167), 1, sym_constraint_set_expression, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(445), 2, + ACTIONS(371), 2, anon_sym_DASH, anon_sym_PLUS, - STATE(233), 5, + STATE(143), 5, sym_scalar, sym_constraint_set_parenthesis, sym_constraint_set_unary_expression, sym_constraint_set_binary_expression, sym_constraint_set_method_call, - [14596] = 9, - ACTIONS(441), 1, + [9701] = 9, + ACTIONS(361), 1, sym_identifier, - ACTIONS(447), 1, + ACTIONS(367), 1, anon_sym_LPAREN, - ACTIONS(453), 1, + ACTIONS(369), 1, aux_sym_base_ten_token1, - STATE(222), 1, + STATE(53), 1, sym__float, - STATE(223), 1, + STATE(55), 1, sym_number, - STATE(246), 1, + STATE(156), 1, sym_constraint_set_expression, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(455), 2, + ACTIONS(371), 2, anon_sym_DASH, anon_sym_PLUS, - STATE(233), 5, + STATE(143), 5, sym_scalar, sym_constraint_set_parenthesis, sym_constraint_set_unary_expression, sym_constraint_set_binary_expression, sym_constraint_set_method_call, - [14630] = 3, + [9735] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(469), 2, + ACTIONS(375), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(467), 11, + ACTIONS(373), 11, anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, @@ -13941,17 +9843,16 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_BANG_EQ, anon_sym_RPAREN, anon_sym_GT_GT_GT, - [14652] = 3, + [9757] = 4, + ACTIONS(377), 1, + anon_sym_COLON_COLON, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(145), 2, + ACTIONS(381), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(143), 11, - sym_identifier, - sym_unit_quote, - anon_sym_COLON_COLON, + ACTIONS(379), 10, anon_sym_DASH, anon_sym_PLUS, anon_sym_STAR, @@ -13960,152 +9861,63 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [14674] = 9, - ACTIONS(441), 1, - sym_identifier, - ACTIONS(443), 1, - aux_sym_base_ten_token1, - ACTIONS(447), 1, - anon_sym_LPAREN, - STATE(78), 1, - sym__float, - STATE(80), 1, - sym_number, - STATE(250), 1, - sym_constraint_set_expression, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(445), 2, - anon_sym_DASH, - anon_sym_PLUS, - STATE(233), 5, - sym_scalar, - sym_constraint_set_parenthesis, - sym_constraint_set_unary_expression, - sym_constraint_set_binary_expression, - sym_constraint_set_method_call, - [14708] = 9, - ACTIONS(441), 1, - sym_identifier, - ACTIONS(443), 1, - aux_sym_base_ten_token1, - ACTIONS(447), 1, - anon_sym_LPAREN, - STATE(78), 1, - sym__float, - STATE(80), 1, - sym_number, - STATE(248), 1, - sym_constraint_set_expression, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(445), 2, - anon_sym_DASH, - anon_sym_PLUS, - STATE(233), 5, - sym_scalar, - sym_constraint_set_parenthesis, - sym_constraint_set_unary_expression, - sym_constraint_set_binary_expression, - sym_constraint_set_method_call, - [14742] = 9, - ACTIONS(441), 1, + anon_sym_RPAREN, + anon_sym_GT_GT_GT, + [9781] = 9, + ACTIONS(361), 1, sym_identifier, - ACTIONS(447), 1, + ACTIONS(367), 1, anon_sym_LPAREN, - ACTIONS(453), 1, + ACTIONS(369), 1, aux_sym_base_ten_token1, - STATE(222), 1, + STATE(53), 1, sym__float, - STATE(223), 1, + STATE(55), 1, sym_number, - STATE(242), 1, + STATE(165), 1, sym_constraint_set_expression, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(455), 2, + ACTIONS(371), 2, anon_sym_DASH, anon_sym_PLUS, - STATE(233), 5, + STATE(143), 5, sym_scalar, sym_constraint_set_parenthesis, sym_constraint_set_unary_expression, sym_constraint_set_binary_expression, sym_constraint_set_method_call, - [14776] = 7, - ACTIONS(457), 1, - anon_sym_COLON_COLON, - STATE(226), 1, - sym__constraint_set_relation, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(471), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(473), 2, - anon_sym_STAR, - anon_sym_SLASH, - ACTIONS(475), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(477), 4, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - [14805] = 7, - ACTIONS(457), 1, + [9815] = 7, + ACTIONS(377), 1, anon_sym_COLON_COLON, - STATE(235), 1, + STATE(153), 1, sym__constraint_set_relation, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(471), 2, + ACTIONS(383), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(473), 2, + ACTIONS(385), 2, anon_sym_STAR, anon_sym_SLASH, - ACTIONS(479), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(481), 4, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - [14834] = 5, - ACTIONS(457), 1, - anon_sym_COLON_COLON, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(461), 2, + ACTIONS(387), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(473), 2, - anon_sym_STAR, - anon_sym_SLASH, - ACTIONS(459), 6, - anon_sym_DASH, - anon_sym_PLUS, + ACTIONS(389), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [14858] = 3, + [9844] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(177), 2, + ACTIONS(141), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(175), 9, + ACTIONS(139), 9, anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, @@ -14115,678 +9927,531 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [14878] = 6, - ACTIONS(457), 1, + [9864] = 6, + ACTIONS(377), 1, anon_sym_COLON_COLON, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(471), 2, + ACTIONS(383), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(473), 2, + ACTIONS(385), 2, anon_sym_STAR, anon_sym_SLASH, - ACTIONS(483), 2, + ACTIONS(391), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(485), 4, + ACTIONS(393), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [14904] = 5, - ACTIONS(457), 1, - anon_sym_COLON_COLON, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(485), 2, - anon_sym_RPAREN, - anon_sym_GT_GT_GT, - ACTIONS(487), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(489), 2, - anon_sym_STAR, - anon_sym_SLASH, - [14924] = 4, - ACTIONS(457), 1, + [9890] = 5, + ACTIONS(377), 1, anon_sym_COLON_COLON, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(489), 2, + ACTIONS(381), 2, + anon_sym_GT, + anon_sym_LT, + ACTIONS(385), 2, anon_sym_STAR, anon_sym_SLASH, - ACTIONS(459), 4, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_RPAREN, - anon_sym_GT_GT_GT, - [14942] = 5, - ACTIONS(457), 1, - anon_sym_COLON_COLON, - ACTIONS(491), 1, - anon_sym_RPAREN, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(487), 2, + ACTIONS(379), 6, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(489), 2, - anon_sym_STAR, - anon_sym_SLASH, - [14961] = 5, - ACTIONS(457), 1, + anon_sym_GT_EQ, + anon_sym_EQ_EQ, + anon_sym_LT_EQ, + anon_sym_BANG_EQ, + [9914] = 4, + ACTIONS(377), 1, anon_sym_COLON_COLON, - ACTIONS(493), 1, - anon_sym_RPAREN, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(487), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(489), 2, + ACTIONS(395), 2, anon_sym_STAR, anon_sym_SLASH, - [14980] = 5, - ACTIONS(457), 1, - anon_sym_COLON_COLON, - ACTIONS(495), 1, + ACTIONS(379), 4, + anon_sym_DASH, + anon_sym_PLUS, + anon_sym_RPAREN, anon_sym_GT_GT_GT, + [9932] = 5, + ACTIONS(377), 1, + anon_sym_COLON_COLON, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(487), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(489), 2, + ACTIONS(393), 2, + anon_sym_RPAREN, + anon_sym_GT_GT_GT, + ACTIONS(395), 2, anon_sym_STAR, anon_sym_SLASH, - [14999] = 7, + ACTIONS(397), 2, + anon_sym_DASH, + anon_sym_PLUS, + [9952] = 7, ACTIONS(37), 1, sym_varadic_dots, - ACTIONS(497), 1, + ACTIONS(399), 1, sym_identifier, - ACTIONS(499), 1, + ACTIONS(401), 1, anon_sym_RPAREN, - STATE(255), 1, + STATE(168), 1, aux_sym_struct_definition_repeat1, - STATE(283), 1, + STATE(199), 1, sym_struct_member, - STATE(300), 1, + STATE(214), 1, sym__struct_final_element, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15022] = 7, - ACTIONS(37), 1, - sym_varadic_dots, - ACTIONS(497), 1, - sym_identifier, - ACTIONS(501), 1, + [9975] = 5, + ACTIONS(377), 1, + anon_sym_COLON_COLON, + ACTIONS(403), 1, anon_sym_RPAREN, - STATE(255), 1, - aux_sym_struct_definition_repeat1, - STATE(283), 1, - sym_struct_member, - STATE(315), 1, - sym__struct_final_element, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15045] = 5, - ACTIONS(457), 1, + ACTIONS(395), 2, + anon_sym_STAR, + anon_sym_SLASH, + ACTIONS(397), 2, + anon_sym_DASH, + anon_sym_PLUS, + [9994] = 5, + ACTIONS(377), 1, anon_sym_COLON_COLON, - ACTIONS(503), 1, - anon_sym_GT_GT_GT, + ACTIONS(405), 1, + anon_sym_RPAREN, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(487), 2, + ACTIONS(395), 2, + anon_sym_STAR, + anon_sym_SLASH, + ACTIONS(397), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(489), 2, + [10013] = 5, + ACTIONS(377), 1, + anon_sym_COLON_COLON, + ACTIONS(407), 1, + anon_sym_GT_GT_GT, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(395), 2, anon_sym_STAR, anon_sym_SLASH, - [15064] = 5, - ACTIONS(505), 1, + ACTIONS(397), 2, + anon_sym_DASH, + anon_sym_PLUS, + [10032] = 5, + ACTIONS(409), 1, sym_identifier, - STATE(255), 1, + STATE(168), 1, aux_sym_struct_definition_repeat1, - STATE(311), 1, + STATE(217), 1, sym_struct_member, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(508), 2, + ACTIONS(412), 2, anon_sym_RPAREN, sym_varadic_dots, - [15082] = 4, - ACTIONS(510), 1, - sym_identifier, - ACTIONS(512), 1, - anon_sym_in, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - STATE(259), 2, - sym_let_in_assignment, - aux_sym_let_in_repeat1, - [15097] = 4, - ACTIONS(510), 1, - sym_identifier, - ACTIONS(514), 1, - anon_sym_in, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - STATE(262), 2, - sym_let_in_assignment, - aux_sym_let_in_repeat1, - [15112] = 4, - ACTIONS(510), 1, + [10050] = 4, + ACTIONS(414), 1, sym_identifier, - ACTIONS(516), 1, + ACTIONS(417), 1, anon_sym_in, ACTIONS(3), 2, sym_comment, sym__whitespace, - STATE(257), 2, + STATE(169), 2, sym_let_in_assignment, aux_sym_let_in_repeat1, - [15127] = 4, - ACTIONS(510), 1, + [10065] = 4, + ACTIONS(419), 1, sym_identifier, - ACTIONS(518), 1, + ACTIONS(421), 1, anon_sym_in, ACTIONS(3), 2, sym_comment, sym__whitespace, - STATE(262), 2, + STATE(173), 2, sym_let_in_assignment, aux_sym_let_in_repeat1, - [15142] = 4, - ACTIONS(510), 1, + [10080] = 4, + ACTIONS(419), 1, sym_identifier, - ACTIONS(520), 1, + ACTIONS(423), 1, anon_sym_in, ACTIONS(3), 2, sym_comment, sym__whitespace, - STATE(262), 2, + STATE(169), 2, sym_let_in_assignment, aux_sym_let_in_repeat1, - [15157] = 4, - ACTIONS(510), 1, + [10095] = 4, + ACTIONS(419), 1, sym_identifier, - ACTIONS(522), 1, + ACTIONS(425), 1, anon_sym_in, ACTIONS(3), 2, sym_comment, sym__whitespace, - STATE(260), 2, + STATE(171), 2, sym_let_in_assignment, aux_sym_let_in_repeat1, - [15172] = 4, - ACTIONS(524), 1, + [10110] = 4, + ACTIONS(419), 1, sym_identifier, - ACTIONS(527), 1, + ACTIONS(427), 1, anon_sym_in, ACTIONS(3), 2, sym_comment, sym__whitespace, - STATE(262), 2, + STATE(169), 2, sym_let_in_assignment, aux_sym_let_in_repeat1, - [15187] = 2, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(508), 3, - sym_identifier, - anon_sym_RPAREN, - sym_varadic_dots, - [15197] = 4, - ACTIONS(529), 1, + [10125] = 4, + ACTIONS(429), 1, anon_sym_COMMA, - ACTIONS(532), 1, + ACTIONS(431), 1, anon_sym_RPAREN, - STATE(264), 1, + STATE(181), 1, aux_sym_dictionary_construction_repeat1, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15211] = 4, - ACTIONS(534), 1, + [10139] = 4, + ACTIONS(433), 1, sym_identifier, - ACTIONS(536), 1, + ACTIONS(435), 1, anon_sym_RPAREN, - STATE(286), 1, + STATE(197), 1, sym_dictionary_member_assignment, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15225] = 4, - ACTIONS(538), 1, + [10153] = 4, + ACTIONS(437), 1, anon_sym_COMMA, - ACTIONS(540), 1, + ACTIONS(440), 1, anon_sym_RPAREN, - STATE(264), 1, + STATE(176), 1, aux_sym_dictionary_construction_repeat1, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15239] = 4, - ACTIONS(534), 1, + [10167] = 4, + ACTIONS(442), 1, sym_identifier, - ACTIONS(540), 1, - anon_sym_RPAREN, - STATE(286), 1, - sym_dictionary_member_assignment, + STATE(194), 1, + aux_sym_constraint_set_fields_repeat1, + STATE(206), 1, + sym_constraint_set_fields, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15253] = 4, - ACTIONS(534), 1, - sym_identifier, - ACTIONS(542), 1, - anon_sym_RPAREN, - STATE(286), 1, - sym_dictionary_member_assignment, + [10181] = 3, + ACTIONS(446), 1, + anon_sym_EQ, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15267] = 4, - ACTIONS(534), 1, - sym_identifier, - ACTIONS(544), 1, + ACTIONS(444), 2, + anon_sym_COMMA, anon_sym_RPAREN, - STATE(275), 1, - sym_dictionary_member_assignment, + [10193] = 2, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15281] = 4, - ACTIONS(546), 1, + ACTIONS(412), 3, sym_identifier, - STATE(280), 1, - aux_sym_constraint_set_fields_repeat1, - STATE(320), 1, - sym_constraint_set_fields, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - [15295] = 4, - ACTIONS(534), 1, + anon_sym_RPAREN, + sym_varadic_dots, + [10203] = 4, + ACTIONS(433), 1, sym_identifier, - ACTIONS(548), 1, + ACTIONS(448), 1, anon_sym_RPAREN, - STATE(273), 1, + STATE(197), 1, sym_dictionary_member_assignment, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15309] = 4, - ACTIONS(542), 1, + [10217] = 4, + ACTIONS(448), 1, anon_sym_RPAREN, - ACTIONS(550), 1, - anon_sym_COMMA, - STATE(264), 1, - aux_sym_dictionary_construction_repeat1, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - [15323] = 4, - ACTIONS(552), 1, + ACTIONS(450), 1, anon_sym_COMMA, - ACTIONS(554), 1, - anon_sym_RPAREN, - STATE(272), 1, + STATE(176), 1, aux_sym_dictionary_construction_repeat1, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15337] = 4, - ACTIONS(534), 1, + [10231] = 4, + ACTIONS(433), 1, sym_identifier, - ACTIONS(556), 1, + ACTIONS(452), 1, anon_sym_RPAREN, - STATE(286), 1, + STATE(174), 1, sym_dictionary_member_assignment, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15351] = 4, - ACTIONS(558), 1, - anon_sym_COMMA, - ACTIONS(560), 1, - anon_sym_RPAREN, - STATE(266), 1, - aux_sym_dictionary_construction_repeat1, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - [15365] = 4, - ACTIONS(546), 1, + [10245] = 3, + ACTIONS(454), 1, sym_identifier, - STATE(280), 1, + STATE(183), 1, aux_sym_constraint_set_fields_repeat1, - STATE(301), 1, - sym_constraint_set_fields, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15379] = 3, - ACTIONS(564), 1, - anon_sym_EQ, + [10256] = 3, + ACTIONS(433), 1, + sym_identifier, + STATE(197), 1, + sym_dictionary_member_assignment, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(562), 2, + [10267] = 3, + ACTIONS(457), 1, anon_sym_COMMA, - anon_sym_RPAREN, - [15391] = 2, + ACTIONS(459), 1, + anon_sym_COLON, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(566), 2, - aux_sym_signed_integer_token1, - aux_sym_unsigned_integer_token1, - [15400] = 3, - ACTIONS(568), 1, + [10278] = 3, + ACTIONS(369), 1, aux_sym_base_ten_token1, - STATE(157), 1, + STATE(54), 1, sym_number, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15411] = 3, - ACTIONS(570), 1, - sym_identifier, - STATE(299), 1, - aux_sym_constraint_set_fields_repeat1, + [10289] = 2, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15422] = 3, - ACTIONS(345), 1, - anon_sym_LPAREN, - STATE(195), 1, - sym_dictionary_construction, + ACTIONS(461), 2, + aux_sym_signed_integer_token1, + aux_sym_unsigned_integer_token1, + [10298] = 3, + ACTIONS(457), 1, + anon_sym_COMMA, + ACTIONS(463), 1, + anon_sym_COLON, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15433] = 2, + [10309] = 3, + ACTIONS(465), 1, + aux_sym_signed_integer_token1, + ACTIONS(467), 1, + aux_sym_unsigned_integer_token1, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(572), 2, - sym_identifier, - anon_sym_in, - [15442] = 3, - ACTIONS(574), 1, - anon_sym_COMMA, - ACTIONS(576), 1, - anon_sym_RPAREN, + [10320] = 3, + ACTIONS(469), 1, + anon_sym_COLON, + STATE(178), 1, + sym_declaration_type, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15453] = 2, + [10331] = 2, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(578), 2, + ACTIONS(471), 2, aux_sym_signed_integer_token1, aux_sym_unsigned_integer_token1, - [15462] = 3, - ACTIONS(534), 1, - sym_identifier, - STATE(286), 1, - sym_dictionary_member_assignment, + [10340] = 2, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15473] = 2, + ACTIONS(473), 2, + aux_sym_signed_integer_token1, + aux_sym_unsigned_integer_token1, + [10349] = 3, + ACTIONS(137), 1, + anon_sym_LPAREN, + STATE(69), 1, + sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(532), 2, - anon_sym_COMMA, - anon_sym_RPAREN, - [15482] = 3, - ACTIONS(576), 1, - anon_sym_RPAREN, - ACTIONS(580), 1, - anon_sym_COMMA, + [10360] = 3, + ACTIONS(475), 1, + sym_identifier, + STATE(183), 1, + aux_sym_constraint_set_fields_repeat1, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15493] = 3, - ACTIONS(582), 1, + [10371] = 3, + ACTIONS(477), 1, aux_sym_base_ten_token1, - STATE(128), 1, + STATE(104), 1, sym_number, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15504] = 3, - ACTIONS(584), 1, - anon_sym_COMMA, - ACTIONS(586), 1, - anon_sym_COLON, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - [15515] = 3, - ACTIONS(588), 1, - anon_sym_COLON, - STATE(277), 1, - sym_declaration_type, + [10382] = 2, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15526] = 3, - ACTIONS(453), 1, - aux_sym_base_ten_token1, - STATE(238), 1, - sym_number, + ACTIONS(479), 2, + sym_identifier, + anon_sym_in, + [10391] = 2, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15537] = 3, - ACTIONS(443), 1, + ACTIONS(440), 2, + anon_sym_COMMA, + anon_sym_RPAREN, + [10400] = 3, + ACTIONS(363), 1, aux_sym_base_ten_token1, - STATE(81), 1, + STATE(151), 1, sym_number, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15548] = 2, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(590), 2, - aux_sym_signed_integer_token1, - aux_sym_unsigned_integer_token1, - [15557] = 3, - ACTIONS(584), 1, + [10411] = 3, + ACTIONS(481), 1, anon_sym_COMMA, - ACTIONS(592), 1, - anon_sym_COLON, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - [15568] = 3, - ACTIONS(594), 1, - aux_sym_signed_integer_token1, - ACTIONS(596), 1, - aux_sym_unsigned_integer_token1, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - [15579] = 2, + ACTIONS(483), 1, + anon_sym_RPAREN, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(598), 2, - aux_sym_signed_integer_token1, - aux_sym_unsigned_integer_token1, - [15588] = 3, - ACTIONS(169), 1, - anon_sym_LPAREN, - STATE(108), 1, - sym_dictionary_construction, + [10422] = 2, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15599] = 3, - ACTIONS(600), 1, + ACTIONS(485), 2, aux_sym_signed_integer_token1, - ACTIONS(602), 1, aux_sym_unsigned_integer_token1, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - [15610] = 3, - ACTIONS(604), 1, - sym_identifier, - STATE(299), 1, - aux_sym_constraint_set_fields_repeat1, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - [15621] = 2, - ACTIONS(607), 1, + [10431] = 3, + ACTIONS(483), 1, anon_sym_RPAREN, + ACTIONS(487), 1, + anon_sym_COMMA, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15629] = 2, - ACTIONS(609), 1, - anon_sym_COLON, + [10442] = 2, + ACTIONS(489), 1, + sym_identifier, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15637] = 2, - ACTIONS(611), 1, + [10450] = 2, + ACTIONS(491), 1, sym_identifier, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15645] = 2, - ACTIONS(613), 1, + [10458] = 2, + ACTIONS(493), 1, aux_sym_hex_token2, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15653] = 2, - ACTIONS(615), 1, + [10466] = 2, + ACTIONS(495), 1, aux_sym_binary_token2, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15661] = 2, - ACTIONS(617), 1, - aux_sym_base_ten_token1, + [10474] = 2, + ACTIONS(497), 1, + anon_sym_COLON, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15669] = 2, - ACTIONS(619), 1, - sym_identifier, + [10482] = 2, + ACTIONS(499), 1, + anon_sym_EQ, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15677] = 2, - ACTIONS(621), 1, + [10490] = 2, + ACTIONS(501), 1, anon_sym_LPAREN, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15685] = 2, - ACTIONS(623), 1, + [10498] = 2, + ACTIONS(503), 1, anon_sym_EQ, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15693] = 2, - ACTIONS(625), 1, - sym_identifier, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - [15701] = 2, - ACTIONS(627), 1, - anon_sym_RPAREN, + [10506] = 2, + ACTIONS(505), 1, + aux_sym_base_ten_token1, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15709] = 2, - ACTIONS(574), 1, + [10514] = 2, + ACTIONS(457), 1, anon_sym_COMMA, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15717] = 2, - ACTIONS(629), 1, - sym_identifier, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - [15725] = 2, - ACTIONS(584), 1, - anon_sym_COMMA, + [10522] = 2, + ACTIONS(507), 1, + ts_builtin_sym_end, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15733] = 2, - ACTIONS(631), 1, + [10530] = 2, + ACTIONS(509), 1, anon_sym_RPAREN, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15741] = 2, - ACTIONS(633), 1, + [10538] = 2, + ACTIONS(511), 1, anon_sym_RPAREN, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15749] = 2, - ACTIONS(635), 1, + [10546] = 2, + ACTIONS(513), 1, sym_identifier, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15757] = 2, - ACTIONS(637), 1, + [10554] = 2, + ACTIONS(515), 1, sym_identifier, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15765] = 2, - ACTIONS(639), 1, - anon_sym_EQ, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - [15773] = 2, - ACTIONS(641), 1, - ts_builtin_sym_end, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - [15781] = 2, - ACTIONS(643), 1, - anon_sym_COLON, + [10562] = 2, + ACTIONS(481), 1, + anon_sym_COMMA, ACTIONS(3), 2, sym_comment, sym__whitespace, - [15789] = 2, - ACTIONS(645), 1, + [10570] = 2, + ACTIONS(517), 1, anon_sym_RPAREN, ACTIONS(3), 2, sym_comment, @@ -14794,642 +10459,476 @@ static const uint16_t ts_small_parse_table[] = { }; static const uint32_t ts_small_parse_table_map[] = { - [SMALL_STATE(4)] = 0, - [SMALL_STATE(5)] = 99, - [SMALL_STATE(6)] = 198, - [SMALL_STATE(7)] = 297, - [SMALL_STATE(8)] = 396, - [SMALL_STATE(9)] = 495, - [SMALL_STATE(10)] = 588, - [SMALL_STATE(11)] = 681, - [SMALL_STATE(12)] = 774, - [SMALL_STATE(13)] = 867, - [SMALL_STATE(14)] = 960, - [SMALL_STATE(15)] = 1053, - [SMALL_STATE(16)] = 1146, - [SMALL_STATE(17)] = 1239, - [SMALL_STATE(18)] = 1332, - [SMALL_STATE(19)] = 1425, - [SMALL_STATE(20)] = 1518, - [SMALL_STATE(21)] = 1611, - [SMALL_STATE(22)] = 1704, - [SMALL_STATE(23)] = 1797, - [SMALL_STATE(24)] = 1890, - [SMALL_STATE(25)] = 1983, - [SMALL_STATE(26)] = 2076, - [SMALL_STATE(27)] = 2169, - [SMALL_STATE(28)] = 2262, - [SMALL_STATE(29)] = 2355, - [SMALL_STATE(30)] = 2448, - [SMALL_STATE(31)] = 2541, - [SMALL_STATE(32)] = 2634, - [SMALL_STATE(33)] = 2727, - [SMALL_STATE(34)] = 2820, - [SMALL_STATE(35)] = 2913, - [SMALL_STATE(36)] = 3006, - [SMALL_STATE(37)] = 3099, - [SMALL_STATE(38)] = 3192, - [SMALL_STATE(39)] = 3285, - [SMALL_STATE(40)] = 3378, - [SMALL_STATE(41)] = 3471, - [SMALL_STATE(42)] = 3564, - [SMALL_STATE(43)] = 3657, - [SMALL_STATE(44)] = 3750, - [SMALL_STATE(45)] = 3843, - [SMALL_STATE(46)] = 3936, - [SMALL_STATE(47)] = 4029, - [SMALL_STATE(48)] = 4122, - [SMALL_STATE(49)] = 4215, - [SMALL_STATE(50)] = 4308, - [SMALL_STATE(51)] = 4401, - [SMALL_STATE(52)] = 4494, - [SMALL_STATE(53)] = 4587, - [SMALL_STATE(54)] = 4680, - [SMALL_STATE(55)] = 4773, - [SMALL_STATE(56)] = 4866, - [SMALL_STATE(57)] = 4959, - [SMALL_STATE(58)] = 5052, - [SMALL_STATE(59)] = 5145, - [SMALL_STATE(60)] = 5238, - [SMALL_STATE(61)] = 5331, - [SMALL_STATE(62)] = 5424, - [SMALL_STATE(63)] = 5517, - [SMALL_STATE(64)] = 5610, - [SMALL_STATE(65)] = 5703, - [SMALL_STATE(66)] = 5796, - [SMALL_STATE(67)] = 5889, - [SMALL_STATE(68)] = 5982, - [SMALL_STATE(69)] = 6075, - [SMALL_STATE(70)] = 6168, - [SMALL_STATE(71)] = 6261, - [SMALL_STATE(72)] = 6354, - [SMALL_STATE(73)] = 6447, - [SMALL_STATE(74)] = 6540, - [SMALL_STATE(75)] = 6633, - [SMALL_STATE(76)] = 6726, - [SMALL_STATE(77)] = 6819, - [SMALL_STATE(78)] = 6912, - [SMALL_STATE(79)] = 6961, - [SMALL_STATE(80)] = 7006, - [SMALL_STATE(81)] = 7050, - [SMALL_STATE(82)] = 7092, - [SMALL_STATE(83)] = 7134, - [SMALL_STATE(84)] = 7177, - [SMALL_STATE(85)] = 7218, - [SMALL_STATE(86)] = 7259, - [SMALL_STATE(87)] = 7308, - [SMALL_STATE(88)] = 7349, - [SMALL_STATE(89)] = 7390, - [SMALL_STATE(90)] = 7430, - [SMALL_STATE(91)] = 7470, - [SMALL_STATE(92)] = 7510, - [SMALL_STATE(93)] = 7564, - [SMALL_STATE(94)] = 7604, - [SMALL_STATE(95)] = 7654, - [SMALL_STATE(96)] = 7710, - [SMALL_STATE(97)] = 7768, - [SMALL_STATE(98)] = 7830, - [SMALL_STATE(99)] = 7890, - [SMALL_STATE(100)] = 7954, - [SMALL_STATE(101)] = 8022, - [SMALL_STATE(102)] = 8092, - [SMALL_STATE(103)] = 8164, - [SMALL_STATE(104)] = 8204, - [SMALL_STATE(105)] = 8278, - [SMALL_STATE(106)] = 8318, - [SMALL_STATE(107)] = 8358, - [SMALL_STATE(108)] = 8398, - [SMALL_STATE(109)] = 8438, - [SMALL_STATE(110)] = 8478, - [SMALL_STATE(111)] = 8518, - [SMALL_STATE(112)] = 8558, - [SMALL_STATE(113)] = 8600, - [SMALL_STATE(114)] = 8640, - [SMALL_STATE(115)] = 8714, - [SMALL_STATE(116)] = 8788, - [SMALL_STATE(117)] = 8862, - [SMALL_STATE(118)] = 8902, - [SMALL_STATE(119)] = 8942, - [SMALL_STATE(120)] = 8982, - [SMALL_STATE(121)] = 9022, - [SMALL_STATE(122)] = 9062, - [SMALL_STATE(123)] = 9136, - [SMALL_STATE(124)] = 9176, - [SMALL_STATE(125)] = 9215, - [SMALL_STATE(126)] = 9255, - [SMALL_STATE(127)] = 9293, - [SMALL_STATE(128)] = 9362, - [SMALL_STATE(129)] = 9397, - [SMALL_STATE(130)] = 9434, - [SMALL_STATE(131)] = 9475, - [SMALL_STATE(132)] = 9516, - [SMALL_STATE(133)] = 9551, - [SMALL_STATE(134)] = 9619, - [SMALL_STATE(135)] = 9673, - [SMALL_STATE(136)] = 9731, - [SMALL_STATE(137)] = 9791, - [SMALL_STATE(138)] = 9853, - [SMALL_STATE(139)] = 9917, - [SMALL_STATE(140)] = 9983, - [SMALL_STATE(141)] = 10051, - [SMALL_STATE(142)] = 10087, - [SMALL_STATE(143)] = 10153, - [SMALL_STATE(144)] = 10219, - [SMALL_STATE(145)] = 10287, - [SMALL_STATE(146)] = 10323, - [SMALL_STATE(147)] = 10389, - [SMALL_STATE(148)] = 10455, - [SMALL_STATE(149)] = 10491, - [SMALL_STATE(150)] = 10547, - [SMALL_STATE(151)] = 10615, - [SMALL_STATE(152)] = 10681, - [SMALL_STATE(153)] = 10749, - [SMALL_STATE(154)] = 10783, - [SMALL_STATE(155)] = 10851, - [SMALL_STATE(156)] = 10885, - [SMALL_STATE(157)] = 10919, - [SMALL_STATE(158)] = 10953, - [SMALL_STATE(159)] = 10995, - [SMALL_STATE(160)] = 11029, - [SMALL_STATE(161)] = 11095, - [SMALL_STATE(162)] = 11163, - [SMALL_STATE(163)] = 11211, - [SMALL_STATE(164)] = 11255, - [SMALL_STATE(165)] = 11305, - [SMALL_STATE(166)] = 11357, - [SMALL_STATE(167)] = 11425, - [SMALL_STATE(168)] = 11490, - [SMALL_STATE(169)] = 11523, - [SMALL_STATE(170)] = 11556, - [SMALL_STATE(171)] = 11589, - [SMALL_STATE(172)] = 11654, - [SMALL_STATE(173)] = 11687, - [SMALL_STATE(174)] = 11752, - [SMALL_STATE(175)] = 11785, - [SMALL_STATE(176)] = 11850, - [SMALL_STATE(177)] = 11883, - [SMALL_STATE(178)] = 11916, - [SMALL_STATE(179)] = 11981, - [SMALL_STATE(180)] = 12014, - [SMALL_STATE(181)] = 12061, - [SMALL_STATE(182)] = 12104, - [SMALL_STATE(183)] = 12153, - [SMALL_STATE(184)] = 12204, - [SMALL_STATE(185)] = 12259, - [SMALL_STATE(186)] = 12312, - [SMALL_STATE(187)] = 12369, - [SMALL_STATE(188)] = 12428, - [SMALL_STATE(189)] = 12489, - [SMALL_STATE(190)] = 12552, - [SMALL_STATE(191)] = 12585, - [SMALL_STATE(192)] = 12650, - [SMALL_STATE(193)] = 12683, - [SMALL_STATE(194)] = 12748, - [SMALL_STATE(195)] = 12781, - [SMALL_STATE(196)] = 12814, - [SMALL_STATE(197)] = 12879, - [SMALL_STATE(198)] = 12912, - [SMALL_STATE(199)] = 12945, - [SMALL_STATE(200)] = 13010, - [SMALL_STATE(201)] = 13075, - [SMALL_STATE(202)] = 13108, - [SMALL_STATE(203)] = 13141, - [SMALL_STATE(204)] = 13174, - [SMALL_STATE(205)] = 13207, - [SMALL_STATE(206)] = 13272, - [SMALL_STATE(207)] = 13337, - [SMALL_STATE(208)] = 13402, - [SMALL_STATE(209)] = 13467, - [SMALL_STATE(210)] = 13532, - [SMALL_STATE(211)] = 13597, - [SMALL_STATE(212)] = 13662, - [SMALL_STATE(213)] = 13727, - [SMALL_STATE(214)] = 13792, - [SMALL_STATE(215)] = 13825, - [SMALL_STATE(216)] = 13858, - [SMALL_STATE(217)] = 13893, - [SMALL_STATE(218)] = 13958, - [SMALL_STATE(219)] = 14023, - [SMALL_STATE(220)] = 14088, - [SMALL_STATE(221)] = 14153, - [SMALL_STATE(222)] = 14181, - [SMALL_STATE(223)] = 14208, - [SMALL_STATE(224)] = 14233, - [SMALL_STATE(225)] = 14256, - [SMALL_STATE(226)] = 14290, - [SMALL_STATE(227)] = 14324, - [SMALL_STATE(228)] = 14346, - [SMALL_STATE(229)] = 14380, - [SMALL_STATE(230)] = 14414, - [SMALL_STATE(231)] = 14448, - [SMALL_STATE(232)] = 14472, - [SMALL_STATE(233)] = 14506, - [SMALL_STATE(234)] = 14528, - [SMALL_STATE(235)] = 14562, - [SMALL_STATE(236)] = 14596, - [SMALL_STATE(237)] = 14630, - [SMALL_STATE(238)] = 14652, - [SMALL_STATE(239)] = 14674, - [SMALL_STATE(240)] = 14708, - [SMALL_STATE(241)] = 14742, - [SMALL_STATE(242)] = 14776, - [SMALL_STATE(243)] = 14805, - [SMALL_STATE(244)] = 14834, - [SMALL_STATE(245)] = 14858, - [SMALL_STATE(246)] = 14878, - [SMALL_STATE(247)] = 14904, - [SMALL_STATE(248)] = 14924, - [SMALL_STATE(249)] = 14942, - [SMALL_STATE(250)] = 14961, - [SMALL_STATE(251)] = 14980, - [SMALL_STATE(252)] = 14999, - [SMALL_STATE(253)] = 15022, - [SMALL_STATE(254)] = 15045, - [SMALL_STATE(255)] = 15064, - [SMALL_STATE(256)] = 15082, - [SMALL_STATE(257)] = 15097, - [SMALL_STATE(258)] = 15112, - [SMALL_STATE(259)] = 15127, - [SMALL_STATE(260)] = 15142, - [SMALL_STATE(261)] = 15157, - [SMALL_STATE(262)] = 15172, - [SMALL_STATE(263)] = 15187, - [SMALL_STATE(264)] = 15197, - [SMALL_STATE(265)] = 15211, - [SMALL_STATE(266)] = 15225, - [SMALL_STATE(267)] = 15239, - [SMALL_STATE(268)] = 15253, - [SMALL_STATE(269)] = 15267, - [SMALL_STATE(270)] = 15281, - [SMALL_STATE(271)] = 15295, - [SMALL_STATE(272)] = 15309, - [SMALL_STATE(273)] = 15323, - [SMALL_STATE(274)] = 15337, - [SMALL_STATE(275)] = 15351, - [SMALL_STATE(276)] = 15365, - [SMALL_STATE(277)] = 15379, - [SMALL_STATE(278)] = 15391, - [SMALL_STATE(279)] = 15400, - [SMALL_STATE(280)] = 15411, - [SMALL_STATE(281)] = 15422, - [SMALL_STATE(282)] = 15433, - [SMALL_STATE(283)] = 15442, - [SMALL_STATE(284)] = 15453, - [SMALL_STATE(285)] = 15462, - [SMALL_STATE(286)] = 15473, - [SMALL_STATE(287)] = 15482, - [SMALL_STATE(288)] = 15493, - [SMALL_STATE(289)] = 15504, - [SMALL_STATE(290)] = 15515, - [SMALL_STATE(291)] = 15526, - [SMALL_STATE(292)] = 15537, - [SMALL_STATE(293)] = 15548, - [SMALL_STATE(294)] = 15557, - [SMALL_STATE(295)] = 15568, - [SMALL_STATE(296)] = 15579, - [SMALL_STATE(297)] = 15588, - [SMALL_STATE(298)] = 15599, - [SMALL_STATE(299)] = 15610, - [SMALL_STATE(300)] = 15621, - [SMALL_STATE(301)] = 15629, - [SMALL_STATE(302)] = 15637, - [SMALL_STATE(303)] = 15645, - [SMALL_STATE(304)] = 15653, - [SMALL_STATE(305)] = 15661, - [SMALL_STATE(306)] = 15669, - [SMALL_STATE(307)] = 15677, - [SMALL_STATE(308)] = 15685, - [SMALL_STATE(309)] = 15693, - [SMALL_STATE(310)] = 15701, - [SMALL_STATE(311)] = 15709, - [SMALL_STATE(312)] = 15717, - [SMALL_STATE(313)] = 15725, - [SMALL_STATE(314)] = 15733, - [SMALL_STATE(315)] = 15741, - [SMALL_STATE(316)] = 15749, - [SMALL_STATE(317)] = 15757, - [SMALL_STATE(318)] = 15765, - [SMALL_STATE(319)] = 15773, - [SMALL_STATE(320)] = 15781, - [SMALL_STATE(321)] = 15789, + [SMALL_STATE(3)] = 0, + [SMALL_STATE(4)] = 99, + [SMALL_STATE(5)] = 198, + [SMALL_STATE(6)] = 297, + [SMALL_STATE(7)] = 390, + [SMALL_STATE(8)] = 483, + [SMALL_STATE(9)] = 576, + [SMALL_STATE(10)] = 669, + [SMALL_STATE(11)] = 762, + [SMALL_STATE(12)] = 855, + [SMALL_STATE(13)] = 948, + [SMALL_STATE(14)] = 1041, + [SMALL_STATE(15)] = 1134, + [SMALL_STATE(16)] = 1227, + [SMALL_STATE(17)] = 1320, + [SMALL_STATE(18)] = 1413, + [SMALL_STATE(19)] = 1506, + [SMALL_STATE(20)] = 1599, + [SMALL_STATE(21)] = 1692, + [SMALL_STATE(22)] = 1785, + [SMALL_STATE(23)] = 1878, + [SMALL_STATE(24)] = 1971, + [SMALL_STATE(25)] = 2064, + [SMALL_STATE(26)] = 2157, + [SMALL_STATE(27)] = 2250, + [SMALL_STATE(28)] = 2343, + [SMALL_STATE(29)] = 2436, + [SMALL_STATE(30)] = 2529, + [SMALL_STATE(31)] = 2622, + [SMALL_STATE(32)] = 2715, + [SMALL_STATE(33)] = 2808, + [SMALL_STATE(34)] = 2901, + [SMALL_STATE(35)] = 2994, + [SMALL_STATE(36)] = 3087, + [SMALL_STATE(37)] = 3180, + [SMALL_STATE(38)] = 3273, + [SMALL_STATE(39)] = 3366, + [SMALL_STATE(40)] = 3459, + [SMALL_STATE(41)] = 3552, + [SMALL_STATE(42)] = 3645, + [SMALL_STATE(43)] = 3738, + [SMALL_STATE(44)] = 3831, + [SMALL_STATE(45)] = 3924, + [SMALL_STATE(46)] = 4017, + [SMALL_STATE(47)] = 4110, + [SMALL_STATE(48)] = 4203, + [SMALL_STATE(49)] = 4296, + [SMALL_STATE(50)] = 4389, + [SMALL_STATE(51)] = 4482, + [SMALL_STATE(52)] = 4575, + [SMALL_STATE(53)] = 4621, + [SMALL_STATE(54)] = 4671, + [SMALL_STATE(55)] = 4714, + [SMALL_STATE(56)] = 4759, + [SMALL_STATE(57)] = 4802, + [SMALL_STATE(58)] = 4846, + [SMALL_STATE(59)] = 4888, + [SMALL_STATE(60)] = 4938, + [SMALL_STATE(61)] = 4980, + [SMALL_STATE(62)] = 5022, + [SMALL_STATE(63)] = 5064, + [SMALL_STATE(64)] = 5129, + [SMALL_STATE(65)] = 5204, + [SMALL_STATE(66)] = 5279, + [SMALL_STATE(67)] = 5320, + [SMALL_STATE(68)] = 5363, + [SMALL_STATE(69)] = 5404, + [SMALL_STATE(70)] = 5445, + [SMALL_STATE(71)] = 5520, + [SMALL_STATE(72)] = 5561, + [SMALL_STATE(73)] = 5602, + [SMALL_STATE(74)] = 5643, + [SMALL_STATE(75)] = 5718, + [SMALL_STATE(76)] = 5793, + [SMALL_STATE(77)] = 5834, + [SMALL_STATE(78)] = 5875, + [SMALL_STATE(79)] = 5916, + [SMALL_STATE(80)] = 5957, + [SMALL_STATE(81)] = 5998, + [SMALL_STATE(82)] = 6039, + [SMALL_STATE(83)] = 6080, + [SMALL_STATE(84)] = 6121, + [SMALL_STATE(85)] = 6162, + [SMALL_STATE(86)] = 6217, + [SMALL_STATE(87)] = 6258, + [SMALL_STATE(88)] = 6309, + [SMALL_STATE(89)] = 6366, + [SMALL_STATE(90)] = 6425, + [SMALL_STATE(91)] = 6488, + [SMALL_STATE(92)] = 6549, + [SMALL_STATE(93)] = 6590, + [SMALL_STATE(94)] = 6659, + [SMALL_STATE(95)] = 6730, + [SMALL_STATE(96)] = 6803, + [SMALL_STATE(97)] = 6844, + [SMALL_STATE(98)] = 6885, + [SMALL_STATE(99)] = 6923, + [SMALL_STATE(100)] = 6964, + [SMALL_STATE(101)] = 7033, + [SMALL_STATE(102)] = 7074, + [SMALL_STATE(103)] = 7110, + [SMALL_STATE(104)] = 7144, + [SMALL_STATE(105)] = 7178, + [SMALL_STATE(106)] = 7244, + [SMALL_STATE(107)] = 7312, + [SMALL_STATE(108)] = 7380, + [SMALL_STATE(109)] = 7448, + [SMALL_STATE(110)] = 7514, + [SMALL_STATE(111)] = 7582, + [SMALL_STATE(112)] = 7639, + [SMALL_STATE(113)] = 7704, + [SMALL_STATE(114)] = 7769, + [SMALL_STATE(115)] = 7834, + [SMALL_STATE(116)] = 7899, + [SMALL_STATE(117)] = 7964, + [SMALL_STATE(118)] = 8029, + [SMALL_STATE(119)] = 8094, + [SMALL_STATE(120)] = 8159, + [SMALL_STATE(121)] = 8206, + [SMALL_STATE(122)] = 8249, + [SMALL_STATE(123)] = 8298, + [SMALL_STATE(124)] = 8349, + [SMALL_STATE(125)] = 8404, + [SMALL_STATE(126)] = 8457, + [SMALL_STATE(127)] = 8516, + [SMALL_STATE(128)] = 8577, + [SMALL_STATE(129)] = 8640, + [SMALL_STATE(130)] = 8705, + [SMALL_STATE(131)] = 8770, + [SMALL_STATE(132)] = 8835, + [SMALL_STATE(133)] = 8900, + [SMALL_STATE(134)] = 8965, + [SMALL_STATE(135)] = 9030, + [SMALL_STATE(136)] = 9095, + [SMALL_STATE(137)] = 9160, + [SMALL_STATE(138)] = 9195, + [SMALL_STATE(139)] = 9260, + [SMALL_STATE(140)] = 9288, + [SMALL_STATE(141)] = 9313, + [SMALL_STATE(142)] = 9336, + [SMALL_STATE(143)] = 9363, + [SMALL_STATE(144)] = 9385, + [SMALL_STATE(145)] = 9407, + [SMALL_STATE(146)] = 9441, + [SMALL_STATE(147)] = 9475, + [SMALL_STATE(148)] = 9509, + [SMALL_STATE(149)] = 9543, + [SMALL_STATE(150)] = 9577, + [SMALL_STATE(151)] = 9611, + [SMALL_STATE(152)] = 9633, + [SMALL_STATE(153)] = 9667, + [SMALL_STATE(154)] = 9701, + [SMALL_STATE(155)] = 9735, + [SMALL_STATE(156)] = 9757, + [SMALL_STATE(157)] = 9781, + [SMALL_STATE(158)] = 9815, + [SMALL_STATE(159)] = 9844, + [SMALL_STATE(160)] = 9864, + [SMALL_STATE(161)] = 9890, + [SMALL_STATE(162)] = 9914, + [SMALL_STATE(163)] = 9932, + [SMALL_STATE(164)] = 9952, + [SMALL_STATE(165)] = 9975, + [SMALL_STATE(166)] = 9994, + [SMALL_STATE(167)] = 10013, + [SMALL_STATE(168)] = 10032, + [SMALL_STATE(169)] = 10050, + [SMALL_STATE(170)] = 10065, + [SMALL_STATE(171)] = 10080, + [SMALL_STATE(172)] = 10095, + [SMALL_STATE(173)] = 10110, + [SMALL_STATE(174)] = 10125, + [SMALL_STATE(175)] = 10139, + [SMALL_STATE(176)] = 10153, + [SMALL_STATE(177)] = 10167, + [SMALL_STATE(178)] = 10181, + [SMALL_STATE(179)] = 10193, + [SMALL_STATE(180)] = 10203, + [SMALL_STATE(181)] = 10217, + [SMALL_STATE(182)] = 10231, + [SMALL_STATE(183)] = 10245, + [SMALL_STATE(184)] = 10256, + [SMALL_STATE(185)] = 10267, + [SMALL_STATE(186)] = 10278, + [SMALL_STATE(187)] = 10289, + [SMALL_STATE(188)] = 10298, + [SMALL_STATE(189)] = 10309, + [SMALL_STATE(190)] = 10320, + [SMALL_STATE(191)] = 10331, + [SMALL_STATE(192)] = 10340, + [SMALL_STATE(193)] = 10349, + [SMALL_STATE(194)] = 10360, + [SMALL_STATE(195)] = 10371, + [SMALL_STATE(196)] = 10382, + [SMALL_STATE(197)] = 10391, + [SMALL_STATE(198)] = 10400, + [SMALL_STATE(199)] = 10411, + [SMALL_STATE(200)] = 10422, + [SMALL_STATE(201)] = 10431, + [SMALL_STATE(202)] = 10442, + [SMALL_STATE(203)] = 10450, + [SMALL_STATE(204)] = 10458, + [SMALL_STATE(205)] = 10466, + [SMALL_STATE(206)] = 10474, + [SMALL_STATE(207)] = 10482, + [SMALL_STATE(208)] = 10490, + [SMALL_STATE(209)] = 10498, + [SMALL_STATE(210)] = 10506, + [SMALL_STATE(211)] = 10514, + [SMALL_STATE(212)] = 10522, + [SMALL_STATE(213)] = 10530, + [SMALL_STATE(214)] = 10538, + [SMALL_STATE(215)] = 10546, + [SMALL_STATE(216)] = 10554, + [SMALL_STATE(217)] = 10562, + [SMALL_STATE(218)] = 10570, }; static const TSParseActionEntry ts_parse_actions[] = { [0] = {.entry = {.count = 0, .reusable = false}}, [1] = {.entry = {.count = 1, .reusable = false}}, RECOVER(), [3] = {.entry = {.count = 1, .reusable = true}}, SHIFT_EXTRA(), - [5] = {.entry = {.count = 1, .reusable = false}}, SHIFT(109), - [7] = {.entry = {.count = 1, .reusable = true}}, SHIFT(109), - [9] = {.entry = {.count = 1, .reusable = false}}, SHIFT(79), - [11] = {.entry = {.count = 1, .reusable = true}}, SHIFT(305), - [13] = {.entry = {.count = 1, .reusable = true}}, SHIFT(303), - [15] = {.entry = {.count = 1, .reusable = true}}, SHIFT(304), - [17] = {.entry = {.count = 1, .reusable = true}}, SHIFT(46), - [19] = {.entry = {.count = 1, .reusable = false}}, SHIFT(106), - [21] = {.entry = {.count = 1, .reusable = true}}, SHIFT(65), - [23] = {.entry = {.count = 1, .reusable = false}}, SHIFT(27), - [25] = {.entry = {.count = 1, .reusable = false}}, SHIFT(256), + [5] = {.entry = {.count = 1, .reusable = false}}, SHIFT(92), + [7] = {.entry = {.count = 1, .reusable = true}}, SHIFT(92), + [9] = {.entry = {.count = 1, .reusable = false}}, SHIFT(52), + [11] = {.entry = {.count = 1, .reusable = true}}, SHIFT(210), + [13] = {.entry = {.count = 1, .reusable = true}}, SHIFT(204), + [15] = {.entry = {.count = 1, .reusable = true}}, SHIFT(205), + [17] = {.entry = {.count = 1, .reusable = true}}, SHIFT(51), + [19] = {.entry = {.count = 1, .reusable = false}}, SHIFT(82), + [21] = {.entry = {.count = 1, .reusable = true}}, SHIFT(27), + [23] = {.entry = {.count = 1, .reusable = false}}, SHIFT(39), + [25] = {.entry = {.count = 1, .reusable = false}}, SHIFT(172), [27] = {.entry = {.count = 1, .reusable = true}}, SHIFT(2), - [29] = {.entry = {.count = 1, .reusable = true}}, SHIFT(5), - [31] = {.entry = {.count = 1, .reusable = true}}, SHIFT(276), - [33] = {.entry = {.count = 1, .reusable = false}}, SHIFT(131), - [35] = {.entry = {.count = 1, .reusable = true}}, SHIFT(83), - [37] = {.entry = {.count = 1, .reusable = true}}, SHIFT(287), - [39] = {.entry = {.count = 1, .reusable = true}}, SHIFT(148), - [41] = {.entry = {.count = 1, .reusable = true}}, SHIFT(123), - [43] = {.entry = {.count = 1, .reusable = true}}, SHIFT(110), - [45] = {.entry = {.count = 1, .reusable = true}}, SHIFT(170), - [47] = {.entry = {.count = 1, .reusable = true}}, SHIFT(177), - [49] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(109), - [52] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(109), - [55] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(79), - [58] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(305), - [61] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(303), - [64] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(304), - [67] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(46), - [70] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(106), - [73] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(65), - [76] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(27), - [79] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(256), - [82] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(2), - [85] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(5), - [88] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), - [90] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(276), - [93] = {.entry = {.count = 1, .reusable = false}}, SHIFT(126), - [95] = {.entry = {.count = 1, .reusable = true}}, SHIFT(33), - [97] = {.entry = {.count = 1, .reusable = false}}, SHIFT(75), - [99] = {.entry = {.count = 1, .reusable = false}}, SHIFT(261), - [101] = {.entry = {.count = 1, .reusable = false}}, SHIFT(214), - [103] = {.entry = {.count = 1, .reusable = true}}, SHIFT(214), - [105] = {.entry = {.count = 1, .reusable = false}}, SHIFT(124), - [107] = {.entry = {.count = 1, .reusable = true}}, SHIFT(74), - [109] = {.entry = {.count = 1, .reusable = false}}, SHIFT(215), - [111] = {.entry = {.count = 1, .reusable = true}}, SHIFT(48), - [113] = {.entry = {.count = 1, .reusable = false}}, SHIFT(76), - [115] = {.entry = {.count = 1, .reusable = false}}, SHIFT(258), - [117] = {.entry = {.count = 1, .reusable = true}}, SHIFT(3), - [119] = {.entry = {.count = 1, .reusable = true}}, SHIFT(6), - [121] = {.entry = {.count = 1, .reusable = true}}, SHIFT(270), - [123] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_scalar, 1, 0, 2), - [125] = {.entry = {.count = 1, .reusable = false}}, SHIFT(88), - [127] = {.entry = {.count = 1, .reusable = true}}, SHIFT(88), - [129] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_scalar, 1, 0, 2), - [131] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_number, 1, 0, 0), - [133] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_number, 1, 0, 0), - [135] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_base_ten, 1, 0, 0), - [137] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__float, 1, 0, 1), - [139] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym__float, 1, 0, 1), - [141] = {.entry = {.count = 1, .reusable = true}}, SHIFT(292), - [143] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__float, 3, 0, 12), - [145] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym__float, 3, 0, 12), - [147] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_dictionary_construction, 2, 0, 0), - [149] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_dictionary_construction, 2, 0, 0), - [151] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_struct_definition, 2, 0, 0), - [153] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_struct_definition, 3, 0, 9), - [155] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_struct_definition, 3, 0, 9), - [157] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_struct_definition, 3, 0, 11), - [159] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_struct_definition, 3, 0, 11), - [161] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_binary_expression, 3, 0, 14), - [163] = {.entry = {.count = 1, .reusable = true}}, SHIFT(316), - [165] = {.entry = {.count = 1, .reusable = true}}, SHIFT(309), - [167] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_binary_expression, 3, 0, 14), - [169] = {.entry = {.count = 1, .reusable = true}}, SHIFT(271), - [171] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_struct_definition, 4, 0, 18), - [173] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_struct_definition, 4, 0, 18), - [175] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_scalar, 2, 0, 5), - [177] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_scalar, 2, 0, 5), - [179] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_parenthesis, 3, 0, 0), - [181] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_parenthesis, 3, 0, 0), - [183] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_function_call, 2, 0, 6), - [185] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_function_call, 2, 0, 6), - [187] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_member_access, 3, 0, 13), - [189] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_member_access, 3, 0, 13), - [191] = {.entry = {.count = 1, .reusable = true}}, SHIFT(10), - [193] = {.entry = {.count = 1, .reusable = false}}, SHIFT(11), - [195] = {.entry = {.count = 1, .reusable = true}}, SHIFT(11), - [197] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_dictionary_construction, 3, 0, 10), - [199] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_dictionary_construction, 3, 0, 10), - [201] = {.entry = {.count = 1, .reusable = true}}, SHIFT(66), - [203] = {.entry = {.count = 1, .reusable = true}}, SHIFT(12), - [205] = {.entry = {.count = 1, .reusable = false}}, SHIFT(13), - [207] = {.entry = {.count = 1, .reusable = false}}, SHIFT(15), - [209] = {.entry = {.count = 1, .reusable = false}}, SHIFT(14), - [211] = {.entry = {.count = 1, .reusable = false}}, SHIFT(16), - [213] = {.entry = {.count = 1, .reusable = true}}, SHIFT(16), - [215] = {.entry = {.count = 1, .reusable = true}}, SHIFT(17), - [217] = {.entry = {.count = 1, .reusable = true}}, SHIFT(18), - [219] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_let_in, 4, 0, 15), - [221] = {.entry = {.count = 1, .reusable = true}}, SHIFT(19), - [223] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_let_in, 4, 0, 15), - [225] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_dictionary_construction, 4, 0, 17), - [227] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_dictionary_construction, 4, 0, 17), - [229] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_boolean, 1, 0, 0), - [231] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_boolean, 1, 0, 0), - [233] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_list, 4, 0, 0), - [235] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_list, 4, 0, 0), - [237] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_method_call, 4, 0, 19), - [239] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_method_call, 4, 0, 19), - [241] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_expression, 1, 0, 0), - [243] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_expression, 1, 0, 0), - [245] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_list, 2, 0, 0), - [247] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_list, 2, 0, 0), - [249] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_vector2, 5, 0, 20), - [251] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_vector2, 5, 0, 20), - [253] = {.entry = {.count = 1, .reusable = true}}, SHIFT(20), - [255] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_dictionary_construction, 5, 0, 23), - [257] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_dictionary_construction, 5, 0, 23), - [259] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_closure_definition, 5, 0, 24), - [261] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_closure_definition, 5, 0, 24), - [263] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_if, 6, 0, 25), - [265] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_if, 6, 0, 25), - [267] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_let_in, 3, 0, 7), - [269] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_let_in, 3, 0, 7), - [271] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_vector3, 7, 0, 26), - [273] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_vector3, 7, 0, 26), - [275] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set, 7, 0, 27), - [277] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_constraint_set, 7, 0, 27), - [279] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_vector4, 9, 0, 28), - [281] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_vector4, 9, 0, 28), - [283] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_signed_integer, 2, 0, 4), - [285] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_signed_integer, 2, 0, 4), - [287] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_unsigned_integer, 2, 0, 4), - [289] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_unsigned_integer, 2, 0, 4), - [291] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_unary_expression, 2, 0, 3), - [293] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_unary_expression, 2, 0, 3), - [295] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_list, 3, 0, 0), - [297] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_list, 3, 0, 0), - [299] = {.entry = {.count = 1, .reusable = true}}, SHIFT(204), - [301] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_declaration_type, 2, 0, 0), - [303] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_declaration_type, 2, 0, 0), - [305] = {.entry = {.count = 1, .reusable = true}}, SHIFT(288), - [307] = {.entry = {.count = 1, .reusable = false}}, SHIFT(25), - [309] = {.entry = {.count = 1, .reusable = false}}, SHIFT(26), - [311] = {.entry = {.count = 1, .reusable = true}}, SHIFT(312), - [313] = {.entry = {.count = 1, .reusable = true}}, SHIFT(70), - [315] = {.entry = {.count = 1, .reusable = true}}, SHIFT(197), - [317] = {.entry = {.count = 1, .reusable = true}}, SHIFT(302), - [319] = {.entry = {.count = 1, .reusable = true}}, SHIFT(50), - [321] = {.entry = {.count = 1, .reusable = true}}, SHIFT(51), - [323] = {.entry = {.count = 1, .reusable = false}}, SHIFT(52), - [325] = {.entry = {.count = 1, .reusable = true}}, SHIFT(52), - [327] = {.entry = {.count = 1, .reusable = true}}, SHIFT(53), - [329] = {.entry = {.count = 1, .reusable = false}}, SHIFT(54), - [331] = {.entry = {.count = 1, .reusable = false}}, SHIFT(55), - [333] = {.entry = {.count = 1, .reusable = false}}, SHIFT(56), - [335] = {.entry = {.count = 1, .reusable = false}}, SHIFT(57), - [337] = {.entry = {.count = 1, .reusable = true}}, SHIFT(57), - [339] = {.entry = {.count = 1, .reusable = true}}, SHIFT(58), - [341] = {.entry = {.count = 1, .reusable = true}}, SHIFT(59), - [343] = {.entry = {.count = 1, .reusable = true}}, SHIFT(60), - [345] = {.entry = {.count = 1, .reusable = true}}, SHIFT(269), - [347] = {.entry = {.count = 1, .reusable = true}}, SHIFT(221), - [349] = {.entry = {.count = 1, .reusable = true}}, SHIFT(107), - [351] = {.entry = {.count = 1, .reusable = true}}, SHIFT(279), - [353] = {.entry = {.count = 1, .reusable = true}}, SHIFT(30), - [355] = {.entry = {.count = 1, .reusable = true}}, SHIFT(111), - [357] = {.entry = {.count = 1, .reusable = true}}, SHIFT(72), - [359] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_struct_member, 4, 0, 22), - [361] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_dictionary_member_assignment, 3, 0, 16), - [363] = {.entry = {.count = 1, .reusable = true}}, SHIFT(194), - [365] = {.entry = {.count = 1, .reusable = true}}, SHIFT(71), - [367] = {.entry = {.count = 1, .reusable = true}}, SHIFT(201), - [369] = {.entry = {.count = 1, .reusable = true}}, SHIFT(32), - [371] = {.entry = {.count = 1, .reusable = true}}, SHIFT(117), - [373] = {.entry = {.count = 1, .reusable = true}}, SHIFT(63), - [375] = {.entry = {.count = 1, .reusable = true}}, SHIFT(35), - [377] = {.entry = {.count = 1, .reusable = true}}, SHIFT(36), - [379] = {.entry = {.count = 1, .reusable = false}}, SHIFT(37), - [381] = {.entry = {.count = 1, .reusable = true}}, SHIFT(37), - [383] = {.entry = {.count = 1, .reusable = true}}, SHIFT(38), - [385] = {.entry = {.count = 1, .reusable = false}}, SHIFT(39), - [387] = {.entry = {.count = 1, .reusable = false}}, SHIFT(40), - [389] = {.entry = {.count = 1, .reusable = false}}, SHIFT(9), - [391] = {.entry = {.count = 1, .reusable = false}}, SHIFT(41), - [393] = {.entry = {.count = 1, .reusable = true}}, SHIFT(41), - [395] = {.entry = {.count = 1, .reusable = true}}, SHIFT(42), - [397] = {.entry = {.count = 1, .reusable = true}}, SHIFT(43), - [399] = {.entry = {.count = 1, .reusable = true}}, SHIFT(44), - [401] = {.entry = {.count = 1, .reusable = true}}, SHIFT(22), - [403] = {.entry = {.count = 1, .reusable = true}}, SHIFT(89), - [405] = {.entry = {.count = 1, .reusable = false}}, SHIFT(29), - [407] = {.entry = {.count = 1, .reusable = true}}, SHIFT(31), - [409] = {.entry = {.count = 1, .reusable = true}}, SHIFT(282), - [411] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_source_file, 1, 0, 0), - [413] = {.entry = {.count = 1, .reusable = true}}, SHIFT(174), - [415] = {.entry = {.count = 1, .reusable = false}}, SHIFT(77), - [417] = {.entry = {.count = 1, .reusable = true}}, SHIFT(47), - [419] = {.entry = {.count = 1, .reusable = true}}, SHIFT(203), - [421] = {.entry = {.count = 1, .reusable = false}}, SHIFT(62), - [423] = {.entry = {.count = 1, .reusable = true}}, SHIFT(119), - [425] = {.entry = {.count = 1, .reusable = true}}, SHIFT(67), - [427] = {.entry = {.count = 1, .reusable = true}}, SHIFT(68), - [429] = {.entry = {.count = 1, .reusable = true}}, SHIFT(69), - [431] = {.entry = {.count = 1, .reusable = true}}, SHIFT(73), - [433] = {.entry = {.count = 1, .reusable = true}}, SHIFT(21), - [435] = {.entry = {.count = 1, .reusable = false}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), - [437] = {.entry = {.count = 1, .reusable = true}}, SHIFT(245), - [439] = {.entry = {.count = 1, .reusable = true}}, SHIFT(291), - [441] = {.entry = {.count = 1, .reusable = true}}, SHIFT(233), - [443] = {.entry = {.count = 1, .reusable = true}}, SHIFT(82), - [445] = {.entry = {.count = 1, .reusable = true}}, SHIFT(232), - [447] = {.entry = {.count = 1, .reusable = true}}, SHIFT(239), - [449] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_parenthesis, 3, 0, 0), - [451] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_constraint_set_parenthesis, 3, 0, 0), - [453] = {.entry = {.count = 1, .reusable = true}}, SHIFT(224), - [455] = {.entry = {.count = 1, .reusable = true}}, SHIFT(236), - [457] = {.entry = {.count = 1, .reusable = true}}, SHIFT(306), - [459] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_binary_expression, 3, 0, 14), - [461] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_constraint_set_binary_expression, 3, 0, 14), - [463] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_expression, 1, 0, 0), - [465] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_constraint_set_expression, 1, 0, 0), - [467] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_method_call, 6, 0, 29), - [469] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_constraint_set_method_call, 6, 0, 29), - [471] = {.entry = {.count = 1, .reusable = true}}, SHIFT(228), - [473] = {.entry = {.count = 1, .reusable = true}}, SHIFT(230), - [475] = {.entry = {.count = 1, .reusable = false}}, SHIFT(226), - [477] = {.entry = {.count = 1, .reusable = true}}, SHIFT(226), - [479] = {.entry = {.count = 1, .reusable = false}}, SHIFT(235), - [481] = {.entry = {.count = 1, .reusable = true}}, SHIFT(235), - [483] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_constraint_set_unary_expression, 2, 0, 3), - [485] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_unary_expression, 2, 0, 3), - [487] = {.entry = {.count = 1, .reusable = true}}, SHIFT(240), - [489] = {.entry = {.count = 1, .reusable = true}}, SHIFT(229), - [491] = {.entry = {.count = 1, .reusable = true}}, SHIFT(237), - [493] = {.entry = {.count = 1, .reusable = true}}, SHIFT(227), - [495] = {.entry = {.count = 1, .reusable = true}}, SHIFT(202), - [497] = {.entry = {.count = 1, .reusable = true}}, SHIFT(290), - [499] = {.entry = {.count = 1, .reusable = true}}, SHIFT(85), - [501] = {.entry = {.count = 1, .reusable = true}}, SHIFT(155), - [503] = {.entry = {.count = 1, .reusable = true}}, SHIFT(118), - [505] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_struct_definition_repeat1, 2, 0, 0), SHIFT_REPEAT(290), - [508] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_struct_definition_repeat1, 2, 0, 0), - [510] = {.entry = {.count = 1, .reusable = false}}, SHIFT(308), - [512] = {.entry = {.count = 1, .reusable = false}}, SHIFT(64), - [514] = {.entry = {.count = 1, .reusable = false}}, SHIFT(61), - [516] = {.entry = {.count = 1, .reusable = false}}, SHIFT(49), - [518] = {.entry = {.count = 1, .reusable = false}}, SHIFT(24), - [520] = {.entry = {.count = 1, .reusable = false}}, SHIFT(45), - [522] = {.entry = {.count = 1, .reusable = false}}, SHIFT(34), - [524] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_let_in_repeat1, 2, 0, 0), SHIFT_REPEAT(308), - [527] = {.entry = {.count = 1, .reusable = false}}, REDUCE(aux_sym_let_in_repeat1, 2, 0, 0), - [529] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_dictionary_construction_repeat1, 2, 0, 0), SHIFT_REPEAT(285), - [532] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_dictionary_construction_repeat1, 2, 0, 0), - [534] = {.entry = {.count = 1, .reusable = true}}, SHIFT(318), - [536] = {.entry = {.count = 1, .reusable = true}}, SHIFT(198), - [538] = {.entry = {.count = 1, .reusable = true}}, SHIFT(265), - [540] = {.entry = {.count = 1, .reusable = true}}, SHIFT(192), - [542] = {.entry = {.count = 1, .reusable = true}}, SHIFT(105), - [544] = {.entry = {.count = 1, .reusable = true}}, SHIFT(190), - [546] = {.entry = {.count = 1, .reusable = true}}, SHIFT(289), - [548] = {.entry = {.count = 1, .reusable = true}}, SHIFT(103), - [550] = {.entry = {.count = 1, .reusable = true}}, SHIFT(274), - [552] = {.entry = {.count = 1, .reusable = true}}, SHIFT(268), - [554] = {.entry = {.count = 1, .reusable = true}}, SHIFT(93), - [556] = {.entry = {.count = 1, .reusable = true}}, SHIFT(113), - [558] = {.entry = {.count = 1, .reusable = true}}, SHIFT(267), - [560] = {.entry = {.count = 1, .reusable = true}}, SHIFT(176), - [562] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_struct_member, 2, 0, 8), - [564] = {.entry = {.count = 1, .reusable = true}}, SHIFT(28), - [566] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_octal, 2, 0, 0), - [568] = {.entry = {.count = 1, .reusable = true}}, SHIFT(156), - [570] = {.entry = {.count = 1, .reusable = true}}, SHIFT(294), - [572] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_let_in_assignment, 4, 0, 21), - [574] = {.entry = {.count = 1, .reusable = true}}, SHIFT(263), - [576] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__struct_final_element, 1, 0, 0), - [578] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_integer, 1, 0, 0), - [580] = {.entry = {.count = 1, .reusable = true}}, SHIFT(321), - [582] = {.entry = {.count = 1, .reusable = true}}, SHIFT(132), - [584] = {.entry = {.count = 1, .reusable = true}}, SHIFT(317), - [586] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_fields, 1, 0, 0), - [588] = {.entry = {.count = 1, .reusable = true}}, SHIFT(26), - [590] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_hex, 2, 0, 0), - [592] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_fields, 2, 0, 0), - [594] = {.entry = {.count = 1, .reusable = true}}, SHIFT(168), - [596] = {.entry = {.count = 1, .reusable = true}}, SHIFT(169), - [598] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_binary, 2, 0, 0), - [600] = {.entry = {.count = 1, .reusable = true}}, SHIFT(120), - [602] = {.entry = {.count = 1, .reusable = true}}, SHIFT(121), - [604] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_constraint_set_fields_repeat1, 2, 0, 0), SHIFT_REPEAT(313), - [607] = {.entry = {.count = 1, .reusable = true}}, SHIFT(87), - [609] = {.entry = {.count = 1, .reusable = true}}, SHIFT(241), - [611] = {.entry = {.count = 1, .reusable = true}}, SHIFT(281), - [613] = {.entry = {.count = 1, .reusable = true}}, SHIFT(293), - [615] = {.entry = {.count = 1, .reusable = true}}, SHIFT(296), - [617] = {.entry = {.count = 1, .reusable = true}}, SHIFT(278), - [619] = {.entry = {.count = 1, .reusable = true}}, SHIFT(307), - [621] = {.entry = {.count = 1, .reusable = true}}, SHIFT(225), - [623] = {.entry = {.count = 1, .reusable = true}}, SHIFT(23), - [625] = {.entry = {.count = 1, .reusable = true}}, SHIFT(297), - [627] = {.entry = {.count = 1, .reusable = true}}, SHIFT(84), - [629] = {.entry = {.count = 1, .reusable = true}}, SHIFT(179), - [631] = {.entry = {.count = 1, .reusable = true}}, SHIFT(153), - [633] = {.entry = {.count = 1, .reusable = true}}, SHIFT(159), - [635] = {.entry = {.count = 1, .reusable = true}}, SHIFT(91), - [637] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_constraint_set_fields_repeat1, 2, 0, 0), - [639] = {.entry = {.count = 1, .reusable = true}}, SHIFT(25), - [641] = {.entry = {.count = 1, .reusable = true}}, ACCEPT_INPUT(), - [643] = {.entry = {.count = 1, .reusable = true}}, SHIFT(234), - [645] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__struct_final_element, 2, 0, 0), + [29] = {.entry = {.count = 1, .reusable = true}}, SHIFT(3), + [31] = {.entry = {.count = 1, .reusable = true}}, SHIFT(177), + [33] = {.entry = {.count = 1, .reusable = false}}, SHIFT(101), + [35] = {.entry = {.count = 1, .reusable = true}}, SHIFT(57), + [37] = {.entry = {.count = 1, .reusable = true}}, SHIFT(201), + [39] = {.entry = {.count = 1, .reusable = true}}, SHIFT(76), + [41] = {.entry = {.count = 1, .reusable = true}}, SHIFT(81), + [43] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(92), + [46] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(92), + [49] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(52), + [52] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(210), + [55] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(204), + [58] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(205), + [61] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(51), + [64] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(82), + [67] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(27), + [70] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(39), + [73] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(172), + [76] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(2), + [79] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(3), + [82] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), + [84] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(177), + [87] = {.entry = {.count = 1, .reusable = false}}, SHIFT(98), + [89] = {.entry = {.count = 1, .reusable = true}}, SHIFT(33), + [91] = {.entry = {.count = 1, .reusable = false}}, SHIFT(7), + [93] = {.entry = {.count = 1, .reusable = false}}, SHIFT(170), + [95] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_number, 1, 0, 0), + [97] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_number, 1, 0, 0), + [99] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_base_ten, 1, 0, 0), + [101] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_scalar, 1, 0, 2), + [103] = {.entry = {.count = 1, .reusable = false}}, SHIFT(60), + [105] = {.entry = {.count = 1, .reusable = true}}, SHIFT(60), + [107] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_scalar, 1, 0, 2), + [109] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__float, 3, 0, 12), + [111] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym__float, 3, 0, 12), + [113] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__float, 1, 0, 1), + [115] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym__float, 1, 0, 1), + [117] = {.entry = {.count = 1, .reusable = true}}, SHIFT(186), + [119] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_dictionary_construction, 2, 0, 0), + [121] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_dictionary_construction, 2, 0, 0), + [123] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_struct_definition, 2, 0, 0), + [125] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_struct_definition, 4, 0, 18), + [127] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_struct_definition, 4, 0, 18), + [129] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_binary_expression, 3, 0, 14), + [131] = {.entry = {.count = 1, .reusable = true}}, SHIFT(216), + [133] = {.entry = {.count = 1, .reusable = true}}, SHIFT(202), + [135] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_binary_expression, 3, 0, 14), + [137] = {.entry = {.count = 1, .reusable = true}}, SHIFT(182), + [139] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_scalar, 2, 0, 5), + [141] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_scalar, 2, 0, 5), + [143] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_struct_definition, 3, 0, 9), + [145] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_struct_definition, 3, 0, 9), + [147] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_struct_definition, 3, 0, 11), + [149] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_struct_definition, 3, 0, 11), + [151] = {.entry = {.count = 1, .reusable = true}}, SHIFT(9), + [153] = {.entry = {.count = 1, .reusable = true}}, SHIFT(10), + [155] = {.entry = {.count = 1, .reusable = false}}, SHIFT(11), + [157] = {.entry = {.count = 1, .reusable = true}}, SHIFT(11), + [159] = {.entry = {.count = 1, .reusable = true}}, SHIFT(12), + [161] = {.entry = {.count = 1, .reusable = false}}, SHIFT(13), + [163] = {.entry = {.count = 1, .reusable = false}}, SHIFT(14), + [165] = {.entry = {.count = 1, .reusable = false}}, SHIFT(15), + [167] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_let_in, 4, 0, 15), + [169] = {.entry = {.count = 1, .reusable = false}}, SHIFT(16), + [171] = {.entry = {.count = 1, .reusable = true}}, SHIFT(16), + [173] = {.entry = {.count = 1, .reusable = true}}, SHIFT(17), + [175] = {.entry = {.count = 1, .reusable = true}}, SHIFT(18), + [177] = {.entry = {.count = 1, .reusable = true}}, SHIFT(19), + [179] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_let_in, 4, 0, 15), + [181] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_let_in, 3, 0, 7), + [183] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_let_in, 3, 0, 7), + [185] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_dictionary_construction, 4, 0, 17), + [187] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_dictionary_construction, 4, 0, 17), + [189] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_expression, 1, 0, 0), + [191] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_expression, 1, 0, 0), + [193] = {.entry = {.count = 1, .reusable = true}}, SHIFT(20), + [195] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_list, 4, 0, 0), + [197] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_list, 4, 0, 0), + [199] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_method_call, 4, 0, 19), + [201] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_method_call, 4, 0, 19), + [203] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_unary_expression, 2, 0, 3), + [205] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_unary_expression, 2, 0, 3), + [207] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_vector2, 5, 0, 20), + [209] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_vector2, 5, 0, 20), + [211] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_parenthesis, 3, 0, 0), + [213] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_parenthesis, 3, 0, 0), + [215] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_dictionary_construction, 5, 0, 23), + [217] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_dictionary_construction, 5, 0, 23), + [219] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_closure_definition, 5, 0, 24), + [221] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_closure_definition, 5, 0, 24), + [223] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_if, 6, 0, 25), + [225] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_if, 6, 0, 25), + [227] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_list, 2, 0, 0), + [229] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_list, 2, 0, 0), + [231] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_vector3, 7, 0, 26), + [233] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_vector3, 7, 0, 26), + [235] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_vector4, 9, 0, 28), + [237] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_vector4, 9, 0, 28), + [239] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_dictionary_construction, 3, 0, 10), + [241] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_dictionary_construction, 3, 0, 10), + [243] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_function_call, 2, 0, 6), + [245] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_function_call, 2, 0, 6), + [247] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_list, 3, 0, 0), + [249] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_list, 3, 0, 0), + [251] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_boolean, 1, 0, 0), + [253] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_boolean, 1, 0, 0), + [255] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_signed_integer, 2, 0, 4), + [257] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_signed_integer, 2, 0, 4), + [259] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_member_access, 3, 0, 13), + [261] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_member_access, 3, 0, 13), + [263] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_unsigned_integer, 2, 0, 4), + [265] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_unsigned_integer, 2, 0, 4), + [267] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set, 7, 0, 27), + [269] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_constraint_set, 7, 0, 27), + [271] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_declaration_type, 2, 0, 0), + [273] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_declaration_type, 2, 0, 0), + [275] = {.entry = {.count = 1, .reusable = false}}, SHIFT(25), + [277] = {.entry = {.count = 1, .reusable = false}}, SHIFT(26), + [279] = {.entry = {.count = 1, .reusable = true}}, SHIFT(195), + [281] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_struct_member, 4, 0, 22), + [283] = {.entry = {.count = 1, .reusable = true}}, SHIFT(139), + [285] = {.entry = {.count = 1, .reusable = true}}, SHIFT(68), + [287] = {.entry = {.count = 1, .reusable = true}}, SHIFT(30), + [289] = {.entry = {.count = 1, .reusable = true}}, SHIFT(71), + [291] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_dictionary_member_assignment, 3, 0, 16), + [293] = {.entry = {.count = 1, .reusable = true}}, SHIFT(32), + [295] = {.entry = {.count = 1, .reusable = true}}, SHIFT(77), + [297] = {.entry = {.count = 1, .reusable = true}}, SHIFT(35), + [299] = {.entry = {.count = 1, .reusable = true}}, SHIFT(36), + [301] = {.entry = {.count = 1, .reusable = false}}, SHIFT(37), + [303] = {.entry = {.count = 1, .reusable = true}}, SHIFT(37), + [305] = {.entry = {.count = 1, .reusable = true}}, SHIFT(38), + [307] = {.entry = {.count = 1, .reusable = false}}, SHIFT(6), + [309] = {.entry = {.count = 1, .reusable = false}}, SHIFT(40), + [311] = {.entry = {.count = 1, .reusable = false}}, SHIFT(41), + [313] = {.entry = {.count = 1, .reusable = false}}, SHIFT(42), + [315] = {.entry = {.count = 1, .reusable = true}}, SHIFT(42), + [317] = {.entry = {.count = 1, .reusable = true}}, SHIFT(43), + [319] = {.entry = {.count = 1, .reusable = true}}, SHIFT(44), + [321] = {.entry = {.count = 1, .reusable = true}}, SHIFT(45), + [323] = {.entry = {.count = 1, .reusable = true}}, SHIFT(50), + [325] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_source_file, 1, 0, 0), + [327] = {.entry = {.count = 1, .reusable = true}}, SHIFT(78), + [329] = {.entry = {.count = 1, .reusable = true}}, SHIFT(31), + [331] = {.entry = {.count = 1, .reusable = true}}, SHIFT(21), + [333] = {.entry = {.count = 1, .reusable = true}}, SHIFT(196), + [335] = {.entry = {.count = 1, .reusable = true}}, SHIFT(72), + [337] = {.entry = {.count = 1, .reusable = false}}, SHIFT(47), + [339] = {.entry = {.count = 1, .reusable = true}}, SHIFT(48), + [341] = {.entry = {.count = 1, .reusable = false}}, SHIFT(29), + [343] = {.entry = {.count = 1, .reusable = true}}, SHIFT(49), + [345] = {.entry = {.count = 1, .reusable = true}}, SHIFT(22), + [347] = {.entry = {.count = 1, .reusable = false}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), + [349] = {.entry = {.count = 1, .reusable = true}}, SHIFT(198), + [351] = {.entry = {.count = 1, .reusable = true}}, SHIFT(159), + [353] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_expression, 1, 0, 0), + [355] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_constraint_set_expression, 1, 0, 0), + [357] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_method_call, 6, 0, 29), + [359] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_constraint_set_method_call, 6, 0, 29), + [361] = {.entry = {.count = 1, .reusable = true}}, SHIFT(143), + [363] = {.entry = {.count = 1, .reusable = true}}, SHIFT(141), + [365] = {.entry = {.count = 1, .reusable = true}}, SHIFT(146), + [367] = {.entry = {.count = 1, .reusable = true}}, SHIFT(148), + [369] = {.entry = {.count = 1, .reusable = true}}, SHIFT(56), + [371] = {.entry = {.count = 1, .reusable = true}}, SHIFT(149), + [373] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_parenthesis, 3, 0, 0), + [375] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_constraint_set_parenthesis, 3, 0, 0), + [377] = {.entry = {.count = 1, .reusable = true}}, SHIFT(215), + [379] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_binary_expression, 3, 0, 14), + [381] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_constraint_set_binary_expression, 3, 0, 14), + [383] = {.entry = {.count = 1, .reusable = true}}, SHIFT(147), + [385] = {.entry = {.count = 1, .reusable = true}}, SHIFT(150), + [387] = {.entry = {.count = 1, .reusable = false}}, SHIFT(153), + [389] = {.entry = {.count = 1, .reusable = true}}, SHIFT(153), + [391] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_constraint_set_unary_expression, 2, 0, 3), + [393] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_unary_expression, 2, 0, 3), + [395] = {.entry = {.count = 1, .reusable = true}}, SHIFT(154), + [397] = {.entry = {.count = 1, .reusable = true}}, SHIFT(152), + [399] = {.entry = {.count = 1, .reusable = true}}, SHIFT(190), + [401] = {.entry = {.count = 1, .reusable = true}}, SHIFT(62), + [403] = {.entry = {.count = 1, .reusable = true}}, SHIFT(144), + [405] = {.entry = {.count = 1, .reusable = true}}, SHIFT(155), + [407] = {.entry = {.count = 1, .reusable = true}}, SHIFT(97), + [409] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_struct_definition_repeat1, 2, 0, 0), SHIFT_REPEAT(190), + [412] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_struct_definition_repeat1, 2, 0, 0), + [414] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_let_in_repeat1, 2, 0, 0), SHIFT_REPEAT(207), + [417] = {.entry = {.count = 1, .reusable = false}}, REDUCE(aux_sym_let_in_repeat1, 2, 0, 0), + [419] = {.entry = {.count = 1, .reusable = false}}, SHIFT(207), + [421] = {.entry = {.count = 1, .reusable = false}}, SHIFT(34), + [423] = {.entry = {.count = 1, .reusable = false}}, SHIFT(24), + [425] = {.entry = {.count = 1, .reusable = false}}, SHIFT(8), + [427] = {.entry = {.count = 1, .reusable = false}}, SHIFT(46), + [429] = {.entry = {.count = 1, .reusable = true}}, SHIFT(180), + [431] = {.entry = {.count = 1, .reusable = true}}, SHIFT(79), + [433] = {.entry = {.count = 1, .reusable = true}}, SHIFT(209), + [435] = {.entry = {.count = 1, .reusable = true}}, SHIFT(73), + [437] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_dictionary_construction_repeat1, 2, 0, 0), SHIFT_REPEAT(184), + [440] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_dictionary_construction_repeat1, 2, 0, 0), + [442] = {.entry = {.count = 1, .reusable = true}}, SHIFT(185), + [444] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_struct_member, 2, 0, 8), + [446] = {.entry = {.count = 1, .reusable = true}}, SHIFT(28), + [448] = {.entry = {.count = 1, .reusable = true}}, SHIFT(66), + [450] = {.entry = {.count = 1, .reusable = true}}, SHIFT(175), + [452] = {.entry = {.count = 1, .reusable = true}}, SHIFT(96), + [454] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_constraint_set_fields_repeat1, 2, 0, 0), SHIFT_REPEAT(211), + [457] = {.entry = {.count = 1, .reusable = true}}, SHIFT(203), + [459] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_fields, 1, 0, 0), + [461] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_octal, 2, 0, 0), + [463] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_fields, 2, 0, 0), + [465] = {.entry = {.count = 1, .reusable = true}}, SHIFT(83), + [467] = {.entry = {.count = 1, .reusable = true}}, SHIFT(86), + [469] = {.entry = {.count = 1, .reusable = true}}, SHIFT(26), + [471] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_hex, 2, 0, 0), + [473] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_binary, 2, 0, 0), + [475] = {.entry = {.count = 1, .reusable = true}}, SHIFT(188), + [477] = {.entry = {.count = 1, .reusable = true}}, SHIFT(103), + [479] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_let_in_assignment, 4, 0, 21), + [481] = {.entry = {.count = 1, .reusable = true}}, SHIFT(179), + [483] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__struct_final_element, 1, 0, 0), + [485] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_integer, 1, 0, 0), + [487] = {.entry = {.count = 1, .reusable = true}}, SHIFT(213), + [489] = {.entry = {.count = 1, .reusable = true}}, SHIFT(193), + [491] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_constraint_set_fields_repeat1, 2, 0, 0), + [493] = {.entry = {.count = 1, .reusable = true}}, SHIFT(191), + [495] = {.entry = {.count = 1, .reusable = true}}, SHIFT(192), + [497] = {.entry = {.count = 1, .reusable = true}}, SHIFT(145), + [499] = {.entry = {.count = 1, .reusable = true}}, SHIFT(23), + [501] = {.entry = {.count = 1, .reusable = true}}, SHIFT(157), + [503] = {.entry = {.count = 1, .reusable = true}}, SHIFT(25), + [505] = {.entry = {.count = 1, .reusable = true}}, SHIFT(187), + [507] = {.entry = {.count = 1, .reusable = true}}, ACCEPT_INPUT(), + [509] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__struct_final_element, 2, 0, 0), + [511] = {.entry = {.count = 1, .reusable = true}}, SHIFT(58), + [513] = {.entry = {.count = 1, .reusable = true}}, SHIFT(208), + [515] = {.entry = {.count = 1, .reusable = true}}, SHIFT(84), + [517] = {.entry = {.count = 1, .reusable = true}}, SHIFT(61), }; #ifdef __cplusplus diff --git a/tree-sitter-command-cad-model/test/corpus/precedence.txt b/tree-sitter-command-cad-model/test/corpus/precedence.txt index 399ce79..55fdaa0 100644 --- a/tree-sitter-command-cad-model/test/corpus/precedence.txt +++ b/tree-sitter-command-cad-model/test/corpus/precedence.txt @@ -36,7 +36,7 @@ Precedence Vectors ================== -<(a, b)> + <(a, b)> == <(a, b)> +{a, b} + {a, b} == {a, b} --- diff --git a/tree-sitter-command-cad-model/test/corpus/primitives.txt b/tree-sitter-command-cad-model/test/corpus/primitives.txt index cdc74f3..bb2ac97 100644 --- a/tree-sitter-command-cad-model/test/corpus/primitives.txt +++ b/tree-sitter-command-cad-model/test/corpus/primitives.txt @@ -220,7 +220,7 @@ Scalar with quoted unit that would not work as an identifier Vector2 ================== -<(1m, 2m)> +{1m, 2m} --- @@ -240,7 +240,7 @@ Vector2 Vector3 ================== -<(1m, 2m, 3m)> +{1m, 2m, 3m} --- @@ -264,7 +264,7 @@ Vector3 Vector4 ================== -<(1m, 2m, 3m, 4m)> +{1m, 2m, 3m, 4m} --- From c3585882519fece72394dcee1f4060830b957a6f Mon Sep 17 00:00:00 2001 From: James Carl Date: Tue, 10 Mar 2026 00:14:53 -0400 Subject: [PATCH 05/71] Update Boolmesh --- Cargo.lock | 20 +++++++--- .../src/execution/values/manifold_mesh.rs | 18 ++++++--- interpreter/src/execution/values/vector.rs | 38 ++----------------- 3 files changed, 31 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 73bcbb9..722a40a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -173,10 +173,12 @@ dependencies = [ [[package]] name = "boolmesh" version = "0.1.9" -source = "git+https://github.com/IamTheCarl/boolmesh.git?branch=command-cad#5cf00cd83345f979948b0cc3fbaea3bff0fdc361" +source = "git+https://github.com/IamTheCarl/boolmesh.git?branch=command-cad#40f230bfa4a08618579f5fb22e0dd1fbaf4aa87f" dependencies = [ + "fxhash", "geo", - "glam 0.30.10", + "nalgebra", + "num-traits", "rayon", "serde", "thiserror 2.0.18", @@ -760,6 +762,15 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + [[package]] name = "generic-array" version = "0.12.4" @@ -991,9 +1002,6 @@ name = "glam" version = "0.30.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19fc433e8437a212d1b6f1e68c7824af3aed907da60afa994e7f542d18d12aa9" -dependencies = [ - "serde_core", -] [[package]] name = "hash32" @@ -1634,6 +1642,7 @@ dependencies = [ "num-complex", "num-rational", "num-traits", + "serde", "simba", "typenum", ] @@ -1684,6 +1693,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", + "serde", ] [[package]] diff --git a/interpreter/src/execution/values/manifold_mesh.rs b/interpreter/src/execution/values/manifold_mesh.rs index 55ee132..11e71ad 100644 --- a/interpreter/src/execution/values/manifold_mesh.rs +++ b/interpreter/src/execution/values/manifold_mesh.rs @@ -85,7 +85,9 @@ impl Object for ManifoldMesh3D { ArethmeticInput::Vector(vector) => { let vector = vector.raw_value(); let manifold = Arc::make_mut(&mut self.0); - manifold.translate(vector.x, vector.y, vector.z); + *manifold = manifold + .translate(vector.x, vector.y, vector.z) + .map_err(|error| error.to_error(context))?; Ok(self.into()) } ArethmeticInput::Manifold(rhs) => { @@ -102,7 +104,9 @@ impl Object for ManifoldMesh3D { ArethmeticInput::Vector(vector) => { let vector = vector.raw_value(); let manifold = Arc::make_mut(&mut self.0); - manifold.translate(-vector.x, -vector.y, -vector.z); + *manifold = manifold + .translate(-vector.x, -vector.y, -vector.z) + .map_err(|error| error.to_error(context))?; Ok(self.into()) } ArethmeticInput::Manifold(rhs) => { @@ -117,7 +121,9 @@ impl Object for ManifoldMesh3D { let input = rhs.downcast::(context)?; let vector = input.raw_value(); let manifold = Arc::make_mut(&mut self.0); - manifold.scale(vector.x, vector.y, vector.z); + *manifold = manifold + .scale(vector.x, vector.y, vector.z) + .map_err(|error| error.to_error(context))?; Ok(self.into()) } @@ -285,7 +291,7 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { let size = size.raw_value(); let mut manifold = generate_cube().map_err(|error| error.to_error(context))?; - manifold.scale(size.x, size.y, size.z); + manifold = manifold.scale(size.x, size.y, size.z).map_err(|error| error.to_error(context))?; Ok(ManifoldMesh3D(Arc::new(manifold))) } @@ -319,7 +325,7 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { let mut manifold = generate_icosphere(subdivions.0 as u32) .map_err(|error| error.to_error(context))?; - manifold.scale(scale, scale, scale); + manifold = manifold.scale(scale, scale, scale).map_err(|error| error.to_error(context))?; Ok(ManifoldMesh3D(Arc::new(manifold))) } @@ -351,7 +357,7 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { let mut manifold = generate_uv_sphere(sectors.0 as usize, stacks.0 as usize) .map_err(|error| error.to_error(context))?; - manifold.scale(scale, scale, scale); + manifold = manifold.scale(scale, scale, scale).map_err(|error| error.to_error(context))?; Ok(ManifoldMesh3D(Arc::new(manifold))) } diff --git a/interpreter/src/execution/values/vector.rs b/interpreter/src/execution/values/vector.rs index dd2e1a2..5d4b524 100644 --- a/interpreter/src/execution/values/vector.rs +++ b/interpreter/src/execution/values/vector.rs @@ -785,15 +785,6 @@ impl StaticType for nalgebra::Vector2 { } } -impl From for boolmesh::Vec2 { - fn from(value: Vector2) -> Self { - Self { - x: value.value.x, - y: value.value.y, - } - } -} - impl VectorInternalType for nalgebra::Vector3 { type BuildFrom = [Float; 3]; type NodeType = compile::Vector3; @@ -925,16 +916,6 @@ impl StaticType for nalgebra::Vector3 { } } -impl From for boolmesh::Vec3 { - fn from(value: Vector3) -> Self { - Self { - x: value.value.x, - y: value.value.y, - z: value.value.z, - } - } -} - impl VectorInternalType for nalgebra::Vector4 { type BuildFrom = [Float; 4]; type NodeType = compile::Vector4; @@ -1060,26 +1041,15 @@ impl StaticType for nalgebra::Vector4 { } } -impl From for boolmesh::Vec4 { - fn from(value: Vector4) -> Self { - Self { - x: value.value.x, - y: value.value.y, - z: value.value.z, - w: value.value.w, - } - } -} - macro_rules! equivalent_boolmesh_vector { (Vector2) => { - boolmesh::Vec2 + nalgebra::Vector2 }; (Vector3) => { - boolmesh::Vec3 + nalgebra::Vector3 }; (Vector4) => { - boolmesh::Vec4 + nalgebra::Vector4 }; } @@ -1113,7 +1083,7 @@ macro_rules! build_vector_type { impl From<$name> for equivalent_boolmesh_vector!($type) { fn from(value: $name) -> Self { - value.0.into() + value.raw_value() } } From 5b336c0ecf1703ad277f8fea2d13cee889d57d67 Mon Sep 17 00:00:00 2001 From: James Carl Date: Wed, 11 Mar 2026 17:41:10 -0400 Subject: [PATCH 06/71] Polygons --- interpreter/src/execution/mod.rs | 13 + .../src/execution/standard_environment.rs | 44 + interpreter/src/execution/values/closure.rs | 10 +- interpreter/src/execution/values/integer.rs | 7 +- interpreter/src/execution/values/iterators.rs | 13 +- interpreter/src/execution/values/list.rs | 35 +- interpreter/src/execution/values/mod.rs | 19 + interpreter/src/execution/values/polygon.rs | 1505 +++++++++++++++++ .../src/execution/values/string/mod.rs | 12 +- .../src/execution/values/value_type.rs | 61 +- 10 files changed, 1700 insertions(+), 19 deletions(-) create mode 100644 interpreter/src/execution/values/polygon.rs diff --git a/interpreter/src/execution/mod.rs b/interpreter/src/execution/mod.rs index 6893345..851928b 100644 --- a/interpreter/src/execution/mod.rs +++ b/interpreter/src/execution/mod.rs @@ -547,6 +547,19 @@ pub(crate) fn test_run(input: &str) -> ExecutionResult { test_context([], |context| execute_expression(context, &root)) } +#[cfg(test)] +pub(crate) fn run_assert_eq(left: &str, right: &str) { + let left = compile::full_compile(left); + let right = compile::full_compile(right); + + test_context([], |context| { + let left = execute_expression(context, &left).expect("Left expression failed"); + let right = execute_expression(context, &right).expect("Right expression failed"); + + pretty_assertions::assert_eq!(left, right) + }) +} + #[cfg(test)] pub(crate) fn test_context( extra_prelude: impl IntoIterator, diff --git a/interpreter/src/execution/standard_environment.rs b/interpreter/src/execution/standard_environment.rs index 179c86b..6d390f4 100644 --- a/interpreter/src/execution/standard_environment.rs +++ b/interpreter/src/execution/standard_environment.rs @@ -89,6 +89,9 @@ fn build_std(context: &ExecutionContext) -> Dictionary { ), ("consts".into(), build_consts(context).into()), ("mesh".into(), build_mesh_3d(context).into()), + ("line_string".into(), build_line_string(context).into()), + ("polygon".into(), build_polygon(context).into()), + ("polygon_set".into(), build_polygon_set(context).into()), ("import".into(), BuiltinFunction::new::().into()), ("range".into(), build_range(context).into()), ]); @@ -176,6 +179,47 @@ fn build_dimension_types( Dictionary::new(context, types) } +fn build_line_string(context: &ExecutionContext) -> Dictionary { + use crate::values::polygon::methods_and_functions::line_string::*; + + let types: HashMap = HashMap::from_iter([( + "from_points".into(), + BuiltinFunction::new::().into(), + )]); + Dictionary::new(context, types) +} + +fn build_polygon(context: &ExecutionContext) -> Dictionary { + use crate::values::polygon::methods_and_functions::polygon::*; + + let types: HashMap = HashMap::from_iter([ + ( + "from_points".into(), + BuiltinFunction::new::().into(), + ), + ( + "from_line_strings".into(), + BuiltinFunction::new::().into(), + ), + ("circle".into(), BuiltinFunction::new::().into()), + ("box".into(), BuiltinFunction::new::().into()), + ( + "box_from_points".into(), + BuiltinFunction::new::().into(), + ), + ]); + Dictionary::new(context, types) +} + +fn build_polygon_set(context: &ExecutionContext) -> Dictionary { + use crate::values::polygon::methods_and_functions::polygon_set::*; + let types: HashMap = HashMap::from_iter([( + "from_polys".into(), + BuiltinFunction::new::().into(), + )]); + Dictionary::new(context, types) +} + fn build_mesh_3d(context: &ExecutionContext) -> Dictionary { use crate::values::manifold_mesh::methods::*; diff --git a/interpreter/src/execution/values/closure.rs b/interpreter/src/execution/values/closure.rs index 60455fe..05802bc 100644 --- a/interpreter/src/execution/values/closure.rs +++ b/interpreter/src/execution/values/closure.rs @@ -58,6 +58,7 @@ impl BuiltinCallableDatabase { crate::execution::register_methods_and_functions(&mut database); super::iterators::register_methods(&mut database); super::transform::register_methods(&mut database); + super::polygon::register_methods_and_functions(&mut database); database } @@ -71,12 +72,15 @@ impl BuiltinCallableDatabase { panic!("Duplicate bultin function name: {}", callable.name()); } - if self + if let Some(old_callable) = self .callables .insert(TypeId::of::(), CallableStorage { callable }) - .is_some() { - panic!("Duplicate bultin function tag: {:?}", TypeId::of::()); + panic!( + "Duplicate bultin function tag: {:?}, originally registered with function `{}`", + TypeId::of::(), + old_callable.name() + ); } } diff --git a/interpreter/src/execution/values/integer.rs b/interpreter/src/execution/values/integer.rs index 8a22731..8a69585 100644 --- a/interpreter/src/execution/values/integer.rs +++ b/interpreter/src/execution/values/integer.rs @@ -853,7 +853,8 @@ where { fn iterate( &self, - callback: impl FnOnce(&mut dyn Iterator) -> ExecutionResult, + _context: &ExecutionContext, + callback: impl FnOnce(&mut dyn Iterator>) -> ExecutionResult, ) -> ExecutionResult { // We had to implement a lot of this manually due to std::range::Step not being stable yet. let mut index = self.start; @@ -868,7 +869,7 @@ where if index != end { let value = index; index = index.decrement(); - Some(Integer(value).into()) + Some(Ok(Integer(value).into())) } else { None } @@ -880,7 +881,7 @@ where if index != end { let value = index; index = index.increment(); - Some(Integer(value).into()) + Some(Ok(Integer(value).into())) } else { None } diff --git a/interpreter/src/execution/values/iterators.rs b/interpreter/src/execution/values/iterators.rs index 2b86576..470c342 100644 --- a/interpreter/src/execution/values/iterators.rs +++ b/interpreter/src/execution/values/iterators.rs @@ -26,6 +26,9 @@ use crate::{ values::{ integer::{RangeSInt, RangeUInt}, list::{ListIterator, ListReverseIterator}, + polygon::{ + InteriorIterator, LineStringIterator, PolygonSetIterator, RevLineStringIterator, + }, string::{CharIterator, LineIterator}, Boolean, BuiltinCallableDatabase, BuiltinFunction, Dictionary, IString, List, MissingAttributeError, Object, StaticType, StaticTypeName, Style, UnsignedInteger, Value, @@ -40,7 +43,8 @@ use itertools::Itertools; pub trait IterableObject { fn iterate( &self, - callback: impl FnOnce(&mut dyn Iterator) -> ExecutionResult, + context: &ExecutionContext, + callback: impl FnOnce(&mut dyn Iterator>) -> ExecutionResult, ) -> ExecutionResult; } @@ -54,6 +58,10 @@ pub enum IterableSource { LineIterator, RangeUInt, RangeSInt, + LineStringIterator, + RevLineStringIterator, + InteriorIterator, + PolygonSetIterator, } #[derive(Debug, Eq, PartialEq, Clone)] @@ -187,9 +195,8 @@ impl ValueIterator { context: &ExecutionContext, callback: IterateCallback<'s, R>, ) -> ExecutionResult { - self.source.iterate(move |iterator| { + self.source.iterate(context, move |iterator| { let mut stages = self.stages.iter(); - let iterator = &mut iterator.map(Ok); if let Some(first_stage) = stages.next() { first_stage.process(context, &mut stages, iterator, callback) diff --git a/interpreter/src/execution/values/list.rs b/interpreter/src/execution/values/list.rs index b85da32..caca500 100644 --- a/interpreter/src/execution/values/list.rs +++ b/interpreter/src/execution/values/list.rs @@ -37,7 +37,7 @@ use std::{borrow::Cow, cmp::Ordering, collections::HashMap, sync::Arc}; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Default, Clone, Eq, PartialEq)] pub struct List { // In theory, we could use a lot less memory by dynamically sizing everything to fit // our smallest type, but we aren't going to implement that today. @@ -115,6 +115,29 @@ impl List { self.map_raw(context, operation_name, operation) .map(|value| value.into()) } + + pub fn iter(&self) -> impl Iterator { + self.values.iter() + } + + pub fn is_empty(&self) -> bool { + self.values.is_empty() + } + + pub fn len(&self) -> usize { + self.values.len() + } +} + +impl IntoIterator for List { + type Item = Value; + + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + let list = Arc::try_unwrap(self.values).unwrap_or_else(|arc| (*arc).clone()); + list.into_iter() + } } impl Object for List { @@ -282,9 +305,10 @@ pub struct ListIterator { impl IterableObject for ListIterator { fn iterate( &self, - callback: impl FnOnce(&mut dyn Iterator) -> ExecutionResult, + _context: &ExecutionContext, + callback: impl FnOnce(&mut dyn Iterator>) -> ExecutionResult, ) -> ExecutionResult { - let mut iter = self.list.values.iter().cloned(); + let mut iter = self.list.values.iter().cloned().map(Ok); callback(&mut iter) } } @@ -297,9 +321,10 @@ pub struct ListReverseIterator { impl IterableObject for ListReverseIterator { fn iterate( &self, - callback: impl FnOnce(&mut dyn Iterator) -> ExecutionResult, + _context: &ExecutionContext, + callback: impl FnOnce(&mut dyn Iterator>) -> ExecutionResult, ) -> ExecutionResult { - let mut iter = self.list.values.iter().rev().cloned(); + let mut iter = self.list.values.iter().rev().cloned().map(Ok); callback(&mut iter) } } diff --git a/interpreter/src/execution/values/mod.rs b/interpreter/src/execution/values/mod.rs index 9e8bbac..6080223 100644 --- a/interpreter/src/execution/values/mod.rs +++ b/interpreter/src/execution/values/mod.rs @@ -68,6 +68,9 @@ pub mod manifold_mesh; mod transform; pub use transform::{Transform2d, Transform3d}; +pub mod polygon; +pub use polygon::{LineString, Polygon, PolygonSet}; + mod value_type; pub use value_type::{StructDefinition, StructMember, ValueType}; @@ -297,6 +300,9 @@ pub enum Value { ValueIterator, Transform2d, Transform3d, + LineString, + Polygon, + PolygonSet, } impl StaticTypeName for Value { @@ -311,6 +317,19 @@ impl StaticType for Value { } } +impl From> for Value +where + T: Into, +{ + fn from(value: Option) -> Self { + if let Some(value) = value { + value.into() + } else { + ValueNone.into() + } + } +} + #[derive(Debug, Eq, PartialEq)] pub struct DowncastError { pub expected: Cow<'static, str>, diff --git a/interpreter/src/execution/values/polygon.rs b/interpreter/src/execution/values/polygon.rs new file mode 100644 index 0000000..15a0bf8 --- /dev/null +++ b/interpreter/src/execution/values/polygon.rs @@ -0,0 +1,1505 @@ +/* + * Copyright 2026 James Carl + * AGPL-3.0-only or AGPL-3.0-or-later + * + * This file is part of Command Cad. + * + * Command CAD is free software: you can redistribute it and/or modify it under the terms of + * the GNU Affero General Public License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License along with this + * program. If not, see . + */ + +use std::sync::Arc; + +use common_data_types::{Dimension, RawFloat}; +use nalgebra::Matrix3; + +use crate::{ + execution::errors::Raise, + values::{ + iterators::IterableObject, BuiltinCallableDatabase, BuiltinFunction, MissingAttributeError, + Object, StaticType, StaticTypeName, Style, Value, ValueType, Vector2, + }, + ExecutionContext, ExecutionResult, +}; + +// Add +// Subtract +// BitOr +// BitXor +// BitAnd +// We need a way to collect a list of polygons into a multi-polygon +// Ray-cast with linestrings and polygons +// to_svg +// from_svg? +// text? +// polygons from fonts +// projection - should probably live in manifold +// slice - should probably live in manifold +// bounding rec - manifold should also have one + +/// Applies a transformation to an object. +trait ApplyTransform { + fn apply_transform(&mut self, transform: &Matrix3); +} + +#[derive(Debug, Clone)] +pub struct LineString(Arc); + +impl Object for LineString { + fn get_type(&self, _context: &ExecutionContext) -> ValueType { + ValueType::LineString + } + + fn format( + &self, + _context: &ExecutionContext, + f: &mut dyn std::fmt::Write, + _style: Style, + _precision: Option, + ) -> std::fmt::Result { + // TODO Lazy way to do this, should come back and make this more proper. + write!(f, "{:?}", self.0) + } + + fn get_attribute( + &self, + context: &ExecutionContext, + attribute: &str, + ) -> crate::ExecutionResult { + match attribute { + "append" => { + Ok(BuiltinFunction::new::().into()) + } + "add_point" => { + Ok(BuiltinFunction::new::().into()) + } + "is_closed" => { + Ok(BuiltinFunction::new::().into()) + } + "close" => { + Ok(BuiltinFunction::new::().into()) + } + "open" => Ok(BuiltinFunction::new::().into()), + "iter_points" => { + Ok(BuiltinFunction::new::().into()) + } + "rev_iter_points" => Ok(BuiltinFunction::new::< + methods_and_functions::line_string::RevIterPoints, + >() + .into()), + "num_points" => { + Ok(BuiltinFunction::new::().into()) + } + "length" => Ok( + BuiltinFunction::new::().into(), + ), + "bounding_box" => Ok(BuiltinFunction::new::< + methods_and_functions::line_string::BoundingBox, + >() + .into()), + "centroid" => { + Ok(BuiltinFunction::new::().into()) + } + "transform" => { + Ok(BuiltinFunction::new::().into()) + } + _ => Err(MissingAttributeError { + name: attribute.into(), + } + .to_error(context)), + } + } +} + +impl std::cmp::Eq for LineString {} + +impl std::cmp::PartialEq for LineString { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} + +impl StaticTypeName for LineString { + fn static_type_name() -> std::borrow::Cow<'static, str> { + "LineString".into() + } +} + +impl StaticType for LineString { + fn static_type() -> ValueType { + ValueType::LineString + } +} + +impl ApplyTransform for geo::LineString { + fn apply_transform(&mut self, transform: &Matrix3) { + for point in self.coords_mut() { + let new_point = transform.transform_point(&nalgebra::Point { + coords: nalgebra::Vector2::new(point.x, point.y), + }); + + *point = geo::Coord { + x: new_point.x, + y: new_point.y, + }; + } + } +} + +#[derive(Debug, Eq, PartialEq, Clone)] +pub struct LineStringIterator { + line_string: LineString, +} + +impl IterableObject for LineStringIterator { + fn iterate( + &self, + context: &ExecutionContext, + callback: impl FnOnce(&mut dyn Iterator>) -> ExecutionResult, + ) -> ExecutionResult { + let mut iter = self.line_string.0.coords().map(|point| { + Vector2::new(context, Dimension::length(), [point.x, point.y]) + .map(|vector| vector.into()) + }); + callback(&mut iter) + } +} + +#[derive(Debug, Eq, PartialEq, Clone)] +pub struct RevLineStringIterator { + line_string: LineString, +} + +impl IterableObject for RevLineStringIterator { + fn iterate( + &self, + context: &ExecutionContext, + callback: impl FnOnce(&mut dyn Iterator>) -> ExecutionResult, + ) -> ExecutionResult { + let mut iter = self.line_string.0.coords().rev().map(|point| { + Vector2::new(context, Dimension::length(), [point.x, point.y]) + .map(|vector| vector.into()) + }); + callback(&mut iter) + } +} + +#[derive(Debug, Clone)] +pub struct Polygon(Arc); + +impl Object for Polygon { + fn get_type(&self, _context: &ExecutionContext) -> ValueType { + ValueType::Polygon + } + + fn format( + &self, + _context: &ExecutionContext, + f: &mut dyn std::fmt::Write, + _style: Style, + _precision: Option, + ) -> std::fmt::Result { + // TODO Lazy way to do this, should come back and make this more proper. + write!(f, "{:?}", self.0) + } + + fn get_attribute( + &self, + context: &ExecutionContext, + attribute: &str, + ) -> crate::ExecutionResult { + match attribute { + "exterior" => { + Ok(BuiltinFunction::new::().into()) + } + "interiors" => { + Ok(BuiltinFunction::new::().into()) + } + "num_interiors" => { + Ok(BuiltinFunction::new::().into()) + } + "is_convex" => { + Ok(BuiltinFunction::new::().into()) + } + "area" => Ok(BuiltinFunction::new::().into()), + "bounding_box" => { + Ok(BuiltinFunction::new::().into()) + } + "centroid" => { + Ok(BuiltinFunction::new::().into()) + } + "transform" => { + Ok(BuiltinFunction::new::().into()) + } + "into_set" => { + Ok(BuiltinFunction::new::().into()) + } + _ => Err(MissingAttributeError { + name: attribute.into(), + } + .to_error(context)), + } + } +} + +impl std::cmp::Eq for Polygon {} + +impl std::cmp::PartialEq for Polygon { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} + +impl StaticTypeName for Polygon { + fn static_type_name() -> std::borrow::Cow<'static, str> { + "Polygon".into() + } +} + +impl StaticType for Polygon { + fn static_type() -> ValueType { + ValueType::Polygon + } +} + +impl ApplyTransform for geo::Polygon { + fn apply_transform(&mut self, transform: &Matrix3) { + self.exterior_mut(|exterior| exterior.apply_transform(transform)); + + self.interiors_mut(|interiors| { + for interior in interiors { + interior.apply_transform(transform); + } + }); + } +} + +#[derive(Debug, Clone)] +pub struct PolygonSet(Arc); + +impl Object for PolygonSet { + fn get_type(&self, _context: &ExecutionContext) -> ValueType { + ValueType::PolygonSet + } + + fn format( + &self, + _context: &ExecutionContext, + f: &mut dyn std::fmt::Write, + _style: Style, + _precision: Option, + ) -> std::fmt::Result { + // TODO Lazy way to do this, should come back and make this more proper. + write!(f, "{:?}", self.0) + } + + fn get_attribute( + &self, + context: &ExecutionContext, + attribute: &str, + ) -> crate::ExecutionResult { + match attribute { + "iter_polys" => { + Ok(BuiltinFunction::new::().into()) + } + "num_poly" => { + Ok(BuiltinFunction::new::().into()) + } + "area" => Ok(BuiltinFunction::new::().into()), + "bounding_box" => Ok(BuiltinFunction::new::< + methods_and_functions::polygon_set::BoundingBox, + >() + .into()), + "centroid" => { + Ok(BuiltinFunction::new::().into()) + } + "transform" => { + Ok(BuiltinFunction::new::().into()) + } + _ => Err(MissingAttributeError { + name: attribute.into(), + } + .to_error(context)), + } + } +} + +impl ApplyTransform for geo::MultiPolygon { + fn apply_transform(&mut self, transform: &Matrix3) { + for polygon in self.0.iter_mut() { + polygon.apply_transform(transform); + } + } +} + +#[derive(Debug, Eq, PartialEq, Clone)] +pub struct InteriorIterator { + polygon: Polygon, +} + +impl IterableObject for InteriorIterator { + fn iterate( + &self, + _context: &ExecutionContext, + callback: impl FnOnce(&mut dyn Iterator>) -> ExecutionResult, + ) -> ExecutionResult { + let mut iter = self + .polygon + .0 + .interiors() + .iter() + .map(|string| LineString(Arc::new(string.clone())).into()) + .map(Ok); + callback(&mut iter) + } +} + +impl std::cmp::Eq for PolygonSet {} + +impl std::cmp::PartialEq for PolygonSet { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} + +impl StaticTypeName for PolygonSet { + fn static_type_name() -> std::borrow::Cow<'static, str> { + "PolygonSet".into() + } +} + +impl StaticType for PolygonSet { + fn static_type() -> ValueType { + ValueType::PolygonSet + } +} + +#[derive(Debug, Eq, PartialEq, Clone)] +pub struct PolygonSetIterator { + polygon_set: PolygonSet, +} + +impl IterableObject for PolygonSetIterator { + fn iterate( + &self, + _context: &ExecutionContext, + callback: impl FnOnce(&mut dyn Iterator>) -> ExecutionResult, + ) -> ExecutionResult { + let mut iter = self + .polygon_set + .0 + .iter() + .map(|polygon| Polygon(Arc::new(polygon.clone())).into()) + .map(Ok); + callback(&mut iter) + } +} + +pub mod methods_and_functions { + use common_data_types::{Dimension, Float, RawFloat}; + use geo::{Area, BoundingRect, Centroid, Point, Rect}; + use imstr::ImString; + + use super::{InteriorIterator, LineString, Polygon, PolygonSet}; + use crate::values::scalar::UnwrapNotNan; + use crate::values::Value; + use crate::ExecutionResult; + use crate::{build_function, build_method, values::BuiltinCallableDatabase}; + use crate::{ + values::{ + iterators::ValueIterator, + scalar::Scalar, + vector::{Length2, Vector2}, + Boolean, Dictionary, List, Transform2d, UnsignedInteger, + }, + ExecutionContext, + }; + use std::{collections::HashMap, sync::Arc}; + + fn bounding_box(context: &ExecutionContext, bound: &B) -> ExecutionResult> + where + B: BoundingRect>>, + { + if let Some(rect) = bound.bounding_rect() { + let min = rect.min(); + let max = rect.max(); + + let rectangle: HashMap = HashMap::from_iter([ + ( + "min".into(), + Vector2::new(context, Dimension::length(), [min.x, min.y])?.into(), + ), + ( + "max".into(), + Vector2::new(context, Dimension::length(), [max.x, max.y])?.into(), + ), + ]); + + Ok(Some(Dictionary::new(context, rectangle))) + } else { + Ok(None) + } + } + + fn centroid(context: &ExecutionContext, centroid: &C) -> ExecutionResult> + where + C: Centroid>>, + { + if let Some(centroid) = centroid.centroid() { + Ok(Some(Vector2::new( + context, + Dimension::length(), + [centroid.x(), centroid.y()], + )?)) + } else { + Ok(None) + } + } + + fn area(context: &ExecutionContext, area: &A) -> ExecutionResult + where + A: Area, + { + let area = area.unsigned_area(); + Ok(Scalar { + dimension: Dimension::area(), + value: Float::new(area).unwrap_not_nan(context)?, + }) + } + + pub mod line_string { + + use common_data_types::{Dimension, Float}; + use geo::{Distance as _, Euclidean}; + + use crate::values::polygon::ApplyTransform; + + use super::super::{LineStringIterator, RevLineStringIterator}; + use super::*; + + pub struct FromPoints; + pub struct Append; + pub struct AddPoint; + pub struct IsClosed; + pub struct Close; + pub struct Open; + pub struct IterPoints; + pub struct RevIterPoints; + pub struct NumPoints; + pub struct StringLength; + pub struct BoundingBox; + pub struct Centroid; + pub struct Transform; + + pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { + build_function!( + database, + FromPoints, "LineString::from_points", ( + context: &ExecutionContext, + points: List) -> LineString + { + let mut collected = Vec::with_capacity(points.len()); + for value in points { + let point: Length2 = value.downcast(context)?; + let point: Vector2 = point.into(); + collected.push(geo::Coord { x: point.raw_value().x, y: point.raw_value().y }); + } + + Ok(LineString(Arc::new(geo::LineString(collected)))) + } + ); + build_method!( + database, + Append, "LineString::append", ( + context: &ExecutionContext, + this: LineString, + other: LineString) -> LineString + { + let mut this = this; + let line_string = Arc::make_mut(&mut this.0); + for point in other.0.coords() { + line_string.0.push(*point); + } + + Ok(this) + } + ); + build_method!( + database, + AddPoint, "LineString::add_point", ( + context: &ExecutionContext, + this: LineString, + p: Length2) -> LineString + { + let mut this = this; + let line_string = Arc::make_mut(&mut this.0); + + let point: Vector2 = p.into(); + line_string.0.push(geo::Coord { x: point.raw_value().x, y: point.raw_value().y }); + + Ok(this) + } + ); + build_method!( + database, + IsClosed, "LineString::is_closed", ( + context: &ExecutionContext, + this: LineString) -> Boolean + { + Ok(Boolean(this.0.is_closed())) + } + ); + build_method!( + database, + Close, "LineString::close", ( + context: &ExecutionContext, + this: LineString) -> LineString + { + if this.0.is_closed() { + Ok(this) + } else { + let mut this = this; + let line_string = Arc::make_mut(&mut this.0); + line_string.close(); + + Ok(this) + } + } + ); + build_method!( + database, + Open, "LineString::open", ( + context: &ExecutionContext, + this: LineString) -> LineString + { + if this.0.is_closed() { + let mut this = this; + let line_string = Arc::make_mut(&mut this.0); + line_string.0.pop(); + + Ok(this) + } else { + Ok(this) + } + } + ); + build_method!( + database, + IterPoints, "LineString::iter_points", ( + context: &ExecutionContext, + this: LineString) -> ValueIterator + { + Ok(ValueIterator::new(LineStringIterator { line_string: this })) + } + ); + build_method!( + database, + RevIterPoints, "LineString::rev_iter_points", ( + context: &ExecutionContext, + this: LineString) -> ValueIterator + { + Ok(ValueIterator::new(RevLineStringIterator { line_string: this })) + } + ); + build_method!( + database, + NumPoints, "LineString::num_points", ( + context: &ExecutionContext, + this: LineString) -> UnsignedInteger + { + Ok(UnsignedInteger::from(this.0.0.len() as u64)) + } + ); + build_method!( + database, + StringLength, "LineString::length", ( + context: &ExecutionContext, + this: LineString) -> Scalar + { + let mut points = this.0.0.iter().peekable(); + + let mut length = 0.0; + while let Some(point) = points.next() { + if let Some(next_point) = points.peek() { + let distance_between_points = Euclidean.distance(*point, **next_point); + length += distance_between_points; + } + } + + Ok(Scalar { + dimension: Dimension::length(), + value: Float::new(length).unwrap_not_nan(context)? + }) + } + ); + build_method!( + database, + BoundingBox, "LineString::bounding_box", ( + context: &ExecutionContext, + this: LineString) -> Option + { + bounding_box(context, &*this.0) + } + ); + build_method!( + database, + Centroid, "LineString::centroid", ( + context: &ExecutionContext, + this: LineString) -> Option + { + centroid(context, &*this.0) + } + ); + build_method!( + database, + Transform, "LineString::transform", ( + context: &ExecutionContext, + this: LineString, + t: Transform2d) -> LineString + { + let mut this = this; + Arc::make_mut(&mut this.0).apply_transform(&t.0); + + Ok(this) + } + ); + } + } + + pub mod polygon { + + use std::f64::consts::PI; + + use geo::IsConvex as _; + use thiserror::Error; + + use crate::{ + execution::errors::Raise, + values::{ + polygon::ApplyTransform as _, + scalar::{Angle, Length}, + ValueNone, + }, + }; + + use super::*; + + pub struct FromPoints; + pub struct FromLineStrings; + pub struct Circle; + pub struct BuildBox; + pub struct BuildBoxFromPoints; + pub struct Exterior; + pub struct Interiors; + pub struct NumInteriors; + pub struct IsConvex; + pub struct Area; + pub struct BoundingBox; + pub struct Centroid; + pub struct Transform; + pub struct IntoSet; + + #[derive(Debug, Error)] + enum CircleError { + #[error("Could not derive radius, please provide radius or diameter")] + NoRadius, + + #[error("Both a radius and a diameter were provided, please provide only one")] + AmbigiousRadius, + + #[error("Cannot determine angle between segment points, provide exactly one of the following: angle_between_points, distance_between_points, or number_of_points.")] + AmbigiousSegmentAngle, + } + + #[derive(Debug)] + struct CircleInfo { + radius: RawFloat, + segment_angle: RawFloat, + number_of_points: usize, + } + + impl CircleInfo { + fn new( + context: &ExecutionContext, + radius: Option, + diameter: Option, + angle_between_points: Option, + distance_between_points: Option, + number_of_points: Option, + ) -> ExecutionResult { + const SEGMENT_ANGLE_RADIANS: RawFloat = 2.0; + + let radius = match (radius, diameter) { + (Some(radius), None) => *radius.value, + (None, Some(diameter)) => *diameter.value / 2.0, + (Some(_), Some(_)) => { + return Err(CircleError::AmbigiousRadius.to_error(context)) + } + (None, None) => return Err(CircleError::NoRadius.to_error(context)), + }; + + let segment_angle = match ( + angle_between_points, + distance_between_points, + number_of_points, + ) { + (Some(angle_between_points), None, None) => *angle_between_points.value, + (None, Some(distance_between_points), None) => { + *distance_between_points.value / radius / PI + } + (None, None, Some(number_of_points)) => { + SEGMENT_ANGLE_RADIANS / number_of_points.0 as RawFloat + } + (_, _, _) => return Err(CircleError::AmbigiousSegmentAngle.to_error(context)), + }; + + let number_of_points = if let Some(number_of_points) = number_of_points { + number_of_points.0 as usize + } else { + (SEGMENT_ANGLE_RADIANS / segment_angle) as usize + }; + + Ok(Self { + radius, + segment_angle, + number_of_points, + }) + } + } + + pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { + build_function!( + database, + FromPoints, "Polygon::from_points", ( + context: &ExecutionContext, + points: List) -> Polygon + { + let mut collected = Vec::with_capacity(points.len()); + for value in points { + let point: Length2 = value.downcast(context)?; + let point: Vector2 = point.into(); + collected.push(geo::Coord { x: point.raw_value().x, y: point.raw_value().y }); + } + + let external = geo::LineString(collected); + Ok(Polygon(Arc::new(geo::Polygon::new(external, vec![])))) + } + ); + build_function!( + database, + FromLineStrings, "Polygon::from_line_strings", ( + context: &ExecutionContext, + exterior: LineString, + interiors: List = List::default().into()) -> Polygon + { + let mut collected = Vec::with_capacity(interiors.len()); + for value in interiors { + let string: LineString = value.downcast(context)?; + collected.push((*string.0).clone()); + } + + let exterior = Arc::unwrap_or_clone(exterior.0); + Ok(Polygon(Arc::new(geo::Polygon::new(exterior, collected)))) + } + ); + build_function!( + database, + Circle, "Polygon::circle", ( + context: &ExecutionContext, + radius: Option = ValueNone.into(), + diameter: Option = ValueNone.into(), + angle_between_points: Option = ValueNone.into(), + distance_between_points: Option = ValueNone.into(), + number_of_points: Option = ValueNone.into()) -> Polygon + { + let circle_info = CircleInfo::new( + context, + radius, + diameter, + angle_between_points, + distance_between_points, + number_of_points, + )?; + + let mut points = Vec::with_capacity(circle_info.number_of_points); + for point_index in 0..circle_info.number_of_points { + let angle_to_point = circle_info.segment_angle * point_index as RawFloat * PI; + let (y, x) = angle_to_point.sin_cos(); + let coord = geo::Coord { x: x * circle_info.radius, y: y * circle_info.radius }; + points.push(coord); + } + + Ok(Polygon(Arc::new(geo::Polygon::new(geo::LineString(points), vec![])))) + } + ); + build_function!( + database, + BuildBox, "Polygon::box", ( + context: &ExecutionContext, + size: Length2, + center: Boolean = Boolean(false).into()) -> Polygon + { + let size = size.raw_value(); + + let (a, b) = if center.0 { + let half = size / 2.0; + (-half, half) + } else { + (nalgebra::Vector2::zeros(), size) + }; + + + let rect = geo::Rect::new( + geo::Coord { x: a.x, y: a.y }, + geo::Coord { x: b.x, y: b.y } + ); + + Ok(Polygon(Arc::new(rect.to_polygon()))) + } + ); + build_function!( + database, + BuildBoxFromPoints, "Polygon::box_from_points", ( + context: &ExecutionContext, + a: Length2, + b: Length2) -> Polygon + { + let a = a.raw_value(); + let b = b.raw_value(); + + let rect = geo::Rect::new( + geo::Coord { x: a.x, y: a.y }, + geo::Coord { x: b.x, y: b.y } + ); + + Ok(Polygon(Arc::new(rect.to_polygon()))) + } + ); + + build_method!( + database, + Exterior, "Polygon::exterior", ( + context: &ExecutionContext, + this: Polygon) -> LineString + { + Ok(LineString(Arc::new(this.0.exterior().clone()))) + } + ); + build_method!( + database, + Interiors, "Polygon::interiors", ( + context: &ExecutionContext, + this: Polygon) -> ValueIterator + { + Ok(ValueIterator::new(InteriorIterator { polygon: this })) + } + ); + build_method!( + database, + NumInteriors, "Polygon::num_interiors", ( + context: &ExecutionContext, + this: Polygon) -> UnsignedInteger + { + Ok(UnsignedInteger::from(this.0.interiors().len() as u64)) + } + ); + build_method!( + database, + IsConvex, "Polygon::is_convex", ( + context: &ExecutionContext, + this: Polygon) -> Boolean + { + Ok(Boolean(this.0.exterior().is_convex())) + } + ); + build_method!( + database, + Area, "Polygon::area", ( + context: &ExecutionContext, + this: Polygon) -> Scalar + { + area(context, &*this.0) + } + ); + build_method!( + database, + BoundingBox, "Polygon::bounding_box", ( + context: &ExecutionContext, + this: Polygon) -> Option + { + bounding_box(context, &*this.0) + } + ); + build_method!( + database, + Centroid, "Polygon::centroid", ( + context: &ExecutionContext, + this: Polygon) -> Option + { + centroid(context, &*this.0) + } + ); + build_method!( + database, + Transform, "Polygon::transform", ( + context: &ExecutionContext, + this: Polygon, + t: Transform2d) -> Polygon + { + let mut this = this; + Arc::make_mut(&mut this.0).apply_transform(&t.0); + + Ok(this) + } + ); + build_method!( + database, + IntoSet, "Polygon::into_set", ( + context: &ExecutionContext, + this: Polygon) -> PolygonSet + { + let polygon = Arc::unwrap_or_clone(this.0); + Ok(PolygonSet(Arc::new(geo::MultiPolygon(vec![polygon])))) + } + ); + } + } + + pub mod polygon_set { + use crate::values::polygon::{ApplyTransform as _, PolygonSetIterator}; + + use super::*; + + pub struct FromPolys; + pub struct IterPolys; + pub struct NumPoly; + pub struct Area; + pub struct BoundingBox; + pub struct Centroid; + pub struct Transform; + + pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { + build_function!( + database, + FromPolys, "PolygonSet::from_polys", ( + context: &ExecutionContext, + polys: List) -> PolygonSet + { + let mut collected = Vec::with_capacity(polys.len()); + for value in polys { + let polygon: Polygon = value.downcast(context)?; + let polygon = Arc::unwrap_or_clone(polygon.0); + collected.push(polygon); + } + + Ok(PolygonSet(Arc::new(geo::MultiPolygon(collected)))) + } + ); + + build_method!( + database, + IterPolys, "PolygonSet::iter_polys", ( + context: &ExecutionContext, + this: PolygonSet) -> ValueIterator + { + Ok(ValueIterator::new(PolygonSetIterator { polygon_set: this })) + } + ); + build_method!( + database, + NumPoly, "PolygonSet::num_polys", ( + context: &ExecutionContext, + this: PolygonSet) -> UnsignedInteger + { + Ok(UnsignedInteger::from(this.0.0.len() as u64)) + } + ); + build_method!( + database, + Area, "PolygonSet::area", ( + context: &ExecutionContext, + this: PolygonSet) -> Scalar + { + area(context, &*this.0) + } + ); + build_method!( + database, + BoundingBox, "PolygonSet::bounding_box", ( + context: &ExecutionContext, + this: PolygonSet) -> Option + { + bounding_box(context, &*this.0) + } + ); + build_method!( + database, + Centroid, "PolygonSet::centroid", ( + context: &ExecutionContext, + this: PolygonSet) -> Option + { + centroid(context, &*this.0) + } + ); + build_method!( + database, + Transform, "PolygonSet::transform", ( + context: &ExecutionContext, + this: PolygonSet, + t: Transform2d) -> PolygonSet + { + let mut this = this; + Arc::make_mut(&mut this.0).apply_transform(&t.0); + + Ok(this) + } + ); + } + } +} + +pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { + methods_and_functions::line_string::register_methods_and_functions(database); + methods_and_functions::polygon::register_methods_and_functions(database); + methods_and_functions::polygon_set::register_methods_and_functions(database); +} + +#[cfg(test)] +mod test { + use super::*; + use crate::execution::{run_assert_eq, test_run}; + use geo::{Coord, Distance as _, Euclidean, Point}; + + #[test] + fn line_string_from_points() { + let result = + test_run("std.line_string.from_points(points = [{0m, 1m}, {2m, 3m}])").unwrap(); + assert_eq!( + result, + LineString(Arc::new(geo::LineString(vec![ + Coord { x: 0.0, y: 1.0 }, + Coord { x: 2.0, y: 3.0 } + ]))) + .into() + ); + } + + #[test] + fn line_string_append() { + run_assert_eq( + "std.line_string.from_points(points = [{0m, 1m}, {2m, 3m}])::append(other = std.line_string.from_points(points = [{4m, 5m}, {6m, 7m}]))::iter_points()::collect_list()", + "[{0m, 1m}, {2m, 3m}, {4m, 5m}, {6m, 7m}]", + ); + } + + #[test] + fn line_string_add_point() { + run_assert_eq( + "std.line_string.from_points(points = [{0m, 1m}, {2m, 3m}])::add_point(p = {4m, 5m})::iter_points()::collect_list()", + "[{0m, 1m}, {2m, 3m}, {4m, 5m}]", + ); + } + + #[test] + fn line_string_is_closed() { + run_assert_eq( + "std.line_string.from_points(points = [{0m, 1m}, {2m, 3m}])::is_closed()", + "false", + ); + run_assert_eq( + "std.line_string.from_points(points = [{0m, 1m}, {2m, 3m}, {0m, 1m}])::is_closed()", + "true", + ); + } + + #[test] + fn line_string_close() { + run_assert_eq( + "std.line_string.from_points(points = [{0m, 1m}, {2m, 3m}])::close()", + "std.line_string.from_points(points = [{0m, 1m}, {2m, 3m}, {0m, 1m}])", + ); + run_assert_eq( + "std.line_string.from_points(points = [{0m, 1m}, {2m, 3m}, {0m, 1m}])::close()", + "std.line_string.from_points(points = [{0m, 1m}, {2m, 3m}, {0m, 1m}])", + ); + } + + #[test] + fn line_string_open() { + run_assert_eq( + "std.line_string.from_points(points = [{0m, 1m}, {2m, 3m}])::open()", + "std.line_string.from_points(points = [{0m, 1m}, {2m, 3m}])", + ); + run_assert_eq( + "std.line_string.from_points(points = [{0m, 1m}, {2m, 3m}, {0m, 1m}])::open()", + "std.line_string.from_points(points = [{0m, 1m}, {2m, 3m}])", + ); + } + + #[test] + fn line_string_iter_points() { + run_assert_eq( + "std.line_string.from_points(points = [{0m, 1m}, {2m, 3m}])::iter_points()::collect_list()", + "[{0m, 1m}, {2m, 3m}]", + ); + } + + #[test] + fn line_string_rev_iter_points() { + run_assert_eq( + "std.line_string.from_points(points = [{0m, 1m}, {2m, 3m}])::rev_iter_points()::collect_list()", + "[{2m, 3m}, {0m, 1m}]", + ); + } + + #[test] + fn line_string_num_points() { + run_assert_eq( + "std.line_string.from_points(points = [{0m, 1m}, {2m, 3m}])::num_points()", + "2u", + ); + } + + #[test] + fn line_string_length() { + run_assert_eq( + "std.line_string.from_points(points = [{0m, 1m}, {0m, 2m}, {0m, 4m}])::length()", + "3m", + ); + } + + #[test] + fn line_string_bounding_box() { + run_assert_eq( + "std.line_string.from_points(points = [{-1m, 2m}, {1m, -2m}])::bounding_box()", + "(min = {-1m, -2m}, max = {1m, 2m})", + ); + } + + #[test] + fn line_string_centroid() { + run_assert_eq( + "std.line_string.from_points(points = [{-1m, 1m}, {1m, -1m}])::centroid()", + "{0m, 0m}", + ); + } + + #[test] + fn line_string_transform() { + run_assert_eq( + "std.line_string.from_points(points = [{0m, 1m}, {2m, 3m}])::transform(t = std.consts.Transform2d::translate(offset = {1m, 2m}))", + "std.line_string.from_points(points = [{1m, 3m}, {3m, 5m}])", + ); + } + + #[test] + fn polygon_from_points() { + let result = + test_run("std.polygon.from_points(points = [{0m, 0m}, {1m, 0m}, {1m, 1m}, {0m, 1m}])") + .unwrap(); + assert_eq!( + result, + Polygon(Arc::new(geo::Polygon::new( + geo::LineString(vec![ + Coord { x: 0.0, y: 0.0 }, + Coord { x: 1.0, y: 0.0 }, + Coord { x: 1.0, y: 1.0 }, + Coord { x: 0.0, y: 1.0 } + ]), + vec![] + ))) + .into() + ); + } + + #[test] + fn polygon_from_line_strings() { + let result = + test_run("std.polygon.from_line_strings(exterior = std.line_string.from_points(points = [{0m, 0m}, {1m, 0m}, {1m, 1m}, {0m, 1m}]))") + .unwrap(); + assert_eq!( + result, + Polygon(Arc::new(geo::Polygon::new( + geo::LineString(vec![ + Coord { x: 0.0, y: 0.0 }, + Coord { x: 1.0, y: 0.0 }, + Coord { x: 1.0, y: 1.0 }, + Coord { x: 0.0, y: 1.0 } + ]), + vec![] + ))) + .into() + ); + } + + #[test] + fn polygon_from_circle() { + // Test angle_between_points + let result = + test_run("std.polygon.circle(radius = 1m, angle_between_points = 1rad)").unwrap(); + let polygon = result.as_polygon().unwrap(); + assert_eq!(polygon.0.exterior().0.len(), 3); + assert!(polygon.0.interiors().is_empty()); + + let result = + test_run("std.polygon.circle(radius = 1m, angle_between_points = 0.5rad)").unwrap(); + let polygon = result.as_polygon().unwrap(); + assert_eq!(polygon.0.exterior().0.len(), 5); + assert!(polygon.0.interiors().is_empty()); + + // Test distance_between_points + let result = + test_run("std.polygon.circle(radius = 1m, distance_between_points = 3.14159m)") + .unwrap(); + let polygon = result.as_polygon().unwrap(); + assert_eq!(polygon.0.exterior().0.len(), 3); + assert!(polygon.0.interiors().is_empty()); + + // Test number_of_points + let result = test_run("std.polygon.circle(radius = 1m, number_of_points = 2u)").unwrap(); + let polygon = result.as_polygon().unwrap(); + assert_eq!(polygon.0.exterior().0.len(), 3); + assert!(polygon.0.interiors().is_empty()); + + let result = test_run("std.polygon.circle(radius = 1m, number_of_points = 3u)").unwrap(); + let polygon = result.as_polygon().unwrap(); + assert_eq!(polygon.0.exterior().0.len(), 4); + assert!(polygon.0.interiors().is_empty()); + + let result = + test_run("std.polygon.circle(radius = 1m, angle_between_points = 0.5rad)").unwrap(); + let polygon = result.as_polygon().unwrap(); + + let expected_coords = [ + Coord { x: 1.0, y: 0.0 }, + Coord { x: 0.0, y: 1.0 }, + Coord { x: -1.0, y: 0.0 }, + Coord { x: 0.0, y: -1.0 }, + Coord { x: 1.0, y: 0.0 }, + ]; + + for (index, (actual, expected)) in expected_coords + .iter() + .zip(polygon.0.exterior().0.iter()) + .enumerate() + { + assert!( + Euclidean.distance(Point(*actual), Point(*expected)) < 0.00001, + "Coordinate {index} was not within tolerance" + ); + } + + let result = + test_run("std.polygon.circle(diameter = 1m, angle_between_points = 0.5rad)").unwrap(); + let polygon = result.as_polygon().unwrap(); + let expected_coords = [ + Coord { x: 0.5, y: 0.0 }, + Coord { x: 0.0, y: 0.5 }, + Coord { x: -0.5, y: 0.0 }, + Coord { x: 0.0, y: -0.5 }, + Coord { x: 0.5, y: 0.0 }, + ]; + + for (index, (actual, expected)) in expected_coords + .iter() + .zip(polygon.0.exterior().0.iter()) + .enumerate() + { + assert!( + Euclidean.distance(Point(*actual), Point(*expected)) < 0.00001, + "Coordinate {index} was not within tolerance" + ); + } + } + + #[test] + fn polygon_from_box() { + run_assert_eq( + "std.polygon.box(size = {1m, 2m})::exterior()::iter_points()::collect_list()", + "[{1m, 0m}, {1m, 2m}, {0m, 2m}, {0m, 0m}, {1m, 0m}]", + ); + + run_assert_eq( + "std.polygon.box(size = {1m, 2m}, center = true)::exterior()::iter_points()::collect_list()", + "[{0.5m, -1m}, {0.5m, 1m}, {-0.5m, 1m}, {-0.5m, -1m}, {0.5m, -1m}]", + ); + } + + #[test] + fn polygon_exterior() { + run_assert_eq( + "std.polygon.from_line_strings(exterior = std.line_string.from_points(points = [{0m, 0m}, {1m, 0m}, {1m, 1m}, {0m, 1m}]))::exterior()", + "std.line_string.from_points(points = [{0m, 0m}, {1m, 0m}, {1m, 1m}, {0m, 1m}, {0m, 0m}])", + ); + } + + #[test] + fn polygon_interiors() { + run_assert_eq( + "std.polygon.from_line_strings(exterior = std.line_string.from_points(points = [{-2m, -2m}, {2m, -2m}, {2m, 2m}, {-2m, 2m}]), interiors = [std.line_string.from_points(points = [{0m, 1m}, {1m, 1m}, {1m, 0m}, {0m, 0m}])])::interiors()::collect_list()", + "[std.line_string.from_points(points = [{0m, 1m}, {1m, 1m}, {1m, 0m}, {0m, 0m}, {0m, 1m}])]", + ); + } + + #[test] + fn polygon_num_interiors() { + run_assert_eq( + "std.polygon.from_line_strings(exterior = std.line_string.from_points(points = []), interiors = [std.line_string.from_points(points = []), std.line_string.from_points(points = []), std.line_string.from_points(points = [])])::num_interiors()", + "3u", + ); + } + + #[test] + fn polygon_is_convex() { + run_assert_eq( + "std.polygon.from_line_strings(exterior = std.line_string.from_points(points = [{0m, 0m}, {1m, 0m}, {1m, 1m}, {0m, 1m}]))::is_convex()", + "true", + ); + + run_assert_eq( + "std.polygon.from_line_strings(exterior = std.line_string.from_points(points = [{0m, 0m}, {1m, 0m}, {1m, 1m}, {0.5m, 0.5m}, {0m, 1m}]))::is_convex()", + "false", + ); + } + + #[test] + fn polygon_area() { + run_assert_eq( + "std.polygon.from_line_strings(exterior = std.line_string.from_points(points = [{0m, 0m}, {1m, 0m}, {1m, 1m}, {0m, 1m}]))::area()", + "1 'm^2'", + ); + } + + #[test] + fn polygon_bounding_box() { + run_assert_eq( + "std.polygon.from_line_strings(exterior = std.line_string.from_points(points = [{0m, 0m}, {1m, 0m}, {1m, 1m}, {0m, 1m}]))::bounding_box()", + "(min = {0m, 0m}, max = {1m, 1m})", + ); + } + + #[test] + fn polygon_centroid() { + run_assert_eq( + "std.polygon.from_line_strings(exterior = std.line_string.from_points(points = [{0m, 0m}, {1m, 0m}, {1m, 1m}, {0m, 1m}]))::centroid()", + "{0.5m, 0.5m}", + ); + } + + #[test] + fn polygon_transform() { + run_assert_eq( + "std.polygon.from_line_strings(exterior = std.line_string.from_points(points = [{0m, 0m}, {1m, 0m}, {1m, 1m}, {0m, 1m}]))::transform(t = std.consts.Transform2d::translate(offset = {1m, 2m}))", + "std.polygon.from_line_strings(exterior = std.line_string.from_points(points = [{1m, 2m}, {2m, 2m}, {2m, 3m}, {1m, 3m}]))", + ); + } + + #[test] + fn polygon_into_set() { + let result = test_run( + "std.polygon.from_points(points = [{0m, 0m}, {1m, 0m}, {1m, 1m}, {0m, 1m}])::into_set()", + ) + .unwrap(); + assert_eq!( + result, + PolygonSet(Arc::new(geo::MultiPolygon(vec![geo::Polygon::new( + geo::LineString(vec![ + Coord { x: 0.0, y: 0.0 }, + Coord { x: 1.0, y: 0.0 }, + Coord { x: 1.0, y: 1.0 }, + Coord { x: 0.0, y: 1.0 } + ]), + vec![] + )]))) + .into() + ); + } + + #[test] + fn polygon_set_from_polys() { + let result = test_run( + "std.polygon_set.from_polys(polys = [std.polygon.from_points(points = [{0m, 0m}, {1m, 0m}, {1m, 1m}, {0m, 1m}]), std.polygon.from_points(points = [{1m, 1m}, {2m, 1m}, {2m, 2m}, {1m, 2m}])])", + ) + .unwrap(); + assert_eq!( + result, + PolygonSet(Arc::new(geo::MultiPolygon(vec![ + geo::Polygon::new( + geo::LineString(vec![ + Coord { x: 0.0, y: 0.0 }, + Coord { x: 1.0, y: 0.0 }, + Coord { x: 1.0, y: 1.0 }, + Coord { x: 0.0, y: 1.0 } + ]), + vec![] + ), + geo::Polygon::new( + geo::LineString(vec![ + Coord { x: 1.0, y: 1.0 }, + Coord { x: 2.0, y: 1.0 }, + Coord { x: 2.0, y: 2.0 }, + Coord { x: 1.0, y: 2.0 } + ]), + vec![] + ) + ]))) + .into() + ); + } + + #[test] + fn polygon_set_iter_polys() { + run_assert_eq( + "std.polygon_set.from_polys(polys = [std.polygon.from_points(points = [{0m, 0m}, {1m, 0m}, {1m, 1m}, {0m, 1m}]), std.polygon.from_points(points = [{1m, 1m}, {2m, 1m}, {2m, 2m}, {1m, 2m}])])::iter_polys()::collect_list()", + "[std.polygon.from_points(points = [{0m, 0m}, {1m, 0m}, {1m, 1m}, {0m, 1m}]), std.polygon.from_points(points = [{1m, 1m}, {2m, 1m}, {2m, 2m}, {1m, 2m}])]", + ); + } + + #[test] + fn polygon_set_num_poly() { + run_assert_eq( + "std.polygon_set.from_polys(polys = [std.polygon.from_points(points = [{0m, 0m}, {1m, 0m}, {1m, 1m}, {0m, 1m}]), std.polygon.from_points(points = [{1m, 1m}, {2m, 1m}, {2m, 2m}, {1m, 2m}])])::num_poly()", + "2u", + ); + } + + #[test] + fn polygon_set_area() { + run_assert_eq( + "std.polygon.from_points(points = [{0m, 0m}, {1m, 0m}, {1m, 1m}, {0m, 1m}])::into_set()::area()", + "1 'm^2'", + ); + } + + #[test] + fn polygon_set_bounding_box() { + run_assert_eq( + "std.polygon.from_points(points = [{0m, 0m}, {1m, 0m}, {1m, 1m}, {0m, 1m}])::into_set()::bounding_box()", + "(min = {0m, 0m}, max = {1m, 1m})", + ); + } + + #[test] + fn polygon_set_centroid() { + run_assert_eq( + "std.polygon.from_points(points = [{0m, 0m}, {1m, 0m}, {1m, 1m}, {0m, 1m}])::into_set()::centroid()", + "{0.5m, 0.5m}", + ); + } + + #[test] + fn polygon_set_transform() { + run_assert_eq( + "std.polygon.from_points(points = [{0m, 0m}, {1m, 0m}, {1m, 1m}, {0m, 1m}])::into_set()::transform(t = std.consts.Transform2d::translate(offset = {1m, 2m}))", + "std.polygon.from_points(points = [{1m, 2m}, {2m, 2m}, {2m, 3m}, {1m, 3m}, {1m, 2m}])::into_set()", + ); + } +} diff --git a/interpreter/src/execution/values/string/mod.rs b/interpreter/src/execution/values/string/mod.rs index 98b0d53..448b67b 100644 --- a/interpreter/src/execution/values/string/mod.rs +++ b/interpreter/src/execution/values/string/mod.rs @@ -147,13 +147,15 @@ pub struct CharIterator { impl IterableObject for CharIterator { fn iterate( &self, - callback: impl FnOnce(&mut dyn Iterator) -> ExecutionResult, + _context: &ExecutionContext, + callback: impl FnOnce(&mut dyn Iterator>) -> ExecutionResult, ) -> ExecutionResult { let mut iter = self .string .0 .chars() - .map(|c| IString(format!("{c}").into()).into()); + .map(|c| IString(format!("{c}").into()).into()) + .map(Ok); callback(&mut iter) } } @@ -167,14 +169,16 @@ pub struct LineIterator { impl IterableObject for LineIterator { fn iterate( &self, - callback: impl FnOnce(&mut dyn Iterator) -> ExecutionResult, + _context: &ExecutionContext, + callback: impl FnOnce(&mut dyn Iterator>) -> ExecutionResult, ) -> ExecutionResult { let mut iterator = self .string .0 .lines() .filter(|line| self.include_empty || !line.is_empty()) - .map(|line| IString(line).into()); + .map(|line| IString(line).into()) + .map(Ok); callback(&mut iterator) } diff --git a/interpreter/src/execution/values/value_type.rs b/interpreter/src/execution/values/value_type.rs index 6536b11..1e8e094 100644 --- a/interpreter/src/execution/values/value_type.rs +++ b/interpreter/src/execution/values/value_type.rs @@ -65,6 +65,9 @@ pub enum ValueType { Iterator, Transform2d, Transform3d, + LineString, + Polygon, + PolygonSet, } impl From for ValueType { @@ -101,6 +104,9 @@ impl ValueType { Self::Iterator => "Iterator".into(), Self::Transform2d => "Transform2d".into(), Self::Transform3d => "Transform3d".into(), + Self::LineString => "LineString".into(), + Self::Polygon => "Polygon".into(), + Self::PolygonSet => "PolygonSet".into(), _ => format!("{}", self).into(), } } @@ -808,7 +814,6 @@ mod test { let error = structure .check_other_qualifies(&dictionary.get_type(context)) .unwrap_err(); - dbg!(&error); assert_eq!( error, TypeQualificationError::Fields { @@ -908,6 +913,60 @@ mod test { ); } + #[test] + fn type_linestring() { + ValueType::LineString + .check_other_qualifies(&ValueType::LineString) + .unwrap(); + + let error = ValueType::LineString + .check_other_qualifies(&ValueType::TypeNone) + .unwrap_err(); + assert_eq!( + error, + TypeQualificationError::This { + expected: ValueType::LineString, + got: ValueType::TypeNone + } + ); + } + + #[test] + fn type_polygon() { + ValueType::Polygon + .check_other_qualifies(&ValueType::Polygon) + .unwrap(); + + let error = ValueType::Polygon + .check_other_qualifies(&ValueType::TypeNone) + .unwrap_err(); + assert_eq!( + error, + TypeQualificationError::This { + expected: ValueType::Polygon, + got: ValueType::TypeNone + } + ); + } + + #[test] + fn type_polygon_set() { + ValueType::PolygonSet + .check_other_qualifies(&ValueType::PolygonSet) + .unwrap(); + + let error = ValueType::PolygonSet + .check_other_qualifies(&ValueType::TypeNone) + .unwrap_err(); + assert_eq!( + error, + TypeQualificationError::This { + expected: ValueType::PolygonSet, + got: ValueType::TypeNone + } + ); + } + #[test] fn combined_type() { let value_type = test_run("std.types.None | std.types.UInt").unwrap(); From b5e9946a214682f5ba1c96a985b400b3a02dff06 Mon Sep 17 00:00:00 2001 From: James Carl Date: Tue, 17 Mar 2026 23:31:58 -0400 Subject: [PATCH 07/71] Fix temp files possibly being on a different filesystem from the store --- interpreter/src/execution/store.rs | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/interpreter/src/execution/store.rs b/interpreter/src/execution/store.rs index 1d659dc..2b3cd53 100644 --- a/interpreter/src/execution/store.rs +++ b/interpreter/src/execution/store.rs @@ -31,12 +31,20 @@ use crate::{ #[derive(Debug)] pub struct Store { + /// Path to the store itself. path: PathBuf, + + /// Temporary directory within the store. + /// Is put into the parent directory of the store because it MUST live on the same filesystem + /// as the store itself, otherwise transferring files into the store may fail. + temp_dir: PathBuf, } impl Store { pub fn new(path: impl Into) -> Self { - Self { path: path.into() } + let path = path.into(); + let temp_dir = path.join("../temp"); + Self { path, temp_dir } } pub fn get_or_init_file( @@ -57,11 +65,12 @@ impl Store { if std::fs::exists(&store_path).map_err(|error| error.to_error(context))? { Ok(store_path) } else { - // TODO should we be creating these in the project directory to increase the chances of - // them being on the same filesystem as the store? + std::fs::create_dir_all(&self.temp_dir) + .map_err(|error| error.to_error(context))?; let mut asset = PendingAsset { store_path, - asset: NamedTempFile::new().map_err(|error| error.to_error(context))?, + asset: NamedTempFile::new_in(&self.temp_dir) + .map_err(|error| error.to_error(context))?, }; init(&mut asset.asset)?; @@ -100,11 +109,12 @@ impl Store { if std::fs::exists(&store_path).map_err(|error| error.to_error(context))? { Ok(store_path) } else { - // TODO should we be creating these in the project directory to increase the chances of - // them being on the same filesystem as the store? + std::fs::create_dir_all(&self.temp_dir) + .map_err(|error| error.to_error(context))?; let mut asset = PendingAsset { store_path, - asset: TempDir::new().map_err(|error| error.to_error(context))?, + asset: TempDir::new_in(&self.temp_dir) + .map_err(|error| error.to_error(context))?, }; init(&mut asset.asset)?; let temp_path = asset.asset.keep(); From be997b58501a81b8d64b8fe85a0fecca5fc7a570 Mon Sep 17 00:00:00 2001 From: James Carl Date: Thu, 19 Mar 2026 01:36:45 -0400 Subject: [PATCH 08/71] Fix stack overflow when printing std --- interpreter/src/execution/values/value_type.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/interpreter/src/execution/values/value_type.rs b/interpreter/src/execution/values/value_type.rs index 1e8e094..5111571 100644 --- a/interpreter/src/execution/values/value_type.rs +++ b/interpreter/src/execution/values/value_type.rs @@ -107,6 +107,7 @@ impl ValueType { Self::LineString => "LineString".into(), Self::Polygon => "Polygon".into(), Self::PolygonSet => "PolygonSet".into(), + Self::ValueType => "ValueType".into(), _ => format!("{}", self).into(), } } From ede9dfd31d92236f21cd87f9831de05c16b2fced Mon Sep 17 00:00:00 2001 From: James Carl Date: Tue, 17 Mar 2026 18:59:56 -0400 Subject: [PATCH 09/71] WIP Gui Viewer --- Cargo.lock | 3220 ++++++++++++++++- Cargo.toml | 7 +- cli/Cargo.toml | 2 +- cli/src/main.rs | 23 +- examples/modeling/export_stls.ccm | 6 + examples/modeling/mesh.ccm | 8 +- flake.nix | 14 +- gui/Cargo.toml | 13 + gui/src/main.rs | 328 ++ interpreter/Cargo.toml | 2 +- interpreter/src/execution/mod.rs | 28 +- .../src/execution/standard_environment.rs | 35 +- interpreter/src/execution/store.rs | 182 +- interpreter/src/execution/values/iterators.rs | 132 +- interpreter/src/execution/values/list.rs | 93 +- .../src/execution/values/manifold_mesh.rs | 5 +- interpreter/src/execution/values/mod.rs | 2 +- .../src/execution/values/value_type.rs | 7 + interpreter/src/lib.rs | 4 +- 19 files changed, 3807 insertions(+), 304 deletions(-) create mode 100644 examples/modeling/export_stls.ccm create mode 100644 gui/Cargo.toml create mode 100644 gui/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 722a40a..45753c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,131 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "ab_glyph" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01c0457472c38ea5bd1c3b5ada5e368271cb550be7a4ca4a0b4634e9913f6cc2" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" + +[[package]] +name = "accesskit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf203f9d3bd8f29f98833d1fbef628df18f759248a547e7e01cfbf63cda36a99" + +[[package]] +name = "accesskit_atspi_common" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "890d241cf51fc784f0ac5ac34dfc847421f8d39da6c7c91a0fcc987db62a8267" +dependencies = [ + "accesskit", + "accesskit_consumer", + "atspi-common", + "serde", + "thiserror 1.0.69", + "zvariant", +] + +[[package]] +name = "accesskit_consumer" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db81010a6895d8707f9072e6ce98070579b43b717193d2614014abd5cb17dd43" +dependencies = [ + "accesskit", + "hashbrown 0.15.5", +] + +[[package]] +name = "accesskit_macos" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0089e5c0ac0ca281e13ea374773898d9354cc28d15af9f0f7394d44a495b575" +dependencies = [ + "accesskit", + "accesskit_consumer", + "hashbrown 0.15.5", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "accesskit_unix" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301e55b39cfc15d9c48943ce5f572204a551646700d0e8efa424585f94fec528" +dependencies = [ + "accesskit", + "accesskit_atspi_common", + "async-channel", + "async-executor", + "async-task", + "atspi", + "futures-lite", + "futures-util", + "serde", + "zbus", +] + +[[package]] +name = "accesskit_windows" +version = "0.29.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2d63dd5041e49c363d83f5419a896ecb074d309c414036f616dc0b04faca971" +dependencies = [ + "accesskit", + "accesskit_consumer", + "hashbrown 0.15.5", + "static_assertions", + "windows 0.61.3", + "windows-core 0.61.2", +] + +[[package]] +name = "accesskit_winit" +version = "0.29.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8cfabe59d0eaca7412bfb1f70198dd31e3b0496fee7e15b066f9c36a1a140a0" +dependencies = [ + "accesskit", + "accesskit_macos", + "accesskit_unix", + "accesskit_windows", + "raw-window-handle", + "winit", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom 0.3.4", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.4" @@ -17,6 +142,33 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "android-activity" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" +dependencies = [ + "android-properties", + "bitflags 2.11.0", + "cc", + "cesu8", + "jni 0.21.1", + "jni-sys 0.3.0", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "num_enum", + "thiserror 1.0.69", +] + +[[package]] +name = "android-properties" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -98,10 +250,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0348a1c054491f4bfe6ab86a7b6ab1e44e45d899005de92f58b3df180b36ddaf" dependencies = [ "clipboard-win", + "image", "log", - "objc2", - "objc2-app-kit", - "objc2-foundation", + "objc2 0.6.3", + "objc2-app-kit 0.3.2", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation 0.3.2", "parking_lot", "percent-encoding", "windows-sys 0.60.2", @@ -119,6 +274,24 @@ dependencies = [ "yansi", ] +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "as-raw-xcb-connection" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" + [[package]] name = "as-slice" version = "0.1.5" @@ -131,6 +304,146 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "ash" +version = "0.38.0+1.3.281" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" +dependencies = [ + "libloading", +] + +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "pin-project-lite", + "slab", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix 1.1.3", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-lock" +version = "3.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-process" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix 1.1.3", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-signal" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix 1.1.3", + "signal-hook-registry", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "atomic-polyfill" version = "1.0.3" @@ -140,6 +453,62 @@ dependencies = [ "critical-section", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "atspi" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c83247582e7508838caf5f316c00791eee0e15c0bf743e6880585b867e16815c" +dependencies = [ + "atspi-common", + "atspi-connection", + "atspi-proxies", +] + +[[package]] +name = "atspi-common" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33dfc05e7cdf90988a197803bf24f5788f94f7c94a69efa95683e8ffe76cfdfb" +dependencies = [ + "enumflags2", + "serde", + "static_assertions", + "zbus", + "zbus-lockstep", + "zbus-lockstep-macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "atspi-connection" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4193d51303d8332304056ae0004714256b46b6635a5c556109b319c0d3784938" +dependencies = [ + "atspi-common", + "atspi-proxies", + "futures-lite", + "zbus", +] + +[[package]] +name = "atspi-proxies" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2eebcb9e7e76f26d0bcfd6f0295e1cd1e6f33bedbc5698a971db8dc43d7751c" +dependencies = [ + "atspi-common", + "serde", + "zbus", +] + [[package]] name = "autocfg" version = "1.5.0" @@ -152,6 +521,27 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.11.0" @@ -161,6 +551,12 @@ dependencies = [ "serde_core", ] +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + [[package]] name = "block-buffer" version = "0.10.4" @@ -170,6 +566,28 @@ dependencies = [ "generic-array 0.14.7", ] +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2 0.5.2", +] + +[[package]] +name = "blocking" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + [[package]] name = "boolmesh" version = "0.1.9" @@ -195,6 +613,20 @@ name = "bytemuck" version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "byteorder" @@ -202,6 +634,69 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + +[[package]] +name = "calloop" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" +dependencies = [ + "bitflags 2.11.0", + "log", + "polling", + "rustix 0.38.44", + "slab", + "thiserror 1.0.69", +] + +[[package]] +name = "calloop" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dbf9978365bac10f54d1d4b04f7ce4427e51f71d61f2fe15e3fed5166474df7" +dependencies = [ + "bitflags 2.11.0", + "polling", + "rustix 1.1.3", + "slab", + "tracing", +] + +[[package]] +name = "calloop-wayland-source" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" +dependencies = [ + "calloop 0.13.0", + "rustix 0.38.44", + "wayland-backend", + "wayland-client", +] + +[[package]] +name = "calloop-wayland-source" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138efcf0940a02ebf0cc8d1eff41a1682a46b431630f4c52450d6265876021fa" +dependencies = [ + "calloop 0.14.4", + "rustix 1.1.3", + "wayland-backend", + "wayland-client", +] + [[package]] name = "cc" version = "1.2.56" @@ -214,12 +709,33 @@ dependencies = [ "shlex", ] +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + [[package]] name = "cfg-if" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "cgl" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff" +dependencies = [ + "libc", +] + [[package]] name = "check_keyword" version = "0.4.1" @@ -238,7 +754,7 @@ dependencies = [ "iana-time-zone", "num-traits", "serde", - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -313,19 +829,49 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7f42f93baa58655bd5b3db91dd9b2073dc8a0c887dc35bd1cfefbd43fc7cf07" +[[package]] +name = "codespan-reporting" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" +dependencies = [ + "serde", + "termcolor", + "unicode-width 0.2.2", +] + [[package]] name = "colorchoice" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "common_data_types" version = "0.1.0" dependencies = [ - "ordered-float", - "paste", - "serde", + "ordered-float", + "paste", + "serde", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", ] [[package]] @@ -355,12 +901,67 @@ dependencies = [ "crossterm", ] +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "core-graphics" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +dependencies = [ + "bitflags 1.3.2", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation 0.9.4", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags 2.11.0", + "core-foundation 0.10.1", + "libc", +] + [[package]] name = "cpufeatures" version = "0.2.17" @@ -370,6 +971,15 @@ dependencies = [ "libc", ] +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + [[package]] name = "critical-section" version = "1.2.0" @@ -464,13 +1074,13 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" dependencies = [ - "bitflags", + "bitflags 2.11.0", "crossterm_winapi", "derive_more", "document-features", "mio", "parking_lot", - "rustix", + "rustix 1.1.3", "serde", "signal-hook", "signal-hook-mio", @@ -486,6 +1096,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + [[package]] name = "crypto-common" version = "0.1.7" @@ -517,6 +1133,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "cursor-icon" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" + [[package]] name = "derive_more" version = "2.1.1" @@ -555,14 +1177,20 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + [[package]] name = "dispatch2" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" dependencies = [ - "bitflags", - "objc2", + "bitflags 2.11.0", + "objc2 0.6.3", ] [[package]] @@ -576,6 +1204,15 @@ dependencies = [ "syn", ] +[[package]] +name = "dlib" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a" +dependencies = [ + "libloading", +] + [[package]] name = "document-features" version = "0.2.12" @@ -591,6 +1228,12 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" +[[package]] +name = "dpi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" + [[package]] name = "dunce" version = "1.0.5" @@ -607,12 +1250,152 @@ dependencies = [ "num-traits", ] +[[package]] +name = "ecolor" +version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71ddb8ac7643d1dba1bb02110e804406dd459a838efcb14011ced10556711a8e" +dependencies = [ + "bytemuck", + "emath", +] + +[[package]] +name = "eframe" +version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "457481173e6db5ca9fa2be93a58df8f4c7be639587aeb4853b526c6cf87db4e6" +dependencies = [ + "ahash", + "bytemuck", + "document-features", + "egui", + "egui-wgpu", + "egui-winit", + "egui_glow", + "glow", + "glutin", + "glutin-winit", + "image", + "js-sys", + "log", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", + "parking_lot", + "percent-encoding", + "pollster", + "profiling", + "raw-window-handle", + "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "web-time", + "wgpu", + "windows-sys 0.61.2", + "winit", +] + +[[package]] +name = "egui" +version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a9b567d356674e9a5121ed3fedfb0a7c31e059fe71f6972b691bcd0bfc284e3" +dependencies = [ + "accesskit", + "ahash", + "bitflags 2.11.0", + "emath", + "epaint", + "log", + "nohash-hasher", + "profiling", + "smallvec", + "unicode-segmentation", +] + +[[package]] +name = "egui-wgpu" +version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e4d209971c84b2352a06174abdba701af1e552ce56b144d96f2bd50a3c91236" +dependencies = [ + "ahash", + "bytemuck", + "document-features", + "egui", + "epaint", + "log", + "profiling", + "thiserror 2.0.18", + "type-map", + "web-time", + "wgpu", + "winit", +] + +[[package]] +name = "egui-winit" +version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec6687e5bb551702f4ad10ac428bab12acf9d53047ebb1082d4a0ed8c6251a29" +dependencies = [ + "accesskit_winit", + "arboard", + "bytemuck", + "egui", + "log", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-ui-kit", + "profiling", + "raw-window-handle", + "smithay-clipboard", + "web-time", + "webbrowser", + "winit", +] + +[[package]] +name = "egui_glow" +version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6420863ea1d90e750f75075231a260030ad8a9f30a7cef82cdc966492dc4c4eb" +dependencies = [ + "bytemuck", + "egui", + "glow", + "log", + "memoffset", + "profiling", + "wasm-bindgen", + "web-sys", + "winit", +] + [[package]] name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "emath" +version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "491bdf728bf25ddd9ad60d4cf1c48588fa82c013a2440b91aa7fc43e34a07c32" +dependencies = [ + "bytemuck", + "mint", +] + +[[package]] +name = "endi" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" + [[package]] name = "enum-map" version = "3.0.0-beta.2" @@ -665,6 +1448,51 @@ dependencies = [ "syn", ] +[[package]] +name = "enumflags2" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "epaint" +version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "009d0dd3c2163823a0abdb899451ecbc78798dec545ee91b43aff1fa790bab62" +dependencies = [ + "ab_glyph", + "ahash", + "bytemuck", + "ecolor", + "emath", + "epaint_default_fonts", + "log", + "nohash-hasher", + "parking_lot", + "profiling", +] + +[[package]] +name = "epaint_default_fonts" +version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c4fbe202b6578d3d56428fa185cdf114a05e49da05f477b3c7f0fbb221f1862" + [[package]] name = "equivalent" version = "1.0.2" @@ -687,12 +1515,53 @@ version = "3.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" +[[package]] +name = "event-listener" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + [[package]] name = "fastrand" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "fax" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05de7d48f37cd6730705cbca900770cab77a89f413d23e100ad7fad7795a0ab" +dependencies = [ + "fax_derive", +] + +[[package]] +name = "fax_derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "fd-lock" version = "4.0.4" @@ -700,10 +1569,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" dependencies = [ "cfg-if", - "rustix", + "rustix 1.1.3", "windows-sys 0.59.0", ] +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + [[package]] name = "file-guard" version = "0.2.0" @@ -726,6 +1604,16 @@ version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "float-cmp" version = "0.10.0" @@ -748,18 +1636,115 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] -name = "foldhash" -version = "0.1.5" +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-task" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] -name = "form_urlencoded" -version = "1.2.2" +name = "futures-util" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ - "percent-encoding", + "futures-core", + "futures-macro", + "futures-task", + "pin-project-lite", + "slab", ] [[package]] @@ -852,8 +1837,8 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" dependencies = [ - "rustix", - "windows-link", + "rustix 1.1.3", + "windows-link 0.2.1", ] [[package]] @@ -898,7 +1883,7 @@ version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b88256088d75a56f8ecfa070513a775dd9107f6530ef14919dac831af9cfe2b" dependencies = [ - "bitflags", + "bitflags 2.11.0", "libc", "libgit2-sys", "log", @@ -907,6 +1892,17 @@ dependencies = [ "url", ] +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api", + "log", + "xml-rs", +] + [[package]] name = "glam" version = "0.14.0" @@ -1003,6 +1999,160 @@ version = "0.30.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19fc433e8437a212d1b6f1e68c7824af3aed907da60afa994e7f542d18d12aa9" +[[package]] +name = "glow" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e5ea60d70410161c8bf5da3fdfeaa1c72ed2c15f8bbb9d19fe3a4fad085f08" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "glutin" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12124de845cacfebedff80e877bb37b5b75c34c5a4c89e47e1cdd67fb6041325" +dependencies = [ + "bitflags 2.11.0", + "cfg_aliases", + "cgl", + "dispatch2", + "glutin_egl_sys", + "glutin_glx_sys", + "glutin_wgl_sys", + "libloading", + "objc2 0.6.3", + "objc2-app-kit 0.3.2", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "once_cell", + "raw-window-handle", + "wayland-sys", + "windows-sys 0.52.0", + "x11-dl", +] + +[[package]] +name = "glutin-winit" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85edca7075f8fc728f28cb8fbb111a96c3b89e930574369e3e9c27eb75d3788f" +dependencies = [ + "cfg_aliases", + "glutin", + "raw-window-handle", + "winit", +] + +[[package]] +name = "glutin_egl_sys" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c4680ba6195f424febdc3ba46e7a42a0e58743f2edb115297b86d7f8ecc02d2" +dependencies = [ + "gl_generator", + "windows-sys 0.52.0", +] + +[[package]] +name = "glutin_glx_sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7bb2938045a88b612499fbcba375a77198e01306f52272e692f8c1f3751185" +dependencies = [ + "gl_generator", + "x11-dl", +] + +[[package]] +name = "glutin_wgl_sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "gpu-alloc" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" +dependencies = [ + "bitflags 2.11.0", + "gpu-alloc-types", +] + +[[package]] +name = "gpu-alloc-types" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" +dependencies = [ + "bitflags 2.11.0", +] + +[[package]] +name = "gpu-allocator" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c151a2a5ef800297b4e79efa4f4bec035c5f51d5ae587287c9b952bdf734cacd" +dependencies = [ + "log", + "presser", + "thiserror 1.0.69", + "windows 0.58.0", +] + +[[package]] +name = "gpu-descriptor" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" +dependencies = [ + "bitflags 2.11.0", + "gpu-descriptor-types", + "hashbrown 0.15.5", +] + +[[package]] +name = "gpu-descriptor-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" +dependencies = [ + "bitflags 2.11.0", +] + +[[package]] +name = "gui" +version = "0.1.0" +dependencies = [ + "anyhow", + "eframe", + "egui", + "interpreter", + "notify", + "oneshot", + "tempfile", +] + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "num-traits", + "zerocopy", +] + [[package]] name = "hash32" version = "0.1.1" @@ -1047,7 +2197,7 @@ checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "allocator-api2", "equivalent", - "foldhash", + "foldhash 0.1.5", ] [[package]] @@ -1055,6 +2205,9 @@ name = "hashbrown" version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "foldhash 0.2.0", +] [[package]] name = "heapless" @@ -1097,12 +2250,24 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hexf-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" + [[package]] name = "i_float" version = "1.15.0" @@ -1158,7 +2323,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core", + "windows-core 0.62.2", ] [[package]] @@ -1278,6 +2443,20 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "image" +version = "0.25.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" +dependencies = [ + "bytemuck", + "byteorder-lite", + "moxcms", + "num-traits", + "png", + "tiff", +] + [[package]] name = "imstr" version = "0.2.0" @@ -1296,6 +2475,26 @@ dependencies = [ "serde_core", ] +[[package]] +name = "inotify" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd5b3eaf1a28b758ac0faa5a4254e8ab2705605496f1b1f3fbbc3988ad73d199" +dependencies = [ + "bitflags 2.11.0", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + [[package]] name = "interpreter" version = "0.1.0" @@ -1381,6 +2580,77 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys 0.3.0", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys 0.4.1", + "log", + "simd_cesu8", + "thiserror 2.0.18", + "walkdir", + "windows-link 0.2.1", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn", +] + [[package]] name = "jobserver" version = "0.1.34" @@ -1407,6 +2677,43 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "khronos-egl" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" +dependencies = [ + "libc", + "libloading", + "pkg-config", +] + +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + +[[package]] +name = "kqueue" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac30106d7dce88daf4a3fcb4879ea939476d5074a9b7ddd0fb97fa4bed5596a" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +dependencies = [ + "bitflags 1.3.2", + "libc", +] + [[package]] name = "lazy-regex" version = "3.6.0" @@ -1475,7 +2782,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -1484,6 +2791,18 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" +[[package]] +name = "libredox" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a" +dependencies = [ + "bitflags 2.11.0", + "libc", + "plain", + "redox_syscall 0.7.3", +] + [[package]] name = "libssh2-sys" version = "0.3.1" @@ -1510,6 +2829,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + [[package]] name = "linux-raw-sys" version = "0.11.0" @@ -1577,6 +2902,15 @@ dependencies = [ "logos-codegen", ] +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + [[package]] name = "matrixmultiply" version = "0.3.10" @@ -1593,15 +2927,64 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +[[package]] +name = "memmap2" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "metal" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00c15a6f673ff72ddcc22394663290f870fb224c1bfce55734a75c414150e605" +dependencies = [ + "bitflags 2.11.0", + "block", + "core-graphics-types 0.2.0", + "foreign-types", + "log", + "objc", + "paste", +] + [[package]] name = "minimad" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df8b688969b16915f3ecadc7829d5b7779dee4977e503f767f34136803d5c06f" +checksum = "df8b688969b16915f3ecadc7829d5b7779dee4977e503f767f34136803d5c06f" +dependencies = [ + "once_cell", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ - "once_cell", + "adler2", + "simd-adler32", ] +[[package]] +name = "mint" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff" + [[package]] name = "mio" version = "1.1.1" @@ -1614,6 +2997,42 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "moxcms" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" +dependencies = [ + "num-traits", + "pxfm", +] + +[[package]] +name = "naga" +version = "27.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "066cf25f0e8b11ee0df221219010f213ad429855f57c494f995590c861a9a7d8" +dependencies = [ + "arrayvec", + "bit-set", + "bitflags 2.11.0", + "cfg-if", + "cfg_aliases", + "codespan-reporting", + "half", + "hashbrown 0.16.1", + "hexf-parse", + "indexmap", + "libm", + "log", + "num-traits", + "once_cell", + "rustc-hash 1.1.0", + "spirv", + "thiserror 2.0.18", + "unicode-ident", +] + [[package]] name = "nalgebra" version = "0.34.1" @@ -1658,6 +3077,42 @@ dependencies = [ "syn", ] +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.11.0", + "jni-sys 0.3.0", + "log", + "ndk-sys", + "num_enum", + "raw-window-handle", + "thiserror 1.0.69", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys 0.3.0", +] + +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + [[package]] name = "nom" version = "8.0.0" @@ -1667,6 +3122,33 @@ dependencies = [ "memchr", ] +[[package]] +name = "notify" +version = "8.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3" +dependencies = [ + "bitflags 2.11.0", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "log", + "mio", + "notify-types", + "walkdir", + "windows-sys 0.60.2", +] + +[[package]] +name = "notify-types" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a" +dependencies = [ + "bitflags 2.11.0", +] + [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -1726,6 +3208,53 @@ dependencies = [ "libm", ] +[[package]] +name = "num_enum" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + [[package]] name = "objc2" version = "0.6.3" @@ -1735,16 +3264,69 @@ dependencies = [ "objc2-encode", ] +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.11.0", + "block2", + "libc", + "objc2 0.5.2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation 0.2.2", + "objc2-quartz-core", +] + [[package]] name = "objc2-app-kit" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ - "bitflags", - "objc2", + "bitflags 2.11.0", + "objc2 0.6.3", + "objc2-core-foundation", "objc2-core-graphics", - "objc2-foundation", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.11.0", + "block2", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.11.0", + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", ] [[package]] @@ -1753,9 +3335,9 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags", + "bitflags 2.11.0", "dispatch2", - "objc2", + "objc2 0.6.3", ] [[package]] @@ -1764,27 +3346,64 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ - "bitflags", + "bitflags 2.11.0", "dispatch2", - "objc2", + "objc2 0.6.3", "objc2-core-foundation", "objc2-io-surface", ] +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal", +] + +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-contacts", + "objc2-foundation 0.2.2", +] + [[package]] name = "objc2-encode" version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.11.0", + "block2", + "dispatch", + "libc", + "objc2 0.5.2", +] + [[package]] name = "objc2-foundation" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags", - "objc2", + "bitflags 2.11.0", + "objc2 0.6.3", "objc2-core-foundation", ] @@ -1794,11 +3413,103 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ - "bitflags", - "objc2", + "bitflags 2.11.0", + "objc2 0.6.3", "objc2-core-foundation", ] +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.11.0", + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.11.0", + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal", +] + +[[package]] +name = "objc2-symbols" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" +dependencies = [ + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" +dependencies = [ + "bitflags 2.11.0", + "block2", + "objc2 0.5.2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-image", + "objc2-core-location", + "objc2-foundation 0.2.2", + "objc2-link-presentation", + "objc2-quartz-core", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-uniform-type-identifiers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.11.0", + "block2", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + [[package]] name = "once_cell" version = "1.21.3" @@ -1811,6 +3522,12 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" +[[package]] +name = "oneshot" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe21416a02c693fb9f980befcb230ecc70b0b3d1cc4abf88b9675c4c1457f0c" + [[package]] name = "openssl-probe" version = "0.1.6" @@ -1829,6 +3546,16 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "orbclient" +version = "0.3.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59aed3b33578edcfa1bc96a321d590d31832b6ad55a26f0313362ce687e9abd6" +dependencies = [ + "libc", + "libredox", +] + [[package]] name = "ordered-float" version = "4.6.0" @@ -1838,6 +3565,16 @@ dependencies = [ "num-traits", ] +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + [[package]] name = "os_pipe" version = "1.2.3" @@ -1848,6 +3585,21 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "owned_ttf_parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36820e9051aca1014ddc75770aab4d68bc1e9e632f0f5627c4086bc216fb583b" +dependencies = [ + "ttf-parser", +] + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + [[package]] name = "parking_lot" version = "0.12.5" @@ -1866,9 +3618,9 @@ checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.18", "smallvec", - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -1942,11 +3694,102 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pin-project" +version = "1.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "piper" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + [[package]] name = "pkg-config" version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + +[[package]] +name = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" +dependencies = [ + "bitflags 2.11.0", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix 1.1.3", + "windows-sys 0.61.2", +] + +[[package]] +name = "pollster" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" + +[[package]] +name = "portable-atomic" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" + +[[package]] +name = "portable-atomic-util" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3" +dependencies = [ + "portable-atomic", +] [[package]] name = "potential_utf" @@ -1966,6 +3809,12 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "presser" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" + [[package]] name = "pretty_assertions" version = "1.4.1" @@ -1986,6 +3835,15 @@ dependencies = [ "syn", ] +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit", +] + [[package]] name = "proc-macro2" version = "1.0.106" @@ -1995,6 +3853,18 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "profiling" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" + +[[package]] +name = "pxfm" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a041e753da8b807c9255f28de81879c78c876392ff2469cde94799b2896b9d" + [[package]] name = "quasiquote" version = "0.1.1" @@ -2017,6 +3887,12 @@ dependencies = [ "quote", ] +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + [[package]] name = "quick-xml" version = "0.38.4" @@ -2024,6 +3900,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c" dependencies = [ "memchr", + "serde", ] [[package]] @@ -2071,6 +3948,18 @@ dependencies = [ "getrandom 0.2.17", ] +[[package]] +name = "range-alloc" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca45419789ae5a7899559e9512e58ca889e41f04f1f2445e9f4b290ceccd1d08" + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + [[package]] name = "rawpointer" version = "0.2.1" @@ -2097,13 +3986,31 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "redox_syscall" version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags", + "bitflags 2.11.0", +] + +[[package]] +name = "redox_syscall" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" +dependencies = [ + "bitflags 2.11.0", ] [[package]] @@ -2157,6 +4064,12 @@ version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" +[[package]] +name = "renderdoc-sys" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" + [[package]] name = "robust" version = "1.2.0" @@ -2224,6 +4137,18 @@ dependencies = [ "smallvec", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + [[package]] name = "rustc-stable-hash" version = "0.1.2" @@ -2239,16 +4164,29 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.11.0", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + [[package]] name = "rustix" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" dependencies = [ - "bitflags", + "bitflags 2.11.0", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.11.0", "windows-sys 0.61.2", ] @@ -2282,12 +4220,31 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sctk-adwaita" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" +dependencies = [ + "ab_glyph", + "log", + "memmap2", + "smithay-client-toolkit 0.19.2", + "tiny-skia", +] + [[package]] name = "selen" version = "0.15.5" @@ -2344,6 +4301,17 @@ dependencies = [ "zmij", ] +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "sha2" version = "0.10.9" @@ -2411,24 +4379,133 @@ dependencies = [ "wide", ] +[[package]] +name = "simd-adler32" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" + +[[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "siphasher" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + [[package]] name = "slice-group-by" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" +[[package]] +name = "slotmap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" +dependencies = [ + "version_check", +] + [[package]] name = "smallvec" version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +[[package]] +name = "smithay-client-toolkit" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" +dependencies = [ + "bitflags 2.11.0", + "calloop 0.13.0", + "calloop-wayland-source 0.3.0", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix 0.38.44", + "thiserror 1.0.69", + "wayland-backend", + "wayland-client", + "wayland-csd-frame", + "wayland-cursor", + "wayland-protocols", + "wayland-protocols-wlr", + "wayland-scanner", + "xkeysym", +] + +[[package]] +name = "smithay-client-toolkit" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0512da38f5e2b31201a93524adb8d3136276fa4fe4aafab4e1f727a82b534cc0" +dependencies = [ + "bitflags 2.11.0", + "calloop 0.14.4", + "calloop-wayland-source 0.4.1", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix 1.1.3", + "thiserror 2.0.18", + "wayland-backend", + "wayland-client", + "wayland-csd-frame", + "wayland-cursor", + "wayland-protocols", + "wayland-protocols-experimental", + "wayland-protocols-misc", + "wayland-protocols-wlr", + "wayland-scanner", + "xkeysym", +] + +[[package]] +name = "smithay-clipboard" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71704c03f739f7745053bde45fa203a46c58d25bc5c4efba1d9a60e9dba81226" +dependencies = [ + "libc", + "smithay-client-toolkit 0.20.0", + "wayland-backend", +] + +[[package]] +name = "smol_str" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" +dependencies = [ + "serde", +] + [[package]] name = "spade" version = "2.15.0" @@ -2450,6 +4527,15 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spirv" +version = "0.3.0+sdk-1.3.268.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" +dependencies = [ + "bitflags 2.11.0", +] + [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -2465,6 +4551,12 @@ dependencies = [ "coalesce", ] +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "stl_io" version = "0.10.0" @@ -2487,6 +4579,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f42444fea5b87a39db4218d9422087e66a85d0e7a0963a439b07bcdf91804006" +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" + [[package]] name = "strip-ansi-escapes" version = "0.2.1" @@ -2544,68 +4642,179 @@ dependencies = [ ] [[package]] -name = "tempfile" -version = "3.25.0" +name = "tempfile" +version = "3.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1" +dependencies = [ + "fastrand", + "getrandom 0.4.1", + "once_cell", + "rustix 1.1.3", + "windows-sys 0.61.2", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "termimad" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "889a9370996b74cf46016ce35b96c248a9ac36d69aab1d112b3e09bc33affa49" +dependencies = [ + "coolor", + "crokey", + "crossbeam", + "lazy-regex", + "minimad", + "serde", + "thiserror 2.0.18", + "unicode-width 0.1.14", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tiff" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63feaf3343d35b6ca4d50483f94843803b0f51634937cc2ec519fc32232bc52" +dependencies = [ + "fax", + "flate2", + "half", + "quick-error", + "weezl", + "zune-jpeg", +] + +[[package]] +name = "tiny-skia" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "log", + "tiny-skia-path", +] + +[[package]] +name = "tiny-skia-path" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] + +[[package]] +name = "tinystr" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ - "fastrand", - "getrandom 0.4.1", - "once_cell", - "rustix", - "windows-sys 0.61.2", + "displaydoc", + "zerovec", ] [[package]] -name = "termimad" -version = "0.34.1" +name = "toml_datetime" +version = "1.0.0+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "889a9370996b74cf46016ce35b96c248a9ac36d69aab1d112b3e09bc33affa49" +checksum = "32c2555c699578a4f59f0cc68e5116c8d7cabbd45e1409b989d4be085b53f13e" dependencies = [ - "coolor", - "crokey", - "crossbeam", - "lazy-regex", - "minimad", - "serde", - "thiserror 2.0.18", - "unicode-width 0.1.14", + "serde_core", ] [[package]] -name = "thiserror" -version = "1.0.69" +name = "toml_edit" +version = "0.25.4+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +checksum = "7193cbd0ce53dc966037f54351dbbcf0d5a642c7f0038c382ef9e677ce8c13f2" dependencies = [ - "thiserror-impl 1.0.69", + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", ] [[package]] -name = "thiserror" -version = "2.0.18" +name = "toml_parser" +version = "1.0.9+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4" dependencies = [ - "thiserror-impl 2.0.18", + "winnow", ] [[package]] -name = "thiserror-impl" -version = "1.0.69" +name = "tracing" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ - "proc-macro2", - "quote", - "syn", + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", ] [[package]] -name = "thiserror-impl" -version = "2.0.18" +name = "tracing-attributes" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", @@ -2613,13 +4822,12 @@ dependencies = [ ] [[package]] -name = "tinystr" -version = "0.8.2" +name = "tracing-core" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ - "displaydoc", - "zerovec", + "once_cell", ] [[package]] @@ -2661,6 +4869,21 @@ dependencies = [ "petgraph", ] +[[package]] +name = "ttf-parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" + +[[package]] +name = "type-map" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb30dbbd9036155e74adad6812e9898d03ec374946234fbcebd5dfc7b9187b90" +dependencies = [ + "rustc-hash 2.1.1", +] + [[package]] name = "type-sitter" version = "0.8.1" @@ -2725,6 +4948,17 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +[[package]] +name = "uds_windows" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" +dependencies = [ + "memoffset", + "tempfile", + "windows-sys 0.61.2", +] + [[package]] name = "uneval" version = "0.2.4" @@ -2826,6 +5060,17 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "uuid" +version = "1.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a68d3c8f01c0cfa54a75291d83601161799e4a89a39e0929f4b0354d88757a37" +dependencies = [ + "js-sys", + "serde_core", + "wasm-bindgen", +] + [[package]] name = "vcpkg" version = "0.2.15" @@ -2894,6 +5139,20 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a42e96ea38f49b191e08a1bab66c7ffdba24b06f9995b39a9dd60222e5b6f1da" +dependencies = [ + "cfg-if", + "futures-util", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.110" @@ -2954,7 +5213,7 @@ version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ - "bitflags", + "bitflags 2.11.0", "hashbrown 0.15.5", "indexmap", "semver", @@ -2968,7 +5227,8 @@ checksum = "fee64194ccd96bf648f42a65a7e589547096dfa702f7cadef84347b66ad164f9" dependencies = [ "cc", "downcast-rs", - "rustix", + "rustix 1.1.3", + "scoped-tls", "smallvec", "wayland-sys", ] @@ -2979,21 +5239,82 @@ version = "0.31.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8e6faa537fbb6c186cb9f1d41f2f811a4120d1b57ec61f50da451a0c5122bec" dependencies = [ - "bitflags", - "rustix", + "bitflags 2.11.0", + "rustix 1.1.3", "wayland-backend", "wayland-scanner", ] +[[package]] +name = "wayland-csd-frame" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" +dependencies = [ + "bitflags 2.11.0", + "cursor-icon", + "wayland-backend", +] + +[[package]] +name = "wayland-cursor" +version = "0.31.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5864c4b5b6064b06b1e8b74ead4a98a6c45a285fe7a0e784d24735f011fdb078" +dependencies = [ + "rustix 1.1.3", + "wayland-client", + "xcursor", +] + [[package]] name = "wayland-protocols" version = "0.32.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baeda9ffbcfc8cd6ddaade385eaf2393bd2115a69523c735f12242353c3df4f3" dependencies = [ - "bitflags", + "bitflags 2.11.0", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-experimental" +version = "20250721.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40a1f863128dcaaec790d7b4b396cc9b9a7a079e878e18c47e6c2d2c5a8dcbb1" +dependencies = [ + "bitflags 2.11.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-misc" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791c58fdeec5406aa37169dd815327d1e47f334219b523444bc26d70ceb4c34e" +dependencies = [ + "bitflags 2.11.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-plasma" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa98634619300a535a9a97f338aed9a5ff1e01a461943e8346ff4ae26007306b" +dependencies = [ + "bitflags 2.11.0", "wayland-backend", "wayland-client", + "wayland-protocols", "wayland-scanner", ] @@ -3003,7 +5324,7 @@ version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9597cdf02cf0c34cd5823786dce6b5ae8598f05c2daf5621b6e178d4f7345f3" dependencies = [ - "bitflags", + "bitflags 2.11.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -3027,9 +5348,205 @@ version = "0.31.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e6dbfc3ac5ef974c92a2235805cc0114033018ae1290a72e474aa8b28cbbdfd" dependencies = [ + "dlib", + "log", + "once_cell", "pkg-config", ] +[[package]] +name = "web-sys" +version = "0.3.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2c7c5718134e770ee62af3b6b4a84518ec10101aad610c024b64d6ff29bb1ff" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webbrowser" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe985f41e291eecef5e5c0770a18d28390addb03331c043964d9e916453d6f16" +dependencies = [ + "core-foundation 0.10.1", + "jni 0.22.4", + "log", + "ndk-context", + "objc2 0.6.3", + "objc2-foundation 0.3.2", + "url", + "web-sys", +] + +[[package]] +name = "weezl" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" + +[[package]] +name = "wgpu" +version = "27.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfe68bac7cde125de7a731c3400723cadaaf1703795ad3f4805f187459cd7a77" +dependencies = [ + "arrayvec", + "bitflags 2.11.0", + "cfg-if", + "cfg_aliases", + "document-features", + "hashbrown 0.16.1", + "js-sys", + "log", + "naga", + "parking_lot", + "portable-atomic", + "profiling", + "raw-window-handle", + "smallvec", + "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "wgpu-core", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-core" +version = "27.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27a75de515543b1897b26119f93731b385a19aea165a1ec5f0e3acecc229cae7" +dependencies = [ + "arrayvec", + "bit-set", + "bit-vec", + "bitflags 2.11.0", + "bytemuck", + "cfg_aliases", + "document-features", + "hashbrown 0.16.1", + "indexmap", + "log", + "naga", + "once_cell", + "parking_lot", + "portable-atomic", + "profiling", + "raw-window-handle", + "rustc-hash 1.1.0", + "smallvec", + "thiserror 2.0.18", + "wgpu-core-deps-apple", + "wgpu-core-deps-emscripten", + "wgpu-core-deps-windows-linux-android", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-core-deps-apple" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0772ae958e9be0c729561d5e3fd9a19679bcdfb945b8b1a1969d9bfe8056d233" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-emscripten" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b06ac3444a95b0813ecfd81ddb2774b66220b264b3e2031152a4a29fda4da6b5" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-windows-linux-android" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71197027d61a71748e4120f05a9242b2ad142e3c01f8c1b47707945a879a03c3" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-hal" +version = "27.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b21cb61c57ee198bc4aff71aeadff4cbb80b927beb912506af9c780d64313ce" +dependencies = [ + "android_system_properties", + "arrayvec", + "ash", + "bit-set", + "bitflags 2.11.0", + "block", + "bytemuck", + "cfg-if", + "cfg_aliases", + "core-graphics-types 0.2.0", + "glow", + "glutin_wgl_sys", + "gpu-alloc", + "gpu-allocator", + "gpu-descriptor", + "hashbrown 0.16.1", + "js-sys", + "khronos-egl", + "libc", + "libloading", + "log", + "metal", + "naga", + "ndk-sys", + "objc", + "once_cell", + "ordered-float", + "parking_lot", + "portable-atomic", + "portable-atomic-util", + "profiling", + "range-alloc", + "raw-window-handle", + "renderdoc-sys", + "smallvec", + "thiserror 2.0.18", + "wasm-bindgen", + "web-sys", + "wgpu-types", + "windows 0.58.0", + "windows-core 0.58.0", +] + +[[package]] +name = "wgpu-types" +version = "27.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afdcf84c395990db737f2dd91628706cb31e86d72e53482320d368e52b5da5eb" +dependencies = [ + "bitflags 2.11.0", + "bytemuck", + "js-sys", + "log", + "thiserror 2.0.18", + "web-sys", +] + [[package]] name = "wide" version = "0.7.33" @@ -3060,16 +5577,74 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" name = "winapi-util" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core 0.58.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.61.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +dependencies = [ + "windows-collections", + "windows-core 0.61.2", + "windows-future", + "windows-link 0.1.3", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core 0.61.2", +] + +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" dependencies = [ - "windows-sys 0.61.2", + "windows-implement 0.58.0", + "windows-interface 0.58.0", + "windows-result 0.2.0", + "windows-strings 0.1.0", + "windows-targets 0.52.6", ] [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "windows-core" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement 0.60.2", + "windows-interface 0.59.3", + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] [[package]] name = "windows-core" @@ -3077,11 +5652,33 @@ version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ - "windows-implement", - "windows-interface", - "windows-link", - "windows-result", - "windows-strings", + "windows-implement 0.60.2", + "windows-interface 0.59.3", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -3095,6 +5692,17 @@ dependencies = [ "syn", ] +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "windows-interface" version = "0.59.3" @@ -3106,19 +5714,72 @@ dependencies = [ "syn", ] +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", +] + [[package]] name = "windows-result" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link", + "windows-link 0.2.1", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result 0.2.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", ] [[package]] @@ -3127,7 +5788,25 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-link", + "windows-link 0.2.1", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -3154,7 +5833,22 @@ version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link", + "windows-link 0.2.1", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", ] [[package]] @@ -3179,7 +5873,7 @@ version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link", + "windows-link 0.2.1", "windows_aarch64_gnullvm 0.53.1", "windows_aarch64_msvc 0.53.1", "windows_i686_gnu 0.53.1", @@ -3190,6 +5884,21 @@ dependencies = [ "windows_x86_64_msvc 0.53.1", ] +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -3202,6 +5911,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -3214,6 +5929,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -3238,6 +5959,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -3250,6 +5977,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -3262,6 +5995,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -3274,6 +6013,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -3286,6 +6031,67 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" +[[package]] +name = "winit" +version = "0.30.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6755fa58a9f8350bd1e472d4c3fcc25f824ec358933bba33306d0b63df5978d" +dependencies = [ + "ahash", + "android-activity", + "atomic-waker", + "bitflags 2.11.0", + "block2", + "bytemuck", + "calloop 0.13.0", + "cfg_aliases", + "concurrent-queue", + "core-foundation 0.9.4", + "core-graphics", + "cursor-icon", + "dpi", + "js-sys", + "libc", + "memmap2", + "ndk", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", + "objc2-ui-kit", + "orbclient", + "percent-encoding", + "pin-project", + "raw-window-handle", + "redox_syscall 0.4.1", + "rustix 0.38.44", + "sctk-adwaita", + "smithay-client-toolkit 0.19.2", + "smol_str", + "tracing", + "unicode-segmentation", + "wasm-bindgen", + "wasm-bindgen-futures", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-protocols-plasma", + "web-sys", + "web-time", + "windows-sys 0.52.0", + "x11-dl", + "x11rb", + "xkbcommon-dl", +] + +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] + [[package]] name = "wit-bindgen" version = "0.51.0" @@ -3344,7 +6150,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", - "bitflags", + "bitflags 2.11.0", "indexmap", "log", "serde", @@ -3383,7 +6189,7 @@ dependencies = [ "libc", "log", "os_pipe", - "rustix", + "rustix 1.1.3", "thiserror 2.0.18", "tree_magic_mini", "wayland-backend", @@ -3398,14 +6204,29 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" +[[package]] +name = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + [[package]] name = "x11rb" version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" dependencies = [ + "as-raw-xcb-connection", "gethostname", - "rustix", + "libc", + "libloading", + "once_cell", + "rustix 1.1.3", "x11rb-protocol", ] @@ -3415,6 +6236,37 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" +[[package]] +name = "xcursor" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" + +[[package]] +name = "xkbcommon-dl" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" +dependencies = [ + "bitflags 2.11.0", + "dlib", + "log", + "once_cell", + "xkeysym", +] + +[[package]] +name = "xkeysym" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" + +[[package]] +name = "xml-rs" +version = "0.8.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" + [[package]] name = "yansi" version = "1.0.1" @@ -3444,6 +6296,103 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zbus" +version = "5.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca82f95dbd3943a40a53cfded6c2d0a2ca26192011846a1810c4256ef92c60bc" +dependencies = [ + "async-broadcast", + "async-executor", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "enumflags2", + "event-listener", + "futures-core", + "futures-lite", + "hex", + "libc", + "ordered-stream", + "rustix 1.1.3", + "serde", + "serde_repr", + "tracing", + "uds_windows", + "uuid", + "windows-sys 0.61.2", + "winnow", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus-lockstep" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6998de05217a084b7578728a9443d04ea4cd80f2a0839b8d78770b76ccd45863" +dependencies = [ + "zbus_xml", + "zvariant", +] + +[[package]] +name = "zbus-lockstep-macros" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10da05367f3a7b7553c8cdf8fa91aee6b64afebe32b51c95177957efc47ca3a0" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "zbus-lockstep", + "zbus_xml", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "5.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897e79616e84aac4b2c46e9132a4f63b93105d54fe8c0e8f6bffc21fa8d49222" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", + "zbus_names", + "zvariant", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffd8af6d5b78619bab301ff3c560a5bd22426150253db278f164d6cf3b72c50f" +dependencies = [ + "serde", + "winnow", + "zvariant", +] + +[[package]] +name = "zbus_xml" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "441a0064125265655bccc3a6af6bef56814d9277ac83fce48b1cd7e160b80eac" +dependencies = [ + "quick-xml", + "serde", + "zbus_names", + "zvariant", +] + [[package]] name = "zerocopy" version = "0.8.40" @@ -3523,3 +6472,58 @@ name = "zmij" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + +[[package]] +name = "zune-core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" + +[[package]] +name = "zune-jpeg" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec5f41c76397b7da451efd19915684f727d7e1d516384ca6bd0ec43ec94de23c" +dependencies = [ + "zune-core", +] + +[[package]] +name = "zvariant" +version = "5.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5708299b21903bbe348e94729f22c49c55d04720a004aa350f1f9c122fd2540b" +dependencies = [ + "endi", + "enumflags2", + "serde", + "winnow", + "zvariant_derive", + "zvariant_utils", +] + +[[package]] +name = "zvariant_derive" +version = "5.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b59b012ebe9c46656f9cc08d8da8b4c726510aef12559da3e5f1bf72780752c" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f75c23a64ef8f40f13a6989991e643554d9bef1d682a281160cf0c1bc389c5e9" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "syn", + "winnow", +] diff --git a/Cargo.toml b/Cargo.toml index c3e2959..a064f05 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,8 @@ members = [ "common_data_types", "tree-sitter-command-cad-model", "units", - "cli" + "cli", + "gui" ] # We skip tree-sitter because it doesn't have actual tests and one of the generated documentation @@ -15,7 +16,8 @@ default-members = [ "interpreter", "common_data_types", "units", - "cli" + "cli", + "gui" ] [workspace.dependencies] @@ -24,3 +26,4 @@ type-sitter = "0.8" tree-sitter = "0.25" tempfile = "3" git2 = "0.20" +anyhow = "1" diff --git a/cli/Cargo.toml b/cli/Cargo.toml index a3a5d02..1c44c14 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -8,7 +8,7 @@ clap = { version = "4.5.54", features = ["derive"] } reedline = { version = "0.45.0", features = ["system_clipboard", "bashisms"] } termimad = "0.34.1" interpreter = { path = "../interpreter/" } -anyhow = "1.0.100" +anyhow = { workspace = true } ariadne = { workspace = true } type-sitter = { workspace = true } tree-sitter = { workspace = true } diff --git a/cli/src/main.rs b/cli/src/main.rs index e12d8df..687d73a 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,11 +1,11 @@ use std::{ collections::HashMap, path::{Path, PathBuf}, - sync::{Arc, Mutex}, + sync::{atomic::AtomicBool, Arc, Mutex}, }; mod arguments; -use anyhow::{Context, Result, anyhow, bail}; +use anyhow::{anyhow, bail, Context, Result}; use arguments::Arguments; use ariadne::{Cache, Label, Report, ReportKind, Source}; use clap::Parser as _; @@ -17,13 +17,14 @@ use type_sitter::Node as _; use crate::arguments::Commands; use interpreter::{ - ExecutionContext, ExecutionFileCache, ImString, LogMessage, Parser, RuntimeLog, - SourceReference, StackScope, StackTrace, Store, build_prelude, + build_prelude, compile::{compile, iter_raw_nodes}, execute_expression, execution::values::BuiltinCallableDatabase, new_parser, run_file, values::{Object, Style, Value}, + ExecutionContext, ExecutionFileCache, FsStore, ImString, LogMessage, Parser, RuntimeLog, + SourceReference, StackScope, StackTrace, Store, }; fn main() { @@ -78,7 +79,7 @@ fn process_file(file: PathBuf) -> Result<()> { } let database = BuiltinCallableDatabase::new(); - let prelude = build_prelude(&database).context("Failed to build prelude")?; + let prelude = build_prelude(&database); let parent = file .parent() @@ -102,11 +103,14 @@ fn process_file(file: PathBuf) -> Result<()> { }; std::fs::create_dir_all(&store_directory).context("Failed to create store directory")?; - let store = Store::new(store_directory); + let store = Store::FsStore(FsStore::new(store_directory)); let log = StderrLog; let files = Mutex::new(HashMap::new()); + let shutdown_signal = AtomicBool::new(false); + let context = ExecutionContext { + shutdown_singal: &shutdown_signal, log: &log as &dyn RuntimeLog, stack_trace: &StackTrace::bootstrap(), stack: &StackScope::top(&prelude), @@ -172,10 +176,10 @@ fn repl() -> Result<()> { let mut parser = new_parser(); let database = BuiltinCallableDatabase::new(); - let prelude = build_prelude(&database).context("Failed to build prelude")?; + let prelude = build_prelude(&database); let store_directory = TempDir::new().unwrap(); - let store = Store::new(store_directory.path()); + let store = Store::FsStore(FsStore::new(store_directory.path())); println!("Store is located at {:?}", store_directory.path()); println!("Store will be deleted on exit."); @@ -267,7 +271,10 @@ fn run_line( let log = StderrLog; let files = Mutex::new(HashMap::new()); + let shutdown_signal = AtomicBool::new(false); + let context = ExecutionContext { + shutdown_singal: &shutdown_signal, log: &log as &dyn RuntimeLog, stack_trace: &StackTrace::top(root.reference.clone()), stack: &StackScope::top(prelude), diff --git a/examples/modeling/export_stls.ccm b/examples/modeling/export_stls.ccm new file mode 100644 index 0000000..d87dfcc --- /dev/null +++ b/examples/modeling/export_stls.ccm @@ -0,0 +1,6 @@ +# These are the same meshes from mesh.ccm, we're just exporting them as stls. +std.import(path = "mesh.ccm") + ::iter() + ::zip(other = ["my_sphere", "my_cube_sphere_or", "my_cube_sphere_and", "my_cube_sphere_xor"]::iter()) + ::map(f = (c: std.types.List()) -> std.types.File: c::get(i = 0u)::to_stl(name = c::get(i = 1u))) + ::collect_list() diff --git a/examples/modeling/mesh.ccm b/examples/modeling/mesh.ccm index 6b23c76..a1ed574 100644 --- a/examples/modeling/mesh.ccm +++ b/examples/modeling/mesh.ccm @@ -1,6 +1,6 @@ [ - std.mesh.icosphere(subdivions = 5u, diameter = 2cm)::to_stl(name="my_sphere"), - (std.mesh.icosphere(subdivions = 5u, diameter = 2cm) | std.mesh.cube(size = {2cm, 2cm, 2cm}) + {1cm, 0cm, 0cm})::to_stl(name="my_cube_sphere_or"), - (std.mesh.icosphere(subdivions = 5u, diameter = 2cm) & std.mesh.cube(size = {2cm, 2cm, 2cm}) + {1cm, 0cm, 0cm})::to_stl(name="my_cube_sphere_and"), - (std.mesh.icosphere(subdivions = 5u, diameter = 2cm) ^ std.mesh.cube(size = {2cm, 2cm, 2cm}) + {1cm, 0cm, 0cm})::to_stl(name="my_cube_sphere_xor") + std.mesh.icosphere(subdivions = 5u, diameter = 2cm), + (std.mesh.icosphere(subdivions = 5u, diameter = 2cm) | std.mesh.cube(size = {2cm, 2cm, 2cm}) + {1cm, 0cm, 0cm}), + (std.mesh.icosphere(subdivions = 5u, diameter = 2cm) & std.mesh.cube(size = {2cm, 2cm, 2cm}) + {1cm, 0cm, 0cm}), + (std.mesh.icosphere(subdivions = 5u, diameter = 2cm) ^ std.mesh.cube(size = {2cm, 2cm, 2cm}) + {1cm, 0cm, 0cm}) ] diff --git a/flake.nix b/flake.nix index 76e6cd2..8cf96e6 100644 --- a/flake.nix +++ b/flake.nix @@ -38,6 +38,16 @@ cargo = fenix-channel.cargo; rustc = fenix-channel.rustc; }); + + gui-dependencies = with pkgs; [ + wayland + libxkbcommon + libX11 + libXcursor + libXi + vulkan-loader + libGL + ]; in rec { packages.default = with pkgs; craneLib.buildPackage { @@ -65,9 +75,9 @@ pkg-config ]; - LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath [ + LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath ([ openssl - ]; + ] ++ gui-dependencies); shellHook = '' export SHELL=${pkgs.bashInteractive}/bin/bash diff --git a/gui/Cargo.toml b/gui/Cargo.toml new file mode 100644 index 0000000..e915e30 --- /dev/null +++ b/gui/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "gui" +version = "0.1.0" +edition = "2024" + +[dependencies] +eframe = { version = "0.33.3", features = ["wgpu"] } +egui = { version = "0.33.3", features = ["mint"] } +interpreter = { path = "../interpreter" } +anyhow = { workspace = true } +oneshot = "0.2.1" +tempfile = { workspace = true } +notify = "8.2.0" diff --git a/gui/src/main.rs b/gui/src/main.rs new file mode 100644 index 0000000..b1001ac --- /dev/null +++ b/gui/src/main.rs @@ -0,0 +1,328 @@ +use std::{ + collections::{HashMap, HashSet}, + fmt::Display, + path::{Path, PathBuf}, + sync::{atomic::AtomicBool, mpsc, Arc, Mutex}, +}; + +use eframe::egui; +use egui::{Color32, RichText}; +use interpreter::{ + build_prelude, compile, execute_expression, new_parser, + values::{BuiltinCallableDatabase, Object, Style, Value}, + ExecutionContext, FsStore, ImString, LogMessage, Parser, RuntimeLog, SourceReference, + StackScope, StackTrace, Store, +}; +use notify::{recommended_watcher, EventKind, RecommendedWatcher, Watcher}; +use tempfile::TempDir; + +fn main() { + let native_options = eframe::NativeOptions::default(); + if let Err(error) = eframe::run_native( + "Command CAD", + native_options, + Box::new(|cc| Ok(Box::new(CommandCAD::new(cc)))), + ) { + eprintln!("Failed to run application: {error}"); + } +} + +#[derive(Debug)] +struct GuiLogger; + +impl RuntimeLog for GuiLogger { + fn push_message(&self, message: LogMessage) { + // TODO + } + + fn collect_syntax_errors<'t>( + &self, + input: &str, + tree: &'t interpreter::compile::RootTree, + file: &'t Arc, + span: SourceReference, + ) { + // TODO + } +} + +struct Runtime { + parser: Parser, + database: BuiltinCallableDatabase, + prelude: HashMap, + repl_file: Arc, +} + +struct RuntimeJob { + expression: String, + egui_context: egui::Context, + response: oneshot::Sender, + shutdown_signal: Arc, +} + +struct PendingJob { + shutdown_signal: Arc, + response: oneshot::Receiver, +} + +enum RuntimeValue { + TextValue(String), + // Polygon(Polygon), + // PolygonSet(PolygonSet), + // ManifoldMesh(ManifoldMesh3D), +} + +enum RuntimeError { + Execution(interpreter::Error), + Parse(String), + Compile(String), +} + +impl Display for RuntimeError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + RuntimeError::Execution(error) => error.fmt(f), + RuntimeError::Parse(error) => error.fmt(f), + RuntimeError::Compile(error) => error.fmt(f), + } + } +} + +struct RuntimeOutput { + result: Result, + files_to_watch: HashSet>, +} + +fn runtime(expression_rx: mpsc::Receiver) { + let database = BuiltinCallableDatabase::new(); + let prelude = build_prelude(&database); + let stack_top = StackScope::top(&prelude); + + let mut parser = new_parser(); + let repl_file = Arc::new(PathBuf::from("repl.ccm")); + + // TODO we should prefer using `.ccad` in the local directory. + // Also we shouldn't be unwrapping on that. + let store_directory = TempDir::new().unwrap(); + let store = Store::FsStore(FsStore::new(store_directory.path())); + + let mut run_expression = |shutdown_signal: Arc, input: String| -> RuntimeOutput { + let files = Mutex::new(HashMap::new()); + let tree = match parser + .parse(&input, None) + .map_err(|error| RuntimeError::Parse(format!("Failed to parse input: {error:?}"))) + { + Ok(tree) => tree, + Err(error) => { + return RuntimeOutput { + result: Err(error), + files_to_watch: HashSet::new(), + } + } + }; + let root = match compile(&repl_file, &input, &tree) + .map_err(|error| RuntimeError::Compile(format!("Failed to compile: {error:?}"))) + { + Ok(root) => root, + Err(error) => { + return RuntimeOutput { + result: Err(error), + files_to_watch: HashSet::new(), + } + } + }; + + let log = GuiLogger; + + let context = ExecutionContext { + shutdown_singal: &shutdown_signal, + log: &log as &dyn RuntimeLog, + stack_trace: &StackTrace::top(root.reference.clone()), + stack: &stack_top, + database: &database, + store: &store, + file_cache: &files, + working_directory: Path::new("."), + import_limit: 100, + }; + + let expression_result = execute_expression(&context, &root); + + let result = match expression_result { + Ok(value) => { + let mut text = String::new(); + value.format(&context, &mut text, Style::Default, None).ok(); + + Ok(RuntimeValue::TextValue(text)) + } + Err(error) => Err(RuntimeError::Execution(error)), + }; + + // TODO we can also use this for better error message formatting. + let files = files.into_inner().expect("File hashmap was poisoned"); + + let files_to_watch: HashSet> = files.keys().cloned().collect(); + + RuntimeOutput { + result, + files_to_watch, + } + }; + + // An error indicates that there are no more senders and that we should shutdown. + while let Ok(command) = expression_rx.recv() { + let result = run_expression(command.shutdown_signal, command.expression); + command.response.send(result).ok(); + command.egui_context.request_repaint(); + } +} + +struct CommandCAD { + expression: String, + expression_tx: mpsc::Sender, + active_job: Option, + last_result: Option>, + watched_files: HashSet>, + file_watcher: Result, + file_updates_rx: mpsc::Receiver>, +} + +impl CommandCAD { + fn new(cc: &eframe::CreationContext<'_>) -> Self { + let (expression_tx, expression_rx) = mpsc::channel(); + std::thread::spawn(|| runtime(expression_rx)); + + let (file_updates_tx, file_updates_rx) = mpsc::channel(); + + let gui_ctx = cc.egui_ctx.clone(); + let file_watcher = recommended_watcher(move |event| { + // Notify and refresh the GUI whenever there's an update to one of the project files. + file_updates_tx.send(event).ok(); + gui_ctx.request_repaint(); + }); + + Self { + expression: String::new(), + expression_tx, + active_job: None, + last_result: None, + watched_files: HashSet::new(), + file_watcher, + file_updates_rx, + } + } + + fn spawn_job(&mut self, ctx: &egui::Context) { + if let Some(pending_job) = self.active_job.take() { + pending_job + .shutdown_signal + .store(true, std::sync::atomic::Ordering::Relaxed); + } + + let shutdown_signal = Arc::new(AtomicBool::new(false)); + + let (response_tx, response_rx) = oneshot::channel(); + + let pending_job = PendingJob { + shutdown_signal: shutdown_signal.clone(), + response: response_rx, + }; + + let runtime_job = RuntimeJob { + expression: self.expression.clone(), + egui_context: ctx.clone(), + response: response_tx, + shutdown_signal, + }; + + self.expression_tx + .send(runtime_job) + .expect("Runtime thread terminated early"); + self.active_job = Some(pending_job); + } + + fn check_if_watched_files_changed(&mut self) -> bool { + match self.file_updates_rx.try_recv() { + Ok(Ok(event)) => matches!(event.kind, EventKind::Modify(_) | EventKind::Remove(_)), + // TODO log that or something. + Ok(Err(error)) => { + // TODO this can be logged better. + let notice_me = 0; + eprintln!("{error}"); + false + } + Err(_) => false, + } + } + + fn check_job(&mut self) { + if let Some(active_job) = &self.active_job { + // This could fail by the thread being closed, but that shouldn't happen and won't + // cause us to panic. + if let Ok(output) = active_job.response.try_recv() { + self.last_result = Some(output.result); + self.active_job = None; + + // Collect a list of files to watch. + if let Ok(watcher) = &mut self.file_watcher { + let removed = self.watched_files.difference(&output.files_to_watch); + let added = output.files_to_watch.difference(&self.watched_files); + + let mut paths = watcher.paths_mut(); + for path in removed { + // TODO log errors and success here. + paths.remove(&path).ok(); + } + + for path in added { + // TODO log errors and success here. + paths.add(&path, notify::RecursiveMode::NonRecursive).ok(); + } + } + + self.watched_files = output.files_to_watch; + } + } + } +} + +impl eframe::App for CommandCAD { + fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { + egui::CentralPanel::default().show(ctx, |ui| { + ui.horizontal(|ui| { + ui.label("Expression: "); + if ui.text_edit_singleline(&mut self.expression).changed() + || self.check_if_watched_files_changed() + { + self.spawn_job(ctx); + } + + if self.active_job.is_some() { + ui.label(RichText::new("Working...").color(Color32::YELLOW)); + } else { + ui.label(RichText::new("Ready").color(Color32::GREEN)); + } + }); + + if let Err(error) = &self.file_watcher { + ui.label( + RichText::new(format!("Failed to setup file watching: {error}\nOutput will not update automatically when files are modified")) + .color(Color32::YELLOW), + ); + } + + // Update the job status. + self.check_job(); + + match &self.last_result { + None => {} + Some(Ok(RuntimeValue::TextValue(text))) => { + ui.label(text); + } + Some(Err(error)) => { + ui.label(RichText::new(format!("{error}")).color(Color32::RED)); + } + } + }); + } +} diff --git a/interpreter/Cargo.toml b/interpreter/Cargo.toml index 4aee18b..784ab7d 100644 --- a/interpreter/Cargo.toml +++ b/interpreter/Cargo.toml @@ -20,7 +20,7 @@ nalgebra = "0.34.1" stack = "0.4.0" paste = "1.0.15" tempfile = { workspace = true } -rayon = "1.11.0" +rayon = "1.11" nom = "8.0.0" ariadne = { workspace = true } levenshtein = "1.0.5" diff --git a/interpreter/src/execution/mod.rs b/interpreter/src/execution/mod.rs index 851928b..55f1d5e 100644 --- a/interpreter/src/execution/mod.rs +++ b/interpreter/src/execution/mod.rs @@ -21,7 +21,7 @@ use std::{ cmp::Ordering, collections::HashMap, path::{Path, PathBuf}, - sync::{Arc, Mutex}, + sync::{atomic::AtomicBool, Arc, Mutex}, }; use crate::{ @@ -55,7 +55,7 @@ use logging::LocatedStr; pub use logging::{ExecutionFileCache, LogLevel, LogMessage, RuntimeLog, StackTrace}; pub use stack::StackScope; mod store; -pub use store::Store; +pub use store::{FsStore, Store, StoreTrait}; use thiserror::Error; use values::{ @@ -210,6 +210,7 @@ pub fn find_all_variable_accesses_in_expression( #[derive(Debug, Clone)] pub struct ExecutionContext<'c> { + pub shutdown_singal: &'c AtomicBool, pub log: &'c dyn RuntimeLog, pub stack_trace: &'c StackTrace<'c>, pub stack: &'c StackScope<'c>, @@ -286,10 +287,24 @@ impl<'s> IntoIterator for &'s ExecutionContext<'_> { } } +#[derive(Debug, Error, Eq, PartialEq)] +pub enum AbortError { + #[error("Execution Aborted")] + Aborted, +} + pub fn execute_expression( context: &ExecutionContext, expression: &compile::AstNode, ) -> ExecutionResult { + if context + .shutdown_singal + .load(std::sync::atomic::Ordering::Relaxed) + { + // We've been told to shutdown. + return Err(AbortError::Aborted.to_error(context)); + } + context.trace_scope( None, expression.reference.clone(), @@ -579,19 +594,24 @@ pub(crate) fn test_context_custom_database( use std::sync::Mutex; use tempfile::TempDir; - let mut prelude = build_prelude(&database).unwrap(); + use crate::execution::store::FsStore; + + let mut prelude = build_prelude(&database); for (name, value) in extra_prelude.into_iter() { prelude.insert(name, value); } let store_directory = TempDir::new().unwrap(); - let store = Store::new(store_directory.path()); + let store = Store::FsStore(FsStore::new(store_directory.path())); let file_cache = Mutex::new(HashMap::new()); let working_directory = Path::new("."); + let shutdown_signal = AtomicBool::new(false); + let context = ExecutionContext { + shutdown_singal: &shutdown_signal, log: &Mutex::new(Vec::new()), stack_trace: &StackTrace::test(), stack: &StackScope::top(&prelude), diff --git a/interpreter/src/execution/standard_environment.rs b/interpreter/src/execution/standard_environment.rs index 6d390f4..fab2791 100644 --- a/interpreter/src/execution/standard_environment.rs +++ b/interpreter/src/execution/standard_environment.rs @@ -16,19 +16,22 @@ * program. If not, see . */ -use std::{collections::HashMap, path::Path, sync::Mutex}; +use std::{ + collections::HashMap, + path::Path, + sync::{atomic::AtomicBool, Mutex}, +}; use common_data_types::{Dimension, Float}; use imstr::ImString; use nalgebra::{Matrix3, Matrix4}; -use tempfile::TempDir; use crate::{ execution::{ functions::Import, logging::StackTrace, stack::StackScope, - store::Store, + store::{DummyStore, Store}, values::{ integer::functions::{RangeSInt, RangeUInt}, BuiltinCallableDatabase, Scalar, SignedInteger, UnsignedInteger, ValueNone, @@ -41,18 +44,20 @@ use crate::{ use super::values::{Dictionary, Value, ValueType}; /// Builds standard library. -pub fn build_prelude( - database: &BuiltinCallableDatabase, -) -> std::io::Result> { +pub fn build_prelude(database: &BuiltinCallableDatabase) -> HashMap { // Build an incomplete context for bootstrapping. let prelude = HashMap::new(); - let store_directory = TempDir::new()?; - let store = Store::new(store_directory.path()); + + // We don't actually use the store for anything during prelude bringup. Use a dummy store for + // this. + let store = Store::DummyStore(DummyStore); let file_cache = Mutex::new(HashMap::new()); let working_directory = Path::new("."); + let shutdown_signal = AtomicBool::new(false); let context = ExecutionContext { + shutdown_singal: &shutdown_signal, log: &Mutex::new(Vec::new()), stack_trace: &StackTrace::bootstrap(), stack: &StackScope::top(&prelude), @@ -63,9 +68,7 @@ pub fn build_prelude( import_limit: 100, }; - let global = HashMap::from([("std".into(), build_std(&context).into())]); - - Ok(global) + HashMap::from([("std".into(), build_std(&context).into())]) } fn build_std(context: &ExecutionContext) -> Dictionary { @@ -156,11 +159,17 @@ fn build_types(context: &ExecutionContext) -> Dictionary { ("ManifoldMesh".into(), ValueType::ManifoldMesh3D.into()), ("Transform2d".into(), ValueType::Transform2d.into()), ("Transform3d".into(), ValueType::Transform3d.into()), - // TODO we need File types. + ("Transform3d".into(), ValueType::Transform3d.into()), + ("Iterator".into(), ValueType::Iterator.into()), + ( + "List".into(), + BuiltinFunction::new::().into(), + ), + ("File".into(), ValueType::File.into()), // TODO we'll need a function to build custom function signature types. // ("Function".into(), ValueType::Closure(Arc)), - // TODO add a function to build custom unit types. + // TODO add a function to build custom scalar and vector unit types. ]); Dictionary::new(context, types) } diff --git a/interpreter/src/execution/store.rs b/interpreter/src/execution/store.rs index 2b3cd53..1bd9966 100644 --- a/interpreter/src/execution/store.rs +++ b/interpreter/src/execution/store.rs @@ -21,16 +21,76 @@ use std::{ path::{Path, PathBuf}, }; +use enum_dispatch::enum_dispatch; use sha2::{Digest, Sha256}; use tempfile::{NamedTempFile, TempDir}; use crate::{ - execution::errors::{ExecutionResult, Raise}, + execution::errors::{ExecutionResult, Raise, StringError}, ExecutionContext, }; +#[enum_dispatch] +pub trait StoreTrait { + fn get_or_init_file( + &self, + context: &ExecutionContext, + hashable: &impl std::hash::Hash, + name: impl AsRef, + init: impl FnOnce(&mut NamedTempFile) -> ExecutionResult<()>, + ) -> ExecutionResult; + + fn get_or_init_directory( + &self, + context: &ExecutionContext, + hashable: &impl std::hash::Hash, + name: impl AsRef, + init: impl FnOnce(&mut TempDir) -> ExecutionResult<()>, + ) -> ExecutionResult; +} + +#[enum_dispatch(StoreTrait)] +#[derive(Debug)] +pub enum Store { + FsStore, + DummyStore, +} + +#[derive(Debug)] +pub struct DummyStore; + +impl StoreTrait for DummyStore { + fn get_or_init_file( + &self, + context: &ExecutionContext, + _hashable: &impl std::hash::Hash, + name: impl AsRef, + _init: impl FnOnce(&mut NamedTempFile) -> ExecutionResult<()>, + ) -> ExecutionResult { + Err(StringError(format!( + "Cannot store a file with a dummy store: {}", + name.as_ref() + )) + .to_error(context)) + } + + fn get_or_init_directory( + &self, + context: &ExecutionContext, + _hashable: &impl std::hash::Hash, + name: impl AsRef, + _init: impl FnOnce(&mut TempDir) -> ExecutionResult<()>, + ) -> ExecutionResult { + Err(StringError(format!( + "Cannot store a directory with a dummy store: {}", + name.as_ref() + )) + .to_error(context)) + } +} + #[derive(Debug)] -pub struct Store { +pub struct FsStore { /// Path to the store itself. path: PathBuf, @@ -40,14 +100,71 @@ pub struct Store { temp_dir: PathBuf, } -impl Store { +impl FsStore { pub fn new(path: impl Into) -> Self { let path = path.into(); let temp_dir = path.join("../temp"); Self { path, temp_dir } } - pub fn get_or_init_file( + fn generate_store_path( + &self, + hashable: &impl std::hash::Hash, + name: impl AsRef, + ) -> PathBuf { + let mut hasher = StoreHasher(Sha256::new()); + hashable.hash(&mut hasher); + let hash = hasher.0.finalize(); + let file_name = { + let mut file_name = hex::encode(&hash[..]); + file_name += "-"; + file_name += name.as_ref(); + file_name + }; + self.path.join(file_name) + } + + fn move_path_into_store( + &self, + context: &ExecutionContext, + temp_path: &Path, + store_path: &Path, + ) -> ExecutionResult<()> { + // Move the file into the store. + match std::fs::rename(temp_path, store_path) { + Ok(_) => Ok(store_path), + Err(error) => { + let result = match error.kind() { + // Seems another thread created the object while we were working. + // That's unfortunate, but we can just use their result. + ErrorKind::AlreadyExists => Ok(store_path), + _ => Err(error), + }; + + // Either way, we need to remove that old directory. + if let Err(error) = std::fs::remove_dir_all(temp_path) { + // This just really isn't our day... + context.log.push_message(super::LogMessage { + origin: context.stack_trace.bottom().clone(), + level: super::LogLevel::Warning, + message: format!( + "Failed to remove temporary file at {temp_path:?}: {error}" + ) + .into(), + }); + } + + result + } + } + .map_err(|error| error.to_error(context))?; + + Ok(()) + } +} + +impl StoreTrait for FsStore { + fn get_or_init_file( &self, context: &ExecutionContext, hashable: &impl std::hash::Hash, @@ -91,7 +208,7 @@ impl Store { ) } - pub fn get_or_init_directory( + fn get_or_init_directory( &self, context: &ExecutionContext, hashable: &impl std::hash::Hash, @@ -125,61 +242,6 @@ impl Store { }, ) } - - fn generate_store_path( - &self, - hashable: &impl std::hash::Hash, - name: impl AsRef, - ) -> PathBuf { - let mut hasher = StoreHasher(Sha256::new()); - hashable.hash(&mut hasher); - let hash = hasher.0.finalize(); - let file_name = { - let mut file_name = hex::encode(&hash[..]); - file_name += "-"; - file_name += name.as_ref(); - file_name - }; - self.path.join(file_name) - } - - fn move_path_into_store( - &self, - context: &ExecutionContext, - temp_path: &Path, - store_path: &Path, - ) -> ExecutionResult<()> { - // Move the file into the store. - match std::fs::rename(temp_path, store_path) { - Ok(_) => Ok(store_path), - Err(error) => { - let result = match error.kind() { - // Seems another thread created the object while we were working. - // That's unfortunate, but we can just use their result. - ErrorKind::AlreadyExists => Ok(store_path), - _ => Err(error), - }; - - // Either way, we need to remove that old directory. - if let Err(error) = std::fs::remove_dir_all(temp_path) { - // This just really isn't our day... - context.log.push_message(super::LogMessage { - origin: context.stack_trace.bottom().clone(), - level: super::LogLevel::Warning, - message: format!( - "Failed to remove temporary file at {temp_path:?}: {error}" - ) - .into(), - }); - } - - result - } - } - .map_err(|error| error.to_error(context))?; - - Ok(()) - } } #[derive(Debug)] diff --git a/interpreter/src/execution/values/iterators.rs b/interpreter/src/execution/values/iterators.rs index 470c342..e69ca3a 100644 --- a/interpreter/src/execution/values/iterators.rs +++ b/interpreter/src/execution/values/iterators.rs @@ -121,37 +121,43 @@ impl Object for ValueIterator { fn get_attribute(&self, context: &ExecutionContext, attribute: &str) -> ExecutionResult { match attribute { - "chunks" => Ok(BuiltinFunction::new::().into()), - "chunks_exact" => Ok(BuiltinFunction::new::().into()), - "chain" => Ok(BuiltinFunction::new::().into()), - "cycle" => Ok(BuiltinFunction::new::().into()), - "debug" => Ok(BuiltinFunction::new::().into()), - "enumerate" => Ok(BuiltinFunction::new::().into()), - "filter" => Ok(BuiltinFunction::new::().into()), - "filter_map" => Ok(BuiltinFunction::new::().into()), - "flatten" => Ok(BuiltinFunction::new::().into()), - "map" => Ok(BuiltinFunction::new::().into()), - "map_while" => Ok(BuiltinFunction::new::().into()), - "skip" => Ok(BuiltinFunction::new::().into()), - "skip_while" => Ok(BuiltinFunction::new::().into()), - "step_by" => Ok(BuiltinFunction::new::().into()), - "take" => Ok(BuiltinFunction::new::().into()), - "take_while" => Ok(BuiltinFunction::new::().into()), - "zip" => Ok(BuiltinFunction::new::().into()), - - "all" => Ok(BuiltinFunction::new::().into()), - "any" => Ok(BuiltinFunction::new::().into()), - "collect_list" => Ok(BuiltinFunction::new::().into()), - "collect_string" => Ok(BuiltinFunction::new::().into()), - "count" => Ok(BuiltinFunction::new::().into()), - "first" => Ok(BuiltinFunction::new::().into()), - "fold" => Ok(BuiltinFunction::new::().into()), - "last" => Ok(BuiltinFunction::new::().into()), - "max" => Ok(BuiltinFunction::new::().into()), - "min" => Ok(BuiltinFunction::new::().into()), - "nth" => Ok(BuiltinFunction::new::().into()), - "product" => Ok(BuiltinFunction::new::().into()), - "sum" => Ok(BuiltinFunction::new::().into()), + "chunks" => Ok(BuiltinFunction::new::().into()), + "chunks_exact" => { + Ok(BuiltinFunction::new::().into()) + } + "chain" => Ok(BuiltinFunction::new::().into()), + "cycle" => Ok(BuiltinFunction::new::().into()), + "debug" => Ok(BuiltinFunction::new::().into()), + "enumerate" => Ok(BuiltinFunction::new::().into()), + "filter" => Ok(BuiltinFunction::new::().into()), + "filter_map" => Ok(BuiltinFunction::new::().into()), + "flatten" => Ok(BuiltinFunction::new::().into()), + "map" => Ok(BuiltinFunction::new::().into()), + "map_while" => Ok(BuiltinFunction::new::().into()), + "skip" => Ok(BuiltinFunction::new::().into()), + "skip_while" => Ok(BuiltinFunction::new::().into()), + "step_by" => Ok(BuiltinFunction::new::().into()), + "take" => Ok(BuiltinFunction::new::().into()), + "take_while" => Ok(BuiltinFunction::new::().into()), + "zip" => Ok(BuiltinFunction::new::().into()), + + "all" => Ok(BuiltinFunction::new::().into()), + "any" => Ok(BuiltinFunction::new::().into()), + "collect_list" => { + Ok(BuiltinFunction::new::().into()) + } + "collect_string" => { + Ok(BuiltinFunction::new::().into()) + } + "count" => Ok(BuiltinFunction::new::().into()), + "first" => Ok(BuiltinFunction::new::().into()), + "fold" => Ok(BuiltinFunction::new::().into()), + "last" => Ok(BuiltinFunction::new::().into()), + "max" => Ok(BuiltinFunction::new::().into()), + "min" => Ok(BuiltinFunction::new::().into()), + "nth" => Ok(BuiltinFunction::new::().into()), + "product" => Ok(BuiltinFunction::new::().into()), + "sum" => Ok(BuiltinFunction::new::().into()), _ => Err(MissingAttributeError { name: attribute.into(), } @@ -550,7 +556,7 @@ impl IteratorStage { } } -pub mod methods { +pub mod methods_and_functions { // Methods to add stages to the iterator: pub struct Chunks; pub struct ChunksExact; @@ -589,7 +595,7 @@ pub mod methods { pub fn register_methods(database: &mut BuiltinCallableDatabase) { build_method!( database, - methods::Chunks, "Iterator::chunks", ( + methods_and_functions::Chunks, "Iterator::chunks", ( context: &ExecutionContext, this: ValueIterator, size: UnsignedInteger @@ -601,8 +607,8 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::ChunksExact, "Iterator::chunks_exact", ( - context: &ExecutionContext, + methods_and_functions::ChunksExact, "Iterator::chunks_exact", ( + methods: &ExecutionContext, this: ValueIterator, size: UnsignedInteger ) -> ValueIterator { @@ -613,7 +619,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Chain, "Iterator::chain", ( + methods_and_functions::Chain, "Iterator::chain", ( context: &ExecutionContext, this: ValueIterator, next: ValueIterator @@ -625,7 +631,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Cycle, "Iterator::cycle", ( + methods_and_functions::Cycle, "Iterator::cycle", ( context: &ExecutionContext, this: ValueIterator, count: UnsignedInteger @@ -637,7 +643,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Debug, "Iterator::debug", ( + methods_and_functions::Debug, "Iterator::debug", ( context: &ExecutionContext, this: ValueIterator ) -> ValueIterator { @@ -648,7 +654,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Enumerate, "Iterator::enumerate", ( + methods_and_functions::Enumerate, "Iterator::enumerate", ( context: &ExecutionContext, this: ValueIterator ) -> ValueIterator { @@ -659,7 +665,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Filter, "Iterator::filter", ( + methods_and_functions::Filter, "Iterator::filter", ( context: &ExecutionContext, this: ValueIterator, f: FilterClosure @@ -671,7 +677,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::FilterMap, "Iterator::filter_map", ( + methods_and_functions::FilterMap, "Iterator::filter_map", ( context: &ExecutionContext, this: ValueIterator, f: FilterMapClosure @@ -683,7 +689,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Flatten, "Iterator::flatten", ( + methods_and_functions::Flatten, "Iterator::flatten", ( context: &ExecutionContext, this: ValueIterator ) -> ValueIterator { @@ -694,7 +700,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Map, "Iterator::map", ( + methods_and_functions::Map, "Iterator::map", ( context: &ExecutionContext, this: ValueIterator, f: MapClosure @@ -706,7 +712,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::MapWhile, "Iterator::map_while", ( + methods_and_functions::MapWhile, "Iterator::map_while", ( context: &ExecutionContext, this: ValueIterator, f: MapWhileClosure @@ -718,7 +724,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Skip, "Iterator::skip", ( + methods_and_functions::Skip, "Iterator::skip", ( context: &ExecutionContext, this: ValueIterator, count: UnsignedInteger @@ -730,7 +736,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::SkipWhile, "Iterator::skip_while", ( + methods_and_functions::SkipWhile, "Iterator::skip_while", ( context: &ExecutionContext, this: ValueIterator, f: SkipWhileClosure @@ -742,7 +748,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::StepBy, "Iterator::step_by", ( + methods_and_functions::StepBy, "Iterator::step_by", ( context: &ExecutionContext, this: ValueIterator, count: UnsignedInteger @@ -754,7 +760,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Take, "Iterator::take", ( + methods_and_functions::Take, "Iterator::take", ( context: &ExecutionContext, this: ValueIterator, count: UnsignedInteger @@ -766,7 +772,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::TakeWhile, "Iterator::take_while", ( + methods_and_functions::TakeWhile, "Iterator::take_while", ( context: &ExecutionContext, this: ValueIterator, f: TakeWhileClosure @@ -778,7 +784,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Zip, "Iterator::zip", ( + methods_and_functions::Zip, "Iterator::zip", ( context: &ExecutionContext, this: ValueIterator, other: ValueIterator @@ -792,7 +798,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { build_closure_type!(AllClosure(c: Value) -> Boolean); build_method!( database, - methods::All, "Iterator::all", ( + methods_and_functions::All, "Iterator::all", ( context: &ExecutionContext, this: ValueIterator, f: AllClosure @@ -824,7 +830,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { build_closure_type!(AnyClosure(c: Value) -> Boolean); build_method!( database, - methods::Any, "Iterator::any", ( + methods_and_functions::Any, "Iterator::any", ( context: &ExecutionContext, this: ValueIterator, f: AnyClosure @@ -854,7 +860,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::CollectList, "Iterator::collect_list", ( + methods_and_functions::CollectList, "Iterator::collect_list", ( context: &ExecutionContext, this: ValueIterator ) -> List { @@ -866,7 +872,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::CollectString, "Iterator::collect_string", ( + methods_and_functions::CollectString, "Iterator::collect_string", ( context: &ExecutionContext, this: ValueIterator ) -> IString { @@ -886,7 +892,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Count, "Iterator::count", ( + methods_and_functions::Count, "Iterator::count", ( context: &ExecutionContext, this: ValueIterator ) -> UnsignedInteger { @@ -897,7 +903,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::First, "Iterator::first", ( + methods_and_functions::First, "Iterator::first", ( context: &ExecutionContext, this: ValueIterator ) -> Value { @@ -914,7 +920,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { build_closure_type!(FoldClosure(previous: Value, c: Value) -> Value); build_method!( database, - methods::Fold, "Iterator::fold",( + methods_and_functions::Fold, "Iterator::fold",( context: &ExecutionContext, this: ValueIterator, init: Value, @@ -945,7 +951,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Last, "Iterator::last", ( + methods_and_functions::Last, "Iterator::last", ( context: &ExecutionContext, this: ValueIterator ) -> Value { @@ -960,7 +966,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Max, "Iterator::max", ( + methods_and_functions::Max, "Iterator::max", ( context: &ExecutionContext, this: ValueIterator ) -> Value { @@ -984,7 +990,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Min, "Iterator::min", ( + methods_and_functions::Min, "Iterator::min", ( context: &ExecutionContext, this: ValueIterator ) -> Value { @@ -1008,7 +1014,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Nth, "Iterator::nth", ( + methods_and_functions::Nth, "Iterator::nth", ( context: &ExecutionContext, this: ValueIterator, n: UnsignedInteger @@ -1024,7 +1030,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Product, "Iterator::product",( + methods_and_functions::Product, "Iterator::product",( context: &ExecutionContext, this: ValueIterator ) -> Value { @@ -1047,7 +1053,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Sum, "Iterator::sum",( + methods_and_functions::Sum, "Iterator::sum",( context: &ExecutionContext, this: ValueIterator ) -> Value { diff --git a/interpreter/src/execution/values/list.rs b/interpreter/src/execution/values/list.rs index caca500..1e255ef 100644 --- a/interpreter/src/execution/values/list.rs +++ b/interpreter/src/execution/values/list.rs @@ -17,7 +17,7 @@ */ use crate::{ - build_closure_type, build_method, + build_closure_type, build_function, build_method, compile::{AstNode, Expression}, execute_expression, execution::{ @@ -175,27 +175,35 @@ impl Object for List { fn get_attribute(&self, context: &ExecutionContext, attribute: &str) -> ExecutionResult { match attribute { - "append" => Ok(BuiltinFunction::new::().into()), - "slice" => Ok(BuiltinFunction::new::().into()), - "get" => Ok(BuiltinFunction::new::().into()), - "chunks" => Ok(BuiltinFunction::new::().into()), + "append" => Ok(BuiltinFunction::new::().into()), + "slice" => Ok(BuiltinFunction::new::().into()), + "get" => Ok(BuiltinFunction::new::().into()), + "chunks" => Ok(BuiltinFunction::new::().into()), - "retain" => Ok(BuiltinFunction::new::().into()), + "retain" => Ok(BuiltinFunction::new::().into()), - "sort" => Ok(BuiltinFunction::new::().into()), - "reverse" => Ok(BuiltinFunction::new::().into()), - "truncate" => Ok(BuiltinFunction::new::().into()), + "sort" => Ok(BuiltinFunction::new::().into()), + "reverse" => Ok(BuiltinFunction::new::().into()), + "truncate" => Ok(BuiltinFunction::new::().into()), - "deduplicate" => Ok(BuiltinFunction::new::().into()), - "union" => Ok(BuiltinFunction::new::().into()), - "intersection" => Ok(BuiltinFunction::new::().into()), - "difference" => Ok(BuiltinFunction::new::().into()), + "deduplicate" => { + Ok(BuiltinFunction::new::().into()) + } + "union" => Ok(BuiltinFunction::new::().into()), + "intersection" => { + Ok(BuiltinFunction::new::().into()) + } + "difference" => Ok(BuiltinFunction::new::().into()), "symmetric_difference" => { - Ok(BuiltinFunction::new::().into()) + Ok(BuiltinFunction::new::().into()) + } + "cartesian_product" => { + Ok(BuiltinFunction::new::().into()) + } + "iter" => Ok(BuiltinFunction::new::().into()), + "iter_reverse" => { + Ok(BuiltinFunction::new::().into()) } - "cartesian_product" => Ok(BuiltinFunction::new::().into()), - "iter" => Ok(BuiltinFunction::new::().into()), - "iter_reverse" => Ok(BuiltinFunction::new::().into()), _ => Err(MissingAttributeError { name: attribute.into(), } @@ -378,7 +386,9 @@ impl std::fmt::Display for SortingError { } } -mod methods { +pub mod methods_and_functions { + pub struct BuildType; + pub struct Append; pub struct Slice; pub struct Get; @@ -406,9 +416,24 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { build_closure_type!(FoldClosure(previous: Value, c: Value) -> Value); build_closure_type!(RetainClosure(c: Value) -> Boolean); + build_function!( + database, + methods_and_functions::BuildType, "List::build_type", ( + context: &ExecutionContext, + r#type: ValueType = ValueType::Any.into() + ) -> ValueType { + if matches!(r#type, ValueType::Any) { + Ok(ValueType::List(None)) + } else { + Ok(ValueType::List(Some(Box::new(r#type)))) + } + + } + ); + build_method!( database, - methods::Append, "List::append", ( + methods_and_functions::Append, "List::append", ( context: &ExecutionContext, this: List, rhs: List @@ -421,7 +446,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Slice, "List::slice", ( + methods_and_functions::Slice, "List::slice", ( context: &ExecutionContext, this: List, start: Option = ValueNone.into(), @@ -451,7 +476,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Get, "List::get", ( + methods_and_functions::Get, "List::get", ( context: &ExecutionContext, this: List, i: UnsignedInteger @@ -467,7 +492,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Chunks, "List::chunks", ( + methods_and_functions::Chunks, "List::chunks", ( context: &ExecutionContext, this: List, size: UnsignedInteger, @@ -493,7 +518,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Retain, "List::retain",( + methods_and_functions::Retain, "List::retain",( context: &ExecutionContext, this: List, f: RetainClosure @@ -518,7 +543,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Sort, "List::sort",( + methods_and_functions::Sort, "List::sort",( context: &ExecutionContext, this: List ) -> List { @@ -544,7 +569,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Reverse, "List::reverse",( + methods_and_functions::Reverse, "List::reverse",( context: &ExecutionContext, this: List ) -> List { @@ -556,7 +581,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Truncate, "List::truncate",( + methods_and_functions::Truncate, "List::truncate",( context: &ExecutionContext, this: List, length: UnsignedInteger @@ -569,7 +594,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Deduplicate, "List::deduplicate",( + methods_and_functions::Deduplicate, "List::deduplicate",( context: &ExecutionContext, this: List ) -> List { @@ -581,7 +606,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Union, "List::union",( + methods_and_functions::Union, "List::union",( context: &ExecutionContext, this: List, other: List @@ -599,7 +624,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Intersection, "List::intersection",( + methods_and_functions::Intersection, "List::intersection",( context: &ExecutionContext, this: List, other: List @@ -617,7 +642,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::Difference, "List::difference",( + methods_and_functions::Difference, "List::difference",( context: &ExecutionContext, this: List, other: List @@ -636,7 +661,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::SymmetricDifference, "List::symmetric_difference",( + methods_and_functions::SymmetricDifference, "List::symmetric_difference",( context: &ExecutionContext, this: List, other: List @@ -662,7 +687,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::CartesianProduct, "List::cartesian_product",( + methods_and_functions::CartesianProduct, "List::cartesian_product",( context: &ExecutionContext, this: List, other: List @@ -682,7 +707,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { build_method!( database, - methods::Iterate, "List::iter",( + methods_and_functions::Iterate, "List::iter",( context: &ExecutionContext, this: List ) -> ValueIterator { @@ -691,7 +716,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { ); build_method!( database, - methods::IterateReverse, "List::iter_reverse",( + methods_and_functions::IterateReverse, "List::iter_reverse",( context: &ExecutionContext, this: List ) -> ValueIterator { diff --git a/interpreter/src/execution/values/manifold_mesh.rs b/interpreter/src/execution/values/manifold_mesh.rs index 11e71ad..3cb6861 100644 --- a/interpreter/src/execution/values/manifold_mesh.rs +++ b/interpreter/src/execution/values/manifold_mesh.rs @@ -26,7 +26,10 @@ use std::{ use crate::{ build_function, build_method, - execution::errors::{ExecutionResult, Raise, StrError}, + execution::{ + errors::{ExecutionResult, Raise, StrError}, + StoreTrait, + }, values::{ scalar::{Length, UnwrapNotNan}, vector::{Length3, Zero3}, diff --git a/interpreter/src/execution/values/mod.rs b/interpreter/src/execution/values/mod.rs index 6080223..e72a3f8 100644 --- a/interpreter/src/execution/values/mod.rs +++ b/interpreter/src/execution/values/mod.rs @@ -50,7 +50,7 @@ pub use closure::{BuiltinCallableDatabase, BuiltinFunction, UserClosure}; pub mod dictionary; pub use dictionary::Dictionary; -mod list; +pub mod list; pub use list::List; mod string; diff --git a/interpreter/src/execution/values/value_type.rs b/interpreter/src/execution/values/value_type.rs index 5111571..02f0170 100644 --- a/interpreter/src/execution/values/value_type.rs +++ b/interpreter/src/execution/values/value_type.rs @@ -40,6 +40,7 @@ use crate::{ }, ExecutionContext, }, + values::StaticType, }; #[derive(Debug, Eq, Clone, PartialEq)] @@ -274,6 +275,12 @@ impl StaticTypeName for ValueType { } } +impl StaticType for ValueType { + fn static_type() -> ValueType { + ValueType::ValueType + } +} + mod methods { pub struct Qualify; pub struct TryQualify; diff --git a/interpreter/src/lib.rs b/interpreter/src/lib.rs index 9356ebc..932da5b 100644 --- a/interpreter/src/lib.rs +++ b/interpreter/src/lib.rs @@ -22,8 +22,8 @@ pub mod execution; pub use compile::{compile, new_parser, Parser, SourceReference}; pub use execution::{ build_prelude, execute_expression, run_file, values, Error, ExecutionContext, - ExecutionFileCache, ExecutionResult, LogLevel, LogMessage, RuntimeLog, StackScope, StackTrace, - Store, + ExecutionFileCache, ExecutionResult, FsStore, LogLevel, LogMessage, RuntimeLog, StackScope, + StackTrace, Store, }; pub use imstr::ImString; pub use tree_sitter::{Point as TextPoint, Range as TextRange}; From c3d923daf85b04bfc423c17775e38923a910ec34 Mon Sep 17 00:00:00 2001 From: James Carl Date: Fri, 20 Mar 2026 01:30:14 -0400 Subject: [PATCH 10/71] Add support for manafold caching --- Cargo.lock | 30 ++- interpreter/Cargo.toml | 1 + interpreter/src/execution/store.rs | 38 +++- .../src/execution/values/manifold_mesh.rs | 195 +++++++++++++----- interpreter/src/execution/values/vector.rs | 46 ++++- 5 files changed, 254 insertions(+), 56 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 45753c0..b6112a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -591,7 +591,7 @@ dependencies = [ [[package]] name = "boolmesh" version = "0.1.9" -source = "git+https://github.com/IamTheCarl/boolmesh.git?branch=command-cad#40f230bfa4a08618579f5fb22e0dd1fbaf4aa87f" +source = "git+https://github.com/IamTheCarl/boolmesh.git?branch=command-cad#0a861a78c1cf3d20e3bfc33f14be49f4a22333a2" dependencies = [ "fxhash", "geo", @@ -757,6 +757,33 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + [[package]] name = "clap" version = "4.5.60" @@ -2501,6 +2528,7 @@ version = "0.1.0" dependencies = [ "ariadne", "boolmesh", + "ciborium", "common_data_types", "enum_dispatch", "enum_downcast", diff --git a/interpreter/Cargo.toml b/interpreter/Cargo.toml index 784ab7d..98637ef 100644 --- a/interpreter/Cargo.toml +++ b/interpreter/Cargo.toml @@ -34,6 +34,7 @@ stl_io = "0.10.0" itertools = "0.14.0" thiserror = "2.0.18" geo = { version = "0.32.0", features = ["serde"] } +ciborium = "0.2.2" [build-dependencies] type-sitter-gen = "0.8" diff --git a/interpreter/src/execution/store.rs b/interpreter/src/execution/store.rs index 1bd9966..3bc4d74 100644 --- a/interpreter/src/execution/store.rs +++ b/interpreter/src/execution/store.rs @@ -17,11 +17,12 @@ */ use std::{ - io::{ErrorKind, Write}, + io::{BufReader, BufWriter, ErrorKind, Write}, path::{Path, PathBuf}, }; use enum_dispatch::enum_dispatch; +use serde::{de::DeserializeOwned, Serialize}; use sha2::{Digest, Sha256}; use tempfile::{NamedTempFile, TempDir}; @@ -40,6 +41,41 @@ pub trait StoreTrait { init: impl FnOnce(&mut NamedTempFile) -> ExecutionResult<()>, ) -> ExecutionResult; + fn get_or_init_object( + &self, + context: &ExecutionContext, + hashable: &impl std::hash::Hash, + name: impl AsRef, + init: impl FnOnce() -> ExecutionResult, + ) -> ExecutionResult + where + S: Serialize + DeserializeOwned, + { + let mut object = None; + let file_path = self.get_or_init_file(context, hashable, name, |file| { + let new_object = init()?; + let mut buf_writer = BufWriter::new(file); + ciborium::into_writer(&new_object, &mut buf_writer) + .map_err(|error| error.to_error(context))?; + buf_writer + .flush() + .map_err(|error| error.to_error(context))?; + + object = Some(new_object); + + Ok(()) + })?; + + if let Some(object) = object { + Ok(object) + } else { + let file = std::fs::File::open(file_path).map_err(|error| error.to_error(context))?; + let reader = BufReader::new(file); + let object = ciborium::from_reader(reader).map_err(|error| error.to_error(context))?; + Ok(object) + } + } + fn get_or_init_directory( &self, context: &ExecutionContext, diff --git a/interpreter/src/execution/values/manifold_mesh.rs b/interpreter/src/execution/values/manifold_mesh.rs index 3cb6861..dc1c64f 100644 --- a/interpreter/src/execution/values/manifold_mesh.rs +++ b/interpreter/src/execution/values/manifold_mesh.rs @@ -47,19 +47,19 @@ impl Eq for ManifoldMesh3D {} impl PartialEq for ManifoldMesh3D { fn eq(&self, other: &Self) -> bool { - // FIXME this is skipping a lot of information. - self.0.ps == other.0.ps + self.0.ps == other.0.ps && self.0.hs == other.0.hs } } impl std::hash::Hash for ManifoldMesh3D { fn hash(&self, state: &mut H) { - // FIXME this is skipping a lot of information. self.0.ps.iter().for_each(|v| { v.x.to_le_bytes().hash(state); v.y.to_le_bytes().hash(state); v.z.to_le_bytes().hash(state); }); + + self.0.hs.iter().for_each(|half_edge| half_edge.hash(state)); } } @@ -86,17 +86,37 @@ impl Object for ManifoldMesh3D { let input = Self::unpack_arithmetic_input(context, 0.0, rhs)?; match input { ArethmeticInput::Vector(vector) => { - let vector = vector.raw_value(); + let raw_vector = vector.raw_value(); + + let new_manifold = context.store.get_or_init_object( + context, + &(&self, &vector), + "manifold-translate", + || { + self.0 + .translate(raw_vector.x, raw_vector.y, raw_vector.z) + .map_err(|error| error.to_error(context)) + }, + )?; let manifold = Arc::make_mut(&mut self.0); - *manifold = manifold - .translate(vector.x, vector.y, vector.z) - .map_err(|error| error.to_error(context))?; + *manifold = new_manifold; + Ok(self.into()) } ArethmeticInput::Manifold(rhs) => { - let manifold = compute_boolean(&self.0, &rhs.0, OpType::Add) - .map_err(|error| error.to_error(context))?; - Ok(Self(Arc::new(manifold)).into()) + let new_manifold = context.store.get_or_init_object( + context, + &(&self, &rhs), + "manifold-or", + || { + compute_boolean(&self.0, &rhs.0, OpType::Add) + .map_err(|error| error.to_error(context)) + }, + )?; + let manifold = Arc::make_mut(&mut self.0); + *manifold = new_manifold; + + Ok(self.into()) } } } @@ -105,54 +125,102 @@ impl Object for ManifoldMesh3D { let input = Self::unpack_arithmetic_input(context, 0.0, rhs)?; match input { ArethmeticInput::Vector(vector) => { - let vector = vector.raw_value(); + let raw_vector = vector.raw_value(); + + let neg_vector = Vector3::new_raw(context, Dimension::length(), -raw_vector)?; + + let new_manifold = context.store.get_or_init_object( + context, + &(&self, &(neg_vector)), + "manifold-translate", + || { + self.0 + .translate(-raw_vector.x, -raw_vector.y, -raw_vector.z) + .map_err(|error| error.to_error(context)) + }, + )?; let manifold = Arc::make_mut(&mut self.0); - *manifold = manifold - .translate(-vector.x, -vector.y, -vector.z) - .map_err(|error| error.to_error(context))?; + *manifold = new_manifold; + Ok(self.into()) } ArethmeticInput::Manifold(rhs) => { - let manifold = compute_boolean(&self.0, &rhs.0, OpType::Subtract) - .map_err(|error| error.to_error(context))?; - Ok(Self(Arc::new(manifold)).into()) + let new_manifold = context.store.get_or_init_object( + context, + &(&self, &rhs), + "manifold-subtract", + || { + compute_boolean(&self.0, &rhs.0, OpType::Subtract) + .map_err(|error| error.to_error(context)) + }, + )?; + let manifold = Arc::make_mut(&mut self.0); + *manifold = new_manifold; + + Ok(self.into()) } } } fn multiply(mut self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { let input = rhs.downcast::(context)?; + let input = input.0; let vector = input.raw_value(); + let new_manifold = context.store.get_or_init_object( + context, + &(&self, &input), + "manifold-scale", + || { + self.0 + .scale(vector.x, vector.y, vector.z) + .map_err(|error| error.to_error(context)) + }, + )?; let manifold = Arc::make_mut(&mut self.0); - *manifold = manifold - .scale(vector.x, vector.y, vector.z) - .map_err(|error| error.to_error(context))?; + *manifold = new_manifold; + Ok(self.into()) } - fn bit_or(self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { + fn bit_or(mut self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { let rhs: &Self = rhs.downcast_for_binary_op_ref(context)?; - let manifold = compute_boolean(&self.0, &rhs.0, OpType::Add) - .map_err(|error| error.to_error(context))?; - Ok(Self(Arc::new(manifold)).into()) + let new_manifold = + context + .store + .get_or_init_object(context, &(&self, rhs), "manifold-or", || { + compute_boolean(&self.0, &rhs.0, OpType::Add) + .map_err(|error| error.to_error(context)) + })?; + let manifold = Arc::make_mut(&mut self.0); + *manifold = new_manifold; + + Ok(self.into()) } - fn bit_xor(self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { + fn bit_xor(mut self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { let rhs: &Self = rhs.downcast_for_binary_op_ref(context)?; + let new_manifold = + context + .store + .get_or_init_object(context, &(&self, rhs), "manifold-xor", || { + // To compute xor, get the intersectiona and then subtract it from the union of the two + // shapes. - // To compute xor, get the intersectiona and then subtract it from the union of the two - // shapes. + let intersection = compute_boolean(&self.0, &rhs.0, OpType::Intersect) + .map_err(|error| error.to_error(context))?; - let intersection = compute_boolean(&self.0, &rhs.0, OpType::Intersect) - .map_err(|error| error.to_error(context))?; + let union = compute_boolean(&self.0, &rhs.0, OpType::Add) + .map_err(|error| error.to_error(context))?; - let union = compute_boolean(&self.0, &rhs.0, OpType::Add) - .map_err(|error| error.to_error(context))?; + let difference = compute_boolean(&union, &intersection, OpType::Subtract) + .map_err(|error| error.to_error(context))?; - let difference = compute_boolean(&union, &intersection, OpType::Subtract) - .map_err(|error| error.to_error(context))?; + Ok(difference) + })?; + let manifold = Arc::make_mut(&mut self.0); + *manifold = new_manifold; - Ok(Self(Arc::new(difference)).into()) + Ok(self.into()) } fn bit_and(self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { @@ -279,8 +347,12 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { { let radius = unpack_radius(context, radius, diameter)?; - let manifold = generate_cone(apex.into(), center.into(), radius, divide.0 as usize) - .map_err(|error| error.to_error(context))?; + let manifold = context + .store + .get_or_init_object(context, &(apex.0, center.0, radius.to_le_bytes(), divide), "manifold-cone", || { + generate_cone(apex.into(), center.into(), radius, divide.0 as usize) + .map_err(|error| error.to_error(context)) + })?; Ok(ManifoldMesh3D(Arc::new(manifold))) } ); @@ -291,10 +363,15 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { size: Length3 ) -> ManifoldMesh3D { let size: Vector3 = size.into(); - let size = size.raw_value(); + let raw_size = size.raw_value(); + + let manifold = context + .store + .get_or_init_object(context, &(&size), "manifold-cube", || { + let manifold = generate_cube().map_err(|error| error.to_error(context))?; + manifold.scale(raw_size.x, raw_size.y, raw_size.z).map_err(|error| error.to_error(context)) + })?; - let mut manifold = generate_cube().map_err(|error| error.to_error(context))?; - manifold = manifold.scale(size.x, size.y, size.z).map_err(|error| error.to_error(context))?; Ok(ManifoldMesh3D(Arc::new(manifold))) } @@ -311,8 +388,13 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { ) -> ManifoldMesh3D { let radius = unpack_radius(context, radius, diameter)?; - let manifold = generate_cylinder(radius, height.into(), sectors.0 as usize, stacks.0 as usize) - .map_err(|error| error.to_error(context))?; + let manifold = context + .store + .get_or_init_object(context, &(radius.to_le_bytes(), height.value.to_le_bytes(), sectors.0, stacks.0), "manifold-cylinder", || { + generate_cylinder(radius, height.into(), sectors.0 as usize, stacks.0 as usize) + .map_err(|error| error.to_error(context)) + })?; + Ok(ManifoldMesh3D(Arc::new(manifold))) } ); @@ -326,9 +408,13 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { ) -> ManifoldMesh3D { let scale = unpack_radius(context, radius, diameter)?; - let mut manifold = generate_icosphere(subdivions.0 as u32) - .map_err(|error| error.to_error(context))?; - manifold = manifold.scale(scale, scale, scale).map_err(|error| error.to_error(context))?; + let manifold = context + .store + .get_or_init_object(context, &(scale.to_le_bytes(), subdivions.0), "manifold-icosphere", || { + let manifold = generate_icosphere(subdivions.0 as u32) + .map_err(|error| error.to_error(context))?; + manifold.scale(scale, scale, scale).map_err(|error| error.to_error(context)) + })?; Ok(ManifoldMesh3D(Arc::new(manifold))) } @@ -338,12 +424,17 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { methods::GenerateTorus, "ManifoldMesh3D::torus", ( context: &ExecutionContext, major_radius: Length, - minor_raidus: Length, + minor_radius: Length, rings: UnsignedInteger, sectors: UnsignedInteger ) -> ManifoldMesh3D { - let manifold = generate_torus(major_radius.into(), minor_raidus.into(), rings.0 as usize, sectors.0 as usize) - .map_err(|error| error.to_error(context))?; + let manifold = context + .store + .get_or_init_object(context, &(major_radius.value.to_le_bytes(), minor_radius.value.to_le_bytes(), rings.0, sectors.0), "manifold-torus", || { + generate_torus(major_radius.into(), minor_radius.into(), rings.0 as usize, sectors.0 as usize) + .map_err(|error| error.to_error(context)) + })?; + Ok(ManifoldMesh3D(Arc::new(manifold))) } ); @@ -358,9 +449,13 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { ) -> ManifoldMesh3D { let scale = unpack_radius(context, radius, diameter)?; - let mut manifold = generate_uv_sphere(sectors.0 as usize, stacks.0 as usize) - .map_err(|error| error.to_error(context))?; - manifold = manifold.scale(scale, scale, scale).map_err(|error| error.to_error(context))?; + let manifold = context + .store + .get_or_init_object(context, &(sectors.0, stacks.0, scale.to_le_bytes()), "manifold-torus", || { + let manifold = generate_uv_sphere(sectors.0 as usize, stacks.0 as usize) + .map_err(|error| error.to_error(context))?; + manifold.scale(scale, scale, scale).map_err(|error| error.to_error(context)) + })?; Ok(ManifoldMesh3D(Arc::new(manifold))) } diff --git a/interpreter/src/execution/values/vector.rs b/interpreter/src/execution/values/vector.rs index 5d4b524..7094869 100644 --- a/interpreter/src/execution/values/vector.rs +++ b/interpreter/src/execution/values/vector.rs @@ -20,7 +20,6 @@ use crate::{ use std::{ borrow::Cow, - hash::Hash, ops::{Add, Div, Mul, Neg, Sub}, }; @@ -30,7 +29,7 @@ pub type Vector2 = Vector>; pub type Vector3 = Vector>; pub type Vector4 = Vector>; -#[derive(Debug, Hash, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq)] pub struct Vector { dimension: Dimension, value: I, @@ -38,6 +37,16 @@ pub struct Vector { impl Eq for Vector where I: PartialEq {} +impl std::hash::Hash for Vector +where + I: VectorInternalType, +{ + fn hash(&self, state: &mut H) { + self.dimension.hash(state); + self.value.hash(state); + } +} + impl Object for Vector where I: VectorInternalType, @@ -199,7 +208,7 @@ where I::from_ast(context, ast_node) } - fn new_raw( + pub fn new_raw( context: &ExecutionContext, dimension: Dimension, value: I, @@ -623,6 +632,8 @@ pub trait VectorInternalType: fn normalize(&self) -> Self; fn angle(&self, other: &Self) -> Float; fn iter(&self) -> impl Iterator; + + fn hash(&self, hasher: &mut impl std::hash::Hasher); } pub trait IsNan { @@ -763,6 +774,10 @@ impl VectorInternalType for nalgebra::Vector2 { fn iter(&self) -> impl Iterator { self.iter().copied() } + + fn hash(&self, hasher: &mut impl std::hash::Hasher) { + std::hash::Hash::hash(&(&self.x.to_le_bytes(), &self.y.to_le_bytes()), hasher) + } } impl TransformableVector for nalgebra::Vector2 { @@ -894,6 +909,17 @@ impl VectorInternalType for nalgebra::Vector3 { fn iter(&self) -> impl Iterator { self.iter().copied() } + + fn hash(&self, hasher: &mut impl std::hash::Hasher) { + std::hash::Hash::hash( + &( + &self.x.to_le_bytes(), + &self.y.to_le_bytes(), + &self.z.to_le_bytes(), + ), + hasher, + ) + } } impl TransformableVector for nalgebra::Vector3 { @@ -1028,6 +1054,18 @@ impl VectorInternalType for nalgebra::Vector4 { fn iter(&self) -> impl Iterator { self.iter().copied() } + + fn hash(&self, hasher: &mut impl std::hash::Hasher) { + std::hash::Hash::hash( + &( + &self.x.to_le_bytes(), + &self.y.to_le_bytes(), + &self.z.to_le_bytes(), + &self.w.to_le_bytes(), + ), + hasher, + ) + } } impl StaticTypeName for nalgebra::Vector4 { fn static_type_name() -> Cow<'static, str> { @@ -1055,7 +1093,7 @@ macro_rules! equivalent_boolmesh_vector { macro_rules! build_vector_type { ($name:ident: $type:tt = $dimension:expr) => { - pub struct $name($type); + pub struct $name(pub $type); impl StaticTypeName for $name { fn static_type_name() -> Cow<'static, str> { From c8eacdf89eca05332b6850e8b243763d98c89ba4 Mon Sep 17 00:00:00 2001 From: James Carl Date: Sat, 21 Mar 2026 00:39:48 -0400 Subject: [PATCH 11/71] Add boolean ops to polygons --- Cargo.lock | 23 ++++++ examples/modeling/line_string.ccm | 1 + examples/modeling/polygon.ccm | 1 + gui/Cargo.toml | 1 + gui/src/main.rs | 40 +++++++---- interpreter/src/execution/values/polygon.rs | 77 ++++++++++++++++++--- interpreter/src/lib.rs | 1 + 7 files changed, 123 insertions(+), 21 deletions(-) create mode 100644 examples/modeling/line_string.ccm create mode 100644 examples/modeling/polygon.ccm diff --git a/Cargo.lock b/Cargo.lock index b6112a8..a3bedf7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1619,6 +1619,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "file-id" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1fc6a637b6dc58414714eddd9170ff187ecb0933d4c7024d1abbd23a3cc26e9" +dependencies = [ + "windows-sys 0.60.2", +] + [[package]] name = "find-msvc-tools" version = "0.1.9" @@ -2164,6 +2173,7 @@ dependencies = [ "egui", "interpreter", "notify", + "notify-debouncer-full", "oneshot", "tempfile", ] @@ -3168,6 +3178,19 @@ dependencies = [ "windows-sys 0.60.2", ] +[[package]] +name = "notify-debouncer-full" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c02b49179cfebc9932238d04d6079912d26de0379328872846118a0fa0dbb302" +dependencies = [ + "file-id", + "log", + "notify", + "notify-types", + "walkdir", +] + [[package]] name = "notify-types" version = "2.1.0" diff --git a/examples/modeling/line_string.ccm b/examples/modeling/line_string.ccm new file mode 100644 index 0000000..eebbb77 --- /dev/null +++ b/examples/modeling/line_string.ccm @@ -0,0 +1 @@ +std.import diff --git a/examples/modeling/polygon.ccm b/examples/modeling/polygon.ccm new file mode 100644 index 0000000..c638adb --- /dev/null +++ b/examples/modeling/polygon.ccm @@ -0,0 +1 @@ +std.polygon.circle(diameter = 1m, distance_between_points = 15cm) - std.polygon.circle(diameter = 0.5m, distance_between_points = 15cm) diff --git a/gui/Cargo.toml b/gui/Cargo.toml index e915e30..7a63833 100644 --- a/gui/Cargo.toml +++ b/gui/Cargo.toml @@ -11,3 +11,4 @@ anyhow = { workspace = true } oneshot = "0.2.1" tempfile = { workspace = true } notify = "8.2.0" +notify-debouncer-full = "0.7" diff --git a/gui/src/main.rs b/gui/src/main.rs index b1001ac..ff3688c 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -3,17 +3,22 @@ use std::{ fmt::Display, path::{Path, PathBuf}, sync::{atomic::AtomicBool, mpsc, Arc, Mutex}, + time::Duration, }; use eframe::egui; -use egui::{Color32, RichText}; +use egui::{ + epaint::{ColorMode, PathShape, PathStroke}, + Color32, Pos2, RichText, Shape, StrokeKind, +}; use interpreter::{ build_prelude, compile, execute_expression, new_parser, - values::{BuiltinCallableDatabase, Object, Style, Value}, + values::{BuiltinCallableDatabase, LineString, Object, Style, Value}, ExecutionContext, FsStore, ImString, LogMessage, Parser, RuntimeLog, SourceReference, StackScope, StackTrace, Store, }; use notify::{recommended_watcher, EventKind, RecommendedWatcher, Watcher}; +use notify_debouncer_full::{new_debouncer, Debouncer, RecommendedCache}; use tempfile::TempDir; fn main() { @@ -67,6 +72,7 @@ struct PendingJob { enum RuntimeValue { TextValue(String), + LineString(LineString), // Polygon(Polygon), // PolygonSet(PolygonSet), // ManifoldMesh(ManifoldMesh3D), @@ -149,6 +155,7 @@ fn runtime(expression_rx: mpsc::Receiver) { let expression_result = execute_expression(&context, &root); let result = match expression_result { + Ok(Value::LineString(line_string)) => Ok(RuntimeValue::LineString(line_string)), Ok(value) => { let mut text = String::new(); value.format(&context, &mut text, Style::Default, None).ok(); @@ -160,7 +167,6 @@ fn runtime(expression_rx: mpsc::Receiver) { // TODO we can also use this for better error message formatting. let files = files.into_inner().expect("File hashmap was poisoned"); - let files_to_watch: HashSet> = files.keys().cloned().collect(); RuntimeOutput { @@ -183,8 +189,8 @@ struct CommandCAD { active_job: Option, last_result: Option>, watched_files: HashSet>, - file_watcher: Result, - file_updates_rx: mpsc::Receiver>, + file_watcher: Result, notify::Error>, + file_updates_rx: mpsc::Receiver, } impl CommandCAD { @@ -195,7 +201,7 @@ impl CommandCAD { let (file_updates_tx, file_updates_rx) = mpsc::channel(); let gui_ctx = cc.egui_ctx.clone(); - let file_watcher = recommended_watcher(move |event| { + let file_watcher = new_debouncer(Duration::from_millis(10), None, move |event| { // Notify and refresh the GUI whenever there's an update to one of the project files. file_updates_tx.send(event).ok(); gui_ctx.request_repaint(); @@ -265,18 +271,21 @@ impl CommandCAD { // Collect a list of files to watch. if let Ok(watcher) = &mut self.file_watcher { - let removed = self.watched_files.difference(&output.files_to_watch); - let added = output.files_to_watch.difference(&self.watched_files); + // We used to be very picky, only adding and removing files from the wather as + // needed. It was eventually discovered that sometimes watchers that were not + // removed (and were not supposed to be removed) would fail to trigger on later + // edits of files, so now we just remove and re-add everything to make sure + // we're in a good known state. let mut paths = watcher.paths_mut(); - for path in removed { + for path in self.watched_files.iter() { // TODO log errors and success here. - paths.remove(&path).ok(); + paths.remove(path).ok(); } - for path in added { + for path in output.files_to_watch.iter() { // TODO log errors and success here. - paths.add(&path, notify::RecursiveMode::NonRecursive).ok(); + paths.add(path, notify::RecursiveMode::NonRecursive).ok(); } } @@ -319,6 +328,13 @@ impl eframe::App for CommandCAD { Some(Ok(RuntimeValue::TextValue(text))) => { ui.label(text); } + Some(Ok(RuntimeValue::LineString(line_string))) => { + // TODO this needs a way to scale. + let painter = ui.painter(); + let line_string = &line_string.0; + let path = PathShape { points: line_string.coords().map(|coord| Pos2::new(coord.x as f32, coord.y as f32)).collect(), closed: line_string.is_closed(), fill: Color32::TRANSPARENT, stroke: PathStroke { width: 2.0, color: ColorMode::TRANSPARENT, kind: StrokeKind::Middle } }; + painter.add(Shape::Path(path)); + } Some(Err(error)) => { ui.label(RichText::new(format!("{error}")).color(Color32::RED)); } diff --git a/interpreter/src/execution/values/polygon.rs b/interpreter/src/execution/values/polygon.rs index 15a0bf8..65ed5ca 100644 --- a/interpreter/src/execution/values/polygon.rs +++ b/interpreter/src/execution/values/polygon.rs @@ -19,13 +19,15 @@ use std::sync::Arc; use common_data_types::{Dimension, RawFloat}; +use geo::{BooleanOps, OpType}; use nalgebra::Matrix3; use crate::{ execution::errors::Raise, values::{ - iterators::IterableObject, BuiltinCallableDatabase, BuiltinFunction, MissingAttributeError, - Object, StaticType, StaticTypeName, Style, Value, ValueType, Vector2, + iterators::IterableObject, BuiltinCallableDatabase, BuiltinFunction, DowncastError, + MissingAttributeError, Object, StaticType, StaticTypeName, Style, Value, ValueType, + Vector2, }, ExecutionContext, ExecutionResult, }; @@ -45,13 +47,30 @@ use crate::{ // slice - should probably live in manifold // bounding rec - manifold should also have one +fn boolean_op_with( + context: &ExecutionContext, + left: &impl BooleanOps, + right: Value, + op: OpType, +) -> ExecutionResult { + match right { + Value::Polygon(right) => Ok(PolygonSet(Arc::new(left.boolean_op(&*right.0, op))).into()), + Value::PolygonSet(right) => Ok(PolygonSet(Arc::new(left.boolean_op(&*right.0, op))).into()), + value => Err(DowncastError { + expected: "Polygon or PolygonSet".into(), + got: value.get_type(context).name(), + } + .to_error(context)), + } +} + /// Applies a transformation to an object. trait ApplyTransform { fn apply_transform(&mut self, transform: &Matrix3); } #[derive(Debug, Clone)] -pub struct LineString(Arc); +pub struct LineString(pub Arc); impl Object for LineString { fn get_type(&self, _context: &ExecutionContext) -> ValueType { @@ -193,7 +212,7 @@ impl IterableObject for RevLineStringIterator { } #[derive(Debug, Clone)] -pub struct Polygon(Arc); +pub struct Polygon(pub Arc); impl Object for Polygon { fn get_type(&self, _context: &ExecutionContext) -> ValueType { @@ -211,6 +230,26 @@ impl Object for Polygon { write!(f, "{:?}", self.0) } + fn addition(self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { + boolean_op_with(context, &*self.0, rhs, OpType::Union) + } + + fn subtraction(self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { + boolean_op_with(context, &*self.0, rhs, OpType::Difference) + } + + fn bit_and(self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { + boolean_op_with(context, &*self.0, rhs, OpType::Intersection) + } + + fn bit_or(self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { + boolean_op_with(context, &*self.0, rhs, OpType::Union) + } + + fn bit_xor(self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { + boolean_op_with(context, &*self.0, rhs, OpType::Xor) + } + fn get_attribute( &self, context: &ExecutionContext, @@ -283,7 +322,7 @@ impl ApplyTransform for geo::Polygon { } #[derive(Debug, Clone)] -pub struct PolygonSet(Arc); +pub struct PolygonSet(pub Arc); impl Object for PolygonSet { fn get_type(&self, _context: &ExecutionContext) -> ValueType { @@ -301,6 +340,26 @@ impl Object for PolygonSet { write!(f, "{:?}", self.0) } + fn addition(self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { + boolean_op_with(context, &*self.0, rhs, OpType::Union) + } + + fn subtraction(self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { + boolean_op_with(context, &*self.0, rhs, OpType::Difference) + } + + fn bit_and(self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { + boolean_op_with(context, &*self.0, rhs, OpType::Intersection) + } + + fn bit_or(self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { + boolean_op_with(context, &*self.0, rhs, OpType::Union) + } + + fn bit_xor(self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { + boolean_op_with(context, &*self.0, rhs, OpType::Xor) + } + fn get_attribute( &self, context: &ExecutionContext, @@ -764,7 +823,7 @@ pub mod methods_and_functions { let number_of_points = if let Some(number_of_points) = number_of_points { number_of_points.0 as usize } else { - (SEGMENT_ANGLE_RADIANS / segment_angle) as usize + (SEGMENT_ANGLE_RADIANS / segment_angle) as usize + 1 }; Ok(Self { @@ -1246,13 +1305,13 @@ mod test { let result = test_run("std.polygon.circle(radius = 1m, angle_between_points = 1rad)").unwrap(); let polygon = result.as_polygon().unwrap(); - assert_eq!(polygon.0.exterior().0.len(), 3); + assert_eq!(polygon.0.exterior().0.len(), 4); assert!(polygon.0.interiors().is_empty()); let result = test_run("std.polygon.circle(radius = 1m, angle_between_points = 0.5rad)").unwrap(); let polygon = result.as_polygon().unwrap(); - assert_eq!(polygon.0.exterior().0.len(), 5); + assert_eq!(polygon.0.exterior().0.len(), 6); assert!(polygon.0.interiors().is_empty()); // Test distance_between_points @@ -1260,7 +1319,7 @@ mod test { test_run("std.polygon.circle(radius = 1m, distance_between_points = 3.14159m)") .unwrap(); let polygon = result.as_polygon().unwrap(); - assert_eq!(polygon.0.exterior().0.len(), 3); + assert_eq!(polygon.0.exterior().0.len(), 4); assert!(polygon.0.interiors().is_empty()); // Test number_of_points diff --git a/interpreter/src/lib.rs b/interpreter/src/lib.rs index 932da5b..0a9ed3b 100644 --- a/interpreter/src/lib.rs +++ b/interpreter/src/lib.rs @@ -25,5 +25,6 @@ pub use execution::{ ExecutionFileCache, ExecutionResult, FsStore, LogLevel, LogMessage, RuntimeLog, StackScope, StackTrace, Store, }; +pub use geo; pub use imstr::ImString; pub use tree_sitter::{Point as TextPoint, Range as TextRange}; From 8b491228278004afdb036d31da2bf5a6fac28ae2 Mon Sep 17 00:00:00 2001 From: James Carl Date: Sat, 21 Mar 2026 11:20:49 -0400 Subject: [PATCH 12/71] Add translation to polygons --- interpreter/src/execution/values/polygon.rs | 113 ++++++++++++++++---- 1 file changed, 91 insertions(+), 22 deletions(-) diff --git a/interpreter/src/execution/values/polygon.rs b/interpreter/src/execution/values/polygon.rs index 65ed5ca..e206210 100644 --- a/interpreter/src/execution/values/polygon.rs +++ b/interpreter/src/execution/values/polygon.rs @@ -20,7 +20,7 @@ use std::sync::Arc; use common_data_types::{Dimension, RawFloat}; use geo::{BooleanOps, OpType}; -use nalgebra::Matrix3; +use nalgebra::{Matrix3, Translation2}; use crate::{ execution::errors::Raise, @@ -32,12 +32,6 @@ use crate::{ ExecutionContext, ExecutionResult, }; -// Add -// Subtract -// BitOr -// BitXor -// BitAnd -// We need a way to collect a list of polygons into a multi-polygon // Ray-cast with linestrings and polygons // to_svg // from_svg? @@ -51,13 +45,14 @@ fn boolean_op_with( context: &ExecutionContext, left: &impl BooleanOps, right: Value, + expected: Option<&'static str>, op: OpType, ) -> ExecutionResult { match right { Value::Polygon(right) => Ok(PolygonSet(Arc::new(left.boolean_op(&*right.0, op))).into()), Value::PolygonSet(right) => Ok(PolygonSet(Arc::new(left.boolean_op(&*right.0, op))).into()), value => Err(DowncastError { - expected: "Polygon or PolygonSet".into(), + expected: expected.unwrap_or("Polygon or PolygonSet").into(), got: value.get_type(context).name(), } .to_error(context)), @@ -67,6 +62,12 @@ fn boolean_op_with( /// Applies a transformation to an object. trait ApplyTransform { fn apply_transform(&mut self, transform: &Matrix3); + + fn translate(&mut self, offset: nalgebra::Vector2) { + let translation = Translation2::from(offset); + let matrix = translation.to_homogeneous(); + self.apply_transform(&matrix); + } } #[derive(Debug, Clone)] @@ -88,6 +89,22 @@ impl Object for LineString { write!(f, "{:?}", self.0) } + fn addition(mut self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { + let offset: Vector2 = rhs.downcast(context)?; + + let polygon = Arc::make_mut(&mut self.0); + polygon.translate(offset.raw_value()); + Ok(self.into()) + } + + fn subtraction(mut self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { + let offset: Vector2 = rhs.downcast(context)?; + + let polygon = Arc::make_mut(&mut self.0); + polygon.translate(-offset.raw_value()); + Ok(self.into()) + } + fn get_attribute( &self, context: &ExecutionContext, @@ -230,24 +247,50 @@ impl Object for Polygon { write!(f, "{:?}", self.0) } - fn addition(self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { - boolean_op_with(context, &*self.0, rhs, OpType::Union) + fn addition(mut self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { + match rhs { + Value::Vector2(offset) => { + let polygon = Arc::make_mut(&mut self.0); + polygon.translate(offset.raw_value()); + Ok(self.into()) + } + rhs => boolean_op_with( + context, + &*self.0, + rhs, + Some("Polygon, PolygonSet, or Vector2"), + OpType::Union, + ), + } } - fn subtraction(self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { - boolean_op_with(context, &*self.0, rhs, OpType::Difference) + fn subtraction(mut self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { + match rhs { + Value::Vector2(offset) => { + let polygon = Arc::make_mut(&mut self.0); + polygon.translate(-offset.raw_value()); + Ok(self.into()) + } + rhs => boolean_op_with( + context, + &*self.0, + rhs, + Some("Polygon, PolygonSet, or Vector2"), + OpType::Difference, + ), + } } fn bit_and(self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { - boolean_op_with(context, &*self.0, rhs, OpType::Intersection) + boolean_op_with(context, &*self.0, rhs, None, OpType::Intersection) } fn bit_or(self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { - boolean_op_with(context, &*self.0, rhs, OpType::Union) + boolean_op_with(context, &*self.0, rhs, None, OpType::Union) } fn bit_xor(self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { - boolean_op_with(context, &*self.0, rhs, OpType::Xor) + boolean_op_with(context, &*self.0, rhs, None, OpType::Xor) } fn get_attribute( @@ -340,24 +383,50 @@ impl Object for PolygonSet { write!(f, "{:?}", self.0) } - fn addition(self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { - boolean_op_with(context, &*self.0, rhs, OpType::Union) + fn addition(mut self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { + match rhs { + Value::Vector2(offset) => { + let polygon = Arc::make_mut(&mut self.0); + polygon.translate(offset.raw_value()); + Ok(self.into()) + } + rhs => boolean_op_with( + context, + &*self.0, + rhs, + Some("Polygon, PolygonSet, or Vector2"), + OpType::Union, + ), + } } - fn subtraction(self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { - boolean_op_with(context, &*self.0, rhs, OpType::Difference) + fn subtraction(mut self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { + match rhs { + Value::Vector2(offset) => { + let polygon = Arc::make_mut(&mut self.0); + polygon.translate(-offset.raw_value()); + Ok(self.into()) + } + rhs => boolean_op_with( + context, + &*self.0, + rhs, + Some("Polygon, PolygonSet, or Vector2"), + OpType::Difference, + ), + } } fn bit_and(self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { - boolean_op_with(context, &*self.0, rhs, OpType::Intersection) + boolean_op_with(context, &*self.0, rhs, None, OpType::Intersection) } fn bit_or(self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { - boolean_op_with(context, &*self.0, rhs, OpType::Union) + boolean_op_with(context, &*self.0, rhs, None, OpType::Union) } fn bit_xor(self, context: &ExecutionContext, rhs: Value) -> ExecutionResult { - boolean_op_with(context, &*self.0, rhs, OpType::Xor) + boolean_op_with(context, &*self.0, rhs, None, OpType::Xor) } fn get_attribute( From 6d148b4c30f33089bd732d4e2f3cceacc799f026 Mon Sep 17 00:00:00 2001 From: James Carl Date: Fri, 20 Mar 2026 02:59:13 -0400 Subject: [PATCH 13/71] Make output view scrollable --- gui/src/main.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gui/src/main.rs b/gui/src/main.rs index ff3688c..66f1271 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -326,7 +326,9 @@ impl eframe::App for CommandCAD { match &self.last_result { None => {} Some(Ok(RuntimeValue::TextValue(text))) => { - ui.label(text); + egui::ScrollArea::vertical().show(ui, |ui| { + ui.label(text); + }); } Some(Ok(RuntimeValue::LineString(line_string))) => { // TODO this needs a way to scale. From bc6dfbab3bc788d7297c78dfbf0a21487fceb12e Mon Sep 17 00:00:00 2001 From: James Carl Date: Sat, 21 Mar 2026 00:40:04 -0400 Subject: [PATCH 14/71] MVP 2D visualizer --- Cargo.lock | 23 ------ examples/modeling/line_string.ccm | 2 +- gui/Cargo.toml | 1 - gui/src/main.rs | 125 +++++++++++++++++++++++------- 4 files changed, 99 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a3bedf7..b6112a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1619,15 +1619,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "file-id" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fc6a637b6dc58414714eddd9170ff187ecb0933d4c7024d1abbd23a3cc26e9" -dependencies = [ - "windows-sys 0.60.2", -] - [[package]] name = "find-msvc-tools" version = "0.1.9" @@ -2173,7 +2164,6 @@ dependencies = [ "egui", "interpreter", "notify", - "notify-debouncer-full", "oneshot", "tempfile", ] @@ -3178,19 +3168,6 @@ dependencies = [ "windows-sys 0.60.2", ] -[[package]] -name = "notify-debouncer-full" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02b49179cfebc9932238d04d6079912d26de0379328872846118a0fa0dbb302" -dependencies = [ - "file-id", - "log", - "notify", - "notify-types", - "walkdir", -] - [[package]] name = "notify-types" version = "2.1.0" diff --git a/examples/modeling/line_string.ccm b/examples/modeling/line_string.ccm index eebbb77..f728e23 100644 --- a/examples/modeling/line_string.ccm +++ b/examples/modeling/line_string.ccm @@ -1 +1 @@ -std.import +std.line_string.from_points(points = [{0m, 0m}, {1m, 0m}, {1m, 1m}, {-1m, 1m}, {-1m, -1m}]) diff --git a/gui/Cargo.toml b/gui/Cargo.toml index 7a63833..e915e30 100644 --- a/gui/Cargo.toml +++ b/gui/Cargo.toml @@ -11,4 +11,3 @@ anyhow = { workspace = true } oneshot = "0.2.1" tempfile = { workspace = true } notify = "8.2.0" -notify-debouncer-full = "0.7" diff --git a/gui/src/main.rs b/gui/src/main.rs index 66f1271..75c712c 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -2,23 +2,17 @@ use std::{ collections::{HashMap, HashSet}, fmt::Display, path::{Path, PathBuf}, - sync::{atomic::AtomicBool, mpsc, Arc, Mutex}, - time::Duration, + sync::{Arc, Mutex, atomic::AtomicBool, mpsc}, time::Duration, }; use eframe::egui; use egui::{ - epaint::{ColorMode, PathShape, PathStroke}, - Color32, Pos2, RichText, Shape, StrokeKind, + Color32, Mesh, Painter, Pos2, Rect, RichText, Shape, StrokeKind, epaint::{ColorMode, PathShape, PathStroke} }; use interpreter::{ - build_prelude, compile, execute_expression, new_parser, - values::{BuiltinCallableDatabase, LineString, Object, Style, Value}, - ExecutionContext, FsStore, ImString, LogMessage, Parser, RuntimeLog, SourceReference, - StackScope, StackTrace, Store, + ExecutionContext, FsStore, LogMessage, Parser, RuntimeLog, SourceReference, StackScope, StackTrace, Store, build_prelude, compile, execute_expression, geo::TriangulateEarcut, new_parser, values::{BuiltinCallableDatabase, LineString, Object, Polygon, PolygonSet, Style, Value} }; use notify::{recommended_watcher, EventKind, RecommendedWatcher, Watcher}; -use notify_debouncer_full::{new_debouncer, Debouncer, RecommendedCache}; use tempfile::TempDir; fn main() { @@ -51,13 +45,6 @@ impl RuntimeLog for GuiLogger { } } -struct Runtime { - parser: Parser, - database: BuiltinCallableDatabase, - prelude: HashMap, - repl_file: Arc, -} - struct RuntimeJob { expression: String, egui_context: egui::Context, @@ -73,8 +60,8 @@ struct PendingJob { enum RuntimeValue { TextValue(String), LineString(LineString), - // Polygon(Polygon), - // PolygonSet(PolygonSet), + Polygon(Polygon), + PolygonSet(PolygonSet), // ManifoldMesh(ManifoldMesh3D), } @@ -156,6 +143,8 @@ fn runtime(expression_rx: mpsc::Receiver) { let result = match expression_result { Ok(Value::LineString(line_string)) => Ok(RuntimeValue::LineString(line_string)), + Ok(Value::Polygon(polygon)) => Ok(RuntimeValue::Polygon(polygon)), + Ok(Value::PolygonSet(polygon_set)) => Ok(RuntimeValue::PolygonSet(polygon_set)), Ok(value) => { let mut text = String::new(); value.format(&context, &mut text, Style::Default, None).ok(); @@ -189,8 +178,8 @@ struct CommandCAD { active_job: Option, last_result: Option>, watched_files: HashSet>, - file_watcher: Result, notify::Error>, - file_updates_rx: mpsc::Receiver, + file_watcher: Result, + file_updates_rx: mpsc::Receiver>, } impl CommandCAD { @@ -201,8 +190,20 @@ impl CommandCAD { let (file_updates_tx, file_updates_rx) = mpsc::channel(); let gui_ctx = cc.egui_ctx.clone(); - let file_watcher = new_debouncer(Duration::from_millis(10), None, move |event| { + let file_watcher = recommended_watcher(move |event: Result| { // Notify and refresh the GUI whenever there's an update to one of the project files. + + // This is a really horrible hack, but I have no idea how to better fix it and it seems + // to be what the "experts" are doing as well (I looked at a higher-level library for + // watching for file changes). Basically, sometimes we get this notification before the + // file is available on disk. We need to check and possibly wait to see if the file is + // actually ready. + if let Ok(event) = &event && matches!(event.kind, EventKind::Create(_) | EventKind::Modify(_)) { + while !event.paths.iter().all(|path| path.exists()) { + std::thread::sleep(Duration::from_millis(10)); + } + } + file_updates_tx.send(event).ok(); gui_ctx.request_repaint(); }); @@ -249,7 +250,7 @@ impl CommandCAD { fn check_if_watched_files_changed(&mut self) -> bool { match self.file_updates_rx.try_recv() { - Ok(Ok(event)) => matches!(event.kind, EventKind::Modify(_) | EventKind::Remove(_)), + Ok(Ok(event)) => matches!(event.kind, EventKind::Modify(_) | EventKind::Create(_)), // TODO log that or something. Ok(Err(error)) => { // TODO this can be logged better. @@ -323,6 +324,10 @@ impl eframe::App for CommandCAD { // Update the job status. self.check_job(); + // TODO Add controls for scale and translation. + // TODO Add some kind of scale legend. + let pixels_per_meter = 100.0; + match &self.last_result { None => {} Some(Ok(RuntimeValue::TextValue(text))) => { @@ -331,11 +336,38 @@ impl eframe::App for CommandCAD { }); } Some(Ok(RuntimeValue::LineString(line_string))) => { - // TODO this needs a way to scale. - let painter = ui.painter(); - let line_string = &line_string.0; - let path = PathShape { points: line_string.coords().map(|coord| Pos2::new(coord.x as f32, coord.y as f32)).collect(), closed: line_string.is_closed(), fill: Color32::TRANSPARENT, stroke: PathStroke { width: 2.0, color: ColorMode::TRANSPARENT, kind: StrokeKind::Middle } }; - painter.add(Shape::Path(path)); + + let draw_area = ui.available_rect_before_wrap(); + let painter = Painter::new( + ui.ctx().clone(), + ui.layer_id(), + draw_area, + ); + + painter.add(paint_linestring(draw_area, pixels_per_meter, StrokeKind::Middle, &line_string.0)); + } + Some(Ok(RuntimeValue::Polygon(polygon))) => { + + let draw_area = ui.available_rect_before_wrap(); + let painter = Painter::new( + ui.ctx().clone(), + ui.layer_id(), + draw_area, + ); + + paint_polygon(&painter, draw_area, pixels_per_meter, &polygon.0); + } + Some(Ok(RuntimeValue::PolygonSet(polygon_set))) => { + let draw_area = ui.available_rect_before_wrap(); + let painter = Painter::new( + ui.ctx().clone(), + ui.layer_id(), + draw_area, + ); + + for polygon in polygon_set.0.iter() { + paint_polygon(&painter, draw_area, pixels_per_meter, polygon); + } } Some(Err(error)) => { ui.label(RichText::new(format!("{error}")).color(Color32::RED)); @@ -344,3 +376,42 @@ impl eframe::App for CommandCAD { }); } } + +fn paint_linestring(draw_area: Rect, pixels_per_meter: f32, stroke_kind: StrokeKind, line_string: &interpreter::geo::LineString) -> Shape { + let center_offset = draw_area.center().to_vec2(); + let path = PathShape { points: line_string.coords().map(|coord| Pos2::new(coord.x as f32, coord.y as f32) * pixels_per_meter + center_offset).collect(), closed: line_string.is_closed(), fill: Color32::TRANSPARENT, stroke: PathStroke { width: 2.0, color: ColorMode::Solid(Color32::WHITE), kind: stroke_kind } }; + Shape::Path(path) +} + +fn paint_polygon(painter: &Painter, draw_area: Rect, pixels_per_meter: f32, polygon: &interpreter::geo::Polygon) { + + // Render fill + // FIXME building this on each frame is HORRIBLE + let center_offset = draw_area.center().to_vec2(); + let mut mesh = Mesh::default(); + let triangulation = polygon.earcut_triangles_raw(); + for vert in triangulation.vertices.chunks(2) { + let x = vert[0]; + let y = vert[1]; + + mesh.colored_vertex(Pos2::new(x as f32, y as f32) * pixels_per_meter + center_offset, Color32::GRAY); + } + + for triangle in triangulation.triangle_indices.chunks(3) { + let a = triangle[0]; + let b = triangle[1]; + let c = triangle[2]; + + mesh.add_triangle(a as u32, b as u32, c as u32); + } + + painter.add(Shape::Mesh(Arc::new(mesh))); + + // Render exterior + painter.add(paint_linestring(draw_area, pixels_per_meter, StrokeKind::Inside, polygon.exterior())); + + // Render interior. + for interior in polygon.interiors() { + painter.add(paint_linestring(draw_area, pixels_per_meter, StrokeKind::Outside, interior)); + } +} From 1b4b018a14850d803309b40eee4bc609834445cf Mon Sep 17 00:00:00 2001 From: James Carl Date: Sat, 21 Mar 2026 01:40:29 -0400 Subject: [PATCH 15/71] Bigger text editing area --- gui/src/main.rs | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/gui/src/main.rs b/gui/src/main.rs index 75c712c..f1d5a3e 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -7,7 +7,7 @@ use std::{ use eframe::egui; use egui::{ - Color32, Mesh, Painter, Pos2, Rect, RichText, Shape, StrokeKind, epaint::{ColorMode, PathShape, PathStroke} + Align, Color32, Layout, Mesh, Painter, Pos2, Rect, RichText, Shape, StrokeKind, TextEdit, epaint::{ColorMode, PathShape, PathStroke} }; use interpreter::{ ExecutionContext, FsStore, LogMessage, Parser, RuntimeLog, SourceReference, StackScope, StackTrace, Store, build_prelude, compile, execute_expression, geo::TriangulateEarcut, new_parser, values::{BuiltinCallableDatabase, LineString, Object, Polygon, PolygonSet, Style, Value} @@ -299,20 +299,21 @@ impl CommandCAD { impl eframe::App for CommandCAD { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { egui::CentralPanel::default().show(ctx, |ui| { - ui.horizontal(|ui| { - ui.label("Expression: "); - if ui.text_edit_singleline(&mut self.expression).changed() - || self.check_if_watched_files_changed() - { - self.spawn_job(ctx); - } + let expression_editor = TextEdit::multiline(&mut self.expression) + .code_editor() + .desired_width(f32::INFINITY) + .hint_text("expression"); + if ui.add(expression_editor).changed() + || self.check_if_watched_files_changed() + { + self.spawn_job(ctx); + } - if self.active_job.is_some() { - ui.label(RichText::new("Working...").color(Color32::YELLOW)); - } else { - ui.label(RichText::new("Ready").color(Color32::GREEN)); - } - }); + if self.active_job.is_some() { + ui.label(RichText::new("Working...").color(Color32::YELLOW)); + } else { + ui.label(RichText::new("Ready").color(Color32::GREEN)); + } if let Err(error) = &self.file_watcher { ui.label( From 8ee05b99233cfb6ae78afa651414ef9a8ab1f474 Mon Sep 17 00:00:00 2001 From: James Carl Date: Sat, 21 Mar 2026 11:03:04 -0400 Subject: [PATCH 16/71] Add 2d navigation controls --- cli/src/main.rs | 9 +-- gui/src/main.rs | 190 ++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 163 insertions(+), 36 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index 687d73a..6100a54 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,11 +1,11 @@ use std::{ collections::HashMap, path::{Path, PathBuf}, - sync::{atomic::AtomicBool, Arc, Mutex}, + sync::{Arc, Mutex, atomic::AtomicBool}, }; mod arguments; -use anyhow::{anyhow, bail, Context, Result}; +use anyhow::{Context, Result, anyhow, bail}; use arguments::Arguments; use ariadne::{Cache, Label, Report, ReportKind, Source}; use clap::Parser as _; @@ -17,14 +17,13 @@ use type_sitter::Node as _; use crate::arguments::Commands; use interpreter::{ - build_prelude, + ExecutionContext, ExecutionFileCache, FsStore, ImString, LogMessage, Parser, RuntimeLog, + SourceReference, StackScope, StackTrace, Store, build_prelude, compile::{compile, iter_raw_nodes}, execute_expression, execution::values::BuiltinCallableDatabase, new_parser, run_file, values::{Object, Style, Value}, - ExecutionContext, ExecutionFileCache, FsStore, ImString, LogMessage, Parser, RuntimeLog, - SourceReference, StackScope, StackTrace, Store, }; fn main() { diff --git a/gui/src/main.rs b/gui/src/main.rs index f1d5a3e..b5cdfed 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -2,17 +2,23 @@ use std::{ collections::{HashMap, HashSet}, fmt::Display, path::{Path, PathBuf}, - sync::{Arc, Mutex, atomic::AtomicBool, mpsc}, time::Duration, + sync::{Arc, Mutex, atomic::AtomicBool, mpsc}, + time::Duration, }; use eframe::egui; use egui::{ - Align, Color32, Layout, Mesh, Painter, Pos2, Rect, RichText, Shape, StrokeKind, TextEdit, epaint::{ColorMode, PathShape, PathStroke} + Color32, Mesh, Painter, Pos2, Rect, RichText, Sense, Shape, StrokeKind, TextEdit, Ui, Vec2, + epaint::{ColorMode, PathShape, PathStroke}, }; use interpreter::{ - ExecutionContext, FsStore, LogMessage, Parser, RuntimeLog, SourceReference, StackScope, StackTrace, Store, build_prelude, compile, execute_expression, geo::TriangulateEarcut, new_parser, values::{BuiltinCallableDatabase, LineString, Object, Polygon, PolygonSet, Style, Value} + ExecutionContext, FsStore, LogMessage, RuntimeLog, SourceReference, StackScope, StackTrace, + Store, build_prelude, compile, execute_expression, + geo::{BoundingRect, Centroid, TriangulateEarcut}, + new_parser, + values::{BuiltinCallableDatabase, LineString, Object, Polygon, PolygonSet, Style, Value}, }; -use notify::{recommended_watcher, EventKind, RecommendedWatcher, Watcher}; +use notify::{EventKind, RecommendedWatcher, Watcher, recommended_watcher}; use tempfile::TempDir; fn main() { @@ -110,7 +116,7 @@ fn runtime(expression_rx: mpsc::Receiver) { return RuntimeOutput { result: Err(error), files_to_watch: HashSet::new(), - } + }; } }; let root = match compile(&repl_file, &input, &tree) @@ -121,7 +127,7 @@ fn runtime(expression_rx: mpsc::Receiver) { return RuntimeOutput { result: Err(error), files_to_watch: HashSet::new(), - } + }; } }; @@ -180,6 +186,8 @@ struct CommandCAD { watched_files: HashSet>, file_watcher: Result, file_updates_rx: mpsc::Receiver>, + + view_state_2d: ViewState2D, } impl CommandCAD { @@ -198,7 +206,9 @@ impl CommandCAD { // watching for file changes). Basically, sometimes we get this notification before the // file is available on disk. We need to check and possibly wait to see if the file is // actually ready. - if let Ok(event) = &event && matches!(event.kind, EventKind::Create(_) | EventKind::Modify(_)) { + if let Ok(event) = &event + && matches!(event.kind, EventKind::Create(_) | EventKind::Modify(_)) + { while !event.paths.iter().all(|path| path.exists()) { std::thread::sleep(Duration::from_millis(10)); } @@ -216,6 +226,7 @@ impl CommandCAD { watched_files: HashSet::new(), file_watcher, file_updates_rx, + view_state_2d: ViewState2D::default(), } } @@ -308,12 +319,20 @@ impl eframe::App for CommandCAD { { self.spawn_job(ctx); } + + let mut draw_area = ui.available_rect_before_wrap(); + draw_area.min.y += 30.0; // We don't know how tall the status bar is at this time, so I + // just assume 30 and that seems to be working well enough. + + ui.horizontal(|ui| { + if self.active_job.is_some() { + ui.label(RichText::new("Working...").color(Color32::YELLOW)); + } else { + ui.label(RichText::new("Ready").color(Color32::GREEN)); + } - if self.active_job.is_some() { - ui.label(RichText::new("Working...").color(Color32::YELLOW)); - } else { - ui.label(RichText::new("Ready").color(Color32::GREEN)); - } + self.view_state_2d.draw_interface(ui, &self.last_result, draw_area); + }); if let Err(error) = &self.file_watcher { ui.label( @@ -325,10 +344,9 @@ impl eframe::App for CommandCAD { // Update the job status. self.check_job(); - // TODO Add controls for scale and translation. // TODO Add some kind of scale legend. - let pixels_per_meter = 100.0; + let draw_area = ui.available_rect_before_wrap(); match &self.last_result { None => {} Some(Ok(RuntimeValue::TextValue(text))) => { @@ -337,29 +355,27 @@ impl eframe::App for CommandCAD { }); } Some(Ok(RuntimeValue::LineString(line_string))) => { - - let draw_area = ui.available_rect_before_wrap(); + self.view_state_2d.update(ui, draw_area); let painter = Painter::new( ui.ctx().clone(), ui.layer_id(), draw_area, ); - painter.add(paint_linestring(draw_area, pixels_per_meter, StrokeKind::Middle, &line_string.0)); + painter.add(paint_linestring(draw_area, &self.view_state_2d, StrokeKind::Middle, &line_string.0)); } Some(Ok(RuntimeValue::Polygon(polygon))) => { - - let draw_area = ui.available_rect_before_wrap(); + self.view_state_2d.update(ui, draw_area); let painter = Painter::new( ui.ctx().clone(), ui.layer_id(), draw_area, ); - paint_polygon(&painter, draw_area, pixels_per_meter, &polygon.0); + paint_polygon(&painter, draw_area, &self.view_state_2d, &polygon.0); } Some(Ok(RuntimeValue::PolygonSet(polygon_set))) => { - let draw_area = ui.available_rect_before_wrap(); + self.view_state_2d.update(ui, draw_area); let painter = Painter::new( ui.ctx().clone(), ui.layer_id(), @@ -367,7 +383,7 @@ impl eframe::App for CommandCAD { ); for polygon in polygon_set.0.iter() { - paint_polygon(&painter, draw_area, pixels_per_meter, polygon); + paint_polygon(&painter, draw_area, &self.view_state_2d, polygon); } } Some(Err(error)) => { @@ -378,14 +394,111 @@ impl eframe::App for CommandCAD { } } -fn paint_linestring(draw_area: Rect, pixels_per_meter: f32, stroke_kind: StrokeKind, line_string: &interpreter::geo::LineString) -> Shape { +#[derive(Debug)] +struct ViewState2D { + offset: Vec2, + pixels_per_meter: f32, +} + +impl Default for ViewState2D { + fn default() -> Self { + Self { + offset: Default::default(), + pixels_per_meter: 100.0, + } + } +} + +impl ViewState2D { + fn fit_to_screen(&mut self, value: &RuntimeValue, draw_area: Rect) { + let (bounds, center) = match value { + RuntimeValue::LineString(line_string) => (line_string.0.bounding_rect(), line_string.0.centroid()), + RuntimeValue::Polygon(polygon) => (polygon.0.bounding_rect(), polygon.0.centroid()), + RuntimeValue::PolygonSet(polygon_set) => (polygon_set.0.bounding_rect(), polygon_set.0.centroid()), + _ => (None, None), + }; + + if let Some(bounds) = bounds { + let size = bounds.max() - bounds.min(); + let dx = draw_area.x_range().span() / size.x as f32; + let dy = draw_area.y_range().span()/ size.y as f32; + self.pixels_per_meter = dx.min(dy); + } else { + // We don't know how to fit this. Just assume the default. + self.pixels_per_meter = Self::default().pixels_per_meter; + } + + if let Some(center) = center { + let offset = Vec2::new(center.0.x as f32, center.0.y as f32) * self.pixels_per_meter; + self.offset = offset; + } else { + // We don't know how to fit this. Just assume the default. + self.offset = Self::default().offset; + } + } + + fn draw_interface( + &mut self, + ui: &mut Ui, + last_result: &Option>, + draw_area: Rect + ) { + if let Some(Ok(value)) = last_result + && matches!( + value, + RuntimeValue::LineString(_) + | RuntimeValue::Polygon(_) + | RuntimeValue::PolygonSet(_) + ) + && ui.button("Fit to screen").clicked() + { + self.fit_to_screen(value, draw_area); + } + } + + fn update(&mut self, ui: &mut Ui, draw_area: Rect) { + let response = ui.allocate_rect(draw_area, Sense::DRAG); + self.offset += response.drag_delta(); + ui.input(|state| { + self.pixels_per_meter += state.smooth_scroll_delta.y; + self.pixels_per_meter = self.pixels_per_meter.max(0.0); + }); + } +} + +fn paint_linestring( + draw_area: Rect, + view_state_2d: &ViewState2D, + stroke_kind: StrokeKind, + line_string: &interpreter::geo::LineString, +) -> Shape { let center_offset = draw_area.center().to_vec2(); - let path = PathShape { points: line_string.coords().map(|coord| Pos2::new(coord.x as f32, coord.y as f32) * pixels_per_meter + center_offset).collect(), closed: line_string.is_closed(), fill: Color32::TRANSPARENT, stroke: PathStroke { width: 2.0, color: ColorMode::Solid(Color32::WHITE), kind: stroke_kind } }; + let path = PathShape { + points: line_string + .coords() + .map(|coord| { + Pos2::new(coord.x as f32, coord.y as f32) * view_state_2d.pixels_per_meter + + center_offset + + view_state_2d.offset + }) + .collect(), + closed: line_string.is_closed(), + fill: Color32::TRANSPARENT, + stroke: PathStroke { + width: 2.0, + color: ColorMode::Solid(Color32::WHITE), + kind: stroke_kind, + }, + }; Shape::Path(path) } -fn paint_polygon(painter: &Painter, draw_area: Rect, pixels_per_meter: f32, polygon: &interpreter::geo::Polygon) { - +fn paint_polygon( + painter: &Painter, + draw_area: Rect, + view_state_2d: &ViewState2D, + polygon: &interpreter::geo::Polygon, +) { // Render fill // FIXME building this on each frame is HORRIBLE let center_offset = draw_area.center().to_vec2(); @@ -395,7 +508,12 @@ fn paint_polygon(painter: &Painter, draw_area: Rect, pixels_per_meter: f32, poly let x = vert[0]; let y = vert[1]; - mesh.colored_vertex(Pos2::new(x as f32, y as f32) * pixels_per_meter + center_offset, Color32::GRAY); + mesh.colored_vertex( + Pos2::new(x as f32, y as f32) * view_state_2d.pixels_per_meter + + center_offset + + view_state_2d.offset, + Color32::GRAY, + ); } for triangle in triangulation.triangle_indices.chunks(3) { @@ -405,14 +523,24 @@ fn paint_polygon(painter: &Painter, draw_area: Rect, pixels_per_meter: f32, poly mesh.add_triangle(a as u32, b as u32, c as u32); } - + painter.add(Shape::Mesh(Arc::new(mesh))); // Render exterior - painter.add(paint_linestring(draw_area, pixels_per_meter, StrokeKind::Inside, polygon.exterior())); - + painter.add(paint_linestring( + draw_area, + view_state_2d, + StrokeKind::Inside, + polygon.exterior(), + )); + // Render interior. for interior in polygon.interiors() { - painter.add(paint_linestring(draw_area, pixels_per_meter, StrokeKind::Outside, interior)); + painter.add(paint_linestring( + draw_area, + view_state_2d, + StrokeKind::Outside, + interior, + )); } } From 28ba79d58bf63efd5c3b9d3097900501c378eeb6 Mon Sep 17 00:00:00 2001 From: James Carl Date: Sat, 21 Mar 2026 11:22:31 -0400 Subject: [PATCH 17/71] Correct Y axis --- gui/src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gui/src/main.rs b/gui/src/main.rs index b5cdfed..07a84ca 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -477,7 +477,7 @@ fn paint_linestring( points: line_string .coords() .map(|coord| { - Pos2::new(coord.x as f32, coord.y as f32) * view_state_2d.pixels_per_meter + Pos2::new(coord.x as f32, -coord.y as f32) * view_state_2d.pixels_per_meter + center_offset + view_state_2d.offset }) @@ -509,7 +509,7 @@ fn paint_polygon( let y = vert[1]; mesh.colored_vertex( - Pos2::new(x as f32, y as f32) * view_state_2d.pixels_per_meter + Pos2::new(x as f32, -y as f32) * view_state_2d.pixels_per_meter + center_offset + view_state_2d.offset, Color32::GRAY, From c29b679681a1b679efe5ef34227dd599539cc990 Mon Sep 17 00:00:00 2001 From: James Carl Date: Sat, 21 Mar 2026 11:25:28 -0400 Subject: [PATCH 18/71] Better centering of objects --- gui/src/main.rs | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/gui/src/main.rs b/gui/src/main.rs index 07a84ca..3797b2c 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -411,11 +411,11 @@ impl Default for ViewState2D { impl ViewState2D { fn fit_to_screen(&mut self, value: &RuntimeValue, draw_area: Rect) { - let (bounds, center) = match value { - RuntimeValue::LineString(line_string) => (line_string.0.bounding_rect(), line_string.0.centroid()), - RuntimeValue::Polygon(polygon) => (polygon.0.bounding_rect(), polygon.0.centroid()), - RuntimeValue::PolygonSet(polygon_set) => (polygon_set.0.bounding_rect(), polygon_set.0.centroid()), - _ => (None, None), + let bounds = match value { + RuntimeValue::LineString(line_string) => line_string.0.bounding_rect(), + RuntimeValue::Polygon(polygon) => polygon.0.bounding_rect(), + RuntimeValue::PolygonSet(polygon_set) => polygon_set.0.bounding_rect(), + _ => None, }; if let Some(bounds) = bounds { @@ -423,17 +423,13 @@ impl ViewState2D { let dx = draw_area.x_range().span() / size.x as f32; let dy = draw_area.y_range().span()/ size.y as f32; self.pixels_per_meter = dx.min(dy); - } else { - // We don't know how to fit this. Just assume the default. - self.pixels_per_meter = Self::default().pixels_per_meter; - } - - if let Some(center) = center { - let offset = Vec2::new(center.0.x as f32, center.0.y as f32) * self.pixels_per_meter; + + let center = bounds.center(); + let offset = Vec2::new(center.x as f32, center.y as f32) * self.pixels_per_meter; self.offset = offset; } else { // We don't know how to fit this. Just assume the default. - self.offset = Self::default().offset; + *self = Self::default(); } } From 04643c8a4fdbba33ca16162984393b363c47dc74 Mon Sep 17 00:00:00 2001 From: James Carl Date: Sat, 21 Mar 2026 17:35:14 -0400 Subject: [PATCH 19/71] Optimize polygon fill rendering --- gui/src/main.rs | 84 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 29 deletions(-) diff --git a/gui/src/main.rs b/gui/src/main.rs index 3797b2c..703490f 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -8,13 +8,12 @@ use std::{ use eframe::egui; use egui::{ - Color32, Mesh, Painter, Pos2, Rect, RichText, Sense, Shape, StrokeKind, TextEdit, Ui, Vec2, - epaint::{ColorMode, PathShape, PathStroke}, + Color32, Mesh, Painter, Pos2, Rect, RichText, Sense, Shape, StrokeKind, TextEdit, Ui, Vec2, emath::TSTransform, epaint::{ColorMode, PathShape, PathStroke} }; use interpreter::{ ExecutionContext, FsStore, LogMessage, RuntimeLog, SourceReference, StackScope, StackTrace, Store, build_prelude, compile, execute_expression, - geo::{BoundingRect, Centroid, TriangulateEarcut}, + geo::{BoundingRect, TriangulateEarcut}, new_parser, values::{BuiltinCallableDatabase, LineString, Object, Polygon, PolygonSet, Style, Value}, }; @@ -66,8 +65,14 @@ struct PendingJob { enum RuntimeValue { TextValue(String), LineString(LineString), - Polygon(Polygon), - PolygonSet(PolygonSet), + Polygon { + polygon: Polygon, + mesh: Arc + }, + PolygonSet { + polygon_set: PolygonSet, + meshes: Vec> + }, // ManifoldMesh(ManifoldMesh3D), } @@ -149,8 +154,22 @@ fn runtime(expression_rx: mpsc::Receiver) { let result = match expression_result { Ok(Value::LineString(line_string)) => Ok(RuntimeValue::LineString(line_string)), - Ok(Value::Polygon(polygon)) => Ok(RuntimeValue::Polygon(polygon)), - Ok(Value::PolygonSet(polygon_set)) => Ok(RuntimeValue::PolygonSet(polygon_set)), + Ok(Value::Polygon(polygon)) => { + let mesh = build_fill_mesh_from_polygon(&polygon.0); + + Ok(RuntimeValue::Polygon { + polygon, + mesh + }) + }, + Ok(Value::PolygonSet(polygon_set)) => { + let meshes = polygon_set.0.iter().map(build_fill_mesh_from_polygon).collect(); + + Ok(RuntimeValue::PolygonSet { + polygon_set, + meshes, + }) + }, Ok(value) => { let mut text = String::new(); value.format(&context, &mut text, Style::Default, None).ok(); @@ -364,7 +383,7 @@ impl eframe::App for CommandCAD { painter.add(paint_linestring(draw_area, &self.view_state_2d, StrokeKind::Middle, &line_string.0)); } - Some(Ok(RuntimeValue::Polygon(polygon))) => { + Some(Ok(RuntimeValue::Polygon { polygon, mesh})) => { self.view_state_2d.update(ui, draw_area); let painter = Painter::new( ui.ctx().clone(), @@ -372,9 +391,9 @@ impl eframe::App for CommandCAD { draw_area, ); - paint_polygon(&painter, draw_area, &self.view_state_2d, &polygon.0); + paint_polygon(&painter, draw_area, &self.view_state_2d, &polygon.0, mesh.clone()); } - Some(Ok(RuntimeValue::PolygonSet(polygon_set))) => { + Some(Ok(RuntimeValue::PolygonSet { polygon_set, meshes })) => { self.view_state_2d.update(ui, draw_area); let painter = Painter::new( ui.ctx().clone(), @@ -382,8 +401,8 @@ impl eframe::App for CommandCAD { draw_area, ); - for polygon in polygon_set.0.iter() { - paint_polygon(&painter, draw_area, &self.view_state_2d, polygon); + for (polygon, mesh) in polygon_set.0.iter().zip(meshes.iter()) { + paint_polygon(&painter, draw_area, &self.view_state_2d, polygon, mesh.clone()); } } Some(Err(error)) => { @@ -413,8 +432,8 @@ impl ViewState2D { fn fit_to_screen(&mut self, value: &RuntimeValue, draw_area: Rect) { let bounds = match value { RuntimeValue::LineString(line_string) => line_string.0.bounding_rect(), - RuntimeValue::Polygon(polygon) => polygon.0.bounding_rect(), - RuntimeValue::PolygonSet(polygon_set) => polygon_set.0.bounding_rect(), + RuntimeValue::Polygon { polygon, .. } => polygon.0.bounding_rect(), + RuntimeValue::PolygonSet { polygon_set, .. } => polygon_set.0.bounding_rect(), _ => None, }; @@ -443,8 +462,8 @@ impl ViewState2D { && matches!( value, RuntimeValue::LineString(_) - | RuntimeValue::Polygon(_) - | RuntimeValue::PolygonSet(_) + | RuntimeValue::Polygon { .. } + | RuntimeValue::PolygonSet { .. } ) && ui.button("Fit to screen").clicked() { @@ -489,15 +508,7 @@ fn paint_linestring( Shape::Path(path) } -fn paint_polygon( - painter: &Painter, - draw_area: Rect, - view_state_2d: &ViewState2D, - polygon: &interpreter::geo::Polygon, -) { - // Render fill - // FIXME building this on each frame is HORRIBLE - let center_offset = draw_area.center().to_vec2(); +fn build_fill_mesh_from_polygon(polygon: &interpreter::geo::Polygon) -> Arc { let mut mesh = Mesh::default(); let triangulation = polygon.earcut_triangles_raw(); for vert in triangulation.vertices.chunks(2) { @@ -505,9 +516,7 @@ fn paint_polygon( let y = vert[1]; mesh.colored_vertex( - Pos2::new(x as f32, -y as f32) * view_state_2d.pixels_per_meter - + center_offset - + view_state_2d.offset, + Pos2::new(x as f32, -y as f32), Color32::GRAY, ); } @@ -520,7 +529,24 @@ fn paint_polygon( mesh.add_triangle(a as u32, b as u32, c as u32); } - painter.add(Shape::Mesh(Arc::new(mesh))); + Arc::new(mesh) +} + +fn paint_polygon( + painter: &Painter, + draw_area: Rect, + view_state_2d: &ViewState2D, + polygon: &interpreter::geo::Polygon, + mesh: Arc, +) { + // Render fill + let center_offset = draw_area.center().to_vec2(); + let mut shape = Shape::Mesh(mesh); + shape.transform(TSTransform { + scaling: view_state_2d.pixels_per_meter, + translation: center_offset + view_state_2d.offset + }); + painter.add(shape); // Render exterior painter.add(paint_linestring( From 18c9f6fe4e17fdfb5f05626986d5d604f4fe4872 Mon Sep 17 00:00:00 2001 From: James Carl Date: Sat, 21 Mar 2026 18:00:06 -0400 Subject: [PATCH 20/71] Move 2D visualization into its own module --- gui/src/main.rs | 177 +++++----------------------------------- gui/src/visualize2d.rs | 181 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 203 insertions(+), 155 deletions(-) create mode 100644 gui/src/visualize2d.rs diff --git a/gui/src/main.rs b/gui/src/main.rs index 703490f..48f2e23 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -1,3 +1,20 @@ +/* + * Copyright 2026 James Carl + * AGPL-3.0-only or AGPL-3.0-or-later + * + * This file is part of Command Cad. + * + * Command CAD is free software: you can redistribute it and/or modify it under the terms of + * the GNU Affero General Public License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License along with this + * program. If not, see . + */ use std::{ collections::{HashMap, HashSet}, fmt::Display, @@ -8,18 +25,21 @@ use std::{ use eframe::egui; use egui::{ - Color32, Mesh, Painter, Pos2, Rect, RichText, Sense, Shape, StrokeKind, TextEdit, Ui, Vec2, emath::TSTransform, epaint::{ColorMode, PathShape, PathStroke} + Color32, Mesh, Painter, RichText, StrokeKind, TextEdit, }; use interpreter::{ ExecutionContext, FsStore, LogMessage, RuntimeLog, SourceReference, StackScope, StackTrace, Store, build_prelude, compile, execute_expression, - geo::{BoundingRect, TriangulateEarcut}, new_parser, values::{BuiltinCallableDatabase, LineString, Object, Polygon, PolygonSet, Style, Value}, }; use notify::{EventKind, RecommendedWatcher, Watcher, recommended_watcher}; use tempfile::TempDir; +use crate::visualize2d::{ViewState2D, build_fill_mesh_from_polygon, paint_linestring, paint_polygon}; + +mod visualize2d; + fn main() { let native_options = eframe::NativeOptions::default(); if let Err(error) = eframe::run_native( @@ -413,156 +433,3 @@ impl eframe::App for CommandCAD { } } -#[derive(Debug)] -struct ViewState2D { - offset: Vec2, - pixels_per_meter: f32, -} - -impl Default for ViewState2D { - fn default() -> Self { - Self { - offset: Default::default(), - pixels_per_meter: 100.0, - } - } -} - -impl ViewState2D { - fn fit_to_screen(&mut self, value: &RuntimeValue, draw_area: Rect) { - let bounds = match value { - RuntimeValue::LineString(line_string) => line_string.0.bounding_rect(), - RuntimeValue::Polygon { polygon, .. } => polygon.0.bounding_rect(), - RuntimeValue::PolygonSet { polygon_set, .. } => polygon_set.0.bounding_rect(), - _ => None, - }; - - if let Some(bounds) = bounds { - let size = bounds.max() - bounds.min(); - let dx = draw_area.x_range().span() / size.x as f32; - let dy = draw_area.y_range().span()/ size.y as f32; - self.pixels_per_meter = dx.min(dy); - - let center = bounds.center(); - let offset = Vec2::new(center.x as f32, center.y as f32) * self.pixels_per_meter; - self.offset = offset; - } else { - // We don't know how to fit this. Just assume the default. - *self = Self::default(); - } - } - - fn draw_interface( - &mut self, - ui: &mut Ui, - last_result: &Option>, - draw_area: Rect - ) { - if let Some(Ok(value)) = last_result - && matches!( - value, - RuntimeValue::LineString(_) - | RuntimeValue::Polygon { .. } - | RuntimeValue::PolygonSet { .. } - ) - && ui.button("Fit to screen").clicked() - { - self.fit_to_screen(value, draw_area); - } - } - - fn update(&mut self, ui: &mut Ui, draw_area: Rect) { - let response = ui.allocate_rect(draw_area, Sense::DRAG); - self.offset += response.drag_delta(); - ui.input(|state| { - self.pixels_per_meter += state.smooth_scroll_delta.y; - self.pixels_per_meter = self.pixels_per_meter.max(0.0); - }); - } -} - -fn paint_linestring( - draw_area: Rect, - view_state_2d: &ViewState2D, - stroke_kind: StrokeKind, - line_string: &interpreter::geo::LineString, -) -> Shape { - let center_offset = draw_area.center().to_vec2(); - let path = PathShape { - points: line_string - .coords() - .map(|coord| { - Pos2::new(coord.x as f32, -coord.y as f32) * view_state_2d.pixels_per_meter - + center_offset - + view_state_2d.offset - }) - .collect(), - closed: line_string.is_closed(), - fill: Color32::TRANSPARENT, - stroke: PathStroke { - width: 2.0, - color: ColorMode::Solid(Color32::WHITE), - kind: stroke_kind, - }, - }; - Shape::Path(path) -} - -fn build_fill_mesh_from_polygon(polygon: &interpreter::geo::Polygon) -> Arc { - let mut mesh = Mesh::default(); - let triangulation = polygon.earcut_triangles_raw(); - for vert in triangulation.vertices.chunks(2) { - let x = vert[0]; - let y = vert[1]; - - mesh.colored_vertex( - Pos2::new(x as f32, -y as f32), - Color32::GRAY, - ); - } - - for triangle in triangulation.triangle_indices.chunks(3) { - let a = triangle[0]; - let b = triangle[1]; - let c = triangle[2]; - - mesh.add_triangle(a as u32, b as u32, c as u32); - } - - Arc::new(mesh) -} - -fn paint_polygon( - painter: &Painter, - draw_area: Rect, - view_state_2d: &ViewState2D, - polygon: &interpreter::geo::Polygon, - mesh: Arc, -) { - // Render fill - let center_offset = draw_area.center().to_vec2(); - let mut shape = Shape::Mesh(mesh); - shape.transform(TSTransform { - scaling: view_state_2d.pixels_per_meter, - translation: center_offset + view_state_2d.offset - }); - painter.add(shape); - - // Render exterior - painter.add(paint_linestring( - draw_area, - view_state_2d, - StrokeKind::Inside, - polygon.exterior(), - )); - - // Render interior. - for interior in polygon.interiors() { - painter.add(paint_linestring( - draw_area, - view_state_2d, - StrokeKind::Outside, - interior, - )); - } -} diff --git a/gui/src/visualize2d.rs b/gui/src/visualize2d.rs new file mode 100644 index 0000000..671124d --- /dev/null +++ b/gui/src/visualize2d.rs @@ -0,0 +1,181 @@ +use std::sync::Arc; + +/* + * Copyright 2026 James Carl + * AGPL-3.0-only or AGPL-3.0-or-later + * + * This file is part of Command Cad. + * + * Command CAD is free software: you can redistribute it and/or modify it under the terms of + * the GNU Affero General Public License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License along with this + * program. If not, see . + */ +use egui::{ + Color32, Mesh, Painter, Pos2, Rect, Sense, Shape, StrokeKind, Ui, Vec2, emath::TSTransform, epaint::{ColorMode, PathShape, PathStroke} +}; +use interpreter::geo::{BoundingRect, TriangulateEarcut}; + +use crate::RuntimeError; + +use super::{RuntimeValue}; + +#[derive(Debug)] +pub struct ViewState2D { + offset: Vec2, + pixels_per_meter: f32, +} + +impl Default for ViewState2D { + fn default() -> Self { + Self { + offset: Default::default(), + pixels_per_meter: 100.0, + } + } +} + +impl ViewState2D { + fn fit_to_screen(&mut self, value: &RuntimeValue, draw_area: Rect) { + let bounds = match value { + RuntimeValue::LineString(line_string) => line_string.0.bounding_rect(), + RuntimeValue::Polygon { polygon, .. } => polygon.0.bounding_rect(), + RuntimeValue::PolygonSet { polygon_set, .. } => polygon_set.0.bounding_rect(), + _ => None, + }; + + if let Some(bounds) = bounds { + let size = bounds.max() - bounds.min(); + let dx = draw_area.x_range().span() / size.x as f32; + let dy = draw_area.y_range().span()/ size.y as f32; + self.pixels_per_meter = dx.min(dy); + + let center = bounds.center(); + let offset = Vec2::new(center.x as f32, center.y as f32) * self.pixels_per_meter; + self.offset = offset; + } else { + // We don't know how to fit this. Just assume the default. + *self = Self::default(); + } + } + + pub fn draw_interface( + &mut self, + ui: &mut Ui, + last_result: &Option>, + draw_area: Rect + ) { + if let Some(Ok(value)) = last_result + && matches!( + value, + RuntimeValue::LineString(_) + | RuntimeValue::Polygon { .. } + | RuntimeValue::PolygonSet { .. } + ) + && ui.button("Fit to screen").clicked() + { + self.fit_to_screen(value, draw_area); + } + } + + pub fn update(&mut self, ui: &mut Ui, draw_area: Rect) { + let response = ui.allocate_rect(draw_area, Sense::DRAG); + self.offset += response.drag_delta(); + ui.input(|state| { + self.pixels_per_meter += state.smooth_scroll_delta.y; + self.pixels_per_meter = self.pixels_per_meter.max(0.0); + }); + } +} + +pub fn paint_linestring( + draw_area: Rect, + view_state_2d: &ViewState2D, + stroke_kind: StrokeKind, + line_string: &interpreter::geo::LineString, +) -> Shape { + let center_offset = draw_area.center().to_vec2(); + let path = PathShape { + points: line_string + .coords() + .map(|coord| { + Pos2::new(coord.x as f32, -coord.y as f32) * view_state_2d.pixels_per_meter + + center_offset + + view_state_2d.offset + }) + .collect(), + closed: line_string.is_closed(), + fill: Color32::TRANSPARENT, + stroke: PathStroke { + width: 2.0, + color: ColorMode::Solid(Color32::WHITE), + kind: stroke_kind, + }, + }; + Shape::Path(path) +} + +pub fn build_fill_mesh_from_polygon(polygon: &interpreter::geo::Polygon) -> Arc { + let mut mesh = Mesh::default(); + let triangulation = polygon.earcut_triangles_raw(); + for vert in triangulation.vertices.chunks(2) { + let x = vert[0]; + let y = vert[1]; + + mesh.colored_vertex( + Pos2::new(x as f32, -y as f32), + Color32::GRAY, + ); + } + + for triangle in triangulation.triangle_indices.chunks(3) { + let a = triangle[0]; + let b = triangle[1]; + let c = triangle[2]; + + mesh.add_triangle(a as u32, b as u32, c as u32); + } + + Arc::new(mesh) +} + +pub fn paint_polygon( + painter: &Painter, + draw_area: Rect, + view_state_2d: &ViewState2D, + polygon: &interpreter::geo::Polygon, + mesh: Arc, +) { + // Render fill + let center_offset = draw_area.center().to_vec2(); + let mut shape = Shape::Mesh(mesh); + shape.transform(TSTransform { + scaling: view_state_2d.pixels_per_meter, + translation: center_offset + view_state_2d.offset + }); + painter.add(shape); + + // Render exterior + painter.add(paint_linestring( + draw_area, + view_state_2d, + StrokeKind::Inside, + polygon.exterior(), + )); + + // Render interior. + for interior in polygon.interiors() { + painter.add(paint_linestring( + draw_area, + view_state_2d, + StrokeKind::Outside, + interior, + )); + } +} From 64f1e6b49a28c72a2c06538bb565c332efe89389 Mon Sep 17 00:00:00 2001 From: James Carl Date: Fri, 27 Mar 2026 17:54:48 -0400 Subject: [PATCH 21/71] WIP 3d visualizer --- Cargo.lock | 3 + Cargo.toml | 1 + gui/Cargo.toml | 10 +- gui/src/main.rs | 124 +++++--- gui/src/shaders/mesh.wgsl | 34 ++ gui/src/visualize2d.rs | 63 ++-- gui/src/visualize3d.rs | 296 ++++++++++++++++++ interpreter/Cargo.toml | 2 +- .../src/execution/values/manifold_mesh.rs | 2 +- 9 files changed, 439 insertions(+), 96 deletions(-) create mode 100644 gui/src/shaders/mesh.wgsl create mode 100644 gui/src/visualize3d.rs diff --git a/Cargo.lock b/Cargo.lock index b6112a8..86b90dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2160,9 +2160,11 @@ name = "gui" version = "0.1.0" dependencies = [ "anyhow", + "bytemuck", "eframe", "egui", "interpreter", + "nalgebra", "notify", "oneshot", "tempfile", @@ -3068,6 +3070,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4d5b3eff5cd580f93da45e64715e8c20a3996342f1e466599cf7a267a0c2f5f" dependencies = [ "approx", + "bytemuck", "glam 0.14.0", "glam 0.15.2", "glam 0.16.0", diff --git a/Cargo.toml b/Cargo.toml index a064f05..cca7093 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,3 +27,4 @@ tree-sitter = "0.25" tempfile = "3" git2 = "0.20" anyhow = "1" +nalgebra = { version = "0.34", features = [ "serde", "bytemuck" ] } diff --git a/gui/Cargo.toml b/gui/Cargo.toml index e915e30..634fd1d 100644 --- a/gui/Cargo.toml +++ b/gui/Cargo.toml @@ -4,10 +4,12 @@ version = "0.1.0" edition = "2024" [dependencies] -eframe = { version = "0.33.3", features = ["wgpu"] } -egui = { version = "0.33.3", features = ["mint"] } +eframe = { version = "0.33", features = ["wgpu"] } +egui = { version = "0.33", features = ["mint"] } interpreter = { path = "../interpreter" } anyhow = { workspace = true } -oneshot = "0.2.1" +oneshot = "0.2" tempfile = { workspace = true } -notify = "8.2.0" +notify = "8" +bytemuck = "1" +nalgebra = { workspace = true } diff --git a/gui/src/main.rs b/gui/src/main.rs index 48f2e23..a9af70e 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -24,21 +24,25 @@ use std::{ }; use eframe::egui; -use egui::{ - Color32, Mesh, Painter, RichText, StrokeKind, TextEdit, -}; +use egui::{Color32, Mesh, Painter, RichText, Sense, StrokeKind, TextEdit}; use interpreter::{ ExecutionContext, FsStore, LogMessage, RuntimeLog, SourceReference, StackScope, StackTrace, - Store, build_prelude, compile, execute_expression, - new_parser, - values::{BuiltinCallableDatabase, LineString, Object, Polygon, PolygonSet, Style, Value}, + Store, build_prelude, compile, execute_expression, new_parser, + values::{ + BuiltinCallableDatabase, LineString, Object, Polygon, PolygonSet, Style, Value, + manifold_mesh::ManifoldMesh3D, + }, }; use notify::{EventKind, RecommendedWatcher, Watcher, recommended_watcher}; use tempfile::TempDir; -use crate::visualize2d::{ViewState2D, build_fill_mesh_from_polygon, paint_linestring, paint_polygon}; +use crate::{ + visualize2d::{ViewState2D, build_fill_mesh_from_polygon, paint_linestring, paint_polygon}, + visualize3d::ViewState3D, +}; mod visualize2d; +mod visualize3d; fn main() { let native_options = eframe::NativeOptions::default(); @@ -87,13 +91,18 @@ enum RuntimeValue { LineString(LineString), Polygon { polygon: Polygon, - mesh: Arc + mesh: Arc, }, PolygonSet { polygon_set: PolygonSet, - meshes: Vec> + meshes: Vec>, }, - // ManifoldMesh(ManifoldMesh3D), + ManifoldMesh(ManifoldMeshState), +} + +struct ManifoldMeshState { + manifold: ManifoldMesh3D, + uploaded_to_gpu: bool, } enum RuntimeError { @@ -177,19 +186,26 @@ fn runtime(expression_rx: mpsc::Receiver) { Ok(Value::Polygon(polygon)) => { let mesh = build_fill_mesh_from_polygon(&polygon.0); - Ok(RuntimeValue::Polygon { - polygon, - mesh - }) - }, + Ok(RuntimeValue::Polygon { polygon, mesh }) + } Ok(Value::PolygonSet(polygon_set)) => { - let meshes = polygon_set.0.iter().map(build_fill_mesh_from_polygon).collect(); + let meshes = polygon_set + .0 + .iter() + .map(build_fill_mesh_from_polygon) + .collect(); Ok(RuntimeValue::PolygonSet { polygon_set, meshes, }) - }, + } + Ok(Value::ManifoldMesh3D(manifold)) => { + Ok(RuntimeValue::ManifoldMesh(ManifoldMeshState { + manifold, + uploaded_to_gpu: false, + })) + } Ok(value) => { let mut text = String::new(); value.format(&context, &mut text, Style::Default, None).ok(); @@ -225,13 +241,12 @@ struct CommandCAD { watched_files: HashSet>, file_watcher: Result, file_updates_rx: mpsc::Receiver>, - - view_state_2d: ViewState2D, + view_state: ViewState, } impl CommandCAD { fn new(cc: &eframe::CreationContext<'_>) -> Self { - let (expression_tx, expression_rx) = mpsc::channel(); + let (mut expression_tx, expression_rx) = mpsc::channel(); std::thread::spawn(|| runtime(expression_rx)); let (file_updates_tx, file_updates_rx) = mpsc::channel(); @@ -265,7 +280,11 @@ impl CommandCAD { watched_files: HashSet::new(), file_watcher, file_updates_rx, - view_state_2d: ViewState2D::default(), + view_state: ViewState { + pixels_per_meter: 100.0, + view_state_2d: ViewState2D::default(), + view_state_3d: ViewState3D::new(cc), + }, } } @@ -358,11 +377,9 @@ impl eframe::App for CommandCAD { { self.spawn_job(ctx); } - let mut draw_area = ui.available_rect_before_wrap(); draw_area.min.y += 30.0; // We don't know how tall the status bar is at this time, so I // just assume 30 and that seems to be working well enough. - ui.horizontal(|ui| { if self.active_job.is_some() { ui.label(RichText::new("Working...").color(Color32::YELLOW)); @@ -370,7 +387,7 @@ impl eframe::App for CommandCAD { ui.label(RichText::new("Ready").color(Color32::GREEN)); } - self.view_state_2d.draw_interface(ui, &self.last_result, draw_area); + self.view_state.view_state_2d.draw_interface(&mut self.view_state.pixels_per_meter, ui, &self.last_result, draw_area); }); if let Err(error) = &self.file_watcher { @@ -385,46 +402,31 @@ impl eframe::App for CommandCAD { // TODO Add some kind of scale legend. - let draw_area = ui.available_rect_before_wrap(); - match &self.last_result { + match &mut self.last_result { None => {} Some(Ok(RuntimeValue::TextValue(text))) => { egui::ScrollArea::vertical().show(ui, |ui| { - ui.label(text); + ui.label(text.as_str()); }); } Some(Ok(RuntimeValue::LineString(line_string))) => { - self.view_state_2d.update(ui, draw_area); - let painter = Painter::new( - ui.ctx().clone(), - ui.layer_id(), - draw_area, - ); - - painter.add(paint_linestring(draw_area, &self.view_state_2d, StrokeKind::Middle, &line_string.0)); + let painter = self.view_state.prep_for_painting(ui); + painter.add(paint_linestring(draw_area, &self.view_state, StrokeKind::Middle, &line_string.0)); } Some(Ok(RuntimeValue::Polygon { polygon, mesh})) => { - self.view_state_2d.update(ui, draw_area); - let painter = Painter::new( - ui.ctx().clone(), - ui.layer_id(), - draw_area, - ); - - paint_polygon(&painter, draw_area, &self.view_state_2d, &polygon.0, mesh.clone()); + let painter = self.view_state.prep_for_painting(ui); + paint_polygon(&painter, draw_area, &self.view_state, &polygon.0, mesh.clone()); } Some(Ok(RuntimeValue::PolygonSet { polygon_set, meshes })) => { - self.view_state_2d.update(ui, draw_area); - let painter = Painter::new( - ui.ctx().clone(), - ui.layer_id(), - draw_area, - ); - + let painter = self.view_state.prep_for_painting(ui); for (polygon, mesh) in polygon_set.0.iter().zip(meshes.iter()) { - paint_polygon(&painter, draw_area, &self.view_state_2d, polygon, mesh.clone()); + paint_polygon(&painter, draw_area, &self.view_state, polygon, mesh.clone()); } } + Some(Ok(RuntimeValue::ManifoldMesh(manifold_state))) => { + let painter = self.view_state.prep_for_painting(ui); + self.view_state.view_state_3d.paint(&self.view_state, manifold_state, painter); + } Some(Err(error)) => { ui.label(RichText::new(format!("{error}")).color(Color32::RED)); } @@ -433,3 +435,23 @@ impl eframe::App for CommandCAD { } } +struct ViewState { + pixels_per_meter: f32, + view_state_2d: ViewState2D, + view_state_3d: ViewState3D, +} + +impl ViewState { + fn prep_for_painting(&mut self, ui: &mut egui::Ui) -> Painter { + let draw_area = ui.available_rect_before_wrap(); + let response = ui.allocate_rect(draw_area, Sense::DRAG); + ui.input(|state| { + self.pixels_per_meter += state.smooth_scroll_delta.y; + self.pixels_per_meter = self.pixels_per_meter.max(0.0); + }); + self.view_state_2d.update(ui, &response); + self.view_state_3d.update(ui, draw_area); + + Painter::new(ui.ctx().clone(), ui.layer_id(), draw_area) + } +} diff --git a/gui/src/shaders/mesh.wgsl b/gui/src/shaders/mesh.wgsl new file mode 100644 index 0000000..630ad2c --- /dev/null +++ b/gui/src/shaders/mesh.wgsl @@ -0,0 +1,34 @@ +struct VertexInput { + @location(0) position: vec3, +} + +struct VertexOut { + @builtin(position) position: vec4, +} + +struct VertexUniform { + view_projection: mat4x4, +}; +@group(0) @binding(0) +var camera: VertexUniform; + +struct ColorUniform { + fill: vec4, +} +@group(1) @binding(0) +var colors: ColorUniform; + +@vertex +fn vs_main(model: VertexInput) -> VertexOut { + var out: VertexOut; + + out.position = camera.view_projection * vec4(model.position, 1.0); + + return out; +} + +@fragment +fn fs_main(in: VertexOut) -> @location(0) vec4 { + // TODO we should shade these based on normal to view. + return colors.fill; +} diff --git a/gui/src/visualize2d.rs b/gui/src/visualize2d.rs index 671124d..386829a 100644 --- a/gui/src/visualize2d.rs +++ b/gui/src/visualize2d.rs @@ -18,31 +18,23 @@ use std::sync::Arc; * program. If not, see . */ use egui::{ - Color32, Mesh, Painter, Pos2, Rect, Sense, Shape, StrokeKind, Ui, Vec2, emath::TSTransform, epaint::{ColorMode, PathShape, PathStroke} + Color32, Mesh, Painter, Pos2, Rect, Response, Shape, StrokeKind, Ui, Vec2, + emath::TSTransform, + epaint::{ColorMode, PathShape, PathStroke}, }; use interpreter::geo::{BoundingRect, TriangulateEarcut}; -use crate::RuntimeError; +use crate::{RuntimeError, ViewState}; -use super::{RuntimeValue}; +use super::RuntimeValue; -#[derive(Debug)] +#[derive(Debug, Default)] pub struct ViewState2D { offset: Vec2, - pixels_per_meter: f32, -} - -impl Default for ViewState2D { - fn default() -> Self { - Self { - offset: Default::default(), - pixels_per_meter: 100.0, - } - } } impl ViewState2D { - fn fit_to_screen(&mut self, value: &RuntimeValue, draw_area: Rect) { + fn fit_to_screen(&mut self, pixels_per_meter: &mut f32, value: &RuntimeValue, draw_area: Rect) { let bounds = match value { RuntimeValue::LineString(line_string) => line_string.0.bounding_rect(), RuntimeValue::Polygon { polygon, .. } => polygon.0.bounding_rect(), @@ -53,11 +45,11 @@ impl ViewState2D { if let Some(bounds) = bounds { let size = bounds.max() - bounds.min(); let dx = draw_area.x_range().span() / size.x as f32; - let dy = draw_area.y_range().span()/ size.y as f32; - self.pixels_per_meter = dx.min(dy); - + let dy = draw_area.y_range().span() / size.y as f32; + *pixels_per_meter = dx.min(dy); + let center = bounds.center(); - let offset = Vec2::new(center.x as f32, center.y as f32) * self.pixels_per_meter; + let offset = Vec2::new(center.x as f32, center.y as f32) * *pixels_per_meter; self.offset = offset; } else { // We don't know how to fit this. Just assume the default. @@ -67,9 +59,10 @@ impl ViewState2D { pub fn draw_interface( &mut self, + pixels_per_meter: &mut f32, ui: &mut Ui, last_result: &Option>, - draw_area: Rect + draw_area: Rect, ) { if let Some(Ok(value)) = last_result && matches!( @@ -80,23 +73,18 @@ impl ViewState2D { ) && ui.button("Fit to screen").clicked() { - self.fit_to_screen(value, draw_area); + self.fit_to_screen(pixels_per_meter, value, draw_area); } } - pub fn update(&mut self, ui: &mut Ui, draw_area: Rect) { - let response = ui.allocate_rect(draw_area, Sense::DRAG); + pub fn update(&mut self, _ui: &mut Ui, response: &Response) { self.offset += response.drag_delta(); - ui.input(|state| { - self.pixels_per_meter += state.smooth_scroll_delta.y; - self.pixels_per_meter = self.pixels_per_meter.max(0.0); - }); } } pub fn paint_linestring( draw_area: Rect, - view_state_2d: &ViewState2D, + view_state: &ViewState, stroke_kind: StrokeKind, line_string: &interpreter::geo::LineString, ) -> Shape { @@ -105,9 +93,9 @@ pub fn paint_linestring( points: line_string .coords() .map(|coord| { - Pos2::new(coord.x as f32, -coord.y as f32) * view_state_2d.pixels_per_meter + Pos2::new(coord.x as f32, -coord.y as f32) * view_state.pixels_per_meter + center_offset - + view_state_2d.offset + + view_state.view_state_2d.offset }) .collect(), closed: line_string.is_closed(), @@ -128,10 +116,7 @@ pub fn build_fill_mesh_from_polygon(polygon: &interpreter::geo::Polygon) -> Arc< let x = vert[0]; let y = vert[1]; - mesh.colored_vertex( - Pos2::new(x as f32, -y as f32), - Color32::GRAY, - ); + mesh.colored_vertex(Pos2::new(x as f32, -y as f32), Color32::GRAY); } for triangle in triangulation.triangle_indices.chunks(3) { @@ -148,7 +133,7 @@ pub fn build_fill_mesh_from_polygon(polygon: &interpreter::geo::Polygon) -> Arc< pub fn paint_polygon( painter: &Painter, draw_area: Rect, - view_state_2d: &ViewState2D, + view_state: &ViewState, polygon: &interpreter::geo::Polygon, mesh: Arc, ) { @@ -156,15 +141,15 @@ pub fn paint_polygon( let center_offset = draw_area.center().to_vec2(); let mut shape = Shape::Mesh(mesh); shape.transform(TSTransform { - scaling: view_state_2d.pixels_per_meter, - translation: center_offset + view_state_2d.offset + scaling: view_state.pixels_per_meter, + translation: center_offset + view_state.view_state_2d.offset, }); painter.add(shape); // Render exterior painter.add(paint_linestring( draw_area, - view_state_2d, + view_state, StrokeKind::Inside, polygon.exterior(), )); @@ -173,7 +158,7 @@ pub fn paint_polygon( for interior in polygon.interiors() { painter.add(paint_linestring( draw_area, - view_state_2d, + view_state, StrokeKind::Outside, interior, )); diff --git a/gui/src/visualize3d.rs b/gui/src/visualize3d.rs new file mode 100644 index 0000000..385185d --- /dev/null +++ b/gui/src/visualize3d.rs @@ -0,0 +1,296 @@ +/* + * Copyright 2026 James Carl + * AGPL-3.0-only or AGPL-3.0-or-later + * + * This file is part of Command Cad. + * + * Command CAD is free software: you can redistribute it and/or modify it under the terms of + * the GNU Affero General Public License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License along with this + * program. If not, see . + */ +use eframe::{ + egui_wgpu, + wgpu::{self, util::DeviceExt as _}, +}; +use egui::{Painter, Rect}; +use interpreter::values::manifold_mesh::ManifoldMesh3D; +use nalgebra::{Matrix4, Vector3}; + +use crate::{ManifoldMeshState, ViewState}; + +const VIEW_NEAR: f32 = -1000.0; +const VIEW_FAR: f32 = 1000.0; + +#[repr(C)] +#[derive(Default, Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)] +struct VertexUniform { + view_projection: Matrix4, + pixels_per_meter: f32, +} + +#[derive(Debug)] +pub struct ViewState3D {} + +impl ViewState3D { + pub fn new(cc: &eframe::CreationContext<'_>) -> Self { + let wgpu_render_state = cc + .wgpu_render_state + .as_ref() + .expect("Project built without WGPU support"); + + let device = &wgpu_render_state.device; + + let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { + label: Some("mesh_shader"), + source: wgpu::ShaderSource::Wgsl(include_str!("./shaders/mesh.wgsl").into()), + }); + + let vertex_bind_group_layout = + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("mesh_vertex_bind_group_layout"), + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::VERTEX, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }], + }); + let fragment_bind_group_layout = + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("fragment_vertex_bind_group_layout"), + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }], + }); + + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("mesh_pipeline_layout"), + bind_group_layouts: &[&vertex_bind_group_layout, &fragment_bind_group_layout], + push_constant_ranges: &[], + }); + + let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("mesh_pipeline"), + layout: Some(&pipeline_layout), + vertex: wgpu::VertexState { + module: &shader, + entry_point: Some("vs_main"), + buffers: &[wgpu::VertexBufferLayout { + array_stride: std::mem::size_of::>() as wgpu::BufferAddress, + step_mode: wgpu::VertexStepMode::Vertex, + attributes: &wgpu::vertex_attr_array![0 => Float32x3], + }], + compilation_options: wgpu::PipelineCompilationOptions::default(), + }, + fragment: Some(wgpu::FragmentState { + module: &shader, + entry_point: Some("fs_main"), + targets: &[Some(wgpu_render_state.target_format.into())], + compilation_options: wgpu::PipelineCompilationOptions::default(), + }), + primitive: wgpu::PrimitiveState::default(), + depth_stencil: None, + multisample: wgpu::MultisampleState::default(), + multiview: None, + cache: None, + }); + + let vertex_uniform_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("vertex_uniform_buffer"), + contents: bytemuck::cast_slice(&[VertexUniform::default()]), + usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, + }); + + let vertex_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: Some("vertex_bind_group"), + layout: &vertex_bind_group_layout, + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: vertex_uniform_buffer.as_entire_binding(), + }], + }); + + let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("vertex_buffer"), + contents: bytemuck::cast_slice::, _>(&[]), + usage: wgpu::BufferUsages::VERTEX, + }); + let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("index_buffer"), + contents: bytemuck::cast_slice::(&[]), + usage: wgpu::BufferUsages::INDEX, + }); + + let fragment_uniform_buffer = + device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("fragment_uniform_buffer"), + contents: bytemuck::cast_slice(&[Matrix4::::zeros()]), + usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, + }); + let fragment_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: Some("fragment_bind_group"), + layout: &fragment_bind_group_layout, + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: fragment_uniform_buffer.as_entire_binding(), + }], + }); + + wgpu_render_state + .renderer + .write() + .callback_resources + .insert(MeshRenderResources { + pipeline, + vertex_bind_group, + vertex_uniform_buffer, + vertex_buffer, + index_buffer, + index_buffer_length: 0, + fragment_bind_group, + }); + + Self {} + } + + pub fn update(&mut self, _ui: &mut egui::Ui, _draw_area: Rect) { + // TODO we need to take mouse input to update our projection matrix with. + } + + pub fn paint( + &self, + view_state: &ViewState, + manifold_state: &mut ManifoldMeshState, + painter: Painter, + ) { + let area = painter.clip_rect(); + painter.add(egui_wgpu::Callback::new_paint_callback( + area, + MeshRenderCallback { + vertex_uniform: VertexUniform { + view_projection: Matrix4::new_orthographic( + area.left(), + area.right(), + area.bottom(), + area.top(), + VIEW_NEAR, + VIEW_FAR, + ), + pixels_per_meter: view_state.pixels_per_meter, + }, + manifold_to_upload: if manifold_state.uploaded_to_gpu { + None + } else { + manifold_state.uploaded_to_gpu = true; + Some(manifold_state.manifold.clone()) + }, + }, + )); + } +} + +struct MeshRenderResources { + pipeline: wgpu::RenderPipeline, + vertex_bind_group: wgpu::BindGroup, + vertex_uniform_buffer: wgpu::Buffer, + vertex_buffer: wgpu::Buffer, + index_buffer: wgpu::Buffer, + index_buffer_length: u32, + fragment_bind_group: wgpu::BindGroup, +} + +struct MeshRenderCallback { + vertex_uniform: VertexUniform, + manifold_to_upload: Option, +} + +impl eframe::egui_wgpu::CallbackTrait for MeshRenderCallback { + fn prepare( + &self, + device: &wgpu::Device, + queue: &wgpu::Queue, + _screen_descriptor: &egui_wgpu::ScreenDescriptor, + _egui_encoder: &mut wgpu::CommandEncoder, + callback_resources: &mut egui_wgpu::CallbackResources, + ) -> Vec { + let resources: &mut MeshRenderResources = callback_resources + .get_mut() + .expect("Mesh render resources were never inserted"); + + queue.write_buffer( + &resources.vertex_uniform_buffer, + 0, + bytemuck::cast_slice(&[self.vertex_uniform]), + ); + + if let Some(manifold) = &self.manifold_to_upload { + resources.vertex_buffer = device.create_buffer(&wgpu::BufferDescriptor { + label: Some("vertex_buffer"), + size: (manifold.0.ps.len() * std::mem::size_of::>()) as u64, + usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST, + mapped_at_creation: false, + }); + for (index, vector) in manifold.0.ps.iter().enumerate() { + queue.write_buffer( + &resources.vertex_buffer, + (index * std::mem::size_of::>()) as u64, + bytemuck::cast_slice(&[vector.cast::()]), + ); + } + + resources.index_buffer = device.create_buffer(&wgpu::BufferDescriptor { + label: Some("index_buffer"), + size: (manifold.0.hs.len() * std::mem::size_of::()) as u64, + usage: wgpu::BufferUsages::INDEX | wgpu::BufferUsages::COPY_DST, + mapped_at_creation: false, + }); + + for (index, half_edge) in manifold.0.hs.iter().enumerate() { + queue.write_buffer( + &resources.index_buffer, + (index * std::mem::size_of::()) as u64, + bytemuck::cast_slice(&[half_edge.tail as u32]), + ); + } + resources.index_buffer_length = manifold.0.hs.len() as u32; + } + + Vec::new() + } + + fn paint( + &self, + _info: egui::PaintCallbackInfo, + render_pass: &mut wgpu::RenderPass<'static>, + callback_resources: &egui_wgpu::CallbackResources, + ) { + let resources: &MeshRenderResources = callback_resources + .get() + .expect("Mesh render resources were never inserted"); + + render_pass.set_pipeline(&resources.pipeline); + render_pass.set_bind_group(0, &resources.vertex_bind_group, &[]); + render_pass.set_bind_group(1, &resources.fragment_bind_group, &[]); + render_pass.set_vertex_buffer(0, resources.vertex_buffer.slice(..)); + render_pass.set_index_buffer(resources.index_buffer.slice(..), wgpu::IndexFormat::Uint32); + render_pass.draw_indexed(0..resources.index_buffer_length, 0, 0..1); + } +} diff --git a/interpreter/Cargo.toml b/interpreter/Cargo.toml index 98637ef..dc7d04f 100644 --- a/interpreter/Cargo.toml +++ b/interpreter/Cargo.toml @@ -16,7 +16,7 @@ enum_downcast = { version = "0.1", features = [ "derive" ] } num-traits = "0.2" hashable-map = { version = "0.4.0", features = ["serde"] } imstr = "0.2.0" -nalgebra = "0.34.1" +nalgebra = { workspace = true } stack = "0.4.0" paste = "1.0.15" tempfile = { workspace = true } diff --git a/interpreter/src/execution/values/manifold_mesh.rs b/interpreter/src/execution/values/manifold_mesh.rs index dc1c64f..f9c3d2c 100644 --- a/interpreter/src/execution/values/manifold_mesh.rs +++ b/interpreter/src/execution/values/manifold_mesh.rs @@ -41,7 +41,7 @@ use crate::{ }; #[derive(Debug, Clone)] -pub struct ManifoldMesh3D(Arc); +pub struct ManifoldMesh3D(pub Arc); impl Eq for ManifoldMesh3D {} From bb77e14d922ee42d209ac3ec176626ca3340c1bb Mon Sep 17 00:00:00 2001 From: James Carl Date: Fri, 3 Apr 2026 02:49:53 -0400 Subject: [PATCH 22/71] Port to bevy --- Cargo.lock | 3317 +++++++++++++++++++++++++++++++++++++---------- flake.nix | 4 +- gui/Cargo.toml | 3 +- gui/src/main.rs | 277 ++-- 4 files changed, 2822 insertions(+), 779 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 86b90dc..6225ded 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,20 +24,6 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf203f9d3bd8f29f98833d1fbef628df18f759248a547e7e01cfbf63cda36a99" -[[package]] -name = "accesskit_atspi_common" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "890d241cf51fc784f0ac5ac34dfc847421f8d39da6c7c91a0fcc987db62a8267" -dependencies = [ - "accesskit", - "accesskit_consumer", - "atspi-common", - "serde", - "thiserror 1.0.69", - "zvariant", -] - [[package]] name = "accesskit_consumer" version = "0.31.0" @@ -62,24 +48,6 @@ dependencies = [ "objc2-foundation 0.2.2", ] -[[package]] -name = "accesskit_unix" -version = "0.17.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301e55b39cfc15d9c48943ce5f572204a551646700d0e8efa424585f94fec528" -dependencies = [ - "accesskit", - "accesskit_atspi_common", - "async-channel", - "async-executor", - "async-task", - "atspi", - "futures-lite", - "futures-util", - "serde", - "zbus", -] - [[package]] name = "accesskit_windows" version = "0.29.2" @@ -102,7 +70,6 @@ checksum = "c8cfabe59d0eaca7412bfb1f70198dd31e3b0496fee7e15b066f9c36a1a140a0" dependencies = [ "accesskit", "accesskit_macos", - "accesskit_unix", "accesskit_windows", "raw-window-handle", "winit", @@ -142,25 +109,46 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "alsa" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed7572b7ba83a31e20d1b48970ee402d2e3e0537dcfe0a3ff4d6eb7508617d43" +dependencies = [ + "alsa-sys", + "bitflags 2.11.0", + "cfg-if", + "libc", +] + +[[package]] +name = "alsa-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" +dependencies = [ + "libc", + "pkg-config", +] + [[package]] name = "android-activity" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" +checksum = "0f2a1bb052857d5dd49572219344a7332b31b76405648eabac5bc68978251bcd" dependencies = [ "android-properties", "bitflags 2.11.0", "cc", - "cesu8", - "jni 0.21.1", - "jni-sys 0.3.0", + "jni 0.22.4", "libc", "log", - "ndk", + "ndk 0.9.0", "ndk-context", - "ndk-sys", + "ndk-sys 0.6.0+11769913", "num_enum", - "thiserror 1.0.69", + "simd_cesu8", + "thiserror 2.0.18", ] [[package]] @@ -169,6 +157,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" +[[package]] +name = "android_log-sys" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84521a3cf562bc62942e294181d9eef17eb38ceb8c68677bc49f144e4c3d4f8d" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -313,6 +307,17 @@ dependencies = [ "libloading", ] +[[package]] +name = "assert_type_match" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f548ad2c4031f2902e3edc1f29c29e835829437de49562d8eb5dc5584d3a1043" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "async-broadcast" version = "0.7.2" @@ -351,6 +356,17 @@ dependencies = [ "slab", ] +[[package]] +name = "async-fs" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8034a681df4aed8b8edbd7fbe472401ecf009251c8b40556b304567052e294c5" +dependencies = [ + "async-lock", + "blocking", + "futures-lite", +] + [[package]] name = "async-io" version = "2.6.0" @@ -381,145 +397,1427 @@ dependencies = [ ] [[package]] -name = "async-process" -version = "2.5.0" +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "atomicow" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52e8890bb9844440d0c412fa74b67fd2f14e85248b6e00708059b6da9e5f8bf" +dependencies = [ + "portable-atomic", + "portable-atomic-util", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" + +[[package]] +name = "bevy" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd310426290cec560221f9750c2f4484be4a8eeea7de3483c423329b465c40e" +dependencies = [ + "bevy_internal", +] + +[[package]] +name = "bevy_a11y" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e887b25c84f384ffe3278a17cf0e4b405eaa3c8fbc3db24d05d560a11780676d" +dependencies = [ + "accesskit", + "bevy_app", + "bevy_derive", + "bevy_ecs", + "bevy_reflect", +] + +[[package]] +name = "bevy_android" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8c58de772ac1148884112e8a456c4f127a94b95a0e42ab5b160b7a11895a241" +dependencies = [ + "android-activity", +] + +[[package]] +name = "bevy_animation" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be5bf5b285f0d3fab983b4505e62e195e06930a29007ffc95bdabde834e163a2" +dependencies = [ + "bevy_animation_macros", + "bevy_app", + "bevy_asset", + "bevy_color", + "bevy_derive", + "bevy_ecs", + "bevy_math", + "bevy_mesh", + "bevy_platform", + "bevy_reflect", + "bevy_time", + "bevy_transform", + "bevy_utils", + "blake3", + "derive_more", + "downcast-rs 2.0.2", + "either", + "petgraph", + "ron", + "serde", + "smallvec", + "thiserror 2.0.18", + "thread_local", + "tracing", + "uuid", +] + +[[package]] +name = "bevy_animation_macros" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cf35516d0e7ac9ec25df533be1bf8cbaa20596a8e65f36838a3f7803a267d6d" +dependencies = [ + "bevy_macro_utils", + "quote", + "syn", +] + +[[package]] +name = "bevy_anti_alias" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" +checksum = "726cc494eb7d6a84ce6291c23636fd451fa4846604dc059fa93febca4e60a928" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_camera", + "bevy_core_pipeline", + "bevy_derive", + "bevy_diagnostic", + "bevy_ecs", + "bevy_image", + "bevy_math", + "bevy_reflect", + "bevy_render", + "bevy_shader", + "bevy_utils", + "tracing", +] + +[[package]] +name = "bevy_app" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "def9f41aa5bf9b9dec8beda307a332798609cffb9d44f71005e0cfb45164f2f6" +dependencies = [ + "bevy_derive", + "bevy_ecs", + "bevy_platform", + "bevy_reflect", + "bevy_tasks", + "bevy_utils", + "cfg-if", + "console_error_panic_hook", + "ctrlc", + "downcast-rs 2.0.2", + "log", + "thiserror 2.0.18", + "variadics_please", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "bevy_asset" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29f86fed15972b9fb1a3f7b092cf0390e67131caaedab15a2707c043e3a3c886" dependencies = [ + "async-broadcast", "async-channel", + "async-fs", "async-io", "async-lock", - "async-signal", - "async-task", - "blocking", - "cfg-if", - "event-listener", + "atomicow", + "bevy_android", + "bevy_app", + "bevy_asset_macros", + "bevy_diagnostic", + "bevy_ecs", + "bevy_platform", + "bevy_reflect", + "bevy_tasks", + "bevy_utils", + "bitflags 2.11.0", + "blake3", + "crossbeam-channel", + "derive_more", + "disqualified", + "downcast-rs 2.0.2", + "either", + "futures-io", "futures-lite", - "rustix 1.1.3", + "futures-util", + "js-sys", + "ron", + "serde", + "stackfuture", + "thiserror 2.0.18", + "tracing", + "uuid", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "bevy_asset_macros" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12cb8d948365b06561b43b7d709282e62a6abb756baac5d8e295206d5e156168" +dependencies = [ + "bevy_macro_utils", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "bevy_audio" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d68da32468ce7f4bb2863b71326acfaaa88e9aef8da8306257cd487d40cede4" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_ecs", + "bevy_math", + "bevy_reflect", + "bevy_transform", + "coreaudio-sys", + "cpal", + "rodio", + "tracing", +] + +[[package]] +name = "bevy_camera" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ed9eed054e14341852236d06a7244597b1ace39ff9ae023fbd188ffde88619" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_color", + "bevy_derive", + "bevy_ecs", + "bevy_image", + "bevy_math", + "bevy_mesh", + "bevy_reflect", + "bevy_transform", + "bevy_utils", + "bevy_window", + "derive_more", + "downcast-rs 2.0.2", + "serde", + "smallvec", + "thiserror 2.0.18", + "wgpu-types", +] + +[[package]] +name = "bevy_color" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb41e8310a85811d14a4e75cfc2d6c07ac70661d6a4883509fc960f622970a8" +dependencies = [ + "bevy_math", + "bevy_reflect", + "bytemuck", + "derive_more", + "encase", + "serde", + "thiserror 2.0.18", + "wgpu-types", +] + +[[package]] +name = "bevy_core_pipeline" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d0810e85c2436e50c67448d48a83bf0bb1b5849899619ae2c7ea817221e9172" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_camera", + "bevy_color", + "bevy_derive", + "bevy_diagnostic", + "bevy_ecs", + "bevy_image", + "bevy_math", + "bevy_platform", + "bevy_reflect", + "bevy_render", + "bevy_shader", + "bevy_transform", + "bevy_utils", + "bevy_window", + "bitflags 2.11.0", + "nonmax", + "radsort", + "smallvec", + "thiserror 2.0.18", + "tracing", +] + +[[package]] +name = "bevy_derive" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "318ee0532c3da93749859d18f89a889c638fbc56aabac4d866583df7b951d103" +dependencies = [ + "bevy_macro_utils", + "quote", + "syn", +] + +[[package]] +name = "bevy_dev_tools" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4f1464a3f5ef5c23d917987714ee89881f9f791e9ff97ecf6600ee846b9569e" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_camera", + "bevy_color", + "bevy_diagnostic", + "bevy_ecs", + "bevy_image", + "bevy_input", + "bevy_math", + "bevy_picking", + "bevy_reflect", + "bevy_render", + "bevy_shader", + "bevy_state", + "bevy_text", + "bevy_time", + "bevy_transform", + "bevy_ui", + "bevy_ui_render", + "bevy_window", + "tracing", +] + +[[package]] +name = "bevy_diagnostic" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec8543a0f7afd56d3499ba80ffab6ef0bad12f93c2d2ca9aa7b1f1b8816c3980" +dependencies = [ + "atomic-waker", + "bevy_app", + "bevy_ecs", + "bevy_platform", + "bevy_tasks", + "bevy_time", + "const-fnv1a-hash", + "log", + "serde", + "sysinfo", +] + +[[package]] +name = "bevy_ecs" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9cf7a3ee41342dd7b5a5d82e200d0e8efb933169247fce853b4ad633d51e87d" +dependencies = [ + "arrayvec", + "bevy_ecs_macros", + "bevy_platform", + "bevy_ptr", + "bevy_reflect", + "bevy_tasks", + "bevy_utils", + "bitflags 2.11.0", + "bumpalo", + "concurrent-queue", + "derive_more", + "fixedbitset", + "indexmap", + "log", + "nonmax", + "serde", + "slotmap", + "smallvec", + "thiserror 2.0.18", + "variadics_please", +] + +[[package]] +name = "bevy_ecs_macros" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "908baf585e2ea16bd53ef0da57b69580478af0059d2dbdb4369991ac9794b618" +dependencies = [ + "bevy_macro_utils", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "bevy_egui" +version = "0.39.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d0a7e4806f3f242326d2c6157531c36d710f3bf320ebc0a1678e44635ed0eac" +dependencies = [ + "arboard", + "bevy_app", + "bevy_asset", + "bevy_camera", + "bevy_color", + "bevy_core_pipeline", + "bevy_derive", + "bevy_ecs", + "bevy_image", + "bevy_input", + "bevy_log", + "bevy_math", + "bevy_mesh", + "bevy_picking", + "bevy_platform", + "bevy_reflect", + "bevy_render", + "bevy_shader", + "bevy_time", + "bevy_transform", + "bevy_ui_render", + "bevy_utils", + "bevy_window", + "bevy_winit", + "bytemuck", + "crossbeam-channel", + "egui", + "encase", + "getrandom 0.3.4", + "image", + "itertools 0.14.0", + "js-sys", + "thread_local", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webbrowser", + "wgpu-types", + "winit", +] + +[[package]] +name = "bevy_encase_derive" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fee46eeddcbc00a805ae00ffa973f224671fc5cf0fe1a796963804faeade90" +dependencies = [ + "bevy_macro_utils", + "encase_derive_impl", +] + +[[package]] +name = "bevy_feathers" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cb29be8f8443c5cc44e1c4710bbe02877e73703c60228ca043f20529a5496c6" +dependencies = [ + "accesskit", + "bevy_a11y", + "bevy_app", + "bevy_asset", + "bevy_camera", + "bevy_color", + "bevy_derive", + "bevy_ecs", + "bevy_input_focus", + "bevy_log", + "bevy_math", + "bevy_picking", + "bevy_platform", + "bevy_reflect", + "bevy_render", + "bevy_shader", + "bevy_text", + "bevy_ui", + "bevy_ui_render", + "bevy_ui_widgets", + "bevy_window", + "smol_str", +] + +[[package]] +name = "bevy_gilrs" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "611827ab0ce43b88c0a695e6603901b5f34687efecaf526c861456c9d8e6fedb" +dependencies = [ + "bevy_app", + "bevy_ecs", + "bevy_input", + "bevy_platform", + "bevy_time", + "gilrs", + "thiserror 2.0.18", + "tracing", +] + +[[package]] +name = "bevy_gizmos" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aaff0dd5f405c83d290c5cd591835f1ae8009894947ab19dadcb323062bd7e7" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_camera", + "bevy_color", + "bevy_ecs", + "bevy_gizmos_macros", + "bevy_light", + "bevy_math", + "bevy_reflect", + "bevy_time", + "bevy_transform", + "bevy_utils", +] + +[[package]] +name = "bevy_gizmos_macros" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6960ea308d7e94adcac5c712553ff86614bba6b663511f3f3812f6bec028b51e" +dependencies = [ + "bevy_macro_utils", + "quote", + "syn", +] + +[[package]] +name = "bevy_gizmos_render" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a8d18c089102de4c5e9326023ad96ba618a6961029f8102a33640b966883237" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_camera", + "bevy_core_pipeline", + "bevy_ecs", + "bevy_gizmos", + "bevy_image", + "bevy_math", + "bevy_mesh", + "bevy_pbr", + "bevy_render", + "bevy_shader", + "bevy_sprite_render", + "bevy_transform", + "bevy_utils", + "bytemuck", + "tracing", +] + +[[package]] +name = "bevy_gltf" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f37fb52655d0439656ca0a1db027d46926e463c81d893d4b1639668e5d7f1c1" +dependencies = [ + "async-lock", + "base64", + "bevy_animation", + "bevy_app", + "bevy_asset", + "bevy_camera", + "bevy_color", + "bevy_ecs", + "bevy_image", + "bevy_light", + "bevy_math", + "bevy_mesh", + "bevy_pbr", + "bevy_platform", + "bevy_reflect", + "bevy_render", + "bevy_scene", + "bevy_tasks", + "bevy_transform", + "fixedbitset", + "gltf", + "itertools 0.14.0", + "percent-encoding", + "serde", + "serde_json", + "smallvec", + "thiserror 2.0.18", + "tracing", +] + +[[package]] +name = "bevy_image" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a71daf9b2afdd032c2b1122d1d501f99126218cb3e9983b3604ec381daa35f22" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_color", + "bevy_ecs", + "bevy_math", + "bevy_platform", + "bevy_reflect", + "bevy_utils", + "bitflags 2.11.0", + "bytemuck", + "futures-lite", + "guillotiere", + "half", + "image", + "ktx2", + "rectangle-pack", + "ruzstd", + "serde", + "thiserror 2.0.18", + "tracing", + "wgpu-types", +] + +[[package]] +name = "bevy_input" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc8ffbd02df34dfc52faf420a5263985973765e228043adf542fd0d790a6b21" +dependencies = [ + "bevy_app", + "bevy_ecs", + "bevy_math", + "bevy_platform", + "bevy_reflect", + "derive_more", + "log", + "smol_str", + "thiserror 2.0.18", +] + +[[package]] +name = "bevy_input_focus" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d48a5bceccb9157549a39ab3de4017f5368b65db6471605e9a3f1c19d91bbc" +dependencies = [ + "bevy_app", + "bevy_ecs", + "bevy_input", + "bevy_math", + "bevy_picking", + "bevy_reflect", + "bevy_window", + "log", + "thiserror 2.0.18", +] + +[[package]] +name = "bevy_internal" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a11df62e49897def470471551c02f13c6fb488e55dddb5ab7ef098132e07754" +dependencies = [ + "bevy_a11y", + "bevy_android", + "bevy_animation", + "bevy_anti_alias", + "bevy_app", + "bevy_asset", + "bevy_audio", + "bevy_camera", + "bevy_color", + "bevy_core_pipeline", + "bevy_derive", + "bevy_dev_tools", + "bevy_diagnostic", + "bevy_ecs", + "bevy_feathers", + "bevy_gilrs", + "bevy_gizmos", + "bevy_gizmos_render", + "bevy_gltf", + "bevy_image", + "bevy_input", + "bevy_input_focus", + "bevy_light", + "bevy_log", + "bevy_math", + "bevy_mesh", + "bevy_pbr", + "bevy_picking", + "bevy_platform", + "bevy_post_process", + "bevy_ptr", + "bevy_reflect", + "bevy_render", + "bevy_scene", + "bevy_shader", + "bevy_sprite", + "bevy_sprite_render", + "bevy_state", + "bevy_tasks", + "bevy_text", + "bevy_time", + "bevy_transform", + "bevy_ui", + "bevy_ui_render", + "bevy_utils", + "bevy_window", + "bevy_winit", +] + +[[package]] +name = "bevy_light" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d9d2ac64390a9baacb3c0fa0f5456ac1553959d5a387874c102a09aab8b92cc" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_camera", + "bevy_color", + "bevy_ecs", + "bevy_image", + "bevy_math", + "bevy_mesh", + "bevy_platform", + "bevy_reflect", + "bevy_transform", + "bevy_utils", + "tracing", +] + +[[package]] +name = "bevy_log" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2aac1187f83a1ab2eae887564f7fb14b4abb3fbe8b2267a6426663463923120" +dependencies = [ + "android_log-sys", + "bevy_app", + "bevy_ecs", + "bevy_platform", + "bevy_utils", + "tracing", + "tracing-log", + "tracing-oslog", + "tracing-subscriber", + "tracing-wasm", +] + +[[package]] +name = "bevy_macro_utils" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b147843b81a7ec548876ff97fa7bfdc646ef2567cb465566259237b39664438" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "toml_edit 0.23.10+spec-1.0.0", +] + +[[package]] +name = "bevy_math" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e931fa969f89c83498b22c97432383afe90e90fd1a5e04fa07be8da4d3bcac84" +dependencies = [ + "approx", + "arrayvec", + "bevy_reflect", + "derive_more", + "glam 0.30.10", + "itertools 0.14.0", + "libm", + "rand 0.9.2", + "rand_distr", + "serde", + "thiserror 2.0.18", + "variadics_please", +] + +[[package]] +name = "bevy_mesh" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "288f590c8173d4cca3cae5f2ba579accd5ed1a35dd3fab338f427eb39d55f05e" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_derive", + "bevy_ecs", + "bevy_image", + "bevy_math", + "bevy_mikktspace", + "bevy_platform", + "bevy_reflect", + "bevy_transform", + "bitflags 2.11.0", + "bytemuck", + "derive_more", + "hexasphere", + "thiserror 2.0.18", + "tracing", + "wgpu-types", +] + +[[package]] +name = "bevy_mikktspace" +version = "0.17.0-dev" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef8e4b7e61dfe7719bb03c884dc270cd46a82efb40f93e9933b990c5c190c59" + +[[package]] +name = "bevy_pbr" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ab6944ffc6fd71604c0fbca68cc3e2a3654edfcdbfd232f9d8b88e3d20fdc0" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_camera", + "bevy_color", + "bevy_core_pipeline", + "bevy_derive", + "bevy_diagnostic", + "bevy_ecs", + "bevy_image", + "bevy_light", + "bevy_log", + "bevy_math", + "bevy_mesh", + "bevy_platform", + "bevy_reflect", + "bevy_render", + "bevy_shader", + "bevy_transform", + "bevy_utils", + "bitflags 2.11.0", + "bytemuck", + "derive_more", + "fixedbitset", + "nonmax", + "offset-allocator", + "smallvec", + "static_assertions", + "thiserror 2.0.18", + "tracing", +] + +[[package]] +name = "bevy_picking" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7d524dbc8f2c9e73f7ab70c148c8f7886f3c24b8aa8c252a38ba68ed06cbf10" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_camera", + "bevy_derive", + "bevy_ecs", + "bevy_input", + "bevy_math", + "bevy_mesh", + "bevy_platform", + "bevy_reflect", + "bevy_time", + "bevy_transform", + "bevy_window", + "crossbeam-channel", + "tracing", + "uuid", +] + +[[package]] +name = "bevy_platform" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec6b36504169b644acd26a5469fd8d371aa6f1d73ee5c01b1b1181ae1cefbf9b" +dependencies = [ + "critical-section", + "foldhash 0.2.0", + "futures-channel", + "hashbrown 0.16.1", + "js-sys", + "portable-atomic", + "portable-atomic-util", + "serde", + "spin 0.10.0", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-time", +] + +[[package]] +name = "bevy_post_process" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f77a4e894aea992e3d6938f1d5898a1cdbb87dba6eebfb95cb4038d0a2600e9" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_camera", + "bevy_color", + "bevy_core_pipeline", + "bevy_derive", + "bevy_ecs", + "bevy_image", + "bevy_math", + "bevy_platform", + "bevy_reflect", + "bevy_render", + "bevy_shader", + "bevy_transform", + "bevy_utils", + "bevy_window", + "bitflags 2.11.0", + "nonmax", + "radsort", + "smallvec", + "thiserror 2.0.18", + "tracing", +] + +[[package]] +name = "bevy_ptr" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7a9329e8dc4e01ced480eeec4902e6d7cb56e56ec37f6fbc4323e5c937290a7" + +[[package]] +name = "bevy_reflect" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1dfeb67a9fe4f59003a84f5f99ba6302141c70e926601cbc6abfd4a1eea9ca9" +dependencies = [ + "assert_type_match", + "bevy_platform", + "bevy_ptr", + "bevy_reflect_derive", + "bevy_utils", + "derive_more", + "disqualified", + "downcast-rs 2.0.2", + "erased-serde", + "foldhash 0.2.0", + "glam 0.30.10", + "indexmap", + "inventory", + "petgraph", + "serde", + "smallvec", + "smol_str", + "thiserror 2.0.18", + "uuid", + "variadics_please", + "wgpu-types", +] + +[[package]] +name = "bevy_reflect_derive" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "475f68c93e9cd5f17e9167635c8533a4f388f12d38245a202359e4c2721d87ba" +dependencies = [ + "bevy_macro_utils", + "indexmap", + "proc-macro2", + "quote", + "syn", + "uuid", +] + +[[package]] +name = "bevy_render" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243523e33fe5dfcebc4240b1eb2fc16e855c5d4c0ea6a8393910740956770f44" +dependencies = [ + "async-channel", + "bevy_app", + "bevy_asset", + "bevy_camera", + "bevy_color", + "bevy_derive", + "bevy_diagnostic", + "bevy_ecs", + "bevy_encase_derive", + "bevy_image", + "bevy_math", + "bevy_mesh", + "bevy_platform", + "bevy_reflect", + "bevy_render_macros", + "bevy_shader", + "bevy_tasks", + "bevy_time", + "bevy_transform", + "bevy_utils", + "bevy_window", + "bitflags 2.11.0", + "bytemuck", + "derive_more", + "downcast-rs 2.0.2", + "encase", + "fixedbitset", + "glam 0.30.10", + "image", + "indexmap", + "js-sys", + "naga", + "nonmax", + "offset-allocator", + "send_wrapper", + "smallvec", + "thiserror 2.0.18", + "tracing", + "variadics_please", + "wasm-bindgen", + "web-sys", + "wgpu", +] + +[[package]] +name = "bevy_render_macros" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66b6325e9c495a71270446784611e8d7f446f927eac8506c4c099fd10cb4c3ed" +dependencies = [ + "bevy_macro_utils", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "bevy_scene" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34cc1047d85ec8048261b63ef675c12f1e6b5782dc0b422fbcee0c140d026bd4" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_camera", + "bevy_derive", + "bevy_ecs", + "bevy_platform", + "bevy_reflect", + "bevy_transform", + "bevy_utils", + "derive_more", + "ron", + "serde", + "thiserror 2.0.18", + "uuid", +] + +[[package]] +name = "bevy_shader" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eea95f0273c32be13d6a0b799a93bc256ad7830759ede595c404d5234302da2" +dependencies = [ + "bevy_asset", + "bevy_platform", + "bevy_reflect", + "naga", + "naga_oil", + "serde", + "thiserror 2.0.18", + "tracing", + "wgpu-types", +] + +[[package]] +name = "bevy_sprite" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96ec5bc0cbdee551b610a46f41d30374bbe42b8951ffc676253c6243ab2b9395" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_camera", + "bevy_color", + "bevy_derive", + "bevy_ecs", + "bevy_image", + "bevy_math", + "bevy_mesh", + "bevy_picking", + "bevy_reflect", + "bevy_text", + "bevy_transform", + "bevy_window", + "radsort", + "tracing", + "wgpu-types", +] + +[[package]] +name = "bevy_sprite_render" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b82cb08905e7ddcea2694a95f757ae7f1fd01e6a7304076bad595d2158e4bfe0" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_camera", + "bevy_color", + "bevy_core_pipeline", + "bevy_derive", + "bevy_ecs", + "bevy_image", + "bevy_math", + "bevy_mesh", + "bevy_platform", + "bevy_reflect", + "bevy_render", + "bevy_shader", + "bevy_sprite", + "bevy_text", + "bevy_transform", + "bevy_utils", + "bitflags 2.11.0", + "bytemuck", + "derive_more", + "fixedbitset", + "nonmax", + "tracing", +] + +[[package]] +name = "bevy_state" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae0682968e97d29c1eccc8c6bb6283f2678d362779bc03f1bb990967059473b" +dependencies = [ + "bevy_app", + "bevy_ecs", + "bevy_platform", + "bevy_reflect", + "bevy_state_macros", + "bevy_utils", + "log", + "variadics_please", ] [[package]] -name = "async-recursion" -version = "1.1.1" +name = "bevy_state_macros" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +checksum = "73d32f90f9cfcef5a44401db7ce206770daaa1707b0fb95eb7a96a6933f54f1b" dependencies = [ - "proc-macro2", + "bevy_macro_utils", "quote", "syn", ] [[package]] -name = "async-signal" -version = "0.2.13" +name = "bevy_tasks" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c" +checksum = "384eb04d80aa38664d69988fd30cbbe03e937ecb65c66aa6abe60ce0bca826aa" dependencies = [ - "async-io", - "async-lock", + "async-channel", + "async-executor", + "async-task", "atomic-waker", - "cfg-if", - "futures-core", - "futures-io", - "rustix 1.1.3", - "signal-hook-registry", - "slab", - "windows-sys 0.61.2", + "bevy_platform", + "concurrent-queue", + "crossbeam-queue", + "derive_more", + "futures-lite", + "heapless 0.9.2", + "pin-project", ] [[package]] -name = "async-task" -version = "4.7.1" +name = "bevy_text" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" +checksum = "fdc5233291dfc22e584de2535f2e37ae9766d37cb5a01652de2133ba202dcb9b" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_color", + "bevy_derive", + "bevy_ecs", + "bevy_image", + "bevy_log", + "bevy_math", + "bevy_platform", + "bevy_reflect", + "bevy_utils", + "cosmic-text", + "serde", + "smallvec", + "sys-locale", + "thiserror 2.0.18", + "tracing", + "wgpu-types", +] [[package]] -name = "async-trait" -version = "0.1.89" +name = "bevy_time" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +checksum = "b5ef9af4e523195e561074cf60fbfad0f4cb8d1db504855fee3c4ce8896c7244" dependencies = [ - "proc-macro2", - "quote", - "syn", + "bevy_app", + "bevy_ecs", + "bevy_platform", + "bevy_reflect", + "crossbeam-channel", + "log", + "serde", ] [[package]] -name = "atomic-polyfill" -version = "1.0.3" +name = "bevy_transform" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +checksum = "3c3bb3de7842fef699344beb03f22bdbff16599d788fe0f47fbb3b1e6fa320eb" dependencies = [ - "critical-section", + "bevy_app", + "bevy_ecs", + "bevy_log", + "bevy_math", + "bevy_reflect", + "bevy_tasks", + "bevy_utils", + "derive_more", + "serde", + "thiserror 2.0.18", ] [[package]] -name = "atomic-waker" -version = "1.1.2" +name = "bevy_ui" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +checksum = "1691a411014085e0d35f8bb8208e5f973edd7ace061a4b1c41c83de21579dc70" +dependencies = [ + "accesskit", + "bevy_a11y", + "bevy_app", + "bevy_asset", + "bevy_camera", + "bevy_color", + "bevy_derive", + "bevy_ecs", + "bevy_image", + "bevy_input", + "bevy_input_focus", + "bevy_math", + "bevy_picking", + "bevy_platform", + "bevy_reflect", + "bevy_sprite", + "bevy_text", + "bevy_transform", + "bevy_utils", + "bevy_window", + "derive_more", + "smallvec", + "taffy", + "thiserror 2.0.18", + "tracing", + "uuid", +] [[package]] -name = "atspi" -version = "0.25.0" +name = "bevy_ui_render" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c83247582e7508838caf5f316c00791eee0e15c0bf743e6880585b867e16815c" -dependencies = [ - "atspi-common", - "atspi-connection", - "atspi-proxies", +checksum = "c2c35402d8a052f512e3fec1f36b26e83eee713fcca57f965c244ee795e1fcb0" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_camera", + "bevy_color", + "bevy_core_pipeline", + "bevy_derive", + "bevy_ecs", + "bevy_image", + "bevy_math", + "bevy_mesh", + "bevy_platform", + "bevy_reflect", + "bevy_render", + "bevy_shader", + "bevy_sprite", + "bevy_sprite_render", + "bevy_text", + "bevy_transform", + "bevy_ui", + "bevy_utils", + "bytemuck", + "derive_more", + "tracing", ] [[package]] -name = "atspi-common" -version = "0.9.0" +name = "bevy_ui_widgets" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33dfc05e7cdf90988a197803bf24f5788f94f7c94a69efa95683e8ffe76cfdfb" +checksum = "b6a63cb818b0de41bdb14990e0ce1aaaa347f871750ab280f80c427e83d72712" dependencies = [ - "enumflags2", - "serde", - "static_assertions", - "zbus", - "zbus-lockstep", - "zbus-lockstep-macros", - "zbus_names", - "zvariant", + "accesskit", + "bevy_a11y", + "bevy_app", + "bevy_camera", + "bevy_ecs", + "bevy_input", + "bevy_input_focus", + "bevy_log", + "bevy_math", + "bevy_picking", + "bevy_reflect", + "bevy_ui", ] [[package]] -name = "atspi-connection" -version = "0.9.0" +name = "bevy_utils" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4193d51303d8332304056ae0004714256b46b6635a5c556109b319c0d3784938" +checksum = "2111910cd7a4b1e6ce07eaaeb6f68a2c0ea0ca609ed0d0d506e3eb161101435b" dependencies = [ - "atspi-common", - "atspi-proxies", - "futures-lite", - "zbus", + "bevy_platform", + "disqualified", + "thread_local", ] [[package]] -name = "atspi-proxies" -version = "0.9.0" +name = "bevy_window" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2eebcb9e7e76f26d0bcfd6f0295e1cd1e6f33bedbc5698a971db8dc43d7751c" +checksum = "6df06e6993a0896bae2fe7644ae6def29a1a92b45dfb1bcebbd92af782be3638" dependencies = [ - "atspi-common", + "bevy_app", + "bevy_asset", + "bevy_ecs", + "bevy_image", + "bevy_input", + "bevy_math", + "bevy_platform", + "bevy_reflect", + "log", + "raw-window-handle", "serde", - "zbus", ] [[package]] -name = "autocfg" -version = "1.5.0" +name = "bevy_winit" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "f2de1c13d32ab8528435b58eca7ab874a1068184c6d6f266ee11433ae99d4069" +dependencies = [ + "accesskit", + "accesskit_winit", + "approx", + "bevy_a11y", + "bevy_android", + "bevy_app", + "bevy_asset", + "bevy_derive", + "bevy_ecs", + "bevy_image", + "bevy_input", + "bevy_input_focus", + "bevy_log", + "bevy_math", + "bevy_platform", + "bevy_reflect", + "bevy_tasks", + "bevy_window", + "bytemuck", + "cfg-if", + "js-sys", + "tracing", + "wasm-bindgen", + "web-sys", + "wgpu-types", + "winit", +] [[package]] -name = "beef" -version = "0.5.2" +name = "bindgen" +version = "0.72.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" +checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" +dependencies = [ + "bitflags 2.11.0", + "cexpr", + "clang-sys", + "itertools 0.13.0", + "proc-macro2", + "quote", + "regex", + "rustc-hash 2.1.2", + "shlex", + "syn", +] [[package]] name = "bit-set" @@ -548,9 +1846,24 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" dependencies = [ + "bytemuck", "serde_core", ] +[[package]] +name = "blake3" +version = "1.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d2d5991425dfd0785aed03aedcf0b321d61975c9b5b3689c774a2610ae0b51e" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "cpufeatures 0.3.0", +] + [[package]] name = "block" version = "0.1.6" @@ -575,6 +1888,15 @@ dependencies = [ "objc2 0.5.2", ] +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2 0.6.3", +] + [[package]] name = "blocking" version = "1.6.2" @@ -660,43 +1982,18 @@ dependencies = [ "thiserror 1.0.69", ] -[[package]] -name = "calloop" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dbf9978365bac10f54d1d4b04f7ce4427e51f71d61f2fe15e3fed5166474df7" -dependencies = [ - "bitflags 2.11.0", - "polling", - "rustix 1.1.3", - "slab", - "tracing", -] - [[package]] name = "calloop-wayland-source" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" dependencies = [ - "calloop 0.13.0", + "calloop", "rustix 0.38.44", "wayland-backend", "wayland-client", ] -[[package]] -name = "calloop-wayland-source" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138efcf0940a02ebf0cc8d1eff41a1682a46b431630f4c52450d6265876021fa" -dependencies = [ - "calloop 0.14.4", - "rustix 1.1.3", - "wayland-backend", - "wayland-client", -] - [[package]] name = "cc" version = "1.2.56" @@ -715,6 +2012,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom 7.1.3", +] + [[package]] name = "cfg-if" version = "1.0.4" @@ -727,15 +2033,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" -[[package]] -name = "cgl" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff" -dependencies = [ - "libc", -] - [[package]] name = "check_keyword" version = "0.4.1" @@ -784,6 +2081,17 @@ dependencies = [ "half", ] +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clap" version = "4.5.60" @@ -899,6 +2207,53 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ "crossbeam-utils", + "portable-atomic", +] + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "const-fnv1a-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b13ea120a812beba79e34316b3942a857c86ec1593cb34f27bb28272ce2cca" + +[[package]] +name = "const_panic" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e262cdaac42494e3ae34c43969f9cdeb7da178bdb4b66fa6a1ea2edb4c8ae652" +dependencies = [ + "typewit", +] + +[[package]] +name = "const_soft_float" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ca1caa64ef4ed453e68bb3db612e51cf1b2f5b871337f0fcab1c8f87cc3dff" + +[[package]] +name = "constant_time_eq" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" + +[[package]] +name = "constgebra" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1aaf9b65849a68662ac6c0810c8893a765c960b907dd7cfab9c4a50bf764fbc" +dependencies = [ + "const_soft_float", ] [[package]] @@ -982,18 +2337,103 @@ dependencies = [ name = "core-graphics-types" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags 2.11.0", + "core-foundation 0.10.1", + "libc", +] + +[[package]] +name = "core_maths" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77745e017f5edba1a9c1d854f6f3a52dac8a12dd5af5d2f54aecf61e43d80d30" +dependencies = [ + "libm", +] + +[[package]] +name = "coreaudio-rs" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "321077172d79c662f64f5071a03120748d5bb652f5231570141be24cfcd2bace" +dependencies = [ + "bitflags 1.3.2", + "core-foundation-sys", + "coreaudio-sys", +] + +[[package]] +name = "coreaudio-sys" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ceec7a6067e62d6f931a2baf6f3a751f4a892595bcec1461a3c94ef9949864b6" +dependencies = [ + "bindgen", +] + +[[package]] +name = "cosmic-text" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4cadaea21e24c49c0c82116f2b465ae6a49d63c90e428b0f8d9ae1f638ac91f" +dependencies = [ + "bitflags 2.11.0", + "fontdb", + "harfrust", + "linebender_resource_handle", + "log", + "rangemap", + "rustc-hash 1.1.0", + "self_cell", + "skrifa 0.39.0", + "smol_str", + "swash", + "sys-locale", + "unicode-bidi", + "unicode-linebreak", + "unicode-script", + "unicode-segmentation", +] + +[[package]] +name = "cpal" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "873dab07c8f743075e57f524c583985fbaf745602acbe916a01539364369a779" +dependencies = [ + "alsa", + "core-foundation-sys", + "coreaudio-rs", + "dasp_sample", + "jni 0.21.1", + "js-sys", + "libc", + "mach2", + "ndk 0.8.0", + "ndk-context", + "oboe", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows 0.54.0", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ - "bitflags 2.11.0", - "core-foundation 0.10.1", "libc", ] [[package]] name = "cpufeatures" -version = "0.2.17" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" dependencies = [ "libc", ] @@ -1160,12 +2600,35 @@ dependencies = [ "memchr", ] +[[package]] +name = "ctrlc" +version = "3.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0b1fab2ae45819af2d0731d60f2afe17227ebb1a1538a236da84c93e9a60162" +dependencies = [ + "dispatch2", + "nix 0.31.2", + "windows-sys 0.61.2", +] + [[package]] name = "cursor-icon" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" +[[package]] +name = "dasp_sample" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" + +[[package]] +name = "data-encoding" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" + [[package]] name = "derive_more" version = "2.1.1" @@ -1186,6 +2649,7 @@ dependencies = [ "quote", "rustc_version", "syn", + "unicode-xid", ] [[package]] @@ -1217,6 +2681,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" dependencies = [ "bitflags 2.11.0", + "block2 0.6.2", + "libc", "objc2 0.6.3", ] @@ -1231,6 +2697,12 @@ dependencies = [ "syn", ] +[[package]] +name = "disqualified" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9c272297e804878a2a4b707cfcfc6d2328b5bb936944613b4fdf2b9269afdfd" + [[package]] name = "dlib" version = "0.5.3" @@ -1255,6 +2727,12 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" +[[package]] +name = "downcast-rs" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "117240f60069e65410b3ae1bb213295bd828f707b5bec6596a1afc8793ce0cbc" + [[package]] name = "dpi" version = "0.1.2" @@ -1287,50 +2765,12 @@ dependencies = [ "emath", ] -[[package]] -name = "eframe" -version = "0.33.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "457481173e6db5ca9fa2be93a58df8f4c7be639587aeb4853b526c6cf87db4e6" -dependencies = [ - "ahash", - "bytemuck", - "document-features", - "egui", - "egui-wgpu", - "egui-winit", - "egui_glow", - "glow", - "glutin", - "glutin-winit", - "image", - "js-sys", - "log", - "objc2 0.5.2", - "objc2-app-kit 0.2.2", - "objc2-foundation 0.2.2", - "parking_lot", - "percent-encoding", - "pollster", - "profiling", - "raw-window-handle", - "static_assertions", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "web-time", - "wgpu", - "windows-sys 0.61.2", - "winit", -] - [[package]] name = "egui" version = "0.33.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a9b567d356674e9a5121ed3fedfb0a7c31e059fe71f6972b691bcd0bfc284e3" dependencies = [ - "accesskit", "ahash", "bitflags 2.11.0", "emath", @@ -1343,85 +2783,51 @@ dependencies = [ ] [[package]] -name = "egui-wgpu" -version = "0.33.3" +name = "either" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e4d209971c84b2352a06174abdba701af1e552ce56b144d96f2bd50a3c91236" -dependencies = [ - "ahash", - "bytemuck", - "document-features", - "egui", - "epaint", - "log", - "profiling", - "thiserror 2.0.18", - "type-map", - "web-time", - "wgpu", - "winit", -] +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] -name = "egui-winit" +name = "emath" version = "0.33.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec6687e5bb551702f4ad10ac428bab12acf9d53047ebb1082d4a0ed8c6251a29" +checksum = "491bdf728bf25ddd9ad60d4cf1c48588fa82c013a2440b91aa7fc43e34a07c32" dependencies = [ - "accesskit_winit", - "arboard", "bytemuck", - "egui", - "log", - "objc2 0.5.2", - "objc2-foundation 0.2.2", - "objc2-ui-kit", - "profiling", - "raw-window-handle", - "smithay-clipboard", - "web-time", - "webbrowser", - "winit", + "mint", ] [[package]] -name = "egui_glow" -version = "0.33.3" +name = "encase" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6420863ea1d90e750f75075231a260030ad8a9f30a7cef82cdc966492dc4c4eb" +checksum = "6e3e0ff2ee0b7aa97428308dd9e1e42369cb22f5fb8dc1c55546637443a60f1e" dependencies = [ - "bytemuck", - "egui", - "glow", - "log", - "memoffset", - "profiling", - "wasm-bindgen", - "web-sys", - "winit", + "const_panic", + "encase_derive", + "thiserror 2.0.18", ] [[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - -[[package]] -name = "emath" -version = "0.33.3" +name = "encase_derive" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "491bdf728bf25ddd9ad60d4cf1c48588fa82c013a2440b91aa7fc43e34a07c32" +checksum = "a4d90c5d7d527c6cb8a3b114efd26a6304d9ab772656e73d8f4e32b1f3d601a2" dependencies = [ - "bytemuck", - "mint", + "encase_derive_impl", ] [[package]] -name = "endi" -version = "1.1.1" +name = "encase_derive_impl" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" +checksum = "c8bad72d8308f7a382de2391ec978ddd736e0103846b965d7e2a63a75768af30" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "enum-map" @@ -1475,27 +2881,6 @@ dependencies = [ "syn", ] -[[package]] -name = "enumflags2" -version = "0.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" -dependencies = [ - "enumflags2_derive", - "serde", -] - -[[package]] -name = "enumflags2_derive" -version = "0.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "epaint" version = "0.33.3" @@ -1526,6 +2911,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "erased-serde" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec" +dependencies = [ + "serde", + "serde_core", + "typeid", +] + [[package]] name = "errno" version = "0.3.14" @@ -1542,6 +2938,15 @@ version = "3.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" +[[package]] +name = "euclid" +version = "0.22.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a05365e3b1c6d1650318537c7460c6923f1abdd272ad6842baa2b509957a06" +dependencies = [ + "num-traits", +] + [[package]] name = "event-listener" version = "5.4.1" @@ -1674,6 +3079,47 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" +[[package]] +name = "font-types" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39a654f404bbcbd48ea58c617c2993ee91d1cb63727a37bf2323a4edeed1b8c5" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "font-types" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73829a7b5c91198af28a99159b7ae4afbb252fb906159ff7f189f3a2ceaa3df2" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "fontconfig-parser" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbc773e24e02d4ddd8395fd30dc147524273a83e54e0f312d986ea30de5f5646" +dependencies = [ + "roxmltree", +] + +[[package]] +name = "fontdb" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "457e789b3d1202543297a350643cf459f836cade38934e7a4cf6a39e7cde2905" +dependencies = [ + "fontconfig-parser", + "log", + "memmap2", + "slotmap", + "tinyvec", + "ttf-parser", +] + [[package]] name = "foreign-types" version = "0.5.0" @@ -1719,6 +3165,15 @@ dependencies = [ "libc", ] +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", +] + [[package]] name = "futures-core" version = "0.3.32" @@ -1824,7 +3279,7 @@ dependencies = [ "i_overlay", "log", "num-traits", - "rand", + "rand 0.8.5", "robust", "rstar 0.12.2", "serde", @@ -1886,9 +3341,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi", "wasip2", + "wasm-bindgen", ] [[package]] @@ -1904,6 +3361,40 @@ dependencies = [ "wasip3", ] +[[package]] +name = "gilrs" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fa85c2e35dc565c90511917897ea4eae16b77f2773d5223536f7b602536d462" +dependencies = [ + "fnv", + "gilrs-core", + "log", + "uuid", + "vec_map", +] + +[[package]] +name = "gilrs-core" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d23f2cc5144060a7f8d9e02d3fce5d06705376568256a509cdbc3c24d47e4f04" +dependencies = [ + "inotify", + "js-sys", + "libc", + "libudev-sys", + "log", + "nix 0.30.1", + "objc2-core-foundation", + "objc2-io-kit", + "uuid", + "vec_map", + "wasm-bindgen", + "web-sys", + "windows 0.62.2", +] + [[package]] name = "git2" version = "0.20.4" @@ -2025,6 +3516,19 @@ name = "glam" version = "0.30.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19fc433e8437a212d1b6f1e68c7824af3aed907da60afa994e7f542d18d12aa9" +dependencies = [ + "bytemuck", + "encase", + "libm", + "rand 0.9.2", + "serde_core", +] + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "glow" @@ -2039,60 +3543,39 @@ dependencies = [ ] [[package]] -name = "glutin" -version = "0.32.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12124de845cacfebedff80e877bb37b5b75c34c5a4c89e47e1cdd67fb6041325" -dependencies = [ - "bitflags 2.11.0", - "cfg_aliases", - "cgl", - "dispatch2", - "glutin_egl_sys", - "glutin_glx_sys", - "glutin_wgl_sys", - "libloading", - "objc2 0.6.3", - "objc2-app-kit 0.3.2", - "objc2-core-foundation", - "objc2-foundation 0.3.2", - "once_cell", - "raw-window-handle", - "wayland-sys", - "windows-sys 0.52.0", - "x11-dl", -] - -[[package]] -name = "glutin-winit" -version = "0.5.0" +name = "gltf" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85edca7075f8fc728f28cb8fbb111a96c3b89e930574369e3e9c27eb75d3788f" +checksum = "e3ce1918195723ce6ac74e80542c5a96a40c2b26162c1957a5cd70799b8cacf7" dependencies = [ - "cfg_aliases", - "glutin", - "raw-window-handle", - "winit", + "byteorder", + "gltf-json", + "lazy_static", + "serde_json", ] [[package]] -name = "glutin_egl_sys" -version = "0.7.1" +name = "gltf-derive" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4680ba6195f424febdc3ba46e7a42a0e58743f2edb115297b86d7f8ecc02d2" +checksum = "14070e711538afba5d6c807edb74bcb84e5dbb9211a3bf5dea0dfab5b24f4c51" dependencies = [ - "gl_generator", - "windows-sys 0.52.0", + "inflections", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "glutin_glx_sys" -version = "0.6.1" +name = "gltf-json" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7bb2938045a88b612499fbcba375a77198e01306f52272e692f8c1f3751185" +checksum = "e6176f9d60a7eab0a877e8e96548605dedbde9190a7ae1e80bbcc1c9af03ab14" dependencies = [ - "gl_generator", - "x11-dl", + "gltf-derive", + "serde", + "serde_derive", + "serde_json", ] [[package]] @@ -2155,13 +3638,20 @@ dependencies = [ "bitflags 2.11.0", ] +[[package]] +name = "grid" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9e2d4c0a8296178d8802098410ca05d86b17a10bb5ab559b3fb404c1f948220" + [[package]] name = "gui" version = "0.1.0" dependencies = [ "anyhow", + "bevy", + "bevy_egui", "bytemuck", - "eframe", "egui", "interpreter", "nalgebra", @@ -2170,6 +3660,16 @@ dependencies = [ "tempfile", ] +[[package]] +name = "guillotiere" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62d5865c036cb1393e23c50693df631d3f5d7bcca4c04fe4cc0fd592e74a782" +dependencies = [ + "euclid", + "svg_fmt", +] + [[package]] name = "half" version = "2.7.1" @@ -2182,6 +3682,19 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "harfrust" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0caaee032384c10dd597af4579c67dee16650d862a9ccbe1233ff1a379abc07" +dependencies = [ + "bitflags 2.11.0", + "bytemuck", + "core_maths", + "read-fonts 0.36.0", + "smallvec", +] + [[package]] name = "hash32" version = "0.1.1" @@ -2235,7 +3748,10 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ + "equivalent", "foldhash 0.2.0", + "serde", + "serde_core", ] [[package]] @@ -2259,7 +3775,7 @@ dependencies = [ "atomic-polyfill", "hash32 0.2.1", "rustc_version", - "spin", + "spin 0.9.8", "stable_deref_trait", ] @@ -2273,6 +3789,17 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "heapless" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af2455f757db2b292a9b1768c4b70186d443bcb3b316252d6b540aec1cd89ed" +dependencies = [ + "hash32 0.3.1", + "portable-atomic", + "stable_deref_trait", +] + [[package]] name = "heck" version = "0.5.0" @@ -2291,6 +3818,17 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hexasphere" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29a164ceff4500f2a72b1d21beaa8aa8ad83aec2b641844c659b190cb3ea2e0b" +dependencies = [ + "constgebra", + "glam 0.30.10", + "tinyvec", +] + [[package]] name = "hexf-parse" version = "0.2.1" @@ -2504,6 +4042,12 @@ dependencies = [ "serde_core", ] +[[package]] +name = "inflections" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a" + [[package]] name = "inotify" version = "0.11.1" @@ -2542,7 +4086,7 @@ dependencies = [ "itertools 0.14.0", "levenshtein", "nalgebra", - "nom", + "nom 8.0.0", "num-traits", "paste", "pretty_assertions", @@ -2562,6 +4106,15 @@ dependencies = [ "unwrap-enum", ] +[[package]] +name = "inventory" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4f0c30c76f2f4ccee3fe55a2435f691ca00c0e4bd87abe4f4a851b1d4dac39b" +dependencies = [ + "rustversion", +] + [[package]] name = "is_terminal_polyfill" version = "1.70.2" @@ -2619,7 +4172,7 @@ dependencies = [ "cesu8", "cfg-if", "combine", - "jni-sys 0.3.0", + "jni-sys 0.3.1", "log", "thiserror 1.0.69", "walkdir", @@ -2658,9 +4211,12 @@ dependencies = [ [[package]] name = "jni-sys" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] [[package]] name = "jni-sys" @@ -2744,6 +4300,15 @@ dependencies = [ "libc", ] +[[package]] +name = "ktx2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff7f53bdf698e7aa7ec916411bbdc8078135da11b66db5182675b2227f6c0d07" +dependencies = [ + "bitflags 2.11.0", +] + [[package]] name = "lazy-regex" version = "3.6.0" @@ -2785,6 +4350,17 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" +[[package]] +name = "lewton" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030" +dependencies = [ + "byteorder", + "ogg", + "tinyvec", +] + [[package]] name = "libc" version = "0.2.182" @@ -2823,9 +4399,9 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a" +checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" dependencies = [ "bitflags 2.11.0", "libc", @@ -2847,6 +4423,16 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "libudev-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c8469b4a23b962c1396b9b451dda50ef5b283e8dd309d69033475fa9b334324" +dependencies = [ + "libc", + "pkg-config", +] + [[package]] name = "libz-sys" version = "1.1.23" @@ -2859,6 +4445,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "linebender_resource_handle" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a5ff6bcca6c4867b1c4fd4ef63e4db7436ef363e0ad7531d1558856bae64f4" + [[package]] name = "linux-raw-sys" version = "0.4.15" @@ -2932,6 +4524,15 @@ dependencies = [ "logos-codegen", ] +[[package]] +name = "mach2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44" +dependencies = [ + "libc", +] + [[package]] name = "malloc_buf" version = "0.0.6" @@ -2941,6 +4542,15 @@ dependencies = [ "libc", ] +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + [[package]] name = "matrixmultiply" version = "0.3.10" @@ -2966,15 +4576,6 @@ dependencies = [ "libc", ] -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - [[package]] name = "metal" version = "0.32.0" @@ -2999,6 +4600,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -3057,12 +4664,30 @@ dependencies = [ "log", "num-traits", "once_cell", + "pp-rs", "rustc-hash 1.1.0", "spirv", "thiserror 2.0.18", "unicode-ident", ] +[[package]] +name = "naga_oil" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "310c347db1b30e69581f3b84dc9a5c311ed583f67851b39b77953cb7a066c97f" +dependencies = [ + "codespan-reporting", + "data-encoding", + "indexmap", + "naga", + "regex", + "rustc-hash 1.1.0", + "thiserror 2.0.18", + "tracing", + "unicode-ident", +] + [[package]] name = "nalgebra" version = "0.34.1" @@ -3108,6 +4733,20 @@ dependencies = [ "syn", ] +[[package]] +name = "ndk" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" +dependencies = [ + "bitflags 2.11.0", + "jni-sys 0.3.1", + "log", + "ndk-sys 0.5.0+25.2.9519653", + "num_enum", + "thiserror 1.0.69", +] + [[package]] name = "ndk" version = "0.9.0" @@ -3115,9 +4754,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ "bitflags 2.11.0", - "jni-sys 0.3.0", + "jni-sys 0.3.1", "log", - "ndk-sys", + "ndk-sys 0.6.0+11769913", "num_enum", "raw-window-handle", "thiserror 1.0.69", @@ -3129,13 +4768,46 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" +[[package]] +name = "ndk-sys" +version = "0.5.0+25.2.9519653" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" +dependencies = [ + "jni-sys 0.3.1", +] + [[package]] name = "ndk-sys" version = "0.6.0+11769913" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" dependencies = [ - "jni-sys 0.3.0", + "jni-sys 0.3.1", +] + +[[package]] +name = "nix" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +dependencies = [ + "bitflags 2.11.0", + "cfg-if", + "cfg_aliases", + "libc", +] + +[[package]] +name = "nix" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" +dependencies = [ + "bitflags 2.11.0", + "cfg-if", + "cfg_aliases", + "libc", ] [[package]] @@ -3144,6 +4816,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nom" version = "8.0.0" @@ -3153,6 +4835,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "nonmax" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "610a5acd306ec67f907abe5567859a3c693fb9886eb1f012ab8f2a47bef3db51" + [[package]] name = "notify" version = "8.2.0" @@ -3180,6 +4868,15 @@ dependencies = [ "bitflags 2.11.0", ] +[[package]] +name = "ntapi" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae" +dependencies = [ + "winapi", +] + [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -3209,6 +4906,17 @@ dependencies = [ "serde", ] +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "num-integer" version = "0.1.46" @@ -3302,7 +5010,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" dependencies = [ "bitflags 2.11.0", - "block2", + "block2 0.5.1", "libc", "objc2 0.5.2", "objc2-core-data", @@ -3319,7 +5027,6 @@ checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ "bitflags 2.11.0", "objc2 0.6.3", - "objc2-core-foundation", "objc2-core-graphics", "objc2-foundation 0.3.2", ] @@ -3331,7 +5038,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" dependencies = [ "bitflags 2.11.0", - "block2", + "block2 0.5.1", "objc2 0.5.2", "objc2-core-location", "objc2-foundation 0.2.2", @@ -3343,7 +5050,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" dependencies = [ - "block2", + "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", ] @@ -3355,7 +5062,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" dependencies = [ "bitflags 2.11.0", - "block2", + "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", ] @@ -3390,7 +5097,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" dependencies = [ - "block2", + "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", "objc2-metal", @@ -3402,7 +5109,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" dependencies = [ - "block2", + "block2 0.5.1", "objc2 0.5.2", "objc2-contacts", "objc2-foundation 0.2.2", @@ -3421,7 +5128,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ "bitflags 2.11.0", - "block2", + "block2 0.5.1", "dispatch", "libc", "objc2 0.5.2", @@ -3438,6 +5145,17 @@ dependencies = [ "objc2-core-foundation", ] +[[package]] +name = "objc2-io-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15" +dependencies = [ + "bitflags 2.11.0", + "libc", + "objc2-core-foundation", +] + [[package]] name = "objc2-io-surface" version = "0.3.2" @@ -3455,7 +5173,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" dependencies = [ - "block2", + "block2 0.5.1", "objc2 0.5.2", "objc2-app-kit 0.2.2", "objc2-foundation 0.2.2", @@ -3468,7 +5186,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" dependencies = [ "bitflags 2.11.0", - "block2", + "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", ] @@ -3480,7 +5198,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ "bitflags 2.11.0", - "block2", + "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", "objc2-metal", @@ -3503,7 +5221,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" dependencies = [ "bitflags 2.11.0", - "block2", + "block2 0.5.1", "objc2 0.5.2", "objc2-cloud-kit", "objc2-core-data", @@ -3523,7 +5241,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" dependencies = [ - "block2", + "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", ] @@ -3535,12 +5253,54 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" dependencies = [ "bitflags 2.11.0", - "block2", + "block2 0.5.1", "objc2 0.5.2", "objc2-core-location", "objc2-foundation 0.2.2", ] +[[package]] +name = "oboe" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8b61bebd49e5d43f5f8cc7ee2891c16e0f41ec7954d36bcb6c14c5e0de867fb" +dependencies = [ + "jni 0.21.1", + "ndk 0.8.0", + "ndk-context", + "num-derive", + "num-traits", + "oboe-sys", +] + +[[package]] +name = "oboe-sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8bb09a4a2b1d668170cfe0a7d5bc103f8999fb316c98099b6a9939c9f2e79d" +dependencies = [ + "cc", +] + +[[package]] +name = "offset-allocator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e234d535da3521eb95106f40f0b73483d80bfb3aacf27c40d7e2b72f1a3e00a2" +dependencies = [ + "log", + "nonmax", +] + +[[package]] +name = "ogg" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e" +dependencies = [ + "byteorder", +] + [[package]] name = "once_cell" version = "1.21.3" @@ -3596,16 +5356,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "ordered-stream" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" -dependencies = [ - "futures-core", - "pin-project-lite", -] - [[package]] name = "os_pipe" version = "1.2.3" @@ -3681,6 +5431,8 @@ dependencies = [ "fixedbitset", "hashbrown 0.15.5", "indexmap", + "serde", + "serde_derive", ] [[package]] @@ -3700,7 +5452,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", - "rand", + "rand 0.8.5", ] [[package]] @@ -3801,12 +5553,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "pollster" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" - [[package]] name = "portable-atomic" version = "1.13.1" @@ -3831,6 +5577,15 @@ dependencies = [ "zerovec", ] +[[package]] +name = "pp-rs" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb458bb7f6e250e6eb79d5026badc10a3ebb8f9a15d1fff0f13d17c71f4d6dee" +dependencies = [ + "unicode-xid", +] + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -3872,7 +5627,7 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit", + "toml_edit 0.25.9+spec-1.1.0", ] [[package]] @@ -3931,7 +5686,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c" dependencies = [ "memchr", - "serde", ] [[package]] @@ -3949,15 +5703,31 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "radsort" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "019b4b213425016d7d84a153c4c73afb0946fbb4840e4eece7ba8848b9d6da22" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + [[package]] name = "rand" -version = "0.8.5" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ - "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.9.0", + "rand_core 0.9.5", ] [[package]] @@ -3967,7 +5737,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", ] [[package]] @@ -3979,12 +5759,37 @@ dependencies = [ "getrandom 0.2.17", ] +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rand_distr" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8615d50dcf34fa31f7ab52692afec947c4dd0ab803cc87cb3b0b4570ff7463" +dependencies = [ + "num-traits", + "rand 0.9.2", +] + [[package]] name = "range-alloc" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca45419789ae5a7899559e9512e58ca889e41f04f1f2445e9f4b290ceccd1d08" +[[package]] +name = "rangemap" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "973443cf09a9c8656b574a866ab68dfa19f0867d0340648c7d2f6a71b8a8ea68" + [[package]] name = "raw-window-handle" version = "0.6.2" @@ -4017,6 +5822,33 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "read-fonts" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eaa2941a4c05443ee3a7b26ab076a553c343ad5995230cc2b1d3e993bdc6345" +dependencies = [ + "bytemuck", + "core_maths", + "font-types 0.10.1", +] + +[[package]] +name = "read-fonts" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b634fabf032fab15307ffd272149b622260f55974d9fad689292a5d33df02e5" +dependencies = [ + "bytemuck", + "font-types 0.11.1", +] + +[[package]] +name = "rectangle-pack" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0d463f2884048e7153449a55166f91028d5b0ea53c79377099ce4e8cf0cf9bb" + [[package]] name = "redox_syscall" version = "0.4.1" @@ -4107,6 +5939,36 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e27ee8bb91ca0adcf0ecb116293afa12d393f9c2b9b9cd54d33e8078fe19839" +[[package]] +name = "rodio" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ceb6607dd738c99bc8cb28eff249b7cd5c8ec88b9db96c0608c1480d140fb1" +dependencies = [ + "cpal", + "lewton", +] + +[[package]] +name = "ron" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4147b952f3f819eca0e99527022f7d6a8d05f111aeb0a62960c74eb283bec8fc" +dependencies = [ + "bitflags 2.11.0", + "once_cell", + "serde", + "serde_derive", + "typeid", + "unicode-ident", +] + +[[package]] +name = "roxmltree" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" + [[package]] name = "rstar" version = "0.8.4" @@ -4176,9 +6038,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hash" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" [[package]] name = "rustc-stable-hash" @@ -4227,6 +6089,15 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +[[package]] +name = "ruzstd" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ff0cc5e135c8870a775d3320910cd9b564ec036b4dc0b8741629020be63f01" +dependencies = [ + "twox-hash", +] + [[package]] name = "ryu" version = "1.0.23" @@ -4272,7 +6143,7 @@ dependencies = [ "ab_glyph", "log", "memmap2", - "smithay-client-toolkit 0.19.2", + "smithay-client-toolkit", "tiny-skia", ] @@ -4282,12 +6153,24 @@ version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "069ccc9fbbb7f2de521452b5c96d7d898b0d2e5f49698adbcfc13914f218d3af" +[[package]] +name = "self_cell" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b12e76d157a900eb52e81bc6e9f3069344290341720e9178cde2407113ac8d89" + [[package]] name = "semver" version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +[[package]] +name = "send_wrapper" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" + [[package]] name = "serde" version = "1.0.228" @@ -4332,17 +6215,6 @@ dependencies = [ "zmij", ] -[[package]] -name = "serde_repr" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "sha2" version = "0.10.9" @@ -4350,10 +6222,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "shlex" version = "1.3.0" @@ -4412,9 +6293,9 @@ dependencies = [ [[package]] name = "simd-adler32" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" [[package]] name = "simd_cesu8" @@ -4438,6 +6319,26 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" +[[package]] +name = "skrifa" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9eb0b904a04d09bd68c65d946617b8ff733009999050f3b851c32fb3cfb60e" +dependencies = [ + "bytemuck", + "read-fonts 0.36.0", +] + +[[package]] +name = "skrifa" +version = "0.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fbdfe3d2475fbd7ddd1f3e5cf8288a30eb3e5f95832829570cd88115a7434ac" +dependencies = [ + "bytemuck", + "read-fonts 0.37.0", +] + [[package]] name = "slab" version = "0.4.12" @@ -4472,8 +6373,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" dependencies = [ "bitflags 2.11.0", - "calloop 0.13.0", - "calloop-wayland-source 0.3.0", + "calloop", + "calloop-wayland-source", "cursor-icon", "libc", "log", @@ -4490,44 +6391,6 @@ dependencies = [ "xkeysym", ] -[[package]] -name = "smithay-client-toolkit" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0512da38f5e2b31201a93524adb8d3136276fa4fe4aafab4e1f727a82b534cc0" -dependencies = [ - "bitflags 2.11.0", - "calloop 0.14.4", - "calloop-wayland-source 0.4.1", - "cursor-icon", - "libc", - "log", - "memmap2", - "rustix 1.1.3", - "thiserror 2.0.18", - "wayland-backend", - "wayland-client", - "wayland-csd-frame", - "wayland-cursor", - "wayland-protocols", - "wayland-protocols-experimental", - "wayland-protocols-misc", - "wayland-protocols-wlr", - "wayland-scanner", - "xkeysym", -] - -[[package]] -name = "smithay-clipboard" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71704c03f739f7745053bde45fa203a46c58d25bc5c4efba1d9a60e9dba81226" -dependencies = [ - "libc", - "smithay-client-toolkit 0.20.0", - "wayland-backend", -] - [[package]] name = "smol_str" version = "0.2.2" @@ -4558,6 +6421,15 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spin" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" +dependencies = [ + "portable-atomic", +] + [[package]] name = "spirv" version = "0.3.0+sdk-1.3.268.0" @@ -4582,6 +6454,15 @@ dependencies = [ "coalesce", ] +[[package]] +name = "stackfuture" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115beb9c69db2393ff10b75a1b8587a51716e5551d015001e55320ed279d32f9" +dependencies = [ + "const_panic", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -4650,6 +6531,23 @@ dependencies = [ "syn", ] +[[package]] +name = "svg_fmt" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0193cc4331cfd2f3d2011ef287590868599a2f33c3e69bc22c1a3d3acf9e02fb" + +[[package]] +name = "swash" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "842f3cd369c2ba38966204f983eaa5e54a8e84a7d7159ed36ade2b6c335aae64" +dependencies = [ + "skrifa 0.40.0", + "yazi", + "zeno", +] + [[package]] name = "syn" version = "2.0.117" @@ -4672,6 +6570,41 @@ dependencies = [ "syn", ] +[[package]] +name = "sys-locale" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4" +dependencies = [ + "libc", +] + +[[package]] +name = "sysinfo" +version = "0.37.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16607d5caffd1c07ce073528f9ed972d88db15dd44023fa57142963be3feb11f" +dependencies = [ + "libc", + "memchr", + "ntapi", + "objc2-core-foundation", + "objc2-io-kit", + "windows 0.61.3", +] + +[[package]] +name = "taffy" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41ba83ebaf2954d31d05d67340fd46cebe99da2b7133b0dd68d70c65473a437b" +dependencies = [ + "arrayvec", + "grid", + "serde", + "slotmap", +] + [[package]] name = "tempfile" version = "3.25.0" @@ -4750,6 +6683,15 @@ dependencies = [ "syn", ] +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + [[package]] name = "tiff" version = "0.11.3" @@ -4799,66 +6741,154 @@ dependencies = [ "zerovec", ] +[[package]] +name = "tinyvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml_datetime" +version = "0.7.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_datetime" -version = "1.0.0+spec-1.1.0" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32c2555c699578a4f59f0cc68e5116c8d7cabbd45e1409b989d4be085b53f13e" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" dependencies = [ "serde_core", ] [[package]] name = "toml_edit" -version = "0.25.4+spec-1.1.0" +version = "0.23.10+spec-1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" +dependencies = [ + "indexmap", + "toml_datetime 0.7.5+spec-1.1.0", + "toml_parser", + "winnow 0.7.15", +] + +[[package]] +name = "toml_edit" +version = "0.25.9+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7193cbd0ce53dc966037f54351dbbcf0d5a642c7f0038c382ef9e677ce8c13f2" +checksum = "da053d28fe57e2c9d21b48261e14e7b4c8b670b54d2c684847b91feaf4c7dac5" dependencies = [ "indexmap", - "toml_datetime", + "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", - "winnow", + "winnow 1.0.1", ] [[package]] name = "toml_parser" -version = "1.0.9+spec-1.1.0" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ca317ebc49f06bd748bfba29533eac9485569dc9bf80b849024b025e814fb9" +dependencies = [ + "winnow 1.0.1", +] + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "winnow", + "log", + "once_cell", + "tracing-core", ] [[package]] -name = "tracing" -version = "0.1.44" +name = "tracing-oslog" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +checksum = "d76902d2a8d5f9f55a81155c08971734071968c90f2d9bfe645fe700579b2950" dependencies = [ - "log", - "pin-project-lite", - "tracing-attributes", + "cc", + "cfg-if", "tracing-core", + "tracing-subscriber", ] [[package]] -name = "tracing-attributes" -version = "0.1.31" +name = "tracing-subscriber" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ - "proc-macro2", - "quote", - "syn", + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", ] [[package]] -name = "tracing-core" -version = "0.1.36" +name = "tracing-wasm" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +checksum = "4575c663a174420fa2d78f4108ff68f65bf2fbb7dd89f33749b6e826b3626e07" dependencies = [ - "once_cell", + "tracing", + "tracing-subscriber", + "wasm-bindgen", ] [[package]] @@ -4896,7 +6926,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8765b90061cba6c22b5831f675da109ae5561588290f9fa2317adab2714d5a6" dependencies = [ "memchr", - "nom", + "nom 8.0.0", "petgraph", ] @@ -4905,15 +6935,15 @@ name = "ttf-parser" version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" +dependencies = [ + "core_maths", +] [[package]] -name = "type-map" -version = "0.5.1" +name = "twox-hash" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb30dbbd9036155e74adad6812e9898d03ec374946234fbcebd5dfc7b9187b90" -dependencies = [ - "rustc-hash 2.1.1", -] +checksum = "9ea3136b675547379c4bd395ca6b938e5ad3c3d20fad76e7fe85f9e0d011419c" [[package]] name = "type-sitter" @@ -4973,6 +7003,12 @@ dependencies = [ "type-sitter-gen", ] +[[package]] +name = "typeid" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" + [[package]] name = "typenum" version = "1.19.0" @@ -4980,15 +7016,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] -name = "uds_windows" -version = "1.2.1" +name = "typewit" +version = "1.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" -dependencies = [ - "memoffset", - "tempfile", - "windows-sys 0.61.2", -] +checksum = "f8c1ae7cc0fdb8b842d65d127cb981574b0d2b249b74d1c7a2986863dc134f71" [[package]] name = "uneval" @@ -5006,12 +7037,30 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" +[[package]] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + +[[package]] +name = "unicode-script" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "383ad40bb927465ec0ce7720e033cb4ca06912855fc35db31b5755d0de75b1ee" + [[package]] name = "unicode-segmentation" version = "1.12.0" @@ -5093,21 +7142,45 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.22.0" +version = "1.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a68d3c8f01c0cfa54a75291d83601161799e4a89a39e0929f4b0354d88757a37" +checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" dependencies = [ + "getrandom 0.4.1", "js-sys", "serde_core", "wasm-bindgen", ] +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "variadics_please" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41b6d82be61465f97d42bd1d15bf20f3b0a3a0905018f38f9d6f6962055b0b5c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "vcpkg" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + [[package]] name = "version_check" version = "0.9.5" @@ -5257,7 +7330,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fee64194ccd96bf648f42a65a7e589547096dfa702f7cadef84347b66ad164f9" dependencies = [ "cc", - "downcast-rs", + "downcast-rs 1.2.1", "rustix 1.1.3", "scoped-tls", "smallvec", @@ -5310,32 +7383,6 @@ dependencies = [ "wayland-scanner", ] -[[package]] -name = "wayland-protocols-experimental" -version = "20250721.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40a1f863128dcaaec790d7b4b396cc9b9a7a079e878e18c47e6c2d2c5a8dcbb1" -dependencies = [ - "bitflags 2.11.0", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "wayland-scanner", -] - -[[package]] -name = "wayland-protocols-misc" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791c58fdeec5406aa37169dd815327d1e47f334219b523444bc26d70ceb4c34e" -dependencies = [ - "bitflags 2.11.0", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "wayland-scanner", -] - [[package]] name = "wayland-protocols-plasma" version = "0.3.10" @@ -5381,7 +7428,6 @@ checksum = "1e6dbfc3ac5ef974c92a2235805cc0114033018ae1290a72e474aa8b28cbbdfd" dependencies = [ "dlib", "log", - "once_cell", "pkg-config", ] @@ -5442,14 +7488,12 @@ dependencies = [ "js-sys", "log", "naga", - "parking_lot", "portable-atomic", "profiling", "raw-window-handle", "smallvec", "static_assertions", "wasm-bindgen", - "wasm-bindgen-futures", "web-sys", "wgpu-core", "wgpu-hal", @@ -5482,7 +7526,7 @@ dependencies = [ "smallvec", "thiserror 2.0.18", "wgpu-core-deps-apple", - "wgpu-core-deps-emscripten", + "wgpu-core-deps-wasm", "wgpu-core-deps-windows-linux-android", "wgpu-hal", "wgpu-types", @@ -5498,10 +7542,10 @@ dependencies = [ ] [[package]] -name = "wgpu-core-deps-emscripten" +name = "wgpu-core-deps-wasm" version = "27.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06ac3444a95b0813ecfd81ddb2774b66220b264b3e2031152a4a29fda4da6b5" +checksum = "9b1027dcf3b027a877e44819df7ceb0e2e98578830f8cd34cd6c3c7c2a7a50b7" dependencies = [ "wgpu-hal", ] @@ -5544,7 +7588,7 @@ dependencies = [ "log", "metal", "naga", - "ndk-sys", + "ndk-sys 0.6.0+11769913", "objc", "once_cell", "ordered-float", @@ -5574,6 +7618,7 @@ dependencies = [ "bytemuck", "js-sys", "log", + "serde", "thiserror 2.0.18", "web-sys", ] @@ -5619,6 +7664,16 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" +dependencies = [ + "windows-core 0.54.0", + "windows-targets 0.52.6", +] + [[package]] name = "windows" version = "0.58.0" @@ -5635,11 +7690,23 @@ version = "0.61.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" dependencies = [ - "windows-collections", + "windows-collections 0.2.0", "windows-core 0.61.2", - "windows-future", + "windows-future 0.2.1", "windows-link 0.1.3", - "windows-numerics", + "windows-numerics 0.2.0", +] + +[[package]] +name = "windows" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" +dependencies = [ + "windows-collections 0.3.2", + "windows-core 0.62.2", + "windows-future 0.3.2", + "windows-numerics 0.3.1", ] [[package]] @@ -5651,6 +7718,25 @@ dependencies = [ "windows-core 0.61.2", ] +[[package]] +name = "windows-collections" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" +dependencies = [ + "windows-core 0.62.2", +] + +[[package]] +name = "windows-core" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" +dependencies = [ + "windows-result 0.1.2", + "windows-targets 0.52.6", +] + [[package]] name = "windows-core" version = "0.58.0" @@ -5698,7 +7784,18 @@ checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" dependencies = [ "windows-core 0.61.2", "windows-link 0.1.3", - "windows-threading", + "windows-threading 0.1.0", +] + +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core 0.62.2", + "windows-link 0.2.1", + "windows-threading 0.2.1", ] [[package]] @@ -5767,6 +7864,25 @@ dependencies = [ "windows-link 0.1.3", ] +[[package]] +name = "windows-numerics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" +dependencies = [ + "windows-core 0.62.2", + "windows-link 0.2.1", +] + +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-result" version = "0.2.0" @@ -5924,6 +8040,15 @@ dependencies = [ "windows-link 0.1.3", ] +[[package]] +name = "windows-threading" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link 0.2.1", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -6072,9 +8197,9 @@ dependencies = [ "android-activity", "atomic-waker", "bitflags 2.11.0", - "block2", + "block2 0.5.1", "bytemuck", - "calloop 0.13.0", + "calloop", "cfg_aliases", "concurrent-queue", "core-foundation 0.9.4", @@ -6084,7 +8209,7 @@ dependencies = [ "js-sys", "libc", "memmap2", - "ndk", + "ndk 0.9.0", "objc2 0.5.2", "objc2-app-kit 0.2.2", "objc2-foundation 0.2.2", @@ -6096,7 +8221,7 @@ dependencies = [ "redox_syscall 0.4.1", "rustix 0.38.44", "sctk-adwaita", - "smithay-client-toolkit 0.19.2", + "smithay-client-toolkit", "smol_str", "tracing", "unicode-segmentation", @@ -6123,6 +8248,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" +dependencies = [ + "memchr", +] + [[package]] name = "wit-bindgen" version = "0.51.0" @@ -6304,6 +8438,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" +[[package]] +name = "yazi" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01738255b5a16e78bbb83e7fbba0a1e7dd506905cfc53f4622d89015a03fbb5" + [[package]] name = "yoke" version = "0.8.1" @@ -6328,101 +8468,10 @@ dependencies = [ ] [[package]] -name = "zbus" -version = "5.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca82f95dbd3943a40a53cfded6c2d0a2ca26192011846a1810c4256ef92c60bc" -dependencies = [ - "async-broadcast", - "async-executor", - "async-io", - "async-lock", - "async-process", - "async-recursion", - "async-task", - "async-trait", - "blocking", - "enumflags2", - "event-listener", - "futures-core", - "futures-lite", - "hex", - "libc", - "ordered-stream", - "rustix 1.1.3", - "serde", - "serde_repr", - "tracing", - "uds_windows", - "uuid", - "windows-sys 0.61.2", - "winnow", - "zbus_macros", - "zbus_names", - "zvariant", -] - -[[package]] -name = "zbus-lockstep" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6998de05217a084b7578728a9443d04ea4cd80f2a0839b8d78770b76ccd45863" -dependencies = [ - "zbus_xml", - "zvariant", -] - -[[package]] -name = "zbus-lockstep-macros" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10da05367f3a7b7553c8cdf8fa91aee6b64afebe32b51c95177957efc47ca3a0" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "zbus-lockstep", - "zbus_xml", - "zvariant", -] - -[[package]] -name = "zbus_macros" -version = "5.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897e79616e84aac4b2c46e9132a4f63b93105d54fe8c0e8f6bffc21fa8d49222" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", - "zbus_names", - "zvariant", - "zvariant_utils", -] - -[[package]] -name = "zbus_names" -version = "4.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffd8af6d5b78619bab301ff3c560a5bd22426150253db278f164d6cf3b72c50f" -dependencies = [ - "serde", - "winnow", - "zvariant", -] - -[[package]] -name = "zbus_xml" -version = "5.1.0" +name = "zeno" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "441a0064125265655bccc3a6af6bef56814d9277ac83fce48b1cd7e160b80eac" -dependencies = [ - "quick-xml", - "serde", - "zbus_names", - "zvariant", -] +checksum = "6df3dc4292935e51816d896edcd52aa30bc297907c26167fec31e2b0c6a32524" [[package]] name = "zerocopy" @@ -6512,49 +8561,9 @@ checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" [[package]] name = "zune-jpeg" -version = "0.5.13" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec5f41c76397b7da451efd19915684f727d7e1d516384ca6bd0ec43ec94de23c" +checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" dependencies = [ "zune-core", ] - -[[package]] -name = "zvariant" -version = "5.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5708299b21903bbe348e94729f22c49c55d04720a004aa350f1f9c122fd2540b" -dependencies = [ - "endi", - "enumflags2", - "serde", - "winnow", - "zvariant_derive", - "zvariant_utils", -] - -[[package]] -name = "zvariant_derive" -version = "5.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b59b012ebe9c46656f9cc08d8da8b4c726510aef12559da3e5f1bf72780752c" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", - "zvariant_utils", -] - -[[package]] -name = "zvariant_utils" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f75c23a64ef8f40f13a6989991e643554d9bef1d682a281160cf0c1bc389c5e9" -dependencies = [ - "proc-macro2", - "quote", - "serde", - "syn", - "winnow", -] diff --git a/flake.nix b/flake.nix index 8cf96e6..e19d5ab 100644 --- a/flake.nix +++ b/flake.nix @@ -47,6 +47,8 @@ libXi vulkan-loader libGL + alsa-lib + udev ]; in rec { @@ -73,7 +75,7 @@ cargo-expand openssl pkg-config - ]; + ] ++ gui-dependencies; LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath ([ openssl diff --git a/gui/Cargo.toml b/gui/Cargo.toml index 634fd1d..df967df 100644 --- a/gui/Cargo.toml +++ b/gui/Cargo.toml @@ -4,7 +4,6 @@ version = "0.1.0" edition = "2024" [dependencies] -eframe = { version = "0.33", features = ["wgpu"] } egui = { version = "0.33", features = ["mint"] } interpreter = { path = "../interpreter" } anyhow = { workspace = true } @@ -13,3 +12,5 @@ tempfile = { workspace = true } notify = "8" bytemuck = "1" nalgebra = { workspace = true } +bevy = "0.18.1" +bevy_egui = "0.39.1" diff --git a/gui/src/main.rs b/gui/src/main.rs index a9af70e..06611d1 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -23,7 +23,11 @@ use std::{ time::Duration, }; -use eframe::egui; +use bevy::{ + prelude::*, + winit::{EventLoopProxyWrapper, WinitSettings, WinitUserEvent}, +}; +use bevy_egui::{EguiContexts, EguiGlobalSettings, EguiPlugin, EguiPrimaryContextPass}; use egui::{Color32, Mesh, Painter, RichText, Sense, StrokeKind, TextEdit}; use interpreter::{ ExecutionContext, FsStore, LogMessage, RuntimeLog, SourceReference, StackScope, StackTrace, @@ -36,23 +40,29 @@ use interpreter::{ use notify::{EventKind, RecommendedWatcher, Watcher, recommended_watcher}; use tempfile::TempDir; -use crate::{ - visualize2d::{ViewState2D, build_fill_mesh_from_polygon, paint_linestring, paint_polygon}, - visualize3d::ViewState3D, +use crate::visualize2d::{ + ViewState2D, build_fill_mesh_from_polygon, paint_linestring, paint_polygon, }; mod visualize2d; -mod visualize3d; +// mod visualize3d; fn main() { - let native_options = eframe::NativeOptions::default(); - if let Err(error) = eframe::run_native( - "Command CAD", - native_options, - Box::new(|cc| Ok(Box::new(CommandCAD::new(cc)))), - ) { - eprintln!("Failed to run application: {error}"); - } + let mut app = App::new(); + app.add_plugins(DefaultPlugins.set(WindowPlugin { + primary_window: Some(Window { + // You may want this set to `true` if you need virtual keyboard work in mobile browsers. + prevent_default_event_handling: false, + title: String::from("Command CAD"), + ..default() + }), + ..default() + })) + .insert_resource(WinitSettings::desktop_app()) + .add_plugins(EguiPlugin::default()) + .add_systems(Startup, setup) + .add_systems(EguiPrimaryContextPass, render_ui); + app.run(); } #[derive(Debug)] @@ -83,7 +93,7 @@ struct RuntimeJob { struct PendingJob { shutdown_signal: Arc, - response: oneshot::Receiver, + response: Mutex>, } enum RuntimeValue { @@ -233,6 +243,7 @@ fn runtime(expression_rx: mpsc::Receiver) { } } +#[derive(Resource)] struct CommandCAD { expression: String, expression_tx: mpsc::Sender, @@ -240,54 +251,11 @@ struct CommandCAD { last_result: Option>, watched_files: HashSet>, file_watcher: Result, - file_updates_rx: mpsc::Receiver>, + file_updates_rx: Mutex>>, view_state: ViewState, } impl CommandCAD { - fn new(cc: &eframe::CreationContext<'_>) -> Self { - let (mut expression_tx, expression_rx) = mpsc::channel(); - std::thread::spawn(|| runtime(expression_rx)); - - let (file_updates_tx, file_updates_rx) = mpsc::channel(); - - let gui_ctx = cc.egui_ctx.clone(); - let file_watcher = recommended_watcher(move |event: Result| { - // Notify and refresh the GUI whenever there's an update to one of the project files. - - // This is a really horrible hack, but I have no idea how to better fix it and it seems - // to be what the "experts" are doing as well (I looked at a higher-level library for - // watching for file changes). Basically, sometimes we get this notification before the - // file is available on disk. We need to check and possibly wait to see if the file is - // actually ready. - if let Ok(event) = &event - && matches!(event.kind, EventKind::Create(_) | EventKind::Modify(_)) - { - while !event.paths.iter().all(|path| path.exists()) { - std::thread::sleep(Duration::from_millis(10)); - } - } - - file_updates_tx.send(event).ok(); - gui_ctx.request_repaint(); - }); - - Self { - expression: String::new(), - expression_tx, - active_job: None, - last_result: None, - watched_files: HashSet::new(), - file_watcher, - file_updates_rx, - view_state: ViewState { - pixels_per_meter: 100.0, - view_state_2d: ViewState2D::default(), - view_state_3d: ViewState3D::new(cc), - }, - } - } - fn spawn_job(&mut self, ctx: &egui::Context) { if let Some(pending_job) = self.active_job.take() { pending_job @@ -301,7 +269,7 @@ impl CommandCAD { let pending_job = PendingJob { shutdown_signal: shutdown_signal.clone(), - response: response_rx, + response: Mutex::new(response_rx), }; let runtime_job = RuntimeJob { @@ -318,7 +286,7 @@ impl CommandCAD { } fn check_if_watched_files_changed(&mut self) -> bool { - match self.file_updates_rx.try_recv() { + match self.file_updates_rx.get_mut().unwrap().try_recv() { Ok(Ok(event)) => matches!(event.kind, EventKind::Modify(_) | EventKind::Create(_)), // TODO log that or something. Ok(Err(error)) => { @@ -332,10 +300,10 @@ impl CommandCAD { } fn check_job(&mut self) { - if let Some(active_job) = &self.active_job { + if let Some(active_job) = &mut self.active_job { // This could fail by the thread being closed, but that shouldn't happen and won't // cause us to panic. - if let Ok(output) = active_job.response.try_recv() { + if let Ok(output) = active_job.response.get_mut().unwrap().try_recv() { self.last_result = Some(output.result); self.active_job = None; @@ -365,80 +333,143 @@ impl CommandCAD { } } -impl eframe::App for CommandCAD { - fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { - egui::CentralPanel::default().show(ctx, |ui| { - let expression_editor = TextEdit::multiline(&mut self.expression) - .code_editor() - .desired_width(f32::INFINITY) - .hint_text("expression"); - if ui.add(expression_editor).changed() - || self.check_if_watched_files_changed() - { - self.spawn_job(ctx); +fn setup( + mut commands: Commands, + event_loop_proxy: Res, + mut egui_global_settings: ResMut, +) { + egui_global_settings.auto_create_primary_context = true; + + // Only update when there are events worth updating for. + commands.insert_resource(WinitSettings::desktop_app()); + + let (expression_tx, expression_rx) = mpsc::channel(); + std::thread::spawn(|| runtime(expression_rx)); + + let (file_updates_tx, file_updates_rx) = mpsc::channel(); + let file_updates_rx = Mutex::new(file_updates_rx); + + let event_loop_proxy = event_loop_proxy.clone(); + let file_watcher = recommended_watcher(move |event: Result| { + // Notify and refresh the GUI whenever there's an update to one of the project files. + + // This is a really horrible hack, but I have no idea how to better fix it and it seems + // to be what the "experts" are doing as well (I looked at a higher-level library for + // watching for file changes). Basically, sometimes we get this notification before the + // file is available on disk. We need to check and possibly wait to see if the file is + // actually ready. + if let Ok(event) = &event + && matches!(event.kind, EventKind::Create(_) | EventKind::Modify(_)) + { + while !event.paths.iter().all(|path| path.exists()) { + std::thread::sleep(Duration::from_millis(10)); } - let mut draw_area = ui.available_rect_before_wrap(); - draw_area.min.y += 30.0; // We don't know how tall the status bar is at this time, so I - // just assume 30 and that seems to be working well enough. - ui.horizontal(|ui| { - if self.active_job.is_some() { - ui.label(RichText::new("Working...").color(Color32::YELLOW)); - } else { - ui.label(RichText::new("Ready").color(Color32::GREEN)); - } + } - self.view_state.view_state_2d.draw_interface(&mut self.view_state.pixels_per_meter, ui, &self.last_result, draw_area); - }); + file_updates_tx.send(event).ok(); + event_loop_proxy + .clone() + .send_event(WinitUserEvent::WakeUp) + .ok(); + }); + + commands.insert_resource(CommandCAD { + expression: String::new(), + expression_tx, + active_job: None, + last_result: None, + watched_files: HashSet::new(), + file_watcher, + file_updates_rx, + view_state: ViewState { + pixels_per_meter: 100.0, + view_state_2d: ViewState2D::default(), + // view_state_3d: ViewState3D::new(cc), + }, + }); + + commands.spawn(Camera2d); +} - if let Err(error) = &self.file_watcher { - ui.label( - RichText::new(format!("Failed to setup file watching: {error}\nOutput will not update automatically when files are modified")) - .color(Color32::YELLOW), - ); +fn render_ui(mut command_cad: ResMut, mut contexts: EguiContexts) -> Result { + let ctx = contexts.ctx_mut()?; + + egui::CentralPanel::default().show(ctx, |ui| { + let expression_editor = TextEdit::multiline(&mut command_cad.expression) + .code_editor() + .desired_width(f32::INFINITY) + .hint_text("expression"); + if ui.add(expression_editor).changed() + || command_cad.check_if_watched_files_changed() + { + command_cad.spawn_job(ctx); + } + let mut draw_area = ui.available_rect_before_wrap(); + draw_area.min.y += 30.0; // We don't know how tall the status bar is at this time, so I + // just assume 30 and that seems to be working well enough. + ui.horizontal(|ui| { + if command_cad.active_job.is_some() { + ui.label(RichText::new("Working...").color(Color32::YELLOW)); + } else { + ui.label(RichText::new("Ready").color(Color32::GREEN)); } - // Update the job status. - self.check_job(); + let command_cad = &mut *command_cad; + command_cad.view_state.view_state_2d.draw_interface(&mut command_cad.view_state.pixels_per_meter, ui, &command_cad.last_result, draw_area); + }); + + if let Err(error) = &command_cad.file_watcher { + ui.label( + RichText::new(format!("Failed to setup file watching: {error}\nOutput will not update automatically when files are modified")) + .color(Color32::YELLOW), + ); + } - // TODO Add some kind of scale legend. + // Update the job status. + command_cad.check_job(); - match &mut self.last_result { - None => {} - Some(Ok(RuntimeValue::TextValue(text))) => { - egui::ScrollArea::vertical().show(ui, |ui| { - ui.label(text.as_str()); - }); - } - Some(Ok(RuntimeValue::LineString(line_string))) => { - let painter = self.view_state.prep_for_painting(ui); - painter.add(paint_linestring(draw_area, &self.view_state, StrokeKind::Middle, &line_string.0)); - } - Some(Ok(RuntimeValue::Polygon { polygon, mesh})) => { - let painter = self.view_state.prep_for_painting(ui); - paint_polygon(&painter, draw_area, &self.view_state, &polygon.0, mesh.clone()); - } - Some(Ok(RuntimeValue::PolygonSet { polygon_set, meshes })) => { - let painter = self.view_state.prep_for_painting(ui); - for (polygon, mesh) in polygon_set.0.iter().zip(meshes.iter()) { - paint_polygon(&painter, draw_area, &self.view_state, polygon, mesh.clone()); - } - } - Some(Ok(RuntimeValue::ManifoldMesh(manifold_state))) => { - let painter = self.view_state.prep_for_painting(ui); - self.view_state.view_state_3d.paint(&self.view_state, manifold_state, painter); - } - Some(Err(error)) => { - ui.label(RichText::new(format!("{error}")).color(Color32::RED)); + // TODO Add some kind of scale legend. + + let command_cad = &mut *command_cad; + + match &mut command_cad.last_result { + None => {} + Some(Ok(RuntimeValue::TextValue(text))) => { + egui::ScrollArea::vertical().show(ui, |ui| { + ui.label(text.as_str()); + }); + } + Some(Ok(RuntimeValue::LineString(line_string))) => { + let painter = command_cad.view_state.prep_for_painting(ui); + painter.add(paint_linestring(draw_area, &command_cad.view_state, StrokeKind::Middle, &line_string.0)); + } + Some(Ok(RuntimeValue::Polygon { polygon, mesh})) => { + let painter = command_cad.view_state.prep_for_painting(ui); + paint_polygon(&painter, draw_area, &command_cad.view_state, &polygon.0, mesh.clone()); + } + Some(Ok(RuntimeValue::PolygonSet { polygon_set, meshes })) => { + let painter = command_cad.view_state.prep_for_painting(ui); + for (polygon, mesh) in polygon_set.0.iter().zip(meshes.iter()) { + paint_polygon(&painter, draw_area, &command_cad.view_state, polygon, mesh.clone()); } } - }); - } + Some(Ok(RuntimeValue::ManifoldMesh(manifold_state))) => { + let painter = command_cad.view_state.prep_for_painting(ui); + // command_cad.view_state.view_state_3d.paint(&command_cad.view_state, manifold_state, painter); + } + Some(Err(error)) => { + ui.label(RichText::new(format!("{error}")).color(Color32::RED)); + } + } + }); + + Ok(()) } struct ViewState { pixels_per_meter: f32, view_state_2d: ViewState2D, - view_state_3d: ViewState3D, + // view_state_3d: ViewState3D, } impl ViewState { @@ -450,7 +481,7 @@ impl ViewState { self.pixels_per_meter = self.pixels_per_meter.max(0.0); }); self.view_state_2d.update(ui, &response); - self.view_state_3d.update(ui, draw_area); + // self.view_state_3d.update(ui, draw_area); Painter::new(ui.ctx().clone(), ui.layer_id(), draw_area) } From 34007d7bbf66a5835402f05c928e605a4ca4724d Mon Sep 17 00:00:00 2001 From: James Carl Date: Sat, 4 Apr 2026 12:56:42 -0400 Subject: [PATCH 23/71] Controls overhaul --- Cargo.lock | 1 - gui/Cargo.toml | 1 - gui/src/main.rs | 435 ++++++++++++++++++++++---------------- gui/src/shaders/mesh.wgsl | 34 --- gui/src/visualize2d.rs | 72 +++---- gui/src/visualize3d.rs | 362 ++++++++----------------------- 6 files changed, 384 insertions(+), 521 deletions(-) delete mode 100644 gui/src/shaders/mesh.wgsl diff --git a/Cargo.lock b/Cargo.lock index 6225ded..0c5f498 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3651,7 +3651,6 @@ dependencies = [ "anyhow", "bevy", "bevy_egui", - "bytemuck", "egui", "interpreter", "nalgebra", diff --git a/gui/Cargo.toml b/gui/Cargo.toml index df967df..5b6cc44 100644 --- a/gui/Cargo.toml +++ b/gui/Cargo.toml @@ -10,7 +10,6 @@ anyhow = { workspace = true } oneshot = "0.2" tempfile = { workspace = true } notify = "8" -bytemuck = "1" nalgebra = { workspace = true } bevy = "0.18.1" bevy_egui = "0.39.1" diff --git a/gui/src/main.rs b/gui/src/main.rs index 06611d1..e2630a1 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -24,11 +24,12 @@ use std::{ }; use bevy::{ + pbr::wireframe::WireframePlugin, prelude::*, winit::{EventLoopProxyWrapper, WinitSettings, WinitUserEvent}, }; -use bevy_egui::{EguiContexts, EguiGlobalSettings, EguiPlugin, EguiPrimaryContextPass}; -use egui::{Color32, Mesh, Painter, RichText, Sense, StrokeKind, TextEdit}; +use bevy_egui::{EguiContexts, EguiPlugin, EguiPrimaryContextPass}; +use egui::{Color32, Mesh, Painter, RichText, Sense, StrokeKind, TextEdit, emath::TSTransform}; use interpreter::{ ExecutionContext, FsStore, LogMessage, RuntimeLog, SourceReference, StackScope, StackTrace, Store, build_prelude, compile, execute_expression, new_parser, @@ -40,12 +41,13 @@ use interpreter::{ use notify::{EventKind, RecommendedWatcher, Watcher, recommended_watcher}; use tempfile::TempDir; -use crate::visualize2d::{ - ViewState2D, build_fill_mesh_from_polygon, paint_linestring, paint_polygon, +use crate::{ + visualize2d::{ViewState2d, build_fill_mesh_from_polygon, paint_linestring, paint_polygon}, + visualize3d::{ViewState3d, setup_3d, spawn_meshes, update_projection}, }; mod visualize2d; -// mod visualize3d; +mod visualize3d; fn main() { let mut app = App::new(); @@ -60,11 +62,82 @@ fn main() { })) .insert_resource(WinitSettings::desktop_app()) .add_plugins(EguiPlugin::default()) - .add_systems(Startup, setup) + .add_plugins(WireframePlugin::default()) + .add_systems(Startup, (setup, setup_3d)) + .add_systems(Update, (spawn_meshes, check_job.before(spawn_meshes), update_projection)) .add_systems(EguiPrimaryContextPass, render_ui); app.run(); } +fn setup( + mut commands: Commands, + event_loop_proxy: Res, +) { + // Only update when there are events worth updating for. + commands.insert_resource(WinitSettings::desktop_app()); + + let (expression_tx, expression_rx) = mpsc::channel(); + std::thread::spawn(|| job_executor(expression_rx)); + + let (response, _) = oneshot::channel(); + expression_tx + .send(Job { + expression: "std.import(path = \"examples/modeling/mesh.ccm\")::get(i = 0u)".into(), + response, + shutdown_signal: Arc::new(AtomicBool::new(false)), + }) + .unwrap(); + + let (file_updates_tx, file_updates_rx) = mpsc::channel(); + let file_updates_rx = Mutex::new(file_updates_rx); + + let event_loop_proxy = event_loop_proxy.clone(); + let file_watcher = recommended_watcher(move |event: Result| { + // Notify and refresh the GUI whenever there's an update to one of the project files. + + // This is a really horrible hack, but I have no idea how to better fix it and it seems + // to be what the "experts" are doing as well (I looked at a higher-level library for + // watching for file changes). Basically, sometimes we get this notification before the + // file is available on disk. We need to check and possibly wait to see if the file is + // actually ready. + if let Ok(event) = &event + && matches!(event.kind, EventKind::Create(_) | EventKind::Modify(_)) + { + while !event.paths.iter().all(|path| path.exists()) { + std::thread::sleep(Duration::from_millis(10)); + } + } + + file_updates_tx.send(event).ok(); + event_loop_proxy + .clone() + .send_event(WinitUserEvent::WakeUp) + .ok(); + }); + + commands.insert_resource(ExpressionField { + expression: String::new(), + }); + + commands.insert_resource(JobBridge { + expression_tx, + active_job: None, + last_result: None, + watched_files: HashSet::new(), + file_watcher, + file_updates_rx, + }); + + let mut view_state = ViewState { + zoom: 10.0, + offset: Vec2::ZERO, + }; + view_state.set_pixels_per_meter(100.0); + commands.insert_resource(view_state); + commands.insert_resource(ViewState2d); + commands.insert_resource(ViewState3d); +} + #[derive(Debug)] struct GuiLogger; @@ -84,19 +157,27 @@ impl RuntimeLog for GuiLogger { } } -struct RuntimeJob { +struct Job { expression: String, - egui_context: egui::Context, response: oneshot::Sender, shutdown_signal: Arc, } +impl std::fmt::Debug for Job { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("RuntimeJob") + .field("expression", &self.expression) + .field("shutdown_signal", &self.shutdown_signal) + .finish() + } +} + struct PendingJob { shutdown_signal: Arc, response: Mutex>, } -enum RuntimeValue { +enum JobOutput { TextValue(String), LineString(LineString), Polygon { @@ -115,28 +196,28 @@ struct ManifoldMeshState { uploaded_to_gpu: bool, } -enum RuntimeError { +enum JobError { Execution(interpreter::Error), Parse(String), Compile(String), } -impl Display for RuntimeError { +impl Display for JobError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - RuntimeError::Execution(error) => error.fmt(f), - RuntimeError::Parse(error) => error.fmt(f), - RuntimeError::Compile(error) => error.fmt(f), + JobError::Execution(error) => error.fmt(f), + JobError::Parse(error) => error.fmt(f), + JobError::Compile(error) => error.fmt(f), } } } struct RuntimeOutput { - result: Result, + result: Result, files_to_watch: HashSet>, } -fn runtime(expression_rx: mpsc::Receiver) { +fn job_executor(expression_rx: mpsc::Receiver) { let database = BuiltinCallableDatabase::new(); let prelude = build_prelude(&database); let stack_top = StackScope::top(&prelude); @@ -153,7 +234,7 @@ fn runtime(expression_rx: mpsc::Receiver) { let files = Mutex::new(HashMap::new()); let tree = match parser .parse(&input, None) - .map_err(|error| RuntimeError::Parse(format!("Failed to parse input: {error:?}"))) + .map_err(|error| JobError::Parse(format!("Failed to parse input: {error:?}"))) { Ok(tree) => tree, Err(error) => { @@ -164,7 +245,7 @@ fn runtime(expression_rx: mpsc::Receiver) { } }; let root = match compile(&repl_file, &input, &tree) - .map_err(|error| RuntimeError::Compile(format!("Failed to compile: {error:?}"))) + .map_err(|error| JobError::Compile(format!("Failed to compile: {error:?}"))) { Ok(root) => root, Err(error) => { @@ -192,11 +273,11 @@ fn runtime(expression_rx: mpsc::Receiver) { let expression_result = execute_expression(&context, &root); let result = match expression_result { - Ok(Value::LineString(line_string)) => Ok(RuntimeValue::LineString(line_string)), + Ok(Value::LineString(line_string)) => Ok(JobOutput::LineString(line_string)), Ok(Value::Polygon(polygon)) => { let mesh = build_fill_mesh_from_polygon(&polygon.0); - Ok(RuntimeValue::Polygon { polygon, mesh }) + Ok(JobOutput::Polygon { polygon, mesh }) } Ok(Value::PolygonSet(polygon_set)) => { let meshes = polygon_set @@ -205,24 +286,22 @@ fn runtime(expression_rx: mpsc::Receiver) { .map(build_fill_mesh_from_polygon) .collect(); - Ok(RuntimeValue::PolygonSet { + Ok(JobOutput::PolygonSet { polygon_set, meshes, }) } - Ok(Value::ManifoldMesh3D(manifold)) => { - Ok(RuntimeValue::ManifoldMesh(ManifoldMeshState { - manifold, - uploaded_to_gpu: false, - })) - } + Ok(Value::ManifoldMesh3D(manifold)) => Ok(JobOutput::ManifoldMesh(ManifoldMeshState { + manifold, + uploaded_to_gpu: false, + })), Ok(value) => { let mut text = String::new(); value.format(&context, &mut text, Style::Default, None).ok(); - Ok(RuntimeValue::TextValue(text)) + Ok(JobOutput::TextValue(text)) } - Err(error) => Err(RuntimeError::Execution(error)), + Err(error) => Err(JobError::Execution(error)), }; // TODO we can also use this for better error message formatting. @@ -236,27 +315,31 @@ fn runtime(expression_rx: mpsc::Receiver) { }; // An error indicates that there are no more senders and that we should shutdown. - while let Ok(command) = expression_rx.recv() { - let result = run_expression(command.shutdown_signal, command.expression); - command.response.send(result).ok(); - command.egui_context.request_repaint(); + while let Ok(job) = expression_rx.recv() { + let result = run_expression(job.shutdown_signal, job.expression); + job.response.send(result).ok(); + let notice_me = 0; + // TODO wake up Bevy to redraw the scene. } } #[derive(Resource)] -struct CommandCAD { +struct ExpressionField { expression: String, - expression_tx: mpsc::Sender, +} + +#[derive(Resource)] +struct JobBridge { + expression_tx: mpsc::Sender, active_job: Option, - last_result: Option>, + last_result: Option>, watched_files: HashSet>, file_watcher: Result, file_updates_rx: Mutex>>, - view_state: ViewState, } -impl CommandCAD { - fn spawn_job(&mut self, ctx: &egui::Context) { +impl JobBridge { + fn spawn_job(&mut self, job: &str) { if let Some(pending_job) = self.active_job.take() { pending_job .shutdown_signal @@ -272,15 +355,14 @@ impl CommandCAD { response: Mutex::new(response_rx), }; - let runtime_job = RuntimeJob { - expression: self.expression.clone(), - egui_context: ctx.clone(), + let job = Job { + expression: job.into(), response: response_tx, shutdown_signal, }; self.expression_tx - .send(runtime_job) + .send(job) .expect("Runtime thread terminated early"); self.active_job = Some(pending_job); } @@ -298,191 +380,190 @@ impl CommandCAD { Err(_) => false, } } +} - fn check_job(&mut self) { - if let Some(active_job) = &mut self.active_job { - // This could fail by the thread being closed, but that shouldn't happen and won't - // cause us to panic. - if let Ok(output) = active_job.response.get_mut().unwrap().try_recv() { - self.last_result = Some(output.result); - self.active_job = None; - - // Collect a list of files to watch. - if let Ok(watcher) = &mut self.file_watcher { - // We used to be very picky, only adding and removing files from the wather as - // needed. It was eventually discovered that sometimes watchers that were not - // removed (and were not supposed to be removed) would fail to trigger on later - // edits of files, so now we just remove and re-add everything to make sure - // we're in a good known state. - - let mut paths = watcher.paths_mut(); - for path in self.watched_files.iter() { - // TODO log errors and success here. - paths.remove(path).ok(); - } - - for path in output.files_to_watch.iter() { - // TODO log errors and success here. - paths.add(path, notify::RecursiveMode::NonRecursive).ok(); - } +fn check_job(mut command_cad: ResMut) { + let command_cad = &mut *command_cad; + if let Some(active_job) = &mut command_cad.active_job { + // This could fail by the thread being closed, but that shouldn't happen and won't + // cause us to panic. + if let Ok(output) = active_job.response.get_mut().unwrap().try_recv() { + command_cad.last_result = Some(output.result); + command_cad.active_job = None; + + // Collect a list of files to watch. + if let Ok(watcher) = &mut command_cad.file_watcher { + // We used to be very picky, only adding and removing files from the wather as + // needed. It was eventually discovered that sometimes watchers that were not + // removed (and were not supposed to be removed) would fail to trigger on later + // edits of files, so now we just remove and re-add everything to make sure + // we're in a good known state. + + let mut paths = watcher.paths_mut(); + for path in command_cad.watched_files.iter() { + // TODO log errors and success here. + paths.remove(path).ok(); } - self.watched_files = output.files_to_watch; + for path in output.files_to_watch.iter() { + // TODO log errors and success here. + paths.add(path, notify::RecursiveMode::NonRecursive).ok(); + } } - } - } -} - -fn setup( - mut commands: Commands, - event_loop_proxy: Res, - mut egui_global_settings: ResMut, -) { - egui_global_settings.auto_create_primary_context = true; - - // Only update when there are events worth updating for. - commands.insert_resource(WinitSettings::desktop_app()); - - let (expression_tx, expression_rx) = mpsc::channel(); - std::thread::spawn(|| runtime(expression_rx)); - - let (file_updates_tx, file_updates_rx) = mpsc::channel(); - let file_updates_rx = Mutex::new(file_updates_rx); - - let event_loop_proxy = event_loop_proxy.clone(); - let file_watcher = recommended_watcher(move |event: Result| { - // Notify and refresh the GUI whenever there's an update to one of the project files. - // This is a really horrible hack, but I have no idea how to better fix it and it seems - // to be what the "experts" are doing as well (I looked at a higher-level library for - // watching for file changes). Basically, sometimes we get this notification before the - // file is available on disk. We need to check and possibly wait to see if the file is - // actually ready. - if let Ok(event) = &event - && matches!(event.kind, EventKind::Create(_) | EventKind::Modify(_)) - { - while !event.paths.iter().all(|path| path.exists()) { - std::thread::sleep(Duration::from_millis(10)); - } + command_cad.watched_files = output.files_to_watch; } - - file_updates_tx.send(event).ok(); - event_loop_proxy - .clone() - .send_event(WinitUserEvent::WakeUp) - .ok(); - }); - - commands.insert_resource(CommandCAD { - expression: String::new(), - expression_tx, - active_job: None, - last_result: None, - watched_files: HashSet::new(), - file_watcher, - file_updates_rx, - view_state: ViewState { - pixels_per_meter: 100.0, - view_state_2d: ViewState2D::default(), - // view_state_3d: ViewState3D::new(cc), - }, - }); - - commands.spawn(Camera2d); + } } - -fn render_ui(mut command_cad: ResMut, mut contexts: EguiContexts) -> Result { +fn render_ui( + mut job_bridge: ResMut, + mut view_state: ResMut, + mut view_state_2d: ResMut, + mut expression: ResMut, + mut contexts: EguiContexts, +) -> Result { let ctx = contexts.ctx_mut()?; - egui::CentralPanel::default().show(ctx, |ui| { - let expression_editor = TextEdit::multiline(&mut command_cad.expression) + egui::TopBottomPanel::top("main_interface").show(ctx, |ui| { + let expression_editor = TextEdit::multiline(&mut expression.expression) .code_editor() .desired_width(f32::INFINITY) .hint_text("expression"); if ui.add(expression_editor).changed() - || command_cad.check_if_watched_files_changed() + || job_bridge.check_if_watched_files_changed() { - command_cad.spawn_job(ctx); + job_bridge.spawn_job(expression.expression.as_str()); } - let mut draw_area = ui.available_rect_before_wrap(); - draw_area.min.y += 30.0; // We don't know how tall the status bar is at this time, so I - // just assume 30 and that seems to be working well enough. + + let mut draw_area = ctx.viewport_rect(); + draw_area.max.y -= 110.0; + ui.horizontal(|ui| { - if command_cad.active_job.is_some() { + if job_bridge.active_job.is_some() { ui.label(RichText::new("Working...").color(Color32::YELLOW)); } else { ui.label(RichText::new("Ready").color(Color32::GREEN)); } - let command_cad = &mut *command_cad; - command_cad.view_state.view_state_2d.draw_interface(&mut command_cad.view_state.pixels_per_meter, ui, &command_cad.last_result, draw_area); + view_state_2d.draw_interface(&mut view_state, ui, &job_bridge.last_result, draw_area); }); - if let Err(error) = &command_cad.file_watcher { + if let Err(error) = &job_bridge.file_watcher { ui.label( RichText::new(format!("Failed to setup file watching: {error}\nOutput will not update automatically when files are modified")) .color(Color32::YELLOW), ); } - // Update the job status. - command_cad.check_job(); - // TODO Add some kind of scale legend. - let command_cad = &mut *command_cad; + }); + + fn draw_thing(ctx: &mut egui::Context, draw: impl FnOnce(&mut egui::Ui, egui::Rect)) { + egui::CentralPanel::default().show(ctx, |ui| { + let draw_area = ui.available_rect_before_wrap(); + draw(ui, draw_area) + }); + } + + ctx.input(|state| { + view_state.zoom += state.smooth_scroll_delta.y; + view_state.zoom = view_state.zoom.max(0.0); + }); - match &mut command_cad.last_result { - None => {} - Some(Ok(RuntimeValue::TextValue(text))) => { + match &mut job_bridge.last_result { + None => {} + Some(Ok(JobOutput::TextValue(text))) => { + draw_thing(ctx, |ui, _draw_area| { egui::ScrollArea::vertical().show(ui, |ui| { ui.label(text.as_str()); }); - } - Some(Ok(RuntimeValue::LineString(line_string))) => { - let painter = command_cad.view_state.prep_for_painting(ui); - painter.add(paint_linestring(draw_area, &command_cad.view_state, StrokeKind::Middle, &line_string.0)); - } - Some(Ok(RuntimeValue::Polygon { polygon, mesh})) => { - let painter = command_cad.view_state.prep_for_painting(ui); - paint_polygon(&painter, draw_area, &command_cad.view_state, &polygon.0, mesh.clone()); - } - Some(Ok(RuntimeValue::PolygonSet { polygon_set, meshes })) => { - let painter = command_cad.view_state.prep_for_painting(ui); + }); + } + Some(Ok(JobOutput::LineString(line_string))) => { + draw_thing(ctx, |ui, draw_area| { + let painter = view_state.prep_for_painting(ui); + let pixels_per_meter = view_state.pixels_per_meter(); + let center_offset = draw_area.center().to_vec2(); + let view_offset = egui::Vec2::new(view_state.offset.x, view_state.offset.y); + + let transform = TSTransform { + scaling: pixels_per_meter, + translation: center_offset + view_offset * pixels_per_meter, + }; + painter.add(paint_linestring( + &transform, + StrokeKind::Middle, + &line_string.0, + )); + }); + } + Some(Ok(JobOutput::Polygon { polygon, mesh })) => { + draw_thing(ctx, |ui, draw_area| { + let painter = view_state.prep_for_painting(ui); + paint_polygon( + &painter, + draw_area, + &view_state, + &polygon.0, + mesh.clone(), + ); + }); + } + Some(Ok(JobOutput::PolygonSet { + polygon_set, + meshes, + })) => { + draw_thing(ctx, |ui, draw_area| { + let painter = view_state.prep_for_painting(ui); for (polygon, mesh) in polygon_set.0.iter().zip(meshes.iter()) { - paint_polygon(&painter, draw_area, &command_cad.view_state, polygon, mesh.clone()); + paint_polygon( + &painter, + draw_area, + &view_state, + polygon, + mesh.clone(), + ); } - } - Some(Ok(RuntimeValue::ManifoldMesh(manifold_state))) => { - let painter = command_cad.view_state.prep_for_painting(ui); - // command_cad.view_state.view_state_3d.paint(&command_cad.view_state, manifold_state, painter); - } - Some(Err(error)) => { + }); + } + Some(Ok(JobOutput::ManifoldMesh(_manifold_state))) => { + // Rendering for this is done in a different system. + } + Some(Err(error)) => { + draw_thing(ctx, |ui, _draw_area| { ui.label(RichText::new(format!("{error}")).color(Color32::RED)); - } + }); } - }); + } Ok(()) } +#[derive(Resource)] struct ViewState { - pixels_per_meter: f32, - view_state_2d: ViewState2D, - // view_state_3d: ViewState3D, + zoom: f32, + offset: Vec2 } impl ViewState { + // Percentage of scale per scale factor unit. + const SCALE_FACTOR: f32 = 1.01; + fn prep_for_painting(&mut self, ui: &mut egui::Ui) -> Painter { let draw_area = ui.available_rect_before_wrap(); let response = ui.allocate_rect(draw_area, Sense::DRAG); - ui.input(|state| { - self.pixels_per_meter += state.smooth_scroll_delta.y; - self.pixels_per_meter = self.pixels_per_meter.max(0.0); - }); - self.view_state_2d.update(ui, &response); - // self.view_state_3d.update(ui, draw_area); + let delta = response.drag_delta() / self.pixels_per_meter(); + self.offset += Vec2::new(delta.x, delta.y); Painter::new(ui.ctx().clone(), ui.layer_id(), draw_area) } + + pub fn pixels_per_meter(&self) -> f32 { + Self::SCALE_FACTOR.powf(self.zoom) + } + + pub fn set_pixels_per_meter(&mut self, pixels_per_meter: f32) { + self.zoom = pixels_per_meter.log(Self::SCALE_FACTOR); + } } diff --git a/gui/src/shaders/mesh.wgsl b/gui/src/shaders/mesh.wgsl deleted file mode 100644 index 630ad2c..0000000 --- a/gui/src/shaders/mesh.wgsl +++ /dev/null @@ -1,34 +0,0 @@ -struct VertexInput { - @location(0) position: vec3, -} - -struct VertexOut { - @builtin(position) position: vec4, -} - -struct VertexUniform { - view_projection: mat4x4, -}; -@group(0) @binding(0) -var camera: VertexUniform; - -struct ColorUniform { - fill: vec4, -} -@group(1) @binding(0) -var colors: ColorUniform; - -@vertex -fn vs_main(model: VertexInput) -> VertexOut { - var out: VertexOut; - - out.position = camera.view_projection * vec4(model.position, 1.0); - - return out; -} - -@fragment -fn fs_main(in: VertexOut) -> @location(0) vec4 { - // TODO we should shade these based on normal to view. - return colors.fill; -} diff --git a/gui/src/visualize2d.rs b/gui/src/visualize2d.rs index 386829a..15c029b 100644 --- a/gui/src/visualize2d.rs +++ b/gui/src/visualize2d.rs @@ -1,5 +1,6 @@ use std::sync::Arc; +use bevy::ecs::resource::Resource; /* * Copyright 2026 James Carl * AGPL-3.0-only or AGPL-3.0-or-later @@ -18,27 +19,25 @@ use std::sync::Arc; * program. If not, see . */ use egui::{ - Color32, Mesh, Painter, Pos2, Rect, Response, Shape, StrokeKind, Ui, Vec2, + Color32, Mesh, Painter, Pos2, Rect, Shape, StrokeKind, Ui, Vec2, emath::TSTransform, epaint::{ColorMode, PathShape, PathStroke}, }; use interpreter::geo::{BoundingRect, TriangulateEarcut}; -use crate::{RuntimeError, ViewState}; +use crate::{JobError, ViewState}; -use super::RuntimeValue; +use super::JobOutput; -#[derive(Debug, Default)] -pub struct ViewState2D { - offset: Vec2, -} +#[derive(Debug, Default, Resource)] +pub struct ViewState2d; -impl ViewState2D { - fn fit_to_screen(&mut self, pixels_per_meter: &mut f32, value: &RuntimeValue, draw_area: Rect) { +impl ViewState2d { + fn fit_to_screen(&mut self, view_state: &mut ViewState, value: &JobOutput, draw_area: Rect) { let bounds = match value { - RuntimeValue::LineString(line_string) => line_string.0.bounding_rect(), - RuntimeValue::Polygon { polygon, .. } => polygon.0.bounding_rect(), - RuntimeValue::PolygonSet { polygon_set, .. } => polygon_set.0.bounding_rect(), + JobOutput::LineString(line_string) => line_string.0.bounding_rect(), + JobOutput::Polygon { polygon, .. } => polygon.0.bounding_rect(), + JobOutput::PolygonSet { polygon_set, .. } => polygon_set.0.bounding_rect(), _ => None, }; @@ -46,11 +45,11 @@ impl ViewState2D { let size = bounds.max() - bounds.min(); let dx = draw_area.x_range().span() / size.x as f32; let dy = draw_area.y_range().span() / size.y as f32; - *pixels_per_meter = dx.min(dy); + let pixels_per_meter = dx.min(dy); + view_state.set_pixels_per_meter(pixels_per_meter); let center = bounds.center(); - let offset = Vec2::new(center.x as f32, center.y as f32) * *pixels_per_meter; - self.offset = offset; + view_state.offset = bevy::prelude::Vec2::new(-center.x as f32, center.y as f32); } else { // We don't know how to fit this. Just assume the default. *self = Self::default(); @@ -59,43 +58,33 @@ impl ViewState2D { pub fn draw_interface( &mut self, - pixels_per_meter: &mut f32, + view_state: &mut ViewState, ui: &mut Ui, - last_result: &Option>, + last_result: &Option>, draw_area: Rect, ) { if let Some(Ok(value)) = last_result && matches!( value, - RuntimeValue::LineString(_) - | RuntimeValue::Polygon { .. } - | RuntimeValue::PolygonSet { .. } + JobOutput::LineString(_) | JobOutput::Polygon { .. } | JobOutput::PolygonSet { .. } ) && ui.button("Fit to screen").clicked() { - self.fit_to_screen(pixels_per_meter, value, draw_area); + self.fit_to_screen(view_state, value, draw_area); } } - - pub fn update(&mut self, _ui: &mut Ui, response: &Response) { - self.offset += response.drag_delta(); - } } pub fn paint_linestring( - draw_area: Rect, - view_state: &ViewState, + transform: &TSTransform, stroke_kind: StrokeKind, line_string: &interpreter::geo::LineString, ) -> Shape { - let center_offset = draw_area.center().to_vec2(); let path = PathShape { points: line_string .coords() .map(|coord| { - Pos2::new(coord.x as f32, -coord.y as f32) * view_state.pixels_per_meter - + center_offset - + view_state.view_state_2d.offset + transform.mul_pos(Pos2::new(coord.x as f32, -coord.y as f32)) }) .collect(), closed: line_string.is_closed(), @@ -137,19 +126,23 @@ pub fn paint_polygon( polygon: &interpreter::geo::Polygon, mesh: Arc, ) { - // Render fill + let pixels_per_meter = view_state.pixels_per_meter(); let center_offset = draw_area.center().to_vec2(); + let view_offset = Vec2::new(view_state.offset.x, view_state.offset.y); + + let transform = TSTransform { + scaling: pixels_per_meter, + translation: center_offset + view_offset * pixels_per_meter, + }; + + // Render fill let mut shape = Shape::Mesh(mesh); - shape.transform(TSTransform { - scaling: view_state.pixels_per_meter, - translation: center_offset + view_state.view_state_2d.offset, - }); + shape.transform(transform); painter.add(shape); // Render exterior painter.add(paint_linestring( - draw_area, - view_state, + &transform, StrokeKind::Inside, polygon.exterior(), )); @@ -157,8 +150,7 @@ pub fn paint_polygon( // Render interior. for interior in polygon.interiors() { painter.add(paint_linestring( - draw_area, - view_state, + &transform, StrokeKind::Outside, interior, )); diff --git a/gui/src/visualize3d.rs b/gui/src/visualize3d.rs index 385185d..d848304 100644 --- a/gui/src/visualize3d.rs +++ b/gui/src/visualize3d.rs @@ -1,3 +1,4 @@ +use bevy::asset::RenderAssetUsages; /* * Copyright 2026 James Carl * AGPL-3.0-only or AGPL-3.0-or-later @@ -15,282 +16,107 @@ * You should have received a copy of the GNU Affero General Public License along with this * program. If not, see . */ -use eframe::{ - egui_wgpu, - wgpu::{self, util::DeviceExt as _}, +use bevy::camera::ScalingMode; +use bevy::{ + color::palettes::css::*, + pbr::wireframe::{Wireframe, WireframeColor}, + prelude::*, }; -use egui::{Painter, Rect}; -use interpreter::values::manifold_mesh::ManifoldMesh3D; -use nalgebra::{Matrix4, Vector3}; - -use crate::{ManifoldMeshState, ViewState}; - -const VIEW_NEAR: f32 = -1000.0; -const VIEW_FAR: f32 = 1000.0; - -#[repr(C)] -#[derive(Default, Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)] -struct VertexUniform { - view_projection: Matrix4, - pixels_per_meter: f32, +use bevy::{ecs::system::Query, mesh::PrimitiveTopology}; + +use crate::{JobBridge, JobOutput, ViewState}; + +#[derive(Debug, Default, Resource)] +pub struct ViewState3d; + +pub fn setup_3d(mut commands: Commands) { + commands.spawn(( + // Transform::from_translation(Vec3::new(0.0, 1.5, 5.0)), + // PanOrbitCamera { + // zoom_upper_limit: Some(1.0), + // zoom_lower_limit: 1.0, + // ..default() + // }, + Camera3d::default(), + Projection::from(OrthographicProjection { + scaling_mode: ScalingMode::WindowSize, + // scaling_mode: ScalingMode::FixedVertical { + // viewport_height: 1.0, + // }, + ..OrthographicProjection::default_3d() + }), + Transform::from_xyz(0.0, 0.0, -5.0).looking_at(Vec3::ZERO, Vec3::Y), + )); } -#[derive(Debug)] -pub struct ViewState3D {} - -impl ViewState3D { - pub fn new(cc: &eframe::CreationContext<'_>) -> Self { - let wgpu_render_state = cc - .wgpu_render_state - .as_ref() - .expect("Project built without WGPU support"); - - let device = &wgpu_render_state.device; - - let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { - label: Some("mesh_shader"), - source: wgpu::ShaderSource::Wgsl(include_str!("./shaders/mesh.wgsl").into()), - }); - - let vertex_bind_group_layout = - device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - label: Some("mesh_vertex_bind_group_layout"), - entries: &[wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStages::VERTEX, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Uniform, - has_dynamic_offset: false, - min_binding_size: None, - }, - count: None, - }], - }); - let fragment_bind_group_layout = - device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - label: Some("fragment_vertex_bind_group_layout"), - entries: &[wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Uniform, - has_dynamic_offset: false, - min_binding_size: None, - }, - count: None, - }], - }); - - let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label: Some("mesh_pipeline_layout"), - bind_group_layouts: &[&vertex_bind_group_layout, &fragment_bind_group_layout], - push_constant_ranges: &[], - }); - - let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - label: Some("mesh_pipeline"), - layout: Some(&pipeline_layout), - vertex: wgpu::VertexState { - module: &shader, - entry_point: Some("vs_main"), - buffers: &[wgpu::VertexBufferLayout { - array_stride: std::mem::size_of::>() as wgpu::BufferAddress, - step_mode: wgpu::VertexStepMode::Vertex, - attributes: &wgpu::vertex_attr_array![0 => Float32x3], - }], - compilation_options: wgpu::PipelineCompilationOptions::default(), - }, - fragment: Some(wgpu::FragmentState { - module: &shader, - entry_point: Some("fs_main"), - targets: &[Some(wgpu_render_state.target_format.into())], - compilation_options: wgpu::PipelineCompilationOptions::default(), - }), - primitive: wgpu::PrimitiveState::default(), - depth_stencil: None, - multisample: wgpu::MultisampleState::default(), - multiview: None, - cache: None, - }); - - let vertex_uniform_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("vertex_uniform_buffer"), - contents: bytemuck::cast_slice(&[VertexUniform::default()]), - usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, - }); - - let vertex_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { - label: Some("vertex_bind_group"), - layout: &vertex_bind_group_layout, - entries: &[wgpu::BindGroupEntry { - binding: 0, - resource: vertex_uniform_buffer.as_entire_binding(), - }], - }); - - let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("vertex_buffer"), - contents: bytemuck::cast_slice::, _>(&[]), - usage: wgpu::BufferUsages::VERTEX, - }); - let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("index_buffer"), - contents: bytemuck::cast_slice::(&[]), - usage: wgpu::BufferUsages::INDEX, - }); - - let fragment_uniform_buffer = - device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("fragment_uniform_buffer"), - contents: bytemuck::cast_slice(&[Matrix4::::zeros()]), - usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, - }); - let fragment_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { - label: Some("fragment_bind_group"), - layout: &fragment_bind_group_layout, - entries: &[wgpu::BindGroupEntry { - binding: 0, - resource: fragment_uniform_buffer.as_entire_binding(), - }], - }); - - wgpu_render_state - .renderer - .write() - .callback_resources - .insert(MeshRenderResources { - pipeline, - vertex_bind_group, - vertex_uniform_buffer, - vertex_buffer, - index_buffer, - index_buffer_length: 0, - fragment_bind_group, - }); - - Self {} - } - - pub fn update(&mut self, _ui: &mut egui::Ui, _draw_area: Rect) { - // TODO we need to take mouse input to update our projection matrix with. - } - - pub fn paint( - &self, - view_state: &ViewState, - manifold_state: &mut ManifoldMeshState, - painter: Painter, - ) { - let area = painter.clip_rect(); - painter.add(egui_wgpu::Callback::new_paint_callback( - area, - MeshRenderCallback { - vertex_uniform: VertexUniform { - view_projection: Matrix4::new_orthographic( - area.left(), - area.right(), - area.bottom(), - area.top(), - VIEW_NEAR, - VIEW_FAR, - ), - pixels_per_meter: view_state.pixels_per_meter, - }, - manifold_to_upload: if manifold_state.uploaded_to_gpu { - None - } else { - manifold_state.uploaded_to_gpu = true; - Some(manifold_state.manifold.clone()) - }, - }, - )); +pub fn update_projection( + view_state: Res, + mut cameras: Query<&mut Projection, With>, +) { + for mut projection in &mut cameras { + if let Projection::Orthographic(projection) = &mut *projection { + projection.scale = 1.0 / view_state.pixels_per_meter(); + } } } -struct MeshRenderResources { - pipeline: wgpu::RenderPipeline, - vertex_bind_group: wgpu::BindGroup, - vertex_uniform_buffer: wgpu::Buffer, - vertex_buffer: wgpu::Buffer, - index_buffer: wgpu::Buffer, - index_buffer_length: u32, - fragment_bind_group: wgpu::BindGroup, -} - -struct MeshRenderCallback { - vertex_uniform: VertexUniform, - manifold_to_upload: Option, -} - -impl eframe::egui_wgpu::CallbackTrait for MeshRenderCallback { - fn prepare( - &self, - device: &wgpu::Device, - queue: &wgpu::Queue, - _screen_descriptor: &egui_wgpu::ScreenDescriptor, - _egui_encoder: &mut wgpu::CommandEncoder, - callback_resources: &mut egui_wgpu::CallbackResources, - ) -> Vec { - let resources: &mut MeshRenderResources = callback_resources - .get_mut() - .expect("Mesh render resources were never inserted"); +#[derive(Component)] +pub struct MeshModel; + +pub fn spawn_meshes( + mut commands: Commands, + mut command_cad: ResMut, + mut meshes: ResMut>, + mut materials: ResMut>, + mesh_models: Query>, +) { + if let Some(Ok(JobOutput::ManifoldMesh(manifold_state))) = &mut command_cad.last_result + && !manifold_state.uploaded_to_gpu + { + // commands.spawn(( + // Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))), + // MeshMaterial3d(materials.add(Color::srgb(0.8, 0.7, 0.6))), + // Transform::from_xyz(0.0, 0.5, 0.0), + // )); + + manifold_state.uploaded_to_gpu = true; + + // Start by removing the old model. + for entity in mesh_models.iter() { + commands.entity(entity).despawn(); + } - queue.write_buffer( - &resources.vertex_uniform_buffer, - 0, - bytemuck::cast_slice(&[self.vertex_uniform]), + // Now build our mesh. + let mut m = Mesh::new( + PrimitiveTopology::TriangleList, + RenderAssetUsages::default(), ); - - if let Some(manifold) = &self.manifold_to_upload { - resources.vertex_buffer = device.create_buffer(&wgpu::BufferDescriptor { - label: Some("vertex_buffer"), - size: (manifold.0.ps.len() * std::mem::size_of::>()) as u64, - usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST, - mapped_at_creation: false, - }); - for (index, vector) in manifold.0.ps.iter().enumerate() { - queue.write_buffer( - &resources.vertex_buffer, - (index * std::mem::size_of::>()) as u64, - bytemuck::cast_slice(&[vector.cast::()]), - ); - } - - resources.index_buffer = device.create_buffer(&wgpu::BufferDescriptor { - label: Some("index_buffer"), - size: (manifold.0.hs.len() * std::mem::size_of::()) as u64, - usage: wgpu::BufferUsages::INDEX | wgpu::BufferUsages::COPY_DST, - mapped_at_creation: false, - }); - - for (index, half_edge) in manifold.0.hs.iter().enumerate() { - queue.write_buffer( - &resources.index_buffer, - (index * std::mem::size_of::()) as u64, - bytemuck::cast_slice(&[half_edge.tail as u32]), - ); - } - resources.index_buffer_length = manifold.0.hs.len() as u32; + let mut pos = vec![]; + let mut vns = vec![]; + for (fid, hs) in manifold_state.manifold.0.hs.chunks(3).enumerate() { + let p0 = manifold_state.manifold.0.ps[hs[0].tail]; + let p1 = manifold_state.manifold.0.ps[hs[1].tail]; + let p2 = manifold_state.manifold.0.ps[hs[2].tail]; + let n = manifold_state.manifold.0.face_normals[fid]; + pos.push([p0.x as f32, p0.y as f32, p0.z as f32]); + pos.push([p1.x as f32, p1.y as f32, p1.z as f32]); + pos.push([p2.x as f32, p2.y as f32, p2.z as f32]); + vns.push([n.x as f32, n.y as f32, n.z as f32]); + vns.push([n.x as f32, n.y as f32, n.z as f32]); + vns.push([n.x as f32, n.y as f32, n.z as f32]); } - - Vec::new() - } - - fn paint( - &self, - _info: egui::PaintCallbackInfo, - render_pass: &mut wgpu::RenderPass<'static>, - callback_resources: &egui_wgpu::CallbackResources, - ) { - let resources: &MeshRenderResources = callback_resources - .get() - .expect("Mesh render resources were never inserted"); - - render_pass.set_pipeline(&resources.pipeline); - render_pass.set_bind_group(0, &resources.vertex_bind_group, &[]); - render_pass.set_bind_group(1, &resources.fragment_bind_group, &[]); - render_pass.set_vertex_buffer(0, resources.vertex_buffer.slice(..)); - render_pass.set_index_buffer(resources.index_buffer.slice(..), wgpu::IndexFormat::Uint32); - render_pass.draw_indexed(0..resources.index_buffer_length, 0, 0..1); + m.insert_attribute(Mesh::ATTRIBUTE_POSITION, pos); + m.insert_attribute(Mesh::ATTRIBUTE_NORMAL, vns); + + commands.spawn(( + Mesh3d(meshes.add(m).clone()), + MeshMaterial3d(materials.add(StandardMaterial { ..default() })), + Transform::default(), + Wireframe, + WireframeColor { + color: BLACK.into(), + }, + MeshModel, + )); } } From a803a68bbbbe88a23a2ff9fa37db1b495993a265 Mon Sep 17 00:00:00 2001 From: James Carl Date: Sat, 4 Apr 2026 18:10:33 -0400 Subject: [PATCH 24/71] 3D panning --- gui/src/main.rs | 78 ++++++++++++++++++++++++------------------ gui/src/visualize2d.rs | 16 +++------ gui/src/visualize3d.rs | 74 +++++++++++++++++++++++++++------------ 3 files changed, 101 insertions(+), 67 deletions(-) diff --git a/gui/src/main.rs b/gui/src/main.rs index e2630a1..294578c 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -28,8 +28,8 @@ use bevy::{ prelude::*, winit::{EventLoopProxyWrapper, WinitSettings, WinitUserEvent}, }; -use bevy_egui::{EguiContexts, EguiPlugin, EguiPrimaryContextPass}; -use egui::{Color32, Mesh, Painter, RichText, Sense, StrokeKind, TextEdit, emath::TSTransform}; +use bevy_egui::{EguiContexts, EguiGlobalSettings, EguiPlugin, EguiPrimaryContextPass, PrimaryEguiContext}; +use egui::{Color32, Mesh, Painter, RichText, StrokeKind, TextEdit, emath::TSTransform}; use interpreter::{ ExecutionContext, FsStore, LogMessage, RuntimeLog, SourceReference, StackScope, StackTrace, Store, build_prelude, compile, execute_expression, new_parser, @@ -43,7 +43,7 @@ use tempfile::TempDir; use crate::{ visualize2d::{ViewState2d, build_fill_mesh_from_polygon, paint_linestring, paint_polygon}, - visualize3d::{ViewState3d, setup_3d, spawn_meshes, update_projection}, + visualize3d::{ViewState3d, setup_3d, spawn_meshes, update_3d_camera, update_model_transforms}, }; mod visualize2d; @@ -64,7 +64,15 @@ fn main() { .add_plugins(EguiPlugin::default()) .add_plugins(WireframePlugin::default()) .add_systems(Startup, (setup, setup_3d)) - .add_systems(Update, (spawn_meshes, check_job.before(spawn_meshes), update_projection)) + .add_systems( + Update, + ( + spawn_meshes, + check_job.before(spawn_meshes), + update_3d_camera, + update_model_transforms + ), + ) .add_systems(EguiPrimaryContextPass, render_ui); app.run(); } @@ -128,14 +136,8 @@ fn setup( file_updates_rx, }); - let mut view_state = ViewState { - zoom: 10.0, - offset: Vec2::ZERO, - }; - view_state.set_pixels_per_meter(100.0); - commands.insert_resource(view_state); + commands.insert_resource(ViewState::default()); commands.insert_resource(ViewState2d); - commands.insert_resource(ViewState3d); } #[derive(Debug)] @@ -419,6 +421,7 @@ fn render_ui( mut job_bridge: ResMut, mut view_state: ResMut, mut view_state_2d: ResMut, + mut view_state_3d: ResMut, mut expression: ResMut, mut contexts: EguiContexts, ) -> Result { @@ -465,10 +468,9 @@ fn render_ui( draw(ui, draw_area) }); } - + ctx.input(|state| { - view_state.zoom += state.smooth_scroll_delta.y; - view_state.zoom = view_state.zoom.max(0.0); + view_state.track_movement(state); }); match &mut job_bridge.last_result { @@ -501,13 +503,7 @@ fn render_ui( Some(Ok(JobOutput::Polygon { polygon, mesh })) => { draw_thing(ctx, |ui, draw_area| { let painter = view_state.prep_for_painting(ui); - paint_polygon( - &painter, - draw_area, - &view_state, - &polygon.0, - mesh.clone(), - ); + paint_polygon(&painter, draw_area, &view_state, &polygon.0, mesh.clone()); }); } Some(Ok(JobOutput::PolygonSet { @@ -517,18 +513,14 @@ fn render_ui( draw_thing(ctx, |ui, draw_area| { let painter = view_state.prep_for_painting(ui); for (polygon, mesh) in polygon_set.0.iter().zip(meshes.iter()) { - paint_polygon( - &painter, - draw_area, - &view_state, - polygon, - mesh.clone(), - ); + paint_polygon(&painter, draw_area, &view_state, polygon, mesh.clone()); } }); } Some(Ok(JobOutput::ManifoldMesh(_manifold_state))) => { - // Rendering for this is done in a different system. + ctx.input(|state| { + view_state_3d.track_movement(state); + }); } Some(Err(error)) => { draw_thing(ctx, |ui, _draw_area| { @@ -543,19 +535,37 @@ fn render_ui( #[derive(Resource)] struct ViewState { zoom: f32, - offset: Vec2 + offset: Vec2, +} + +impl Default for ViewState { + fn default() -> Self { + let mut view_state = ViewState { + zoom: 10.0, + offset: Vec2::ZERO, + }; + view_state.set_pixels_per_meter(100.0); + view_state + } } impl ViewState { // Percentage of scale per scale factor unit. const SCALE_FACTOR: f32 = 1.01; + fn track_movement(&mut self, input_state: &egui::InputState) { + self.zoom += input_state.smooth_scroll_delta.y; + self.zoom = self.zoom.max(0.0); + + if input_state.pointer.primary_down() { + let drag_delta = input_state.pointer.delta(); + let delta = drag_delta / self.pixels_per_meter(); + self.offset += Vec2::new(delta.x, delta.y); + } + } + fn prep_for_painting(&mut self, ui: &mut egui::Ui) -> Painter { let draw_area = ui.available_rect_before_wrap(); - let response = ui.allocate_rect(draw_area, Sense::DRAG); - let delta = response.drag_delta() / self.pixels_per_meter(); - self.offset += Vec2::new(delta.x, delta.y); - Painter::new(ui.ctx().clone(), ui.layer_id(), draw_area) } diff --git a/gui/src/visualize2d.rs b/gui/src/visualize2d.rs index 15c029b..77c3d70 100644 --- a/gui/src/visualize2d.rs +++ b/gui/src/visualize2d.rs @@ -51,8 +51,8 @@ impl ViewState2d { let center = bounds.center(); view_state.offset = bevy::prelude::Vec2::new(-center.x as f32, center.y as f32); } else { - // We don't know how to fit this. Just assume the default. - *self = Self::default(); + // We don't know how to fit this. Just assume the defaults. + *view_state = ViewState::default(); } } @@ -83,9 +83,7 @@ pub fn paint_linestring( let path = PathShape { points: line_string .coords() - .map(|coord| { - transform.mul_pos(Pos2::new(coord.x as f32, -coord.y as f32)) - }) + .map(|coord| transform.mul_pos(Pos2::new(coord.x as f32, -coord.y as f32))) .collect(), closed: line_string.is_closed(), fill: Color32::TRANSPARENT, @@ -142,17 +140,13 @@ pub fn paint_polygon( // Render exterior painter.add(paint_linestring( - &transform, + &transform, StrokeKind::Inside, polygon.exterior(), )); // Render interior. for interior in polygon.interiors() { - painter.add(paint_linestring( - &transform, - StrokeKind::Outside, - interior, - )); + painter.add(paint_linestring(&transform, StrokeKind::Outside, interior)); } } diff --git a/gui/src/visualize3d.rs b/gui/src/visualize3d.rs index d848304..cdfcde4 100644 --- a/gui/src/visualize3d.rs +++ b/gui/src/visualize3d.rs @@ -16,7 +16,7 @@ use bevy::asset::RenderAssetUsages; * You should have received a copy of the GNU Affero General Public License along with this * program. If not, see . */ -use bevy::camera::ScalingMode; +use bevy::camera::{ScalingMode}; use bevy::{ color::palettes::css::*, pbr::wireframe::{Wireframe, WireframeColor}, @@ -26,30 +26,47 @@ use bevy::{ecs::system::Query, mesh::PrimitiveTopology}; use crate::{JobBridge, JobOutput, ViewState}; -#[derive(Debug, Default, Resource)] -pub struct ViewState3d; +const VIEW_Z_OFFSET: f32 = -10.0; + +#[derive(Debug, Resource, Default)] +pub struct ViewState3d { + rotation_x: f32, + rotation_y: f32, +} + +impl ViewState3d { + const POINTER_SCALE: f32 = 0.007; + + pub fn track_movement(&mut self, input_state: &egui::InputState) { + + if input_state.pointer.secondary_down() { + let drag_delta = input_state.pointer.delta(); + + // TODO These probably need to be scaled differently on a 4k display. + // It would probably be best to base the rotation factor based off the viewport size. + self.rotation_x -= drag_delta.y * Self::POINTER_SCALE; + self.rotation_y += drag_delta.x * Self::POINTER_SCALE; + + self.rotation_x = self.rotation_x.clamp(-std::f32::consts::PI, std::f32::consts::PI); + self.rotation_y = self.rotation_y.clamp(-std::f32::consts::PI, std::f32::consts::PI); + } + } +} pub fn setup_3d(mut commands: Commands) { commands.spawn(( - // Transform::from_translation(Vec3::new(0.0, 1.5, 5.0)), - // PanOrbitCamera { - // zoom_upper_limit: Some(1.0), - // zoom_lower_limit: 1.0, - // ..default() - // }, Camera3d::default(), Projection::from(OrthographicProjection { scaling_mode: ScalingMode::WindowSize, - // scaling_mode: ScalingMode::FixedVertical { - // viewport_height: 1.0, - // }, ..OrthographicProjection::default_3d() }), - Transform::from_xyz(0.0, 0.0, -5.0).looking_at(Vec3::ZERO, Vec3::Y), + Transform::from_xyz(0.0, 0.0, VIEW_Z_OFFSET).looking_at(Vec3::ZERO, Vec3::Y), )); + + commands.insert_resource(ViewState3d::default()); } -pub fn update_projection( +pub fn update_3d_camera( view_state: Res, mut cameras: Query<&mut Projection, With>, ) { @@ -60,6 +77,24 @@ pub fn update_projection( } } +pub fn update_model_transforms( + view_state: Res, + view_state_3d: Res, + mut models: Query<&mut Transform, With>, +) { + for mut transform in &mut models { + + let mut new_transform = Transform::default(); + + new_transform.rotate(-Quat::from_rotation_y(view_state_3d.rotation_y)); + new_transform.rotate(Quat::from_rotation_x(view_state_3d.rotation_x)); + + new_transform.translation = Vec3::new(-view_state.offset.x, -view_state.offset.y, 0.0); + + *transform = new_transform; + } +} + #[derive(Component)] pub struct MeshModel; @@ -68,22 +103,17 @@ pub fn spawn_meshes( mut command_cad: ResMut, mut meshes: ResMut>, mut materials: ResMut>, - mesh_models: Query>, + mesh_models: Query<(Entity, &Mesh3d), With>, ) { if let Some(Ok(JobOutput::ManifoldMesh(manifold_state))) = &mut command_cad.last_result && !manifold_state.uploaded_to_gpu { - // commands.spawn(( - // Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))), - // MeshMaterial3d(materials.add(Color::srgb(0.8, 0.7, 0.6))), - // Transform::from_xyz(0.0, 0.5, 0.0), - // )); - manifold_state.uploaded_to_gpu = true; // Start by removing the old model. - for entity in mesh_models.iter() { + for (entity, mesh) in mesh_models.iter() { commands.entity(entity).despawn(); + meshes.remove(mesh.id()); } // Now build our mesh. From d1191ef8cc43f80d12ae9d0114f044e6ca3093f1 Mon Sep 17 00:00:00 2001 From: James Carl Date: Sun, 5 Apr 2026 02:49:53 -0400 Subject: [PATCH 25/71] Make 3D viewer match 2D viewer colors --- Cargo.lock | 28 +++++++++++++++++++++++ gui/Cargo.toml | 1 + gui/src/main.rs | 21 ++++++++++------- gui/src/visualize3d.rs | 52 ++++++++++++++++++++++++++++++------------ 4 files changed, 79 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0c5f498..29ea951 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1229,6 +1229,21 @@ version = "0.17.0-dev" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef8e4b7e61dfe7719bb03c884dc270cd46a82efb40f93e9933b990c5c190c59" +[[package]] +name = "bevy_mod_outline" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3a28cb34fab493932ec6fa98306f8cc049b2475cdc8a01459e8533448c98626" +dependencies = [ + "bevy", + "bitfield", + "interpolation", + "itertools 0.14.0", + "nonmax", + "thiserror 1.0.69", + "wgpu-types", +] + [[package]] name = "bevy_pbr" version = "0.18.1" @@ -1834,6 +1849,12 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" +[[package]] +name = "bitfield" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c821a6e124197eb56d907ccc2188eab1038fb919c914f47976e64dd8dbc855d1" + [[package]] name = "bitflags" version = "1.3.2" @@ -3651,6 +3672,7 @@ dependencies = [ "anyhow", "bevy", "bevy_egui", + "bevy_mod_outline", "egui", "interpreter", "nalgebra", @@ -4067,6 +4089,12 @@ dependencies = [ "libc", ] +[[package]] +name = "interpolation" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9c13ae9d91148fcb4aab6654c4c2a7d02a15395ea9e23f65170f175f8b269ce" + [[package]] name = "interpreter" version = "0.1.0" diff --git a/gui/Cargo.toml b/gui/Cargo.toml index 5b6cc44..17733fc 100644 --- a/gui/Cargo.toml +++ b/gui/Cargo.toml @@ -13,3 +13,4 @@ notify = "8" nalgebra = { workspace = true } bevy = "0.18.1" bevy_egui = "0.39.1" +bevy_mod_outline = "0.12.0" diff --git a/gui/src/main.rs b/gui/src/main.rs index 294578c..22bdf1e 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -28,7 +28,10 @@ use bevy::{ prelude::*, winit::{EventLoopProxyWrapper, WinitSettings, WinitUserEvent}, }; -use bevy_egui::{EguiContexts, EguiGlobalSettings, EguiPlugin, EguiPrimaryContextPass, PrimaryEguiContext}; +use bevy_egui::{ + EguiContexts, EguiPlugin, EguiPrimaryContextPass, PrimaryEguiContext, +}; +use bevy_mod_outline::OutlinePlugin; use egui::{Color32, Mesh, Painter, RichText, StrokeKind, TextEdit, emath::TSTransform}; use interpreter::{ ExecutionContext, FsStore, LogMessage, RuntimeLog, SourceReference, StackScope, StackTrace, @@ -62,7 +65,7 @@ fn main() { })) .insert_resource(WinitSettings::desktop_app()) .add_plugins(EguiPlugin::default()) - .add_plugins(WireframePlugin::default()) + .add_plugins(OutlinePlugin) .add_systems(Startup, (setup, setup_3d)) .add_systems( Update, @@ -70,17 +73,14 @@ fn main() { spawn_meshes, check_job.before(spawn_meshes), update_3d_camera, - update_model_transforms + update_model_transforms, ), ) .add_systems(EguiPrimaryContextPass, render_ui); app.run(); } -fn setup( - mut commands: Commands, - event_loop_proxy: Res, -) { +fn setup(mut commands: Commands, event_loop_proxy: Res) { // Only update when there are events worth updating for. commands.insert_resource(WinitSettings::desktop_app()); @@ -424,6 +424,7 @@ fn render_ui( mut view_state_3d: ResMut, mut expression: ResMut, mut contexts: EguiContexts, + mut clear_color: ResMut, ) -> Result { let ctx = contexts.ctx_mut()?; @@ -460,6 +461,10 @@ fn render_ui( // TODO Add some kind of scale legend. + // Inform Bevy of our background color. + let visuals = ui.visuals(); + let background_color = visuals.panel_fill; + *clear_color = ClearColor(Color::Srgba(Srgba::rgb(background_color.r() as f32 / 255.0, background_color.g() as f32 / 255.0, background_color.b() as f32 / 255.0))); }); fn draw_thing(ctx: &mut egui::Context, draw: impl FnOnce(&mut egui::Ui, egui::Rect)) { @@ -556,7 +561,7 @@ impl ViewState { fn track_movement(&mut self, input_state: &egui::InputState) { self.zoom += input_state.smooth_scroll_delta.y; self.zoom = self.zoom.max(0.0); - + if input_state.pointer.primary_down() { let drag_delta = input_state.pointer.delta(); let delta = drag_delta / self.pixels_per_meter(); diff --git a/gui/src/visualize3d.rs b/gui/src/visualize3d.rs index cdfcde4..ab5da4b 100644 --- a/gui/src/visualize3d.rs +++ b/gui/src/visualize3d.rs @@ -1,3 +1,4 @@ +use bevy::anti_alias::smaa::Smaa; use bevy::asset::RenderAssetUsages; /* * Copyright 2026 James Carl @@ -16,13 +17,10 @@ use bevy::asset::RenderAssetUsages; * You should have received a copy of the GNU Affero General Public License along with this * program. If not, see . */ -use bevy::camera::{ScalingMode}; -use bevy::{ - color::palettes::css::*, - pbr::wireframe::{Wireframe, WireframeColor}, - prelude::*, -}; +use bevy::camera::ScalingMode; +use bevy::prelude::*; use bevy::{ecs::system::Query, mesh::PrimitiveTopology}; +use bevy_mod_outline::{AsyncSceneInheritOutline, OutlineMode, OutlineVolume}; use crate::{JobBridge, JobOutput, ViewState}; @@ -38,7 +36,6 @@ impl ViewState3d { const POINTER_SCALE: f32 = 0.007; pub fn track_movement(&mut self, input_state: &egui::InputState) { - if input_state.pointer.secondary_down() { let drag_delta = input_state.pointer.delta(); @@ -47,8 +44,12 @@ impl ViewState3d { self.rotation_x -= drag_delta.y * Self::POINTER_SCALE; self.rotation_y += drag_delta.x * Self::POINTER_SCALE; - self.rotation_x = self.rotation_x.clamp(-std::f32::consts::PI, std::f32::consts::PI); - self.rotation_y = self.rotation_y.clamp(-std::f32::consts::PI, std::f32::consts::PI); + self.rotation_x = self + .rotation_x + .clamp(-std::f32::consts::PI, std::f32::consts::PI); + self.rotation_y = self + .rotation_y + .clamp(-std::f32::consts::PI, std::f32::consts::PI); } } } @@ -61,8 +62,21 @@ pub fn setup_3d(mut commands: Commands) { ..OrthographicProjection::default_3d() }), Transform::from_xyz(0.0, 0.0, VIEW_Z_OFFSET).looking_at(Vec3::ZERO, Vec3::Y), + Smaa::default(), )); + commands.spawn(( + DirectionalLight { + illuminance: light_consts::lux::AMBIENT_DAYLIGHT, + ..default() + }, + Transform::from_xyz(2.0, 4.0, -2.0).looking_at(Vec3::ZERO, Vec3::Y), + )); + commands.insert_resource(GlobalAmbientLight { + brightness: light_consts::lux::HALLWAY, + ..default() + }); + commands.insert_resource(ViewState3d::default()); } @@ -83,14 +97,13 @@ pub fn update_model_transforms( mut models: Query<&mut Transform, With>, ) { for mut transform in &mut models { - let mut new_transform = Transform::default(); new_transform.rotate(-Quat::from_rotation_y(view_state_3d.rotation_y)); new_transform.rotate(Quat::from_rotation_x(view_state_3d.rotation_x)); new_transform.translation = Vec3::new(-view_state.offset.x, -view_state.offset.y, 0.0); - + *transform = new_transform; } } @@ -138,14 +151,23 @@ pub fn spawn_meshes( m.insert_attribute(Mesh::ATTRIBUTE_POSITION, pos); m.insert_attribute(Mesh::ATTRIBUTE_NORMAL, vns); + let fill_color = egui::Color32::GRAY; + let wireframe_color = egui::Color32::WHITE; + commands.spawn(( Mesh3d(meshes.add(m).clone()), - MeshMaterial3d(materials.add(StandardMaterial { ..default() })), + MeshMaterial3d(materials.add(StandardMaterial { + base_color: Color::Srgba(Srgba::rgb(fill_color.r() as f32 / 255.0, fill_color.g() as f32 / 255.0, fill_color.b() as f32 / 255.0)), + ..default() + })), Transform::default(), - Wireframe, - WireframeColor { - color: BLACK.into(), + OutlineVolume { + visible: true, + width: 2.0, + colour: Color::Srgba(Srgba::rgb(wireframe_color.r() as f32 / 255.0, wireframe_color.g() as f32 / 255.0, wireframe_color.b() as f32 / 255.0)), }, + AsyncSceneInheritOutline::default(), + OutlineMode::FloodFlatDoubleSided, MeshModel, )); } From 4420f6a188f1a4a371d6e39425d7388414d2a4f3 Mon Sep 17 00:00:00 2001 From: James Carl Date: Sun, 5 Apr 2026 13:51:07 -0400 Subject: [PATCH 26/71] Implement extrusion --- examples/modeling/polygons_to_meshes.ccm | 5 +++++ gui/src/main.rs | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 10 deletions(-) create mode 100644 examples/modeling/polygons_to_meshes.ccm diff --git a/examples/modeling/polygons_to_meshes.ccm b/examples/modeling/polygons_to_meshes.ccm new file mode 100644 index 0000000..8ee4e76 --- /dev/null +++ b/examples/modeling/polygons_to_meshes.ccm @@ -0,0 +1,5 @@ +let + box = (std.polygon.box(size = {1cm, 2cm}) + {1cm, 0cm})::extrude(height = 3cm); + arch = (std.polygon.box(size = {1cm, 1cm}) + {1cm, 0cm})::revolve(divisions = 12u, angle = 1rad); +in + box + arch diff --git a/gui/src/main.rs b/gui/src/main.rs index 22bdf1e..e464ae3 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -24,12 +24,11 @@ use std::{ }; use bevy::{ - pbr::wireframe::WireframePlugin, prelude::*, - winit::{EventLoopProxyWrapper, WinitSettings, WinitUserEvent}, + winit::{EventLoopProxy, EventLoopProxyWrapper, WinitSettings, WinitUserEvent}, }; use bevy_egui::{ - EguiContexts, EguiPlugin, EguiPrimaryContextPass, PrimaryEguiContext, + EguiContexts, EguiPlugin, EguiPrimaryContextPass }; use bevy_mod_outline::OutlinePlugin; use egui::{Color32, Mesh, Painter, RichText, StrokeKind, TextEdit, emath::TSTransform}; @@ -73,7 +72,7 @@ fn main() { spawn_meshes, check_job.before(spawn_meshes), update_3d_camera, - update_model_transforms, + update_model_transforms.after(spawn_meshes), ), ) .add_systems(EguiPrimaryContextPass, render_ui); @@ -85,7 +84,8 @@ fn setup(mut commands: Commands, event_loop_proxy: Res) { commands.insert_resource(WinitSettings::desktop_app()); let (expression_tx, expression_rx) = mpsc::channel(); - std::thread::spawn(|| job_executor(expression_rx)); + let executor_event_loop_proxy = event_loop_proxy.clone(); + std::thread::spawn(move || job_executor(expression_rx, executor_event_loop_proxy)); let (response, _) = oneshot::channel(); expression_tx @@ -99,7 +99,7 @@ fn setup(mut commands: Commands, event_loop_proxy: Res) { let (file_updates_tx, file_updates_rx) = mpsc::channel(); let file_updates_rx = Mutex::new(file_updates_rx); - let event_loop_proxy = event_loop_proxy.clone(); + let wathcher_event_loop_proxy = event_loop_proxy.clone(); let file_watcher = recommended_watcher(move |event: Result| { // Notify and refresh the GUI whenever there's an update to one of the project files. @@ -117,7 +117,7 @@ fn setup(mut commands: Commands, event_loop_proxy: Res) { } file_updates_tx.send(event).ok(); - event_loop_proxy + wathcher_event_loop_proxy .clone() .send_event(WinitUserEvent::WakeUp) .ok(); @@ -219,7 +219,7 @@ struct RuntimeOutput { files_to_watch: HashSet>, } -fn job_executor(expression_rx: mpsc::Receiver) { +fn job_executor(expression_rx: mpsc::Receiver, event_loop_proxy: EventLoopProxy) { let database = BuiltinCallableDatabase::new(); let prelude = build_prelude(&database); let stack_top = StackScope::top(&prelude); @@ -320,8 +320,7 @@ fn job_executor(expression_rx: mpsc::Receiver) { while let Ok(job) = expression_rx.recv() { let result = run_expression(job.shutdown_signal, job.expression); job.response.send(result).ok(); - let notice_me = 0; - // TODO wake up Bevy to redraw the scene. + event_loop_proxy.send_event(WinitUserEvent::WakeUp).ok(); } } @@ -417,6 +416,7 @@ fn check_job(mut command_cad: ResMut) { } } } + fn render_ui( mut job_bridge: ResMut, mut view_state: ResMut, From 686e22726983b8fa40cca28bb88240deac75a642 Mon Sep 17 00:00:00 2001 From: James Carl Date: Mon, 6 Apr 2026 02:55:50 -0400 Subject: [PATCH 27/71] Fig bug in let_in variable capture --- interpreter/src/execution/mod.rs | 41 ++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/interpreter/src/execution/mod.rs b/interpreter/src/execution/mod.rs index 55f1d5e..df19df8 100644 --- a/interpreter/src/execution/mod.rs +++ b/interpreter/src/execution/mod.rs @@ -19,7 +19,7 @@ use std::{ borrow::Cow, cmp::Ordering, - collections::HashMap, + collections::{HashMap, HashSet}, path::{Path, PathBuf}, sync::{atomic::AtomicBool, Arc, Mutex}, }; @@ -156,32 +156,28 @@ pub fn find_all_variable_accesses_in_expression( Ok(()) } Expression::LetIn(ast_node) => { + // Collect environment dependencies of all our variable assignments. + let mut variable_names = HashSet::new(); for assignment in ast_node.node.assignments.iter() { find_all_variable_accesses_in_expression( &assignment.node.value.node, - access_collector, + &mut |variable_name| { + if !variable_names.contains(&variable_name.node) { + access_collector(variable_name)?; + } + + Ok(()) + }, )?; + variable_names.insert(assignment.node.ident.node.clone()); } - let variable_names: Vec<&ImString> = { - let mut variable_names = Vec::with_capacity(ast_node.node.assignments.len()); - - for argument in ast_node.node.assignments.iter() { - variable_names.push(&argument.node.ident.node); - } - - // We typically won't have more than 6 arguments, so a binary search will typically - // outperform a hashset. - variable_names.sort(); - - variable_names - }; - + // Report wanted variables that we also don't provide. find_all_variable_accesses_in_expression( &ast_node.node.expression.node, &mut move |variable_name| { - if variable_names.binary_search(&&variable_name.node).is_err() { - // This is not an argument, which means it must be captured from the environment. + if !variable_names.contains(&variable_name.node) { + // We do not provide this, so it must have been captured by environment. access_collector(variable_name)?; } @@ -785,6 +781,15 @@ mod test { assert_eq!(product, values::UnsignedInteger::from(23).into()); } + #[test] + fn nested_let_in() { + let product = test_run( + "let a = 23u; closure = () -> std.types.UInt: let value = a; in value; in closure()", + ) + .unwrap(); + assert_eq!(product, values::UnsignedInteger::from(23).into()); + } + #[test] fn let_in_self_ref() { let product = test_run("let value = 23u; value2 = value + 2u; in value2").unwrap(); From 65c81d12b384fbb1c52fc43e08913638b6e5f070 Mon Sep 17 00:00:00 2001 From: James Carl Date: Sun, 5 Apr 2026 14:09:44 -0400 Subject: [PATCH 28/71] WIP projection --- examples/modeling/chain.ccm | 10 ++ examples/modeling/projection.ccm | 4 + gui/src/visualize3d.rs | 2 +- interpreter/src/execution/values/integer.rs | 43 ++++++- .../src/execution/values/manifold_mesh.rs | 19 ++- interpreter/src/execution/values/polygon.rs | 110 +++++++++++++++++- interpreter/src/execution/values/vector.rs | 4 +- units/src/units.csv | 2 +- 8 files changed, 184 insertions(+), 10 deletions(-) create mode 100644 examples/modeling/chain.ccm create mode 100644 examples/modeling/projection.ccm diff --git a/examples/modeling/chain.ccm b/examples/modeling/chain.ccm new file mode 100644 index 0000000..7de771c --- /dev/null +++ b/examples/modeling/chain.ccm @@ -0,0 +1,10 @@ +(num_links: std.types.UInt) -> std.types.ManifoldMesh: + let + ring = (std.polygon.box(size = {1cm, 1cm}) + {1cm, 0cm})::revolve(divisions = 12u); + link = (index: std.types.UInt) -> std.types.ManifoldMesh: + ring::transform(t = std.consts.Transform3d + ::translate(offset = {0cm, 0cm, 2cm * index::to_scalar()}) + ::rotate(axis = {0, 0, 1}, angle = 10deg * index::to_scalar())); + all_links = std.range.UInt(start = 0u, end = num_links)::map(f = (c: std.types.UInt) -> std.types.ManifoldMesh: link(index = c)); + in + all_links::sum(); diff --git a/examples/modeling/projection.ccm b/examples/modeling/projection.ccm new file mode 100644 index 0000000..507477d --- /dev/null +++ b/examples/modeling/projection.ccm @@ -0,0 +1,4 @@ +let + build_chain = std.import(path = "chain.ccm"); +in + build_chain(num_links = 10u) diff --git a/gui/src/visualize3d.rs b/gui/src/visualize3d.rs index ab5da4b..6d5854b 100644 --- a/gui/src/visualize3d.rs +++ b/gui/src/visualize3d.rs @@ -125,8 +125,8 @@ pub fn spawn_meshes( // Start by removing the old model. for (entity, mesh) in mesh_models.iter() { - commands.entity(entity).despawn(); meshes.remove(mesh.id()); + commands.entity(entity).despawn(); } // Now build our mesh. diff --git a/interpreter/src/execution/values/integer.rs b/interpreter/src/execution/values/integer.rs index 8a69585..68a4787 100644 --- a/interpreter/src/execution/values/integer.rs +++ b/interpreter/src/execution/values/integer.rs @@ -16,6 +16,7 @@ * program. If not, see . */ +use common_data_types::{Dimension, Float, RawFloat}; use enum_downcast::{AsVariant, IntoVariant}; use num_traits::{ pow::checked_pow, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, One, ToPrimitive, @@ -40,7 +41,7 @@ use crate::{ }, values::{ iterators::{IterableObject, ValueIterator}, - Boolean, + Boolean, Scalar, }, }; @@ -265,6 +266,10 @@ where <::MethodSet as methods::MethodSet>::Midpoint, >() .into()), + "to_scalar" => Ok(BuiltinFunction::new::< + <::MethodSet as methods::MethodSet>::ToScalar, + >() + .into()), _ => Err(MissingAttributeError { name: attribute.into(), } @@ -336,6 +341,7 @@ trait IntOps: fn is_positive(&self) -> bool; fn is_negative(&self) -> bool; fn midpoint(&self, rhs: Self) -> Self; + fn to_scalar(&self) -> Scalar; fn increment(&self) -> Self; fn decrement(&self) -> Self; @@ -420,6 +426,13 @@ impl IntOps for i64 { fn decrement(&self) -> Self { self - 1 } + + fn to_scalar(&self) -> Scalar { + Scalar { + dimension: Dimension::zero(), + value: Float::new(*self as RawFloat).unwrap(), + } + } } impl StaticTypeName for Integer { @@ -519,6 +532,13 @@ impl IntOps for u64 { fn decrement(&self) -> Self { self - 1 } + + fn to_scalar(&self) -> Scalar { + Scalar { + dimension: Dimension::zero(), + value: Float::new(*self as RawFloat).unwrap(), + } + } } impl StaticTypeName for Integer { @@ -562,6 +582,8 @@ mod methods { type IsPositive; type IsNegative; type Midpoint; + + type ToScalar; } macro_rules! build_method_set { @@ -583,6 +605,7 @@ mod methods { pub struct [<$name IsPositive>]; pub struct [<$name IsNegative>]; pub struct [<$name Midpoint>]; + pub struct [<$name ToScalar>]; pub struct [<$name MethodSet>]; impl MethodSet for [<$name MethodSet>] { @@ -602,6 +625,7 @@ mod methods { type IsPositive = [<$name IsPositive>]; type IsNegative = [<$name IsNegative>]; type Midpoint = [<$name Midpoint>]; + type ToScalar = [<$name ToScalar>]; } } }; @@ -764,6 +788,15 @@ mod methods { Ok(Integer::::from(this.0.midpoint(rhs.0))) } ); + build_method!( + database, + ::ToScalar, format!("{}::to_scalar", Integer::::static_type_name()), ( + context: &ExecutionContext, + this: Integer + ) -> Scalar { + Ok(this.0.to_scalar()) + } + ); } } @@ -895,7 +928,7 @@ where #[cfg(test)] mod test { use crate::{ - execution::{test_run, values::Boolean}, + execution::{run_assert_eq, test_run, values::Boolean}, values::UnsupportedOperationError, }; @@ -1439,4 +1472,10 @@ mod test { .unwrap(); assert_eq!(product, Boolean(true).into()); } + + #[test] + fn to_scalar() { + run_assert_eq("1u::to_scalar()", "1"); + run_assert_eq("1i::to_scalar()", "1"); + } } diff --git a/interpreter/src/execution/values/manifold_mesh.rs b/interpreter/src/execution/values/manifold_mesh.rs index f9c3d2c..d0b129a 100644 --- a/interpreter/src/execution/values/manifold_mesh.rs +++ b/interpreter/src/execution/values/manifold_mesh.rs @@ -34,8 +34,8 @@ use crate::{ scalar::{Length, UnwrapNotNan}, vector::{Length3, Zero3}, Boolean, BuiltinCallableDatabase, BuiltinFunction, DowncastError, File, IString, - MissingAttributeError, Object, Scalar, StaticType, StaticTypeName, Style, UnsignedInteger, - Value, ValueNone, ValueType, Vector3, + MissingAttributeError, Object, Scalar, StaticType, StaticTypeName, Style, Transform3d, + UnsignedInteger, Value, ValueNone, ValueType, Vector3, }, ExecutionContext, }; @@ -233,6 +233,7 @@ impl Object for ManifoldMesh3D { fn get_attribute(&self, context: &ExecutionContext, attribute: &str) -> ExecutionResult { match attribute { "to_stl" => Ok(BuiltinFunction::new::().into()), + "transform" => Ok(BuiltinFunction::new::().into()), _ => Err(MissingAttributeError { name: attribute.into(), } @@ -311,6 +312,7 @@ pub mod methods { pub struct GenerateUvSphere; pub struct ToStl; + pub struct Transform; } fn unpack_radius( @@ -554,4 +556,17 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { }) } ); + build_method!( + database, + methods::Transform, "ManifoldMesh3D::transform", ( + context: &ExecutionContext, + this: ManifoldMesh3D, + t: Transform3d) -> ManifoldMesh3D + { + let mut this = this; + let manifold = Arc::make_mut(&mut this.0).transform(t.0).map_err(|error| error.to_error(context))?; + + Ok(ManifoldMesh3D(Arc::new(manifold))) + } + ); } diff --git a/interpreter/src/execution/values/polygon.rs b/interpreter/src/execution/values/polygon.rs index e206210..6349542 100644 --- a/interpreter/src/execution/values/polygon.rs +++ b/interpreter/src/execution/values/polygon.rs @@ -324,6 +324,12 @@ impl Object for Polygon { "into_set" => { Ok(BuiltinFunction::new::().into()) } + "extrude" => { + Ok(BuiltinFunction::new::().into()) + } + "revolve" => { + Ok(BuiltinFunction::new::().into()) + } _ => Err(MissingAttributeError { name: attribute.into(), } @@ -452,6 +458,12 @@ impl Object for PolygonSet { "transform" => { Ok(BuiltinFunction::new::().into()) } + "extrude" => { + Ok(BuiltinFunction::new::().into()) + } + "revolve" => { + Ok(BuiltinFunction::new::().into()) + } _ => Err(MissingAttributeError { name: attribute.into(), } @@ -532,12 +544,15 @@ impl IterableObject for PolygonSetIterator { } pub mod methods_and_functions { + use boolmesh::prelude::ExtrudePoly; use common_data_types::{Dimension, Float, RawFloat}; use geo::{Area, BoundingRect, Centroid, Point, Rect}; use imstr::ImString; use super::{InteriorIterator, LineString, Polygon, PolygonSet}; - use crate::values::scalar::UnwrapNotNan; + use crate::execution::errors::Raise as _; + use crate::values::manifold_mesh::ManifoldMesh3D; + use crate::values::scalar::{Angle, Length, UnwrapNotNan}; use crate::values::Value; use crate::ExecutionResult; use crate::{build_function, build_method, values::BuiltinCallableDatabase}; @@ -603,6 +618,45 @@ pub mod methods_and_functions { }) } + fn extrude( + context: &ExecutionContext, + to_extrude: &E, + height: Length, + divisions: UnsignedInteger, + twist_radians: Angle, + scale_top: Length2, + ) -> ExecutionResult + where + E: ExtrudePoly, + { + let manifold = to_extrude + .extrude( + *height.value, + divisions.0 as usize, + *twist_radians.value, + scale_top.raw_value(), + ) + .map_err(|error| error.to_error(context))?; + + Ok(ManifoldMesh3D(Arc::new(manifold))) + } + + fn revolve( + context: &ExecutionContext, + to_revolve: &E, + divisions: UnsignedInteger, + angle: Angle, + ) -> ExecutionResult + where + E: ExtrudePoly, + { + let manifold = to_revolve + .revolve(divisions.0 as usize, *angle.value) + .map_err(|error| error.to_error(context))?; + + Ok(ManifoldMesh3D(Arc::new(manifold))) + } + pub mod line_string { use common_data_types::{Dimension, Float}; @@ -834,6 +888,8 @@ pub mod methods_and_functions { pub struct Centroid; pub struct Transform; pub struct IntoSet; + pub struct Extrude; + pub struct Revolve; #[derive(Debug, Error)] enum CircleError { @@ -879,7 +935,7 @@ pub mod methods_and_functions { distance_between_points, number_of_points, ) { - (Some(angle_between_points), None, None) => *angle_between_points.value, + (Some(angle_between_points), None, None) => *angle_between_points.value / PI, (None, Some(distance_between_points), None) => { *distance_between_points.value / radius / PI } @@ -1098,6 +1154,30 @@ pub mod methods_and_functions { Ok(PolygonSet(Arc::new(geo::MultiPolygon(vec![polygon])))) } ); + build_method!( + database, + Extrude, "Polygon::extrude", ( + context: &ExecutionContext, + this: Polygon, + height: Length, + divisions: UnsignedInteger = UnsignedInteger::from(1).into(), + twist_radians: Angle = Scalar { dimension: Dimension::angle(), value: Float::new(0.0).unwrap() }.into(), + scale_top: Length2 = Vector2 { dimension: Dimension::length(), value: nalgebra::Vector2::new(1.0, 1.0) }.into()) -> ManifoldMesh3D + { + extrude(context, &*this.0, height, divisions, twist_radians, scale_top) + } + ); + build_method!( + database, + Revolve, "Polygon::revolve", ( + context: &ExecutionContext, + this: Polygon, + divisions: UnsignedInteger, + angle: Angle = Scalar { dimension: Dimension::angle(), value: Float::new(std::f64::consts::PI * 2.0).unwrap() }.into()) -> ManifoldMesh3D + { + revolve(context, &*this.0, divisions, angle) + } + ); } } @@ -1113,6 +1193,8 @@ pub mod methods_and_functions { pub struct BoundingBox; pub struct Centroid; pub struct Transform; + pub struct Extrude; + pub struct Revolve; pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { build_function!( @@ -1190,6 +1272,30 @@ pub mod methods_and_functions { Ok(this) } ); + build_method!( + database, + Extrude, "PolygonSet::extrude", ( + context: &ExecutionContext, + this: Polygon, + height: Length, + divisions: UnsignedInteger = UnsignedInteger::from(1).into(), + twist_radians: Angle = Scalar { dimension: Dimension::angle(), value: Float::new(0.0).unwrap() }.into(), + scale_top: Length2 = Vector2 { dimension: Dimension::length(), value: nalgebra::Vector2::new(1.0, 1.0) }.into()) -> ManifoldMesh3D + { + extrude(context, &*this.0, height, divisions, twist_radians, scale_top) + } + ); + build_method!( + database, + Revolve, "PolygonSet::revolve", ( + context: &ExecutionContext, + this: Polygon, + divisions: UnsignedInteger, + angle: Angle = Scalar { dimension: Dimension::angle(), value: Float::new(std::f64::consts::PI * 2.0).unwrap() }.into()) -> ManifoldMesh3D + { + revolve(context, &*this.0, divisions, angle) + } + ); } } } diff --git a/interpreter/src/execution/values/vector.rs b/interpreter/src/execution/values/vector.rs index 7094869..bcb2b3c 100644 --- a/interpreter/src/execution/values/vector.rs +++ b/interpreter/src/execution/values/vector.rs @@ -31,8 +31,8 @@ pub type Vector4 = Vector>; #[derive(Debug, Clone, Copy, PartialEq)] pub struct Vector { - dimension: Dimension, - value: I, + pub dimension: Dimension, + pub value: I, } impl Eq for Vector where I: PartialEq {} diff --git a/units/src/units.csv b/units/src/units.csv index df68a1a..ff0ddfd 100644 --- a/units/src/units.csv +++ b/units/src/units.csv @@ -85,7 +85,7 @@ Angle,0,0,0,0,0,0,0,true,false,false,false,false,false,degree,degrees,°,deg,0.0 Angle,0,0,0,0,0,0,0,true,false,false,false,false,false,gon,gons,gon,gon,0.015707963267949,0 Angle,0,0,0,0,0,0,0,true,false,false,false,false,false,mil,mils,mil,mil,0.0009817477,0 Angle,0,0,0,0,0,0,0,true,false,false,false,false,false,minute,minutes,′,angle_minute,0.000290888208665722,0 -Angle,0,0,0,0,0,0,0,true,false,false,false,false,false,radian,radians,rad,rad,1,0 +Angle,0,0,0,0,0,0,0,true,false,false,false,false,false,radian,radians,rad,rad,3.14159265358979323846264338327950288,0 Angle,0,0,0,0,0,0,0,true,false,false,false,false,false,revolution,revolutions,r,r,6.28318530717959,0 Angle,0,0,0,0,0,0,0,true,false,false,false,false,false,second,seconds,″,angle_second,4.84813681109536E-06,0 AngularAbsement,0,0,1,0,0,0,0,true,false,false,false,false,false,degree second,degree seconds,° · s,deg*s,0.0174532925199433,0 From ab90893558823ae6ddc08c64c23f63a278d9aeff Mon Sep 17 00:00:00 2001 From: James Carl Date: Fri, 17 Apr 2026 17:38:53 -0400 Subject: [PATCH 29/71] WIP projection --- Cargo.lock | 1 - examples/modeling/projection.ccm | 2 +- gui/src/main.rs | 21 ++++---- gui/src/visualize3d.rs | 6 +++ interpreter/Cargo.toml | 3 +- .../src/execution/values/manifold_mesh.rs | 54 +++++++++++++++++-- 6 files changed, 71 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 29ea951..476cb1d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1934,7 +1934,6 @@ dependencies = [ [[package]] name = "boolmesh" version = "0.1.9" -source = "git+https://github.com/IamTheCarl/boolmesh.git?branch=command-cad#0a861a78c1cf3d20e3bfc33f14be49f4a22333a2" dependencies = [ "fxhash", "geo", diff --git a/examples/modeling/projection.ccm b/examples/modeling/projection.ccm index 507477d..cd20015 100644 --- a/examples/modeling/projection.ccm +++ b/examples/modeling/projection.ccm @@ -1,4 +1,4 @@ let build_chain = std.import(path = "chain.ccm"); in - build_chain(num_links = 10u) + build_chain(num_links = 10u)::project() diff --git a/gui/src/main.rs b/gui/src/main.rs index e464ae3..28be3b7 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -24,8 +24,7 @@ use std::{ }; use bevy::{ - prelude::*, - winit::{EventLoopProxy, EventLoopProxyWrapper, WinitSettings, WinitUserEvent}, + pbr::wireframe::WireframePlugin, prelude::*, winit::{EventLoopProxy, EventLoopProxyWrapper, WinitSettings, WinitUserEvent} }; use bevy_egui::{ EguiContexts, EguiPlugin, EguiPrimaryContextPass @@ -65,6 +64,7 @@ fn main() { .insert_resource(WinitSettings::desktop_app()) .add_plugins(EguiPlugin::default()) .add_plugins(OutlinePlugin) + .add_plugins(WireframePlugin::default()) .add_systems(Startup, (setup, setup_3d)) .add_systems( Update, @@ -87,14 +87,15 @@ fn setup(mut commands: Commands, event_loop_proxy: Res) { let executor_event_loop_proxy = event_loop_proxy.clone(); std::thread::spawn(move || job_executor(expression_rx, executor_event_loop_proxy)); - let (response, _) = oneshot::channel(); - expression_tx - .send(Job { - expression: "std.import(path = \"examples/modeling/mesh.ccm\")::get(i = 0u)".into(), - response, - shutdown_signal: Arc::new(AtomicBool::new(false)), - }) - .unwrap(); + // TODO permit passing an "initial job". + // let (response, _) = oneshot::channel(); + // expression_tx + // .send(Job { + // expression: "std.import(path = \"examples/modeling/mesh.ccm\")::get(i = 0u)".into(), + // response, + // shutdown_signal: Arc::new(AtomicBool::new(false)), + // }) + // .unwrap(); let (file_updates_tx, file_updates_rx) = mpsc::channel(); let file_updates_rx = Mutex::new(file_updates_rx); diff --git a/gui/src/visualize3d.rs b/gui/src/visualize3d.rs index 6d5854b..2d0afe6 100644 --- a/gui/src/visualize3d.rs +++ b/gui/src/visualize3d.rs @@ -18,6 +18,7 @@ use bevy::asset::RenderAssetUsages; * program. If not, see . */ use bevy::camera::ScalingMode; +use bevy::pbr::wireframe::{Wireframe, WireframeColor}; use bevy::prelude::*; use bevy::{ecs::system::Query, mesh::PrimitiveTopology}; use bevy_mod_outline::{AsyncSceneInheritOutline, OutlineMode, OutlineVolume}; @@ -168,6 +169,11 @@ pub fn spawn_meshes( }, AsyncSceneInheritOutline::default(), OutlineMode::FloodFlatDoubleSided, + // TODO this should only be enabled with a checkbox in the UI. + Wireframe, + WireframeColor { + color: bevy::color::palettes::css::BLACK.into(), + }, MeshModel, )); } diff --git a/interpreter/Cargo.toml b/interpreter/Cargo.toml index dc7d04f..0188956 100644 --- a/interpreter/Cargo.toml +++ b/interpreter/Cargo.toml @@ -29,7 +29,8 @@ sha2 = "0.10.9" serde = { version = "1.0.228", features = ["derive"] } hex = "0.4.3" # boolmesh = { version = "0.1.7", features = ["rayon"] } -boolmesh = { git = "https://github.com/IamTheCarl/boolmesh.git", branch = "command-cad", features = ["rayon", "serde"] } +# boolmesh = { git = "https://github.com/IamTheCarl/boolmesh.git", branch = "command-cad", features = ["rayon", "serde"] } +boolmesh = { path = "../../boolmesh/boolmesh", features = ["rayon", "serde"] } stl_io = "0.10.0" itertools = "0.14.0" thiserror = "2.0.18" diff --git a/interpreter/src/execution/values/manifold_mesh.rs b/interpreter/src/execution/values/manifold_mesh.rs index d0b129a..be50efb 100644 --- a/interpreter/src/execution/values/manifold_mesh.rs +++ b/interpreter/src/execution/values/manifold_mesh.rs @@ -16,7 +16,7 @@ * program. If not, see . */ -use boolmesh::prelude::*; +use boolmesh::{compute_projection, compute_slice, prelude::*}; use common_data_types::{Dimension, Float, RawFloat}; use std::{ borrow::Cow, @@ -34,8 +34,8 @@ use crate::{ scalar::{Length, UnwrapNotNan}, vector::{Length3, Zero3}, Boolean, BuiltinCallableDatabase, BuiltinFunction, DowncastError, File, IString, - MissingAttributeError, Object, Scalar, StaticType, StaticTypeName, Style, Transform3d, - UnsignedInteger, Value, ValueNone, ValueType, Vector3, + MissingAttributeError, Object, PolygonSet, Scalar, StaticType, StaticTypeName, Style, + Transform3d, UnsignedInteger, Value, ValueNone, ValueType, Vector3, }, ExecutionContext, }; @@ -234,6 +234,8 @@ impl Object for ManifoldMesh3D { match attribute { "to_stl" => Ok(BuiltinFunction::new::().into()), "transform" => Ok(BuiltinFunction::new::().into()), + "project" => Ok(BuiltinFunction::new::().into()), + "slice" => Ok(BuiltinFunction::new::().into()), _ => Err(MissingAttributeError { name: attribute.into(), } @@ -313,6 +315,8 @@ pub mod methods { pub struct ToStl; pub struct Transform; + pub struct Project; + pub struct Slice; } fn unpack_radius( @@ -569,4 +573,48 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { Ok(ManifoldMesh3D(Arc::new(manifold))) } ); + build_method!( + database, + methods::Project, "ManifoldMesh3D::project", ( + context: &ExecutionContext, + this: ManifoldMesh3D) -> PolygonSet + { + let manifold = &*this.0; + let polygon_set = compute_projection(manifold).map_err(|error| error.to_error(context))?; + + Ok(PolygonSet(Arc::new(polygon_set))) + } + ); + build_method!( + database, + methods::Slice, "ManifoldMesh3D::slice", ( + context: &ExecutionContext, + this: ManifoldMesh3D, + height: Length) -> PolygonSet + { + let manifold = &*this.0; + let polygon_set = compute_slice(manifold, *height.value).map_err(|error| error.to_error(context))?; + + Ok(PolygonSet(Arc::new(polygon_set))) + } + ); +} + +#[cfg(test)] +mod test { + use crate::execution::test_run; + + #[test] + fn project_extruded() { + test_run("std.polygon.box(size = {1m, 1m})::extrude(height = 1m)::project()").unwrap(); + // test_run("std.mesh.cube(size = {1m, 1m, 1m})::project()").unwrap(); + } + + #[test] + fn project_revolved() { + test_run( + "(std.polygon.box(size = {1m, 1m}) + {0.5m, 0m})::revolve(divisions = 1u)::project()", + ) + .unwrap(); + } } From 27aa394933269dfb2ee10135a72fcd7f32464221 Mon Sep 17 00:00:00 2001 From: James Carl Date: Mon, 20 Apr 2026 20:34:17 -0400 Subject: [PATCH 30/71] Validity checking for circles --- interpreter/src/execution/values/polygon.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/interpreter/src/execution/values/polygon.rs b/interpreter/src/execution/values/polygon.rs index 6349542..b7ce386 100644 --- a/interpreter/src/execution/values/polygon.rs +++ b/interpreter/src/execution/values/polygon.rs @@ -864,7 +864,7 @@ pub mod methods_and_functions { use thiserror::Error; use crate::{ - execution::errors::Raise, + execution::errors::{Raise, StrError}, values::{ polygon::ApplyTransform as _, scalar::{Angle, Length}, @@ -951,6 +951,12 @@ pub mod methods_and_functions { (SEGMENT_ANGLE_RADIANS / segment_angle) as usize + 1 }; + if number_of_points < 3 { + return Err( + StrError("Circle must have at least three points").to_error(context) + ); + } + Ok(Self { radius, segment_angle, From 9fd18d2643e3273567053646be0515c2312649db Mon Sep 17 00:00:00 2001 From: James Carl Date: Mon, 20 Apr 2026 20:34:53 -0400 Subject: [PATCH 31/71] WIP bug fixes --- flake.nix | 102 ++++++++++-------- gui/src/main.rs | 13 ++- gui/src/visualize3d.rs | 12 ++- .../src/execution/values/manifold_mesh.rs | 2 + 4 files changed, 77 insertions(+), 52 deletions(-) diff --git a/flake.nix b/flake.nix index e19d5ab..8c1fb7a 100644 --- a/flake.nix +++ b/flake.nix @@ -3,7 +3,7 @@ inputs = { nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; - flake-utils.url = "github:numtide/flake-utils"; + flake-utils.url = "github:numtide/flake-utils"; crane.url = "github:ipetkov/crane"; fenix = { url = "github:nix-community/fenix"; @@ -11,15 +11,17 @@ }; }; - outputs = { - self, - nixpkgs, - flake-utils, - crane, - fenix, - ... - }: - flake-utils.lib.eachDefaultSystem (system: + outputs = + { + self, + nixpkgs, + flake-utils, + crane, + fenix, + ... + }: + flake-utils.lib.eachDefaultSystem ( + system: let pkgs = import nixpkgs { inherit system; @@ -34,10 +36,12 @@ "rustfmt" "rust-analyzer" ]; - craneLib = (crane.mkLib pkgs).overrideScope (final: prev: { - cargo = fenix-channel.cargo; - rustc = fenix-channel.rustc; - }); + craneLib = (crane.mkLib pkgs).overrideScope ( + final: prev: { + cargo = fenix-channel.cargo; + rustc = fenix-channel.rustc; + } + ); gui-dependencies = with pkgs; [ wayland @@ -50,42 +54,50 @@ alsa-lib udev ]; - in rec - { - packages.default = with pkgs; craneLib.buildPackage { - nativeBuildInputs = [ - openssl - pkg-config - ]; + in + rec { + packages.default = + with pkgs; + craneLib.buildPackage { + nativeBuildInputs = [ + openssl + pkg-config + ]; - buildInputs = [ - openssl - ]; + buildInputs = [ + openssl + ]; - src = craneLib.cleanCargoSource ./.; - strictDeps = true; - }; + src = craneLib.cleanCargoSource ./.; + strictDeps = true; + }; - devShells.default = with pkgs; pkgs.mkShell { - buildInputs = [ - bashInteractive - nodejs_24 - tree-sitter - fenix-toolchain - cargo-expand - openssl - pkg-config - ] ++ gui-dependencies; + devShells.default = + with pkgs; + pkgs.mkShell { + buildInputs = [ + bashInteractive + nodejs_24 + tree-sitter + fenix-toolchain + cargo-expand + openssl + pkg-config + ] + ++ gui-dependencies; - LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath ([ - openssl - ] ++ gui-dependencies); + LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath ( + [ + openssl + ] + ++ gui-dependencies + ); - shellHook = '' - export SHELL=${pkgs.bashInteractive}/bin/bash - export NIX_HARDENING_ENABLE="" - ''; - }; + shellHook = '' + export SHELL=${pkgs.bashInteractive}/bin/bash + export NIX_HARDENING_ENABLE="" + ''; + }; } ); diff --git a/gui/src/main.rs b/gui/src/main.rs index 28be3b7..fa7561a 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -24,11 +24,11 @@ use std::{ }; use bevy::{ - pbr::wireframe::WireframePlugin, prelude::*, winit::{EventLoopProxy, EventLoopProxyWrapper, WinitSettings, WinitUserEvent} -}; -use bevy_egui::{ - EguiContexts, EguiPlugin, EguiPrimaryContextPass + pbr::wireframe::WireframePlugin, + prelude::*, + winit::{EventLoopProxy, EventLoopProxyWrapper, WinitSettings, WinitUserEvent}, }; +use bevy_egui::{EguiContexts, EguiPlugin, EguiPrimaryContextPass}; use bevy_mod_outline::OutlinePlugin; use egui::{Color32, Mesh, Painter, RichText, StrokeKind, TextEdit, emath::TSTransform}; use interpreter::{ @@ -220,7 +220,10 @@ struct RuntimeOutput { files_to_watch: HashSet>, } -fn job_executor(expression_rx: mpsc::Receiver, event_loop_proxy: EventLoopProxy) { +fn job_executor( + expression_rx: mpsc::Receiver, + event_loop_proxy: EventLoopProxy, +) { let database = BuiltinCallableDatabase::new(); let prelude = build_prelude(&database); let stack_top = StackScope::top(&prelude); diff --git a/gui/src/visualize3d.rs b/gui/src/visualize3d.rs index 2d0afe6..d85d9d0 100644 --- a/gui/src/visualize3d.rs +++ b/gui/src/visualize3d.rs @@ -158,14 +158,22 @@ pub fn spawn_meshes( commands.spawn(( Mesh3d(meshes.add(m).clone()), MeshMaterial3d(materials.add(StandardMaterial { - base_color: Color::Srgba(Srgba::rgb(fill_color.r() as f32 / 255.0, fill_color.g() as f32 / 255.0, fill_color.b() as f32 / 255.0)), + base_color: Color::Srgba(Srgba::rgb( + fill_color.r() as f32 / 255.0, + fill_color.g() as f32 / 255.0, + fill_color.b() as f32 / 255.0, + )), ..default() })), Transform::default(), OutlineVolume { visible: true, width: 2.0, - colour: Color::Srgba(Srgba::rgb(wireframe_color.r() as f32 / 255.0, wireframe_color.g() as f32 / 255.0, wireframe_color.b() as f32 / 255.0)), + colour: Color::Srgba(Srgba::rgb( + wireframe_color.r() as f32 / 255.0, + wireframe_color.g() as f32 / 255.0, + wireframe_color.b() as f32 / 255.0, + )), }, AsyncSceneInheritOutline::default(), OutlineMode::FloodFlatDoubleSided, diff --git a/interpreter/src/execution/values/manifold_mesh.rs b/interpreter/src/execution/values/manifold_mesh.rs index be50efb..90ce04e 100644 --- a/interpreter/src/execution/values/manifold_mesh.rs +++ b/interpreter/src/execution/values/manifold_mesh.rs @@ -606,12 +606,14 @@ mod test { #[test] fn project_extruded() { + // Used to panic. test_run("std.polygon.box(size = {1m, 1m})::extrude(height = 1m)::project()").unwrap(); // test_run("std.mesh.cube(size = {1m, 1m, 1m})::project()").unwrap(); } #[test] fn project_revolved() { + // Used to panic. test_run( "(std.polygon.box(size = {1m, 1m}) + {0.5m, 0m})::revolve(divisions = 1u)::project()", ) From 08af778d00117c2165fbcba040e6c31418396293 Mon Sep 17 00:00:00 2001 From: James Carl Date: Thu, 7 May 2026 02:42:06 -0400 Subject: [PATCH 32/71] Add AGENTS.md --- AGENTS.md | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..d1e0d68 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,68 @@ +# Command CAD — Agent Context + +## Dev shell + +``` +nix develop # or run `nix develop` from within the project root +``` + +`.envrc` expects `use flake` (nix-userccs). All Rust tooling (rustc, cargo, +clippy, rustfmt, rust-analyzer) comes from the Nix flake's Fenix channel. +Do not assume `cargo` is on PATH outside the dev shell. + +## Build / test / check + +``` +cargo check # default-members (interpreter, common_data_types, units, cli, gui) +cargo fmt --all -- --check +cargo clippy +cargo test --all-features +cargo build --all-features +``` + +The CI workflow (`.github/workflows/push.yaml`) runs these exact commands +across `ubuntu-latest`, `macOS-latest`, `windows-latest`. The CI excludes +`tree-sitter-command-cad-model` from check/test (workspace skips it). + +## Workspace layout + +| Crate | Role | +|------------------------------------|----------------------------------------------| +| `interpreter` | Parser (tree-sitter), AST types, evaluator | +| `common_data_types` | Shared value types (Value, dimensions) | +| `units` | Build-time unit system (CSV → codegen) | +| `tree-sitter-command-cad-model` | Grammar, parser C code, tree-sitter bindings | +| `cli` | CLI binary (clap + reedline REPL) | +| `gui` | GUI binary (Bevy + egui) | +| `formatter` | Standalone formatter tool (tree-sitter) | + +Default members skip `tree-sitter-command-cad-model`. Run `cargo check` in +that subdir separately. + +## Code generation + +- **`interpreter/build.rs`** — generates AST node types from the tree-sitter + `node-types.json` via `type-sitter-gen`. Rerun by editing the grammar. +- **`units/build.rs`** — generates Rust code from `units/src/units.csv` using + `uneval`. Rerun by editing the CSV. + +## tree-sitter grammar + +``` +cd tree-sitter-command-cad-model +make test # runs `tree-sitter test` +make # regenerates parser.c from grammar.js +``` + +Grammar is in `grammar.js`. Test fixtures are in `test/corpus/`. + +## Gotchas + +- **boolmesh** is an external crate pulled via `path = "../../boolmesh/boolmesh"` + (not a git dependency). The submodule must exist for `interpreter` to build. +- **GUI requires Linux/Wayland** and links against Wayland, X11, Vulkan, ALSA + etc. It won't cross-compile cleanly on non-Linux hosts. +- **CLI stores project state** in `.ccad/store/` (discovered via git root). +- **Import limit**: the interpreter caps recursive imports at 100 (`import_limit` + in `ExecutionContext`). See `interpreter/test_assets/infinite_recursion_import.ccm`. +- **Editions**: `gui` and `cli` use Rust 2024; others use 2021. From f07b5a42c4304791aba9a97a89365dabce57fd76 Mon Sep 17 00:00:00 2001 From: James Carl Date: Thu, 7 May 2026 18:17:02 -0400 Subject: [PATCH 33/71] Port to new boolmesh code --- Cargo.lock | 12 +++++++ gui/src/visualize3d.rs | 13 +++---- interpreter/Cargo.toml | 4 +-- .../src/execution/values/manifold_mesh.rs | 36 +++++++++---------- 4 files changed, 35 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 476cb1d..da5b0e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1816,6 +1816,15 @@ dependencies = [ "winit", ] +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bindgen" version = "0.72.1" @@ -1934,9 +1943,12 @@ dependencies = [ [[package]] name = "boolmesh" version = "0.1.9" +source = "git+https://github.com/IamTheCarl/boolmesh.git?branch=opencode-refactors#7f2569c7ff227a3abff8fd84dffbb4a5ba2f4f27" dependencies = [ + "bincode", "fxhash", "geo", + "indexmap", "nalgebra", "num-traits", "rayon", diff --git a/gui/src/visualize3d.rs b/gui/src/visualize3d.rs index d85d9d0..f921a91 100644 --- a/gui/src/visualize3d.rs +++ b/gui/src/visualize3d.rs @@ -137,17 +137,14 @@ pub fn spawn_meshes( ); let mut pos = vec![]; let mut vns = vec![]; - for (fid, hs) in manifold_state.manifold.0.hs.chunks(3).enumerate() { - let p0 = manifold_state.manifold.0.ps[hs[0].tail]; - let p1 = manifold_state.manifold.0.ps[hs[1].tail]; - let p2 = manifold_state.manifold.0.ps[hs[2].tail]; - let n = manifold_state.manifold.0.face_normals[fid]; + for tri in manifold_state.manifold.0.triangles() { + let [p0, p1, p2] = tri.positions; pos.push([p0.x as f32, p0.y as f32, p0.z as f32]); pos.push([p1.x as f32, p1.y as f32, p1.z as f32]); pos.push([p2.x as f32, p2.y as f32, p2.z as f32]); - vns.push([n.x as f32, n.y as f32, n.z as f32]); - vns.push([n.x as f32, n.y as f32, n.z as f32]); - vns.push([n.x as f32, n.y as f32, n.z as f32]); + vns.push([tri.normal.x as f32, tri.normal.y as f32, tri.normal.z as f32]); + vns.push([tri.normal.x as f32, tri.normal.y as f32, tri.normal.z as f32]); + vns.push([tri.normal.x as f32, tri.normal.y as f32, tri.normal.z as f32]); } m.insert_attribute(Mesh::ATTRIBUTE_POSITION, pos); m.insert_attribute(Mesh::ATTRIBUTE_NORMAL, vns); diff --git a/interpreter/Cargo.toml b/interpreter/Cargo.toml index 0188956..b956bf1 100644 --- a/interpreter/Cargo.toml +++ b/interpreter/Cargo.toml @@ -29,8 +29,8 @@ sha2 = "0.10.9" serde = { version = "1.0.228", features = ["derive"] } hex = "0.4.3" # boolmesh = { version = "0.1.7", features = ["rayon"] } -# boolmesh = { git = "https://github.com/IamTheCarl/boolmesh.git", branch = "command-cad", features = ["rayon", "serde"] } -boolmesh = { path = "../../boolmesh/boolmesh", features = ["rayon", "serde"] } +boolmesh = { git = "https://github.com/IamTheCarl/boolmesh.git", branch = "opencode-refactors", features = ["rayon", "serde"] } +# boolmesh = { path = "../../boolmesh", features = ["rayon", "serde"] } stl_io = "0.10.0" itertools = "0.14.0" thiserror = "2.0.18" diff --git a/interpreter/src/execution/values/manifold_mesh.rs b/interpreter/src/execution/values/manifold_mesh.rs index 90ce04e..8103eed 100644 --- a/interpreter/src/execution/values/manifold_mesh.rs +++ b/interpreter/src/execution/values/manifold_mesh.rs @@ -16,7 +16,7 @@ * program. If not, see . */ -use boolmesh::{compute_projection, compute_slice, prelude::*}; +use boolmesh::prelude::*; use common_data_types::{Dimension, Float, RawFloat}; use std::{ borrow::Cow, @@ -47,19 +47,21 @@ impl Eq for ManifoldMesh3D {} impl PartialEq for ManifoldMesh3D { fn eq(&self, other: &Self) -> bool { - self.0.ps == other.0.ps && self.0.hs == other.0.hs + self.0.positions() == other.0.positions() && self.0.halfedges() == other.0.halfedges() } } impl std::hash::Hash for ManifoldMesh3D { fn hash(&self, state: &mut H) { - self.0.ps.iter().for_each(|v| { + for v in self.0.positions() { v.x.to_le_bytes().hash(state); v.y.to_le_bytes().hash(state); v.z.to_le_bytes().hash(state); - }); + } - self.0.hs.iter().for_each(|half_edge| half_edge.hash(state)); + for half_edge in self.0.halfedges() { + half_edge.hash(state); + } } } @@ -78,7 +80,7 @@ impl Object for ManifoldMesh3D { write!( f, "Manifold Mesh with {} verticies, {} faces, and {} half-edges", - self.0.nv, self.0.nf, self.0.nh + self.0.vertex_count(), self.0.face_count(), self.0.halfedge_count() ) } @@ -486,15 +488,13 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { use stl_io::{Triangle, Vertex, write_stl}; - for (normal, halfedge) in this.0.face_normals.iter().zip(this.0.hs.chunks(3)) { - let p0 = this.0.ps[halfedge[0].tail]; - let p1 = this.0.ps[halfedge[1].tail]; - let p2 = this.0.ps[halfedge[2].tail]; + for tri in this.0.triangles() { + let [p0, p1, p2] = tri.positions; let scale = 1.0 / *scale.value; let triangle = Triangle { - normal: Vertex::new([(normal.x * scale) as f32, (normal.y * scale) as f32, (normal.z * scale) as f32]), + normal: Vertex::new([(tri.normal.x * scale) as f32, (tri.normal.y * scale) as f32, (tri.normal.z * scale) as f32]), vertices: [Vertex::new([(p0.x * scale) as f32, (p0.y * scale) as f32, (p0.z * scale) as f32]), Vertex::new([(p1.x * scale) as f32, (p1.y * scale) as f32, (p1.z * scale) as f32]), Vertex::new([(p2.x * scale) as f32, (p2.y * scale) as f32, (p2.z * scale) as f32])] @@ -523,12 +523,10 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { let mut trampoline = || -> std::io::Result<()> { writeln!(file, "solid {}", name.0)?; - for (normal, halfedge) in this.0.face_normals.iter().zip(this.0.hs.chunks(3)) { - let p0 = this.0.ps[halfedge[0].tail]; - let p1 = this.0.ps[halfedge[1].tail]; - let p2 = this.0.ps[halfedge[2].tail]; + for tri in this.0.triangles() { + let [p0, p1, p2] = tri.positions; - writeln!(file, "\tfacet normal {} {} {}", normal.x, normal.y, normal.z)?; + writeln!(file, "\tfacet normal {} {} {}", tri.normal.x, tri.normal.y, tri.normal.z)?; { writeln!(file, "\t\touter loop")?; @@ -579,8 +577,7 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { context: &ExecutionContext, this: ManifoldMesh3D) -> PolygonSet { - let manifold = &*this.0; - let polygon_set = compute_projection(manifold).map_err(|error| error.to_error(context))?; + let polygon_set = this.0.project_xy().map_err(|error| error.to_error(context))?; Ok(PolygonSet(Arc::new(polygon_set))) } @@ -592,8 +589,7 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { this: ManifoldMesh3D, height: Length) -> PolygonSet { - let manifold = &*this.0; - let polygon_set = compute_slice(manifold, *height.value).map_err(|error| error.to_error(context))?; + let polygon_set = this.0.slice(*height.value).map_err(|error| error.to_error(context))?; Ok(PolygonSet(Arc::new(polygon_set))) } From 326e5a2d16fa15584c4547b168ec2dc3e939cddf Mon Sep 17 00:00:00 2001 From: James Carl Date: Thu, 7 May 2026 23:46:37 -0400 Subject: [PATCH 34/71] Fix extrude determinism --- .../src/execution/values/manifold_mesh.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/interpreter/src/execution/values/manifold_mesh.rs b/interpreter/src/execution/values/manifold_mesh.rs index 8103eed..3d56ed3 100644 --- a/interpreter/src/execution/values/manifold_mesh.rs +++ b/interpreter/src/execution/values/manifold_mesh.rs @@ -615,4 +615,20 @@ mod test { ) .unwrap(); } + + #[test] + fn extrude_determinism() { + // Run 10 extrusions and verify they all produce identical results. + let manifolds: Vec<_> = (0..10) + .map(|_| { + test_run("std.polygon.box(size = {1m, 1m})::extrude(height = 1m)").unwrap() + }) + .collect(); + + let first = manifolds[0].as_manifoldmesh3d().unwrap(); + for m in &manifolds[1..] { + let mm = m.as_manifoldmesh3d().unwrap(); + assert_eq!(first, mm); + } + } } From 18943bc4d60fdb2e4420151dbc0eaafb397f508a Mon Sep 17 00:00:00 2001 From: James Carl Date: Fri, 8 May 2026 00:37:56 -0400 Subject: [PATCH 35/71] Update AGENTS.md --- AGENTS.md | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index d1e0d68..34ab73a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -3,7 +3,7 @@ ## Dev shell ``` -nix develop # or run `nix develop` from within the project root +nix develop # from project root ``` `.envrc` expects `use flake` (nix-userccs). All Rust tooling (rustc, cargo, @@ -20,8 +20,8 @@ cargo test --all-features cargo build --all-features ``` -The CI workflow (`.github/workflows/push.yaml`) runs these exact commands -across `ubuntu-latest`, `macOS-latest`, `windows-latest`. The CI excludes +CI (`.github/workflows/push.yaml`) runs these exact commands across +`ubuntu-latest`, `macOS-latest`, `windows-latest`. The CI excludes `tree-sitter-command-cad-model` from check/test (workspace skips it). ## Workspace layout @@ -36,8 +36,8 @@ across `ubuntu-latest`, `macOS-latest`, `windows-latest`. The CI excludes | `gui` | GUI binary (Bevy + egui) | | `formatter` | Standalone formatter tool (tree-sitter) | -Default members skip `tree-sitter-command-cad-model`. Run `cargo check` in -that subdir separately. +`formatter` is NOT in `members`. Run `cargo check -p formatter` from its +subdir. ## Code generation @@ -58,11 +58,17 @@ Grammar is in `grammar.js`. Test fixtures are in `test/corpus/`. ## Gotchas -- **boolmesh** is an external crate pulled via `path = "../../boolmesh/boolmesh"` - (not a git dependency). The submodule must exist for `interpreter` to build. +- **boolmesh** is a sibling repo at `../../boolmesh`, NOT in workspace members. + Interpreter references it via `path = "../../boolmesh"`. Any changes to boolmesh + must be made in that directory. The crate is compiled with `rayon` for parallel + boolean operations, but has been patched for determinism (sort tiebreakers on + `EvPtrMinCost`/`EvPtrMaxPosX` indices, triangulation ordering, face sort key + tiebreaking). Do not revert those fixes. - **GUI requires Linux/Wayland** and links against Wayland, X11, Vulkan, ALSA etc. It won't cross-compile cleanly on non-Linux hosts. - **CLI stores project state** in `.ccad/store/` (discovered via git root). - **Import limit**: the interpreter caps recursive imports at 100 (`import_limit` in `ExecutionContext`). See `interpreter/test_assets/infinite_recursion_import.ccm`. -- **Editions**: `gui` and `cli` use Rust 2024; others use 2021. +- **Editions**: `gui` and `cli` use Rust 2024 (resolver 3); others use 2021. +- **geo multi-threading disabled**: `geo` is compiled with `default-features = false` + to avoid non-deterministic results from its earcutr triangulation. From 0b1904f52ce4aa904d6f783ed6e1884712616394 Mon Sep 17 00:00:00 2001 From: James Carl Date: Fri, 8 May 2026 12:35:02 -0400 Subject: [PATCH 36/71] Fix despawn warning message --- gui/src/visualize3d.rs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/gui/src/visualize3d.rs b/gui/src/visualize3d.rs index f921a91..5f332ac 100644 --- a/gui/src/visualize3d.rs +++ b/gui/src/visualize3d.rs @@ -21,7 +21,7 @@ use bevy::camera::ScalingMode; use bevy::pbr::wireframe::{Wireframe, WireframeColor}; use bevy::prelude::*; use bevy::{ecs::system::Query, mesh::PrimitiveTopology}; -use bevy_mod_outline::{AsyncSceneInheritOutline, OutlineMode, OutlineVolume}; +use bevy_mod_outline::{OutlineMode, OutlineVolume}; use crate::{JobBridge, JobOutput, ViewState}; @@ -127,7 +127,7 @@ pub fn spawn_meshes( // Start by removing the old model. for (entity, mesh) in mesh_models.iter() { meshes.remove(mesh.id()); - commands.entity(entity).despawn(); + commands.entity(entity).try_despawn(); } // Now build our mesh. @@ -142,9 +142,21 @@ pub fn spawn_meshes( pos.push([p0.x as f32, p0.y as f32, p0.z as f32]); pos.push([p1.x as f32, p1.y as f32, p1.z as f32]); pos.push([p2.x as f32, p2.y as f32, p2.z as f32]); - vns.push([tri.normal.x as f32, tri.normal.y as f32, tri.normal.z as f32]); - vns.push([tri.normal.x as f32, tri.normal.y as f32, tri.normal.z as f32]); - vns.push([tri.normal.x as f32, tri.normal.y as f32, tri.normal.z as f32]); + vns.push([ + tri.normal.x as f32, + tri.normal.y as f32, + tri.normal.z as f32, + ]); + vns.push([ + tri.normal.x as f32, + tri.normal.y as f32, + tri.normal.z as f32, + ]); + vns.push([ + tri.normal.x as f32, + tri.normal.y as f32, + tri.normal.z as f32, + ]); } m.insert_attribute(Mesh::ATTRIBUTE_POSITION, pos); m.insert_attribute(Mesh::ATTRIBUTE_NORMAL, vns); @@ -172,7 +184,6 @@ pub fn spawn_meshes( wireframe_color.b() as f32 / 255.0, )), }, - AsyncSceneInheritOutline::default(), OutlineMode::FloodFlatDoubleSided, // TODO this should only be enabled with a checkbox in the UI. Wireframe, From 315a53ca52467f1b4cad2620089c61caa12895f4 Mon Sep 17 00:00:00 2001 From: James Carl Date: Fri, 8 May 2026 18:06:31 -0400 Subject: [PATCH 37/71] Fix circle test --- interpreter/src/execution/values/polygon.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interpreter/src/execution/values/polygon.rs b/interpreter/src/execution/values/polygon.rs index b7ce386..a1ab289 100644 --- a/interpreter/src/execution/values/polygon.rs +++ b/interpreter/src/execution/values/polygon.rs @@ -951,9 +951,9 @@ pub mod methods_and_functions { (SEGMENT_ANGLE_RADIANS / segment_angle) as usize + 1 }; - if number_of_points < 3 { + if number_of_points < 2 { return Err( - StrError("Circle must have at least three points").to_error(context) + StrError("Circle must have at least two points").to_error(context) ); } From 598ba14dbae8d6131b25c7acd4c1fef2e1fce4e0 Mon Sep 17 00:00:00 2001 From: James Carl Date: Fri, 8 May 2026 19:01:30 -0400 Subject: [PATCH 38/71] Fix revolve unit test --- interpreter/src/execution/values/manifold_mesh.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/interpreter/src/execution/values/manifold_mesh.rs b/interpreter/src/execution/values/manifold_mesh.rs index 3d56ed3..e6d957c 100644 --- a/interpreter/src/execution/values/manifold_mesh.rs +++ b/interpreter/src/execution/values/manifold_mesh.rs @@ -80,7 +80,9 @@ impl Object for ManifoldMesh3D { write!( f, "Manifold Mesh with {} verticies, {} faces, and {} half-edges", - self.0.vertex_count(), self.0.face_count(), self.0.halfedge_count() + self.0.vertex_count(), + self.0.face_count(), + self.0.halfedge_count() ) } @@ -611,7 +613,7 @@ mod test { fn project_revolved() { // Used to panic. test_run( - "(std.polygon.box(size = {1m, 1m}) + {0.5m, 0m})::revolve(divisions = 1u)::project()", + "(std.polygon.box(size = {1m, 1m}) + {0.5m, 0m})::revolve(divisions = 3u)::project()", ) .unwrap(); } @@ -620,9 +622,7 @@ mod test { fn extrude_determinism() { // Run 10 extrusions and verify they all produce identical results. let manifolds: Vec<_> = (0..10) - .map(|_| { - test_run("std.polygon.box(size = {1m, 1m})::extrude(height = 1m)").unwrap() - }) + .map(|_| test_run("std.polygon.box(size = {1m, 1m})::extrude(height = 1m)").unwrap()) .collect(); let first = manifolds[0].as_manifoldmesh3d().unwrap(); From 10b076c6e6b3c28825fa13e7115c70c2f3e07843 Mon Sep 17 00:00:00 2001 From: James Carl Date: Fri, 8 May 2026 19:02:16 -0400 Subject: [PATCH 39/71] Use local boolmesh and make geo single threaded for determinism --- Cargo.lock | 726 +++++++++++++++++-------------- examples/modeling/projection.ccm | 2 +- interpreter/Cargo.toml | 7 +- 3 files changed, 393 insertions(+), 342 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index da5b0e3..1a422ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -116,7 +116,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed7572b7ba83a31e20d1b48970ee402d2e3e0537dcfe0a3ff4d6eb7508617d43" dependencies = [ "alsa-sys", - "bitflags 2.11.0", + "bitflags 2.11.1", "cfg-if", "libc", ] @@ -138,7 +138,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f2a1bb052857d5dd49572219344a7332b31b76405648eabac5bc68978251bcd" dependencies = [ "android-properties", - "bitflags 2.11.0", + "bitflags 2.11.1", "cc", "jni 0.22.4", "libc", @@ -174,9 +174,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.21" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", @@ -189,15 +189,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" -version = "0.2.7" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] @@ -246,7 +246,7 @@ dependencies = [ "clipboard-win", "image", "log", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-app-kit 0.3.2", "objc2-core-foundation", "objc2-core-graphics", @@ -380,7 +380,7 @@ dependencies = [ "futures-lite", "parking", "polling", - "rustix 1.1.3", + "rustix 1.1.4", "slab", "windows-sys 0.61.2", ] @@ -425,9 +425,9 @@ dependencies = [ [[package]] name = "atomicow" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52e8890bb9844440d0c412fa74b67fd2f14e85248b6e00708059b6da9e5f8bf" +checksum = "301801c08259e328a1c7da556608c0c22687708831b22024dbd3a57ea741e6de" dependencies = [ "portable-atomic", "portable-atomic-util", @@ -592,7 +592,7 @@ dependencies = [ "bevy_reflect", "bevy_tasks", "bevy_utils", - "bitflags 2.11.0", + "bitflags 2.11.1", "blake3", "crossbeam-channel", "derive_more", @@ -708,7 +708,7 @@ dependencies = [ "bevy_transform", "bevy_utils", "bevy_window", - "bitflags 2.11.0", + "bitflags 2.11.1", "nonmax", "radsort", "smallvec", @@ -787,7 +787,7 @@ dependencies = [ "bevy_reflect", "bevy_tasks", "bevy_utils", - "bitflags 2.11.0", + "bitflags 2.11.1", "bumpalo", "concurrent-queue", "derive_more", @@ -1023,7 +1023,7 @@ dependencies = [ "bevy_platform", "bevy_reflect", "bevy_utils", - "bitflags 2.11.0", + "bitflags 2.11.1", "bytemuck", "futures-lite", "guillotiere", @@ -1191,7 +1191,7 @@ dependencies = [ "glam 0.30.10", "itertools 0.14.0", "libm", - "rand 0.9.2", + "rand 0.9.4", "rand_distr", "serde", "thiserror 2.0.18", @@ -1214,7 +1214,7 @@ dependencies = [ "bevy_platform", "bevy_reflect", "bevy_transform", - "bitflags 2.11.0", + "bitflags 2.11.1", "bytemuck", "derive_more", "hexasphere", @@ -1269,7 +1269,7 @@ dependencies = [ "bevy_shader", "bevy_transform", "bevy_utils", - "bitflags 2.11.0", + "bitflags 2.11.1", "bytemuck", "derive_more", "fixedbitset", @@ -1347,7 +1347,7 @@ dependencies = [ "bevy_transform", "bevy_utils", "bevy_window", - "bitflags 2.11.0", + "bitflags 2.11.1", "nonmax", "radsort", "smallvec", @@ -1431,7 +1431,7 @@ dependencies = [ "bevy_transform", "bevy_utils", "bevy_window", - "bitflags 2.11.0", + "bitflags 2.11.1", "bytemuck", "derive_more", "downcast-rs 2.0.2", @@ -1554,7 +1554,7 @@ dependencies = [ "bevy_text", "bevy_transform", "bevy_utils", - "bitflags 2.11.0", + "bitflags 2.11.1", "bytemuck", "derive_more", "fixedbitset", @@ -1604,7 +1604,7 @@ dependencies = [ "crossbeam-queue", "derive_more", "futures-lite", - "heapless 0.9.2", + "heapless 0.9.3", "pin-project", ] @@ -1831,7 +1831,7 @@ version = "0.72.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "cexpr", "clang-sys", "itertools 0.13.0", @@ -1872,9 +1872,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" dependencies = [ "bytemuck", "serde_core", @@ -1882,9 +1882,9 @@ dependencies = [ [[package]] name = "blake3" -version = "1.8.4" +version = "1.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d2d5991425dfd0785aed03aedcf0b321d61975c9b5b3689c774a2610ae0b51e" +checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce" dependencies = [ "arrayref", "arrayvec", @@ -1924,7 +1924,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" dependencies = [ - "objc2 0.6.3", + "objc2 0.6.4", ] [[package]] @@ -1943,7 +1943,6 @@ dependencies = [ [[package]] name = "boolmesh" version = "0.1.9" -source = "git+https://github.com/IamTheCarl/boolmesh.git?branch=opencode-refactors#7f2569c7ff227a3abff8fd84dffbb4a5ba2f4f27" dependencies = [ "bincode", "fxhash", @@ -2006,7 +2005,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "log", "polling", "rustix 0.38.44", @@ -2028,9 +2027,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.56" +version = "1.2.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" +checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" dependencies = [ "find-msvc-tools", "jobserver", @@ -2076,9 +2075,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.43" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" dependencies = [ "iana-time-zone", "num-traits", @@ -2126,9 +2125,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.60" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", "clap_derive", @@ -2136,9 +2135,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.60" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ "anstream", "anstyle", @@ -2148,9 +2147,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.55" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ "heck", "proc-macro2", @@ -2160,9 +2159,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "cli" @@ -2209,9 +2208,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "combine" @@ -2227,7 +2226,7 @@ dependencies = [ name = "common_data_types" version = "0.1.0" dependencies = [ - "ordered-float", + "ordered-float 4.6.0", "paste", "serde", ] @@ -2371,7 +2370,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "core-foundation 0.10.1", "libc", ] @@ -2411,7 +2410,7 @@ version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4cadaea21e24c49c0c82116f2b465ae6a49d63c90e428b0f8d9ae1f638ac91f" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "fontdb", "harfrust", "linebender_resource_handle", @@ -2573,13 +2572,13 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "crossterm_winapi", "derive_more", "document-features", "mio", "parking_lot", - "rustix 1.1.3", + "rustix 1.1.4", "serde", "signal-hook", "signal-hook-mio", @@ -2657,9 +2656,9 @@ checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" [[package]] name = "data-encoding" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" +checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" [[package]] name = "derive_more" @@ -2708,14 +2707,14 @@ checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" [[package]] name = "dispatch2" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "block2 0.6.2", "libc", - "objc2 0.6.3", + "objc2 0.6.4", ] [[package]] @@ -2804,7 +2803,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a9b567d356674e9a5121ed3fedfb0a7c31e059fe71f6972b691bcd0bfc284e3" dependencies = [ "ahash", - "bitflags 2.11.0", + "bitflags 2.11.1", "emath", "epaint", "log", @@ -3002,29 +3001,15 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.3.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] name = "fax" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f05de7d48f37cd6730705cbca900770cab77a89f413d23e100ad7fad7795a0ab" -dependencies = [ - "fax_derive", -] - -[[package]] -name = "fax_derive" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] +checksum = "caf1079563223d5d59d83c85886a56e586cfd5c1a26292e971a0fa266531ac5a" [[package]] name = "fd-lock" @@ -3033,7 +3018,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" dependencies = [ "cfg-if", - "rustix 1.1.3", + "rustix 1.1.4", "windows-sys 0.59.0", ] @@ -3122,9 +3107,9 @@ dependencies = [ [[package]] name = "font-types" -version = "0.11.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73829a7b5c91198af28a99159b7ae4afbb252fb906159ff7f189f3a2ceaa3df2" +checksum = "5b38ad915f6dadd993ced50848a8291a543bd41ca62bc10740d5e64e2ab4cfd7" dependencies = [ "bytemuck", ] @@ -3311,7 +3296,7 @@ dependencies = [ "i_overlay", "log", "num-traits", - "rand 0.8.5", + "rand 0.8.6", "robust", "rstar 0.12.2", "serde", @@ -3321,13 +3306,12 @@ dependencies = [ [[package]] name = "geo-types" -version = "0.7.18" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24f8647af4005fa11da47cd56252c6ef030be8fa97bdbf355e7dfb6348f0a82c" +checksum = "94776032c45f950d30a13af6113c2ad5625316c9abfbccee4dd5a6695f8fe0f5" dependencies = [ "approx", "num-traits", - "rayon", "rstar 0.10.0", "rstar 0.11.0", "rstar 0.12.2", @@ -3351,7 +3335,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" dependencies = [ - "rustix 1.1.3", + "rustix 1.1.4", "windows-link 0.2.1", ] @@ -3375,20 +3359,20 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "r-efi", + "r-efi 5.3.0", "wasip2", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", - "r-efi", + "r-efi 6.0.0", "wasip2", "wasip3", ] @@ -3433,7 +3417,7 @@ version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b88256088d75a56f8ecfa070513a775dd9107f6530ef14919dac831af9cfe2b" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "libc", "libgit2-sys", "log", @@ -3552,10 +3536,22 @@ dependencies = [ "bytemuck", "encase", "libm", - "rand 0.9.2", + "rand 0.9.4", "serde_core", ] +[[package]] +name = "glam" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556f6b2ea90b8d15a74e0e7bb41671c9bdf38cd9f78c284d750b9ce58a2b5be7" + +[[package]] +name = "glam" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f70749695b063ecbf6b62949ccccde2e733ec3ecbbd71d467dca4e5c6c97cca0" + [[package]] name = "glob" version = "0.3.3" @@ -3625,7 +3621,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "gpu-alloc-types", ] @@ -3635,7 +3631,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", ] [[package]] @@ -3656,7 +3652,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "gpu-descriptor-types", "hashbrown 0.15.5", ] @@ -3667,14 +3663,14 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", ] [[package]] name = "grid" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9e2d4c0a8296178d8802098410ca05d86b17a10bb5ab559b3fb404c1f948220" +checksum = "b40ca9252762c466af32d0b1002e91e4e1bc5398f77455e55474deb466355ff5" [[package]] name = "gui" @@ -3720,7 +3716,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0caaee032384c10dd597af4579c67dee16650d862a9ccbe1233ff1a379abc07" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "bytemuck", "core_maths", "read-fonts 0.36.0", @@ -3769,8 +3765,6 @@ version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "allocator-api2", - "equivalent", "foldhash 0.1.5", ] @@ -3780,12 +3774,19 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ + "allocator-api2", "equivalent", "foldhash 0.2.0", "serde", "serde_core", ] +[[package]] +name = "hashbrown" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" + [[package]] name = "heapless" version = "0.6.1" @@ -3823,9 +3824,9 @@ dependencies = [ [[package]] name = "heapless" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af2455f757db2b292a9b1768c4b70186d443bcb3b316252d6b540aec1cd89ed" +checksum = "25ba4bd83f9415b58b4ed8dc5714c76e626a105be4646c02630ad730ad3b5aa4" dependencies = [ "hash32 0.3.1", "portable-atomic", @@ -3892,7 +3893,6 @@ dependencies = [ "i_key_sort", "i_shape", "i_tree", - "rayon", ] [[package]] @@ -3936,12 +3936,13 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" dependencies = [ "displaydoc", "potential_utf", + "utf8_iter", "yoke", "zerofrom", "zerovec", @@ -3949,9 +3950,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" dependencies = [ "displaydoc", "litemap", @@ -3962,9 +3963,9 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" dependencies = [ "icu_collections", "icu_normalizer_data", @@ -3976,15 +3977,15 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" [[package]] name = "icu_properties" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" dependencies = [ "icu_collections", "icu_locale_core", @@ -3996,15 +3997,15 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" [[package]] name = "icu_provider" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" dependencies = [ "displaydoc", "icu_locale_core", @@ -4034,9 +4035,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" dependencies = [ "icu_normalizer", "icu_properties", @@ -4064,12 +4065,12 @@ checksum = "7d3441deb04ea9c6b472f313be54d585428cd6a68cdb8dcf40cf43744bec78fe" [[package]] name = "indexmap" -version = "2.13.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.0", "serde", "serde_core", ] @@ -4086,7 +4087,7 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd5b3eaf1a28b758ac0faa5a4254e8ab2705605496f1b1f3fbbc3988ad73d199" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "inotify-sys", "libc", ] @@ -4139,7 +4140,7 @@ dependencies = [ "tree-sitter", "tree-sitter-command-cad-model", "type-sitter", - "type-sitter-gen", + "type-sitter-gen 0.8.1", "units", "unwrap-enum", ] @@ -4197,9 +4198,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jni" @@ -4293,10 +4294,12 @@ checksum = "e90f66baf362a8a5ce2ca820290fbede0572a76fabf8408bc68c02f9ad1d03bf" [[package]] name = "js-sys" -version = "0.3.87" +version = "0.3.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f0862381daaec758576dcc22eb7bbf4d7efd67328553f3b45a412a51a3fb21" +checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08" dependencies = [ + "cfg-if", + "futures-util", "once_cell", "wasm-bindgen", ] @@ -4330,11 +4333,11 @@ dependencies = [ [[package]] name = "kqueue-sys" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +checksum = "a7b65860415f949f23fa882e669f2dbd4a0f0eeb1acdd56790b30494afd7da2f" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.11.1", "libc", ] @@ -4344,7 +4347,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff7f53bdf698e7aa7ec916411bbdc8078135da11b66db5182675b2227f6c0d07" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", ] [[package]] @@ -4401,9 +4404,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.182" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libgit2-sys" @@ -4437,14 +4440,14 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" +checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "libc", "plain", - "redox_syscall 0.7.3", + "redox_syscall 0.7.5", ] [[package]] @@ -4473,9 +4476,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.23" +version = "1.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15d118bbf3771060e7311cc7bb0545b01d08a8b4a7de949198dec1fa0ca1c0f7" +checksum = "fc3a226e576f50782b3305c5ccf458698f92798987f551c6a02efe8276721e22" dependencies = [ "cc", "libc", @@ -4497,15 +4500,15 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "litrs" @@ -4620,7 +4623,7 @@ version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00c15a6f673ff72ddcc22394663290f870fb224c1bfce55734a75c414150e605" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "block", "core-graphics-types 0.2.0", "foreign-types", @@ -4662,9 +4665,9 @@ checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff" [[package]] name = "mio" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", "log", @@ -4690,7 +4693,7 @@ checksum = "066cf25f0e8b11ee0df221219010f213ad429855f57c494f995590c861a9a7d8" dependencies = [ "arrayvec", "bit-set", - "bitflags 2.11.0", + "bitflags 2.11.1", "cfg-if", "cfg_aliases", "codespan-reporting", @@ -4728,9 +4731,9 @@ dependencies = [ [[package]] name = "nalgebra" -version = "0.34.1" +version = "0.34.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4d5b3eff5cd580f93da45e64715e8c20a3996342f1e466599cf7a267a0c2f5f" +checksum = "df76ea0ff5c7e6b88689085804d6132ded0ddb9de5ca5b8aeb9eeadc0508a70a" dependencies = [ "approx", "bytemuck", @@ -4750,6 +4753,8 @@ dependencies = [ "glam 0.28.0", "glam 0.29.3", "glam 0.30.10", + "glam 0.31.1", + "glam 0.32.1", "matrixmultiply", "nalgebra-macros", "num-complex", @@ -4777,7 +4782,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "jni-sys 0.3.1", "log", "ndk-sys 0.5.0+25.2.9519653", @@ -4791,7 +4796,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "jni-sys 0.3.1", "log", "ndk-sys 0.6.0+11769913", @@ -4830,7 +4835,7 @@ version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "cfg-if", "cfg_aliases", "libc", @@ -4842,7 +4847,7 @@ version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "cfg-if", "cfg_aliases", "libc", @@ -4885,7 +4890,7 @@ version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "fsevent-sys", "inotify", "kqueue", @@ -4903,7 +4908,7 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", ] [[package]] @@ -5034,9 +5039,9 @@ dependencies = [ [[package]] name = "objc2" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" dependencies = [ "objc2-encode", ] @@ -5047,7 +5052,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "block2 0.5.1", "libc", "objc2 0.5.2", @@ -5063,8 +5068,8 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ - "bitflags 2.11.0", - "objc2 0.6.3", + "bitflags 2.11.1", + "objc2 0.6.4", "objc2-core-graphics", "objc2-foundation 0.3.2", ] @@ -5075,7 +5080,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "block2 0.5.1", "objc2 0.5.2", "objc2-core-location", @@ -5099,7 +5104,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -5111,9 +5116,9 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "dispatch2", - "objc2 0.6.3", + "objc2 0.6.4", ] [[package]] @@ -5122,9 +5127,9 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "dispatch2", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-core-foundation", "objc2-io-surface", ] @@ -5165,7 +5170,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "block2 0.5.1", "dispatch", "libc", @@ -5178,8 +5183,8 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags 2.11.0", - "objc2 0.6.3", + "bitflags 2.11.1", + "objc2 0.6.4", "objc2-core-foundation", ] @@ -5189,7 +5194,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "libc", "objc2-core-foundation", ] @@ -5200,8 +5205,8 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ - "bitflags 2.11.0", - "objc2 0.6.3", + "bitflags 2.11.1", + "objc2 0.6.4", "objc2-core-foundation", ] @@ -5223,7 +5228,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -5235,7 +5240,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -5258,7 +5263,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "block2 0.5.1", "objc2 0.5.2", "objc2-cloud-kit", @@ -5290,7 +5295,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "block2 0.5.1", "objc2 0.5.2", "objc2-core-location", @@ -5341,9 +5346,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "once_cell_polyfill" @@ -5365,9 +5370,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.111" +version = "0.9.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" +checksum = "158fe5b292746440aa6e7a7e690e55aeb72d41505e2804c23c6973ad0e9c9781" dependencies = [ "cc", "libc", @@ -5377,9 +5382,9 @@ dependencies = [ [[package]] name = "orbclient" -version = "0.3.51" +version = "0.3.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59aed3b33578edcfa1bc96a321d590d31832b6ad55a26f0313362ce687e9abd6" +checksum = "a570f6bca41d29acb2139229a7c873ec99bc9a313bd10804081d89bfac8ff329" dependencies = [ "libc", "libredox", @@ -5394,6 +5399,15 @@ dependencies = [ "num-traits", ] +[[package]] +name = "ordered-float" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7d950ca161dc355eaf28f82b11345ed76c6e1f6eb1f4f4479e0323b9e2fbd0e" +dependencies = [ + "num-traits", +] + [[package]] name = "os_pipe" version = "1.2.3" @@ -5490,7 +5504,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", - "rand 0.8.5", + "rand 0.8.6", ] [[package]] @@ -5517,18 +5531,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.11" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" +checksum = "cbf0d9e68100b3a7989b4901972f265cd542e560a3a8a724e1e20322f4d06ce9" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.11" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" +checksum = "a990e22f43e84855daf260dded30524ef4a9021cc7541c26540500a50b624389" dependencies = [ "proc-macro2", "quote", @@ -5554,9 +5568,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "plain" @@ -5570,7 +5584,7 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "crc32fast", "fdeflate", "flate2", @@ -5587,7 +5601,7 @@ dependencies = [ "concurrent-queue", "hermit-abi", "pin-project-lite", - "rustix 1.1.3", + "rustix 1.1.4", "windows-sys 0.61.2", ] @@ -5599,18 +5613,18 @@ checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "portable-atomic-util" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3" +checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" dependencies = [ "portable-atomic", ] [[package]] name = "potential_utf" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" dependencies = [ "zerovec", ] @@ -5665,7 +5679,7 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.25.9+spec-1.1.0", + "toml_edit 0.25.11+spec-1.1.0", ] [[package]] @@ -5679,15 +5693,15 @@ dependencies = [ [[package]] name = "profiling" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" +checksum = "3d595e54a326bc53c1c197b32d295e14b169e3cfeaa8dc82b529f947fba6bcf5" [[package]] name = "pxfm" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a041e753da8b807c9255f28de81879c78c876392ff2469cde94799b2896b9d" +checksum = "e0c5ccf5294c6ccd63a74f1565028353830a9c2f5eb0c682c355c471726a6e3f" [[package]] name = "quasiquote" @@ -5719,18 +5733,18 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quick-xml" -version = "0.38.4" +version = "0.39.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c" +checksum = "721da970c312655cde9b4ffe0547f20a8494866a4af5ff51f18b7c633d0c870b" dependencies = [ "memchr", ] [[package]] name = "quote" -version = "1.0.44" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -5741,6 +5755,12 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "radsort" version = "0.1.1" @@ -5749,9 +5769,9 @@ checksum = "019b4b213425016d7d84a153c4c73afb0946fbb4840e4eece7ba8848b9d6da22" [[package]] name = "rand" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", "rand_chacha 0.3.1", @@ -5760,9 +5780,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.5", @@ -5813,7 +5833,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8615d50dcf34fa31f7ab52692afec947c4dd0ab803cc87cb3b0b4570ff7463" dependencies = [ "num-traits", - "rand 0.9.2", + "rand 0.9.4", ] [[package]] @@ -5842,9 +5862,9 @@ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" [[package]] name = "rayon" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" dependencies = [ "either", "rayon-core", @@ -5878,7 +5898,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b634fabf032fab15307ffd272149b622260f55974d9fad689292a5d33df02e5" dependencies = [ "bytemuck", - "font-types 0.11.1", + "font-types 0.11.3", ] [[package]] @@ -5902,16 +5922,16 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", ] [[package]] name = "redox_syscall" -version = "0.7.3" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" +checksum = "4666a1a60d8412eab19d94f6d13dcc9cea0a5ef4fdf6a5db306537413c661b1b" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", ] [[package]] @@ -5961,9 +5981,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "renderdoc-sys" @@ -5993,7 +6013,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4147b952f3f819eca0e99527022f7d6a8d05f111aeb0a62960c74eb283bec8fc" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "once_cell", "serde", "serde_derive", @@ -6101,7 +6121,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "errno", "libc", "linux-raw-sys 0.4.15", @@ -6110,14 +6130,14 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "errno", "libc", - "linux-raw-sys 0.11.0", + "linux-raw-sys 0.12.1", "windows-sys 0.61.2", ] @@ -6199,9 +6219,9 @@ checksum = "b12e76d157a900eb52e81bc6e9f3069344290341720e9178cde2407113ac8d89" [[package]] name = "semver" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "send_wrapper" @@ -6353,9 +6373,9 @@ checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "siphasher" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" [[package]] name = "skrifa" @@ -6410,7 +6430,7 @@ version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "calloop", "calloop-wayland-source", "cursor-icon", @@ -6440,11 +6460,11 @@ dependencies = [ [[package]] name = "spade" -version = "2.15.0" +version = "2.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb313e1c8afee5b5647e00ee0fe6855e3d529eb863a0fdae1d60006c4d1e9990" +checksum = "9699399fd9349b00b184f5635b074f9ec93afffef30c853f8c875b32c0f8c7fa" dependencies = [ - "hashbrown 0.15.5", + "hashbrown 0.16.1", "num-traits", "robust", "smallvec", @@ -6474,7 +6494,7 @@ version = "0.3.0+sdk-1.3.268.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", ] [[package]] @@ -6645,14 +6665,14 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.25.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.1", + "getrandom 0.4.2", "once_cell", - "rustix 1.1.3", + "rustix 1.1.4", "windows-sys 0.61.2", ] @@ -6771,9 +6791,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", "zerovec", @@ -6826,23 +6846,23 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.25.9+spec-1.1.0" +version = "0.25.11+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da053d28fe57e2c9d21b48261e14e7b4c8b670b54d2c684847b91feaf4c7dac5" +checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" dependencies = [ "indexmap", "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", - "winnow 1.0.1", + "winnow 1.0.2", ] [[package]] name = "toml_parser" -version = "1.1.1+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39ca317ebc49f06bd748bfba29533eac9485569dc9bf80b849024b025e814fb9" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow 1.0.1", + "winnow 1.0.2", ] [[package]] @@ -7021,11 +7041,39 @@ dependencies = [ "walkdir", ] +[[package]] +name = "type-sitter-gen" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2672c36a09a0150c5f18d34ac5b8146e43d1903ba604a12e4f1d762e1b4aaed1" +dependencies = [ + "cc", + "check_keyword", + "convert_case 0.8.0", + "dunce", + "enum-map", + "join-lazy-fmt", + "libc", + "libloading", + "logos", + "prettyplease", + "proc-macro2", + "quote", + "rustc-stable-hash", + "serde", + "serde_json", + "slice-group-by", + "syn", + "tree-sitter", + "tree-sitter-language", + "walkdir", +] + [[package]] name = "type-sitter-lib" -version = "0.8.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "092e2a9b5f4eb14bdd2246eb1557b2b99e67fe43be3e0411535d9483e73236b7" +checksum = "7744972e54c4e99eaf0e21be3b0dbe6b79dfb2cffe096c51beed34eca3aa760f" dependencies = [ "streaming-iterator", "tree-sitter", @@ -7033,12 +7081,12 @@ dependencies = [ [[package]] name = "type-sitter-proc" -version = "0.8.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4240aa23c38a18dc53f8422374fac3d7514654ec28258ef173b53ba9bee37a6e" +checksum = "e03a2a733db6a6b4e7ea3cd05ceb2fa742b20b66462b424ab89d87397a4b635c" dependencies = [ "syn", - "type-sitter-gen", + "type-sitter-gen 0.9.0", ] [[package]] @@ -7049,15 +7097,15 @@ checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" [[package]] name = "typenum" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" [[package]] name = "typewit" -version = "1.14.2" +version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8c1ae7cc0fdb8b842d65d127cb981574b0d2b249b74d1c7a2986863dc134f71" +checksum = "214ca0b2191785cbc06209b9ca1861e048e39b5ba33574b3cedd58363d5bb5f6" [[package]] name = "uneval" @@ -7101,9 +7149,9 @@ checksum = "383ad40bb927465ec0ce7720e033cb4ca06912855fc35db31b5755d0de75b1ee" [[package]] name = "unicode-segmentation" -version = "1.12.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" [[package]] name = "unicode-width" @@ -7180,11 +7228,11 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.23.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" dependencies = [ - "getrandom 0.4.1", + "getrandom 0.4.2", "js-sys", "serde_core", "wasm-bindgen", @@ -7252,11 +7300,11 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.2+wasi-0.2.9" +version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.57.1", ] [[package]] @@ -7265,14 +7313,14 @@ version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.51.0", ] [[package]] name = "wasm-bindgen" -version = "0.2.110" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1de241cdc66a9d91bd84f097039eb140cdc6eec47e0cdbaf9d932a1dd6c35866" +checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790" dependencies = [ "cfg-if", "once_cell", @@ -7283,23 +7331,19 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.60" +version = "0.4.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a42e96ea38f49b191e08a1bab66c7ffdba24b06f9995b39a9dd60222e5b6f1da" +checksum = "96492d0d3ffba25305a7dc88720d250b1401d7edca02cc3bcd50633b424673b8" dependencies = [ - "cfg-if", - "futures-util", "js-sys", - "once_cell", "wasm-bindgen", - "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.110" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12fdf6649048f2e3de6d7d5ff3ced779cdedee0e0baffd7dff5cdfa3abc8a52" +checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -7307,9 +7351,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.110" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e63d1795c565ac3462334c1e396fd46dbf481c40f51f5072c310717bc4fb309" +checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2" dependencies = [ "bumpalo", "proc-macro2", @@ -7320,9 +7364,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.110" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9f9cdac23a5ce71f6bf9f8824898a501e511892791ea2a0c6b8568c68b9cb53" +checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441" dependencies = [ "unicode-ident", ] @@ -7355,7 +7399,7 @@ version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "hashbrown 0.15.5", "indexmap", "semver", @@ -7363,13 +7407,13 @@ dependencies = [ [[package]] name = "wayland-backend" -version = "0.3.12" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fee64194ccd96bf648f42a65a7e589547096dfa702f7cadef84347b66ad164f9" +checksum = "2857dd20b54e916ec7253b3d6b4d5c4d7d4ca2c33c2e11c6c76a99bd8744755d" dependencies = [ "cc", "downcast-rs 1.2.1", - "rustix 1.1.3", + "rustix 1.1.4", "scoped-tls", "smallvec", "wayland-sys", @@ -7377,12 +7421,12 @@ dependencies = [ [[package]] name = "wayland-client" -version = "0.31.12" +version = "0.31.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e6faa537fbb6c186cb9f1d41f2f811a4120d1b57ec61f50da451a0c5122bec" +checksum = "645c7c96bb74690c3189b5c9cb4ca1627062bb23693a4fad9d8c3de958260144" dependencies = [ - "bitflags 2.11.0", - "rustix 1.1.3", + "bitflags 2.11.1", + "rustix 1.1.4", "wayland-backend", "wayland-scanner", ] @@ -7393,29 +7437,29 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "cursor-icon", "wayland-backend", ] [[package]] name = "wayland-cursor" -version = "0.31.12" +version = "0.31.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5864c4b5b6064b06b1e8b74ead4a98a6c45a285fe7a0e784d24735f011fdb078" +checksum = "4a52d18780be9b1314328a3de5f930b73d2200112e3849ca6cb11822793fb34d" dependencies = [ - "rustix 1.1.3", + "rustix 1.1.4", "wayland-client", "xcursor", ] [[package]] name = "wayland-protocols" -version = "0.32.10" +version = "0.32.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baeda9ffbcfc8cd6ddaade385eaf2393bd2115a69523c735f12242353c3df4f3" +checksum = "563a85523cade2429938e790815fd7319062103b9f4a2dc806e9b53b95982d8f" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "wayland-backend", "wayland-client", "wayland-scanner", @@ -7423,11 +7467,11 @@ dependencies = [ [[package]] name = "wayland-protocols-plasma" -version = "0.3.10" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa98634619300a535a9a97f338aed9a5ff1e01a461943e8346ff4ae26007306b" +checksum = "2b6d8cf1eb2c1c31ed1f5643c88a6e53538129d4af80030c8cabd1f9fa884d91" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "wayland-backend", "wayland-client", "wayland-protocols", @@ -7436,11 +7480,11 @@ dependencies = [ [[package]] name = "wayland-protocols-wlr" -version = "0.3.10" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9597cdf02cf0c34cd5823786dce6b5ae8598f05c2daf5621b6e178d4f7345f3" +checksum = "eb04e52f7836d7c7976c78ca0250d61e33873c34156a2a1fc9474828ec268234" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "wayland-backend", "wayland-client", "wayland-protocols", @@ -7449,9 +7493,9 @@ dependencies = [ [[package]] name = "wayland-scanner" -version = "0.31.8" +version = "0.31.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5423e94b6a63e68e439803a3e153a9252d5ead12fd853334e2ad33997e3889e3" +checksum = "9c324a910fd86ebdc364a3e61ec1f11737d3b1d6c273c0239ee8ff4bc0d24b4a" dependencies = [ "proc-macro2", "quick-xml", @@ -7460,9 +7504,9 @@ dependencies = [ [[package]] name = "wayland-sys" -version = "0.31.8" +version = "0.31.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6dbfc3ac5ef974c92a2235805cc0114033018ae1290a72e474aa8b28cbbdfd" +checksum = "d8eab23fefc9e41f8e841df4a9c707e8a8c4ed26e944ef69297184de2785e3be" dependencies = [ "dlib", "log", @@ -7471,9 +7515,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.87" +version = "0.3.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2c7c5718134e770ee62af3b6b4a84518ec10101aad610c024b64d6ff29bb1ff" +checksum = "4b572dff8bcf38bad0fa19729c89bb5748b2b9b1d8be70cf90df697e3a8f32aa" dependencies = [ "js-sys", "wasm-bindgen", @@ -7491,15 +7535,15 @@ dependencies = [ [[package]] name = "webbrowser" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe985f41e291eecef5e5c0770a18d28390addb03331c043964d9e916453d6f16" +checksum = "0fc95580916af1e68ff6a7be07446fc5db73ebf71cf092de939bbf5f7e189f72" dependencies = [ "core-foundation 0.10.1", "jni 0.22.4", "log", "ndk-context", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-foundation 0.3.2", "url", "web-sys", @@ -7518,7 +7562,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfe68bac7cde125de7a731c3400723cadaaf1703795ad3f4805f187459cd7a77" dependencies = [ "arrayvec", - "bitflags 2.11.0", + "bitflags 2.11.1", "cfg-if", "cfg_aliases", "document-features", @@ -7547,7 +7591,7 @@ dependencies = [ "arrayvec", "bit-set", "bit-vec", - "bitflags 2.11.0", + "bitflags 2.11.1", "bytemuck", "cfg_aliases", "document-features", @@ -7607,7 +7651,7 @@ dependencies = [ "arrayvec", "ash", "bit-set", - "bitflags 2.11.0", + "bitflags 2.11.1", "block", "bytemuck", "cfg-if", @@ -7629,7 +7673,7 @@ dependencies = [ "ndk-sys 0.6.0+11769913", "objc", "once_cell", - "ordered-float", + "ordered-float 5.3.0", "parking_lot", "portable-atomic", "portable-atomic-util", @@ -7652,7 +7696,7 @@ version = "27.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afdcf84c395990db737f2dd91628706cb31e86d72e53482320d368e52b5da5eb" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "bytemuck", "js-sys", "log", @@ -8234,7 +8278,7 @@ dependencies = [ "ahash", "android-activity", "atomic-waker", - "bitflags 2.11.0", + "bitflags 2.11.1", "block2 0.5.1", "bytemuck", "calloop", @@ -8288,9 +8332,9 @@ dependencies = [ [[package]] name = "winnow" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" +checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" dependencies = [ "memchr", ] @@ -8304,6 +8348,12 @@ dependencies = [ "wit-bindgen-rust-macro", ] +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + [[package]] name = "wit-bindgen-core" version = "0.51.0" @@ -8353,7 +8403,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", - "bitflags 2.11.0", + "bitflags 2.11.1", "indexmap", "log", "serde", @@ -8392,7 +8442,7 @@ dependencies = [ "libc", "log", "os_pipe", - "rustix 1.1.3", + "rustix 1.1.4", "thiserror 2.0.18", "tree_magic_mini", "wayland-backend", @@ -8403,9 +8453,9 @@ dependencies = [ [[package]] name = "writeable" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "x11-dl" @@ -8429,7 +8479,7 @@ dependencies = [ "libc", "libloading", "once_cell", - "rustix 1.1.3", + "rustix 1.1.4", "x11rb-protocol", ] @@ -8451,7 +8501,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "dlib", "log", "once_cell", @@ -8484,9 +8534,9 @@ checksum = "e01738255b5a16e78bbb83e7fbba0a1e7dd506905cfc53f4622d89015a03fbb5" [[package]] name = "yoke" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" dependencies = [ "stable_deref_trait", "yoke-derive", @@ -8495,9 +8545,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", @@ -8513,18 +8563,18 @@ checksum = "6df3dc4292935e51816d896edcd52aa30bc297907c26167fec31e2b0c6a32524" [[package]] name = "zerocopy" -version = "0.8.40" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a789c6e490b576db9f7e6b6d661bcc9799f7c0ac8352f56ea20193b2681532e5" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.40" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" dependencies = [ "proc-macro2", "quote", @@ -8533,18 +8583,18 @@ dependencies = [ [[package]] name = "zerofrom" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", @@ -8554,9 +8604,9 @@ dependencies = [ [[package]] name = "zerotrie" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" dependencies = [ "displaydoc", "yoke", @@ -8565,9 +8615,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" dependencies = [ "yoke", "zerofrom", @@ -8576,9 +8626,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", diff --git a/examples/modeling/projection.ccm b/examples/modeling/projection.ccm index cd20015..2187e90 100644 --- a/examples/modeling/projection.ccm +++ b/examples/modeling/projection.ccm @@ -1,4 +1,4 @@ let build_chain = std.import(path = "chain.ccm"); in - build_chain(num_links = 10u)::project() + build_chain(num_links = 5u)::project() diff --git a/interpreter/Cargo.toml b/interpreter/Cargo.toml index b956bf1..8ae77ec 100644 --- a/interpreter/Cargo.toml +++ b/interpreter/Cargo.toml @@ -29,12 +29,13 @@ sha2 = "0.10.9" serde = { version = "1.0.228", features = ["derive"] } hex = "0.4.3" # boolmesh = { version = "0.1.7", features = ["rayon"] } -boolmesh = { git = "https://github.com/IamTheCarl/boolmesh.git", branch = "opencode-refactors", features = ["rayon", "serde"] } -# boolmesh = { path = "../../boolmesh", features = ["rayon", "serde"] } +# boolmesh = { git = "https://github.com/IamTheCarl/boolmesh.git", branch = "opencode-refactors", features = ["rayon", "serde"] } +boolmesh = { path = "../../boolmesh", features = ["rayon", "serde"] } stl_io = "0.10.0" itertools = "0.14.0" thiserror = "2.0.18" -geo = { version = "0.32.0", features = ["serde"] } +# We have to disable multi-threading to get deterministic results from geo. +geo = { version = "0.32", default-features = false, features = ["serde", "earcutr", "spade"] } ciborium = "0.2.2" [build-dependencies] From 28a767a64d91242624e337b3460595615cea5c45 Mon Sep 17 00:00:00 2001 From: James Carl Date: Mon, 18 May 2026 01:42:00 -0400 Subject: [PATCH 40/71] Update AGENTS.md --- AGENTS.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 34ab73a..afb8814 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -72,3 +72,8 @@ Grammar is in `grammar.js`. Test fixtures are in `test/corpus/`. - **Editions**: `gui` and `cli` use Rust 2024 (resolver 3); others use 2021. - **geo multi-threading disabled**: `geo` is compiled with `default-features = false` to avoid non-deterministic results from its earcutr triangulation. +- **tree-sitter doc test**: `cargo test --all` fails on + `tree-sitter-command-cad-model` doctest (`assertion failed: !tree.root_node().has_error()`). + CI excludes it; `cargo test` runs 0 tests by default. +- **CLI commands**: `ccad repl` (REPL) and `ccad file ` (evaluate a .ccad file). + REPL uses a temp dir for store; file mode discovers `.ccad/store/` via git root. From bb6c46b79f42bdfc930e856c7601458f8fffbcf2 Mon Sep 17 00:00:00 2001 From: James Carl Date: Thu, 21 May 2026 14:29:12 -0400 Subject: [PATCH 41/71] Had Opencode fix the NixGL issues on my Steam Deck --- Cargo.lock | 1 + flake.nix | 18 ++++++++++++++++++ interpreter/Cargo.toml | 4 ++-- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1a422ab..0e9987e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1943,6 +1943,7 @@ dependencies = [ [[package]] name = "boolmesh" version = "0.1.9" +source = "git+https://github.com/IamTheCarl/boolmesh.git?branch=opencode-refactors#c79aa8277e8f3639987b3119218046ea756fe2b1" dependencies = [ "bincode", "fxhash", diff --git a/flake.nix b/flake.nix index 8c1fb7a..dc24f61 100644 --- a/flake.nix +++ b/flake.nix @@ -53,6 +53,8 @@ libGL alsa-lib udev + mesa + libglvnd ]; in rec { @@ -96,6 +98,22 @@ shellHook = '' export SHELL=${pkgs.bashInteractive}/bin/bash export NIX_HARDENING_ENABLE="" + export LD_LIBRARY_PATH="${mesa.outPath}/lib:${libglvnd.outPath}/lib:$LD_LIBRARY_PATH" + export LIBGL_DRIVERS_PATH="${mesa.outPath}/lib/dri" + export GBM_BACKENDS_PATH="${mesa.outPath}/lib/gbm" + export __EGL_VENDOR_LIBRARY_FILENAMES="${mesa.outPath}/share/glvnd/egl_vendor.d/50_mesa.json" + export VK_ICD_FILENAMES="${mesa.outPath}/share/vulkan/icd.d/lvp_icd.x86_64.json" + export LIBVA_DRIVERS_PATH="${mesa.outPath}/lib/dri" + # nixGL wrapper for Vulkan-on-OpenGL rendering on SteamOS + nixGL() { + export LD_LIBRARY_PATH="${mesa.outPath}/lib:${libglvnd.outPath}/lib:$LD_LIBRARY_PATH" + export LIBGL_DRIVERS_PATH="${mesa.outPath}/lib/dri" + export GBM_BACKENDS_PATH="${mesa.outPath}/lib/gbm" + export __EGL_VENDOR_LIBRARY_FILENAMES="${mesa.outPath}/share/glvnd/egl_vendor.d/50_mesa.json" + export VK_ICD_FILENAMES="${mesa.outPath}/share/vulkan/icd.d/lvp_icd.x86_64.json" + export LIBVA_DRIVERS_PATH="${mesa.outPath}/lib/dri" + exec "$@" + } ''; }; diff --git a/interpreter/Cargo.toml b/interpreter/Cargo.toml index 8ae77ec..16c1fbd 100644 --- a/interpreter/Cargo.toml +++ b/interpreter/Cargo.toml @@ -29,8 +29,8 @@ sha2 = "0.10.9" serde = { version = "1.0.228", features = ["derive"] } hex = "0.4.3" # boolmesh = { version = "0.1.7", features = ["rayon"] } -# boolmesh = { git = "https://github.com/IamTheCarl/boolmesh.git", branch = "opencode-refactors", features = ["rayon", "serde"] } -boolmesh = { path = "../../boolmesh", features = ["rayon", "serde"] } +boolmesh = { git = "https://github.com/IamTheCarl/boolmesh.git", branch = "opencode-refactors", features = ["rayon", "serde"] } +# boolmesh = { path = "../../boolmesh", features = ["rayon", "serde"] } stl_io = "0.10.0" itertools = "0.14.0" thiserror = "2.0.18" From e8366fd10ff1664d16c084fb6afb7ecbe9a598a0 Mon Sep 17 00:00:00 2001 From: James Carl Date: Thu, 21 May 2026 14:49:16 -0400 Subject: [PATCH 42/71] Fix hardware acceleration on non-nixos --- flake.nix | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index dc24f61..a560905 100644 --- a/flake.nix +++ b/flake.nix @@ -102,7 +102,8 @@ export LIBGL_DRIVERS_PATH="${mesa.outPath}/lib/dri" export GBM_BACKENDS_PATH="${mesa.outPath}/lib/gbm" export __EGL_VENDOR_LIBRARY_FILENAMES="${mesa.outPath}/share/glvnd/egl_vendor.d/50_mesa.json" - export VK_ICD_FILENAMES="${mesa.outPath}/share/vulkan/icd.d/lvp_icd.x86_64.json" + export VK_ICD_FILENAMES="${mesa.outPath}/share/vulkan/icd.d/radeon_icd.x86_64.json:${mesa.outPath}/share/vulkan/icd.d/intel_icd.x86_64.json:${mesa.outPath}/share/vulkan/icd.d/nouveau_icd.x86_64.json" + export VK_LAYER_PATH="${mesa.outPath}/share/vulkan/implicit_layer.d" export LIBVA_DRIVERS_PATH="${mesa.outPath}/lib/dri" # nixGL wrapper for Vulkan-on-OpenGL rendering on SteamOS nixGL() { @@ -110,7 +111,8 @@ export LIBGL_DRIVERS_PATH="${mesa.outPath}/lib/dri" export GBM_BACKENDS_PATH="${mesa.outPath}/lib/gbm" export __EGL_VENDOR_LIBRARY_FILENAMES="${mesa.outPath}/share/glvnd/egl_vendor.d/50_mesa.json" - export VK_ICD_FILENAMES="${mesa.outPath}/share/vulkan/icd.d/lvp_icd.x86_64.json" + export VK_ICD_FILENAMES="${mesa.outPath}/share/vulkan/icd.d/radeon_icd.x86_64.json:${mesa.outPath}/share/vulkan/icd.d/intel_icd.x86_64.json:${mesa.outPath}/share/vulkan/icd.d/nouveau_icd.x86_64.json" + export VK_LAYER_PATH="${mesa.outPath}/share/vulkan/implicit_layer.d" export LIBVA_DRIVERS_PATH="${mesa.outPath}/lib/dri" exec "$@" } From 628569860deada1a63e45d23c822d97b71cd5752 Mon Sep 17 00:00:00 2001 From: James Carl Date: Thu, 21 May 2026 15:04:13 -0400 Subject: [PATCH 43/71] Clean up flake.nix --- flake.nix | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/flake.nix b/flake.nix index a560905..c8f71b5 100644 --- a/flake.nix +++ b/flake.nix @@ -13,7 +13,6 @@ outputs = { - self, nixpkgs, flake-utils, crane, @@ -43,6 +42,16 @@ } ); + core-dependencies = with pkgs; [ + bashInteractive + nodejs_24 + tree-sitter + fenix-toolchain + cargo-expand + openssl + pkg-config + ]; + gui-dependencies = with pkgs; [ wayland libxkbcommon @@ -57,7 +66,7 @@ libglvnd ]; in - rec { + { packages.default = with pkgs; craneLib.buildPackage { @@ -74,19 +83,22 @@ strictDeps = true; }; - devShells.default = - with pkgs; - pkgs.mkShell { - buildInputs = [ - bashInteractive - nodejs_24 - tree-sitter - fenix-toolchain - cargo-expand + devShells = with pkgs; rec { + common = mkShell { + buildInputs = core-dependencies; + + LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath [ openssl - pkg-config - ] - ++ gui-dependencies; + ]; + + shellHook = '' + export SHELL=${pkgs.bashInteractive}/bin/bash + export NIX_HARDENING_ENABLE="" + ''; + }; + + gui = mkShell { + buildInputs = core-dependencies ++ gui-dependencies; LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath ( [ @@ -119,6 +131,8 @@ ''; }; + default = gui; + }; } ); } From f4a3fca55cfe27ef633fd3a86b0e683afb85d514 Mon Sep 17 00:00:00 2001 From: James Carl Date: Thu, 21 May 2026 15:57:40 -0400 Subject: [PATCH 44/71] Add ALSA to development environment --- flake.nix | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index c8f71b5..21b17c0 100644 --- a/flake.nix +++ b/flake.nix @@ -61,6 +61,8 @@ vulkan-loader libGL alsa-lib + alsa-plugins + pipewire udev mesa libglvnd @@ -110,7 +112,7 @@ shellHook = '' export SHELL=${pkgs.bashInteractive}/bin/bash export NIX_HARDENING_ENABLE="" - export LD_LIBRARY_PATH="${mesa.outPath}/lib:${libglvnd.outPath}/lib:$LD_LIBRARY_PATH" + export LD_LIBRARY_PATH="${mesa.outPath}/lib:${libglvnd.outPath}/lib:${alsa-plugins.outPath}/lib/alsa-lib:${pipewire.outPath}/lib/alsa-lib:$LD_LIBRARY_PATH" export LIBGL_DRIVERS_PATH="${mesa.outPath}/lib/dri" export GBM_BACKENDS_PATH="${mesa.outPath}/lib/gbm" export __EGL_VENDOR_LIBRARY_FILENAMES="${mesa.outPath}/share/glvnd/egl_vendor.d/50_mesa.json" @@ -119,7 +121,7 @@ export LIBVA_DRIVERS_PATH="${mesa.outPath}/lib/dri" # nixGL wrapper for Vulkan-on-OpenGL rendering on SteamOS nixGL() { - export LD_LIBRARY_PATH="${mesa.outPath}/lib:${libglvnd.outPath}/lib:$LD_LIBRARY_PATH" + export LD_LIBRARY_PATH="${mesa.outPath}/lib:${libglvnd.outPath}/lib:${alsa-plugins.outPath}/lib/alsa-lib:${pipewire.outPath}/lib/alsa-lib:$LD_LIBRARY_PATH" export LIBGL_DRIVERS_PATH="${mesa.outPath}/lib/dri" export GBM_BACKENDS_PATH="${mesa.outPath}/lib/gbm" export __EGL_VENDOR_LIBRARY_FILENAMES="${mesa.outPath}/share/glvnd/egl_vendor.d/50_mesa.json" From 541611898e8de3df83246f715551b3f7bb64a77c Mon Sep 17 00:00:00 2001 From: James Carl Date: Thu, 21 May 2026 17:46:23 -0400 Subject: [PATCH 45/71] Implement pan-orbit style camera for 3D view --- AGENTS.md | 6 +++ gui/src/main.rs | 91 +++++++++++------------------------- gui/src/visualize2d.rs | 67 ++++++++++++++++++++++----- gui/src/visualize3d.rs | 102 ++++++++++++++++++++++++++++++++++------- 4 files changed, 174 insertions(+), 92 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index afb8814..ededaae 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -77,3 +77,9 @@ Grammar is in `grammar.js`. Test fixtures are in `test/corpus/`. CI excludes it; `cargo test` runs 0 tests by default. - **CLI commands**: `ccad repl` (REPL) and `ccad file ` (evaluate a .ccad file). REPL uses a temp dir for store; file mode discovers `.ccad/store/` via git root. +- **Bevy query disjoint**: when two systems in the same schedule access `Transform` on + entities that share no components, Bevy may complain about overlapping queries. Add + `Without` to each `Query` to make them disjoint. E.g. in `gui/src/visualize3d.rs` + a camera query and a light query both read `Transform` — use + `(With, Without)` and + `(With, Without)`. diff --git a/gui/src/main.rs b/gui/src/main.rs index fa7561a..e244c1a 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -30,7 +30,7 @@ use bevy::{ }; use bevy_egui::{EguiContexts, EguiPlugin, EguiPrimaryContextPass}; use bevy_mod_outline::OutlinePlugin; -use egui::{Color32, Mesh, Painter, RichText, StrokeKind, TextEdit, emath::TSTransform}; +use egui::{Color32, Mesh, RichText, StrokeKind, TextEdit, emath::TSTransform}; use interpreter::{ ExecutionContext, FsStore, LogMessage, RuntimeLog, SourceReference, StackScope, StackTrace, Store, build_prelude, compile, execute_expression, new_parser, @@ -44,7 +44,7 @@ use tempfile::TempDir; use crate::{ visualize2d::{ViewState2d, build_fill_mesh_from_polygon, paint_linestring, paint_polygon}, - visualize3d::{ViewState3d, setup_3d, spawn_meshes, update_3d_camera, update_model_transforms}, + visualize3d::{ViewState3d, orbit_camera, orbit_light, setup_3d, spawn_meshes, update_3d_camera}, }; mod visualize2d; @@ -72,7 +72,8 @@ fn main() { spawn_meshes, check_job.before(spawn_meshes), update_3d_camera, - update_model_transforms.after(spawn_meshes), + orbit_camera.after(spawn_meshes), + orbit_light.after(orbit_camera), ), ) .add_systems(EguiPrimaryContextPass, render_ui); @@ -137,8 +138,7 @@ fn setup(mut commands: Commands, event_loop_proxy: Res) { file_updates_rx, }); - commands.insert_resource(ViewState::default()); - commands.insert_resource(ViewState2d); + commands.insert_resource(ViewState2d::default()); } #[derive(Debug)] @@ -423,12 +423,12 @@ fn check_job(mut command_cad: ResMut) { fn render_ui( mut job_bridge: ResMut, - mut view_state: ResMut, mut view_state_2d: ResMut, mut view_state_3d: ResMut, mut expression: ResMut, mut contexts: EguiContexts, mut clear_color: ResMut, + cameras: Query<&Transform, With>, ) -> Result { let ctx = contexts.ctx_mut()?; @@ -453,7 +453,7 @@ fn render_ui( ui.label(RichText::new("Ready").color(Color32::GREEN)); } - view_state_2d.draw_interface(&mut view_state, ui, &job_bridge.last_result, draw_area); + view_state_2d.draw_interface(ui, &job_bridge.last_result, draw_area); }); if let Err(error) = &job_bridge.file_watcher { @@ -479,7 +479,7 @@ fn render_ui( } ctx.input(|state| { - view_state.track_movement(state); + view_state_2d.track_movement(state); }); match &mut job_bridge.last_result { @@ -493,10 +493,11 @@ fn render_ui( } Some(Ok(JobOutput::LineString(line_string))) => { draw_thing(ctx, |ui, draw_area| { - let painter = view_state.prep_for_painting(ui); - let pixels_per_meter = view_state.pixels_per_meter(); + let painter = view_state_2d.prep_for_painting(ui); + let pixels_per_meter = view_state_2d.pixels_per_meter(); let center_offset = draw_area.center().to_vec2(); - let view_offset = egui::Vec2::new(view_state.offset.x, view_state.offset.y); + let view_offset = + egui::Vec2::new(view_state_2d.offset().x, view_state_2d.offset().y); let transform = TSTransform { scaling: pixels_per_meter, @@ -511,8 +512,14 @@ fn render_ui( } Some(Ok(JobOutput::Polygon { polygon, mesh })) => { draw_thing(ctx, |ui, draw_area| { - let painter = view_state.prep_for_painting(ui); - paint_polygon(&painter, draw_area, &view_state, &polygon.0, mesh.clone()); + let painter = view_state_2d.prep_for_painting(ui); + paint_polygon( + &painter, + draw_area, + &view_state_2d, + &polygon.0, + mesh.clone(), + ); }); } Some(Ok(JobOutput::PolygonSet { @@ -520,16 +527,18 @@ fn render_ui( meshes, })) => { draw_thing(ctx, |ui, draw_area| { - let painter = view_state.prep_for_painting(ui); + let painter = view_state_2d.prep_for_painting(ui); for (polygon, mesh) in polygon_set.0.iter().zip(meshes.iter()) { - paint_polygon(&painter, draw_area, &view_state, polygon, mesh.clone()); + paint_polygon(&painter, draw_area, &view_state_2d, polygon, mesh.clone()); } }); } Some(Ok(JobOutput::ManifoldMesh(_manifold_state))) => { - ctx.input(|state| { - view_state_3d.track_movement(state); - }); + if let Ok(camera_transform) = cameras.single() { + ctx.input(|state| { + view_state_3d.track_movement(camera_transform, state); + }); + } } Some(Err(error)) => { draw_thing(ctx, |ui, _draw_area| { @@ -540,49 +549,3 @@ fn render_ui( Ok(()) } - -#[derive(Resource)] -struct ViewState { - zoom: f32, - offset: Vec2, -} - -impl Default for ViewState { - fn default() -> Self { - let mut view_state = ViewState { - zoom: 10.0, - offset: Vec2::ZERO, - }; - view_state.set_pixels_per_meter(100.0); - view_state - } -} - -impl ViewState { - // Percentage of scale per scale factor unit. - const SCALE_FACTOR: f32 = 1.01; - - fn track_movement(&mut self, input_state: &egui::InputState) { - self.zoom += input_state.smooth_scroll_delta.y; - self.zoom = self.zoom.max(0.0); - - if input_state.pointer.primary_down() { - let drag_delta = input_state.pointer.delta(); - let delta = drag_delta / self.pixels_per_meter(); - self.offset += Vec2::new(delta.x, delta.y); - } - } - - fn prep_for_painting(&mut self, ui: &mut egui::Ui) -> Painter { - let draw_area = ui.available_rect_before_wrap(); - Painter::new(ui.ctx().clone(), ui.layer_id(), draw_area) - } - - pub fn pixels_per_meter(&self) -> f32 { - Self::SCALE_FACTOR.powf(self.zoom) - } - - pub fn set_pixels_per_meter(&mut self, pixels_per_meter: f32) { - self.zoom = pixels_per_meter.log(Self::SCALE_FACTOR); - } -} diff --git a/gui/src/visualize2d.rs b/gui/src/visualize2d.rs index 77c3d70..77c5ccb 100644 --- a/gui/src/visualize2d.rs +++ b/gui/src/visualize2d.rs @@ -25,15 +25,60 @@ use egui::{ }; use interpreter::geo::{BoundingRect, TriangulateEarcut}; -use crate::{JobError, ViewState}; - use super::JobOutput; -#[derive(Debug, Default, Resource)] -pub struct ViewState2d; +use crate::JobError; + +#[derive(Debug, Resource)] +pub struct ViewState2d { + offset: egui::Vec2, + zoom: f32, +} + +impl Default for ViewState2d { + fn default() -> Self { + let mut view_state = ViewState2d { + offset: egui::Vec2::ZERO, + zoom: 0.0, + }; + view_state.set_pixels_per_meter(10.0); + view_state + } +} impl ViewState2d { - fn fit_to_screen(&mut self, view_state: &mut ViewState, value: &JobOutput, draw_area: Rect) { + // Percentage of scale per scale factor unit. + const SCALE_FACTOR: f32 = 1.01; + + pub fn track_movement(&mut self, input_state: &egui::InputState) { + self.zoom += input_state.smooth_scroll_delta.y; + self.zoom = self.zoom.max(0.0); + + if input_state.pointer.primary_down() { + let drag_delta = input_state.pointer.delta(); + let delta = drag_delta / self.pixels_per_meter(); + self.offset += egui::Vec2::new(delta.x, delta.y); + } + } + + pub fn prep_for_painting(&mut self, ui: &mut Ui) -> Painter { + let draw_area = ui.available_rect_before_wrap(); + Painter::new(ui.ctx().clone(), ui.layer_id(), draw_area) + } + + pub fn pixels_per_meter(&self) -> f32 { + Self::SCALE_FACTOR.powf(self.zoom) + } + + pub fn set_pixels_per_meter(&mut self, pixels_per_meter: f32) { + self.zoom = pixels_per_meter.log(Self::SCALE_FACTOR); + } + + pub fn offset(&self) -> Vec2 { + self.offset + } + + fn fit_to_screen(&mut self, value: &JobOutput, draw_area: Rect) { let bounds = match value { JobOutput::LineString(line_string) => line_string.0.bounding_rect(), JobOutput::Polygon { polygon, .. } => polygon.0.bounding_rect(), @@ -46,19 +91,17 @@ impl ViewState2d { let dx = draw_area.x_range().span() / size.x as f32; let dy = draw_area.y_range().span() / size.y as f32; let pixels_per_meter = dx.min(dy); - view_state.set_pixels_per_meter(pixels_per_meter); + self.set_pixels_per_meter(pixels_per_meter); let center = bounds.center(); - view_state.offset = bevy::prelude::Vec2::new(-center.x as f32, center.y as f32); + self.offset = egui::Vec2::new(-center.x as f32, center.y as f32); } else { - // We don't know how to fit this. Just assume the defaults. - *view_state = ViewState::default(); + *self = ViewState2d::default(); } } pub fn draw_interface( &mut self, - view_state: &mut ViewState, ui: &mut Ui, last_result: &Option>, draw_area: Rect, @@ -70,7 +113,7 @@ impl ViewState2d { ) && ui.button("Fit to screen").clicked() { - self.fit_to_screen(view_state, value, draw_area); + self.fit_to_screen(value, draw_area); } } } @@ -120,7 +163,7 @@ pub fn build_fill_mesh_from_polygon(polygon: &interpreter::geo::Polygon) -> Arc< pub fn paint_polygon( painter: &Painter, draw_area: Rect, - view_state: &ViewState, + view_state: &ViewState2d, polygon: &interpreter::geo::Polygon, mesh: Arc, ) { diff --git a/gui/src/visualize3d.rs b/gui/src/visualize3d.rs index 5f332ac..c75061d 100644 --- a/gui/src/visualize3d.rs +++ b/gui/src/visualize3d.rs @@ -23,21 +23,62 @@ use bevy::prelude::*; use bevy::{ecs::system::Query, mesh::PrimitiveTopology}; use bevy_mod_outline::{OutlineMode, OutlineVolume}; -use crate::{JobBridge, JobOutput, ViewState}; +use crate::{JobBridge, JobOutput}; const VIEW_Z_OFFSET: f32 = -10.0; -#[derive(Debug, Resource, Default)] +#[derive(Debug, Resource)] pub struct ViewState3d { + offset: bevy::prelude::Vec3, + zoom: f32, rotation_x: f32, rotation_y: f32, } +impl Default for ViewState3d { + fn default() -> Self { + let mut view_state = ViewState3d { + offset: bevy::prelude::Vec3::ZERO, + zoom: 0.0, + rotation_x: 0.0, + rotation_y: 0.0, + }; + view_state.set_pixels_per_meter(10.0); + view_state + } +} + impl ViewState3d { + pub fn offset(&self) -> bevy::prelude::Vec3 { + self.offset + } +} + +impl ViewState3d { + // Percentage of scale per scale factor unit. + const SCALE_FACTOR: f32 = 1.01; const POINTER_SCALE: f32 = 0.007; - pub fn track_movement(&mut self, input_state: &egui::InputState) { - if input_state.pointer.secondary_down() { + pub fn pixels_per_meter(&self) -> f32 { + Self::SCALE_FACTOR.powf(self.zoom) + } + + pub fn set_pixels_per_meter(&mut self, pixels_per_meter: f32) { + self.zoom = pixels_per_meter.log(Self::SCALE_FACTOR); + } + + pub fn track_movement(&mut self, camera_transform: &Transform, input_state: &egui::InputState) { + self.zoom += input_state.smooth_scroll_delta.y; + self.zoom = self.zoom.max(0.0); + + if input_state.pointer.primary_down() { + let drag_delta = input_state.pointer.delta(); + let delta = drag_delta / self.pixels_per_meter(); + let right = camera_transform.right(); + let up = camera_transform.up(); + + self.offset += right * -delta.x + up * delta.y; + } else if input_state.pointer.secondary_down() { let drag_delta = input_state.pointer.delta(); // TODO These probably need to be scaled differently on a 4k display. @@ -47,7 +88,7 @@ impl ViewState3d { self.rotation_x = self .rotation_x - .clamp(-std::f32::consts::PI, std::f32::consts::PI); + .clamp(-89_f32.to_radians(), 89_f32.to_radians()); self.rotation_y = self .rotation_y .clamp(-std::f32::consts::PI, std::f32::consts::PI); @@ -82,30 +123,59 @@ pub fn setup_3d(mut commands: Commands) { } pub fn update_3d_camera( - view_state: Res, + view_state_3d: Res, mut cameras: Query<&mut Projection, With>, ) { for mut projection in &mut cameras { if let Projection::Orthographic(projection) = &mut *projection { - projection.scale = 1.0 / view_state.pixels_per_meter(); + projection.scale = 1.0 / view_state_3d.pixels_per_meter(); } } } -pub fn update_model_transforms( - view_state: Res, +pub fn orbit_camera( view_state_3d: Res, - mut models: Query<&mut Transform, With>, + mut cameras: Query<(&mut Transform, &Camera3d), With>, ) { - for mut transform in &mut models { - let mut new_transform = Transform::default(); + let radius = VIEW_Z_OFFSET.abs(); + let (yaw, pitch) = (view_state_3d.rotation_y, view_state_3d.rotation_x); + + let x = view_state_3d.offset().x + + yaw.sin() * pitch.cos() * radius; + let z = view_state_3d.offset().z + - yaw.cos() * pitch.cos() * radius; + let y = view_state_3d.offset().y + pitch.sin() * radius; - new_transform.rotate(-Quat::from_rotation_y(view_state_3d.rotation_y)); - new_transform.rotate(Quat::from_rotation_x(view_state_3d.rotation_x)); + let camera_pos = Vec3::new(x, y, z); + let forward = (view_state_3d.offset() - camera_pos).normalize(); + let back = -forward; - new_transform.translation = Vec3::new(-view_state.offset.x, -view_state.offset.y, 0.0); + let right = Vec3::Y + .cross(back) + .normalize(); + let up = back.cross(right); - *transform = new_transform; + let cam_rot = Mat4::from_cols( + Vec4::new(right.x, right.y, right.z, 0.0), + Vec4::new(up.x, up.y, up.z, 0.0), + Vec4::new(back.x, back.y, back.z, 0.0), + Vec4::new(0.0, 0.0, 0.0, 1.0), + ); + + for (mut transform, _camera) in &mut cameras { + transform.translation = camera_pos; + transform.rotation = Quat::from_mat4(&cam_rot); + } +} + +pub fn orbit_light( + cameras: Query<&Transform, (With, Without)>, + mut lights: Query<&mut Transform, (With, Without)>, +) { + let camera_transform = cameras.single().unwrap(); + for mut light in &mut lights { + light.translation = camera_transform.translation; + light.rotation = camera_transform.rotation; } } From fa9bb869e2bdda155c6eba6f3fbd37553a7b7e84 Mon Sep 17 00:00:00 2001 From: James Carl Date: Fri, 22 May 2026 00:14:07 -0400 Subject: [PATCH 46/71] Implement 'Fit to screen' for 3D view --- gui/src/main.rs | 14 ++++++-- gui/src/visualize3d.rs | 77 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 75 insertions(+), 16 deletions(-) diff --git a/gui/src/main.rs b/gui/src/main.rs index e244c1a..37a7534 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -44,7 +44,9 @@ use tempfile::TempDir; use crate::{ visualize2d::{ViewState2d, build_fill_mesh_from_polygon, paint_linestring, paint_polygon}, - visualize3d::{ViewState3d, orbit_camera, orbit_light, setup_3d, spawn_meshes, update_3d_camera}, + visualize3d::{ + ViewState3d, orbit_camera, orbit_light, setup_3d, spawn_meshes, update_3d_camera, + }, }; mod visualize2d; @@ -432,6 +434,8 @@ fn render_ui( ) -> Result { let ctx = contexts.ctx_mut()?; + let camera_transform = cameras.single().ok(); + egui::TopBottomPanel::top("main_interface").show(ctx, |ui| { let expression_editor = TextEdit::multiline(&mut expression.expression) .code_editor() @@ -443,8 +447,10 @@ fn render_ui( job_bridge.spawn_job(expression.expression.as_str()); } + const TOOLBAR_OFFSET: f32 = 110.0; + let mut draw_area = ctx.viewport_rect(); - draw_area.max.y -= 110.0; + draw_area.max.y -= TOOLBAR_OFFSET; ui.horizontal(|ui| { if job_bridge.active_job.is_some() { @@ -454,6 +460,10 @@ fn render_ui( } view_state_2d.draw_interface(ui, &job_bridge.last_result, draw_area); + + if let Some(camera_transform) = &camera_transform { + view_state_3d.draw_interface(ui, &job_bridge.last_result, draw_area, camera_transform, TOOLBAR_OFFSET); + } }); if let Err(error) = &job_bridge.file_watcher { diff --git a/gui/src/visualize3d.rs b/gui/src/visualize3d.rs index c75061d..0f59123 100644 --- a/gui/src/visualize3d.rs +++ b/gui/src/visualize3d.rs @@ -1,5 +1,3 @@ -use bevy::anti_alias::smaa::Smaa; -use bevy::asset::RenderAssetUsages; /* * Copyright 2026 James Carl * AGPL-3.0-only or AGPL-3.0-or-later @@ -17,13 +15,18 @@ use bevy::asset::RenderAssetUsages; * You should have received a copy of the GNU Affero General Public License along with this * program. If not, see . */ -use bevy::camera::ScalingMode; -use bevy::pbr::wireframe::{Wireframe, WireframeColor}; -use bevy::prelude::*; -use bevy::{ecs::system::Query, mesh::PrimitiveTopology}; +use bevy::{ + anti_alias::smaa::Smaa, + asset::RenderAssetUsages, + camera::ScalingMode, + pbr::wireframe::{Wireframe, WireframeColor}, + prelude::*, + {ecs::system::Query, mesh::PrimitiveTopology}, +}; use bevy_mod_outline::{OutlineMode, OutlineVolume}; use crate::{JobBridge, JobOutput}; +use interpreter::values::manifold_mesh::ManifoldMesh3D; const VIEW_Z_OFFSET: f32 = -10.0; @@ -67,6 +70,56 @@ impl ViewState3d { self.zoom = pixels_per_meter.log(Self::SCALE_FACTOR); } + pub fn fit_to_screen( + &mut self, + draw_area: egui::Rect, + camera_transform: &Transform, + toolbar_offset: f32, + manifold: &ManifoldMesh3D, + ) { + let camera_rotation = camera_transform.rotation; + let camera_inverse = camera_rotation.inverse(); + + let mut min = Vec3::MAX; + let mut max = Vec3::MIN; + + for p in manifold + .0 + .triangles() + .flat_map(|triangle| triangle.positions) + { + let v = Vec3::new(p.x as f32, p.y as f32, p.z as f32); + let p_local = camera_inverse * v; + + min = min.min(p_local); + max = max.max(p_local); + } + + let size = max - min; + let dx = draw_area.x_range().span() / size.x; + let dy = draw_area.y_range().span() / size.y; + let pixels_per_meter = dx.min(dy); + self.set_pixels_per_meter(pixels_per_meter); + + self.offset = camera_rotation * ((min + max) / 2.0) + + camera_rotation * Vec3::new(0.0, toolbar_offset / pixels_per_meter / 2.0, 0.0); + } + + pub fn draw_interface( + &mut self, + ui: &mut egui::Ui, + last_result: &Option>, + draw_area: egui::Rect, + camera_transform: &Transform, + toolbar_offset: f32, + ) { + if let Some(Ok(JobOutput::ManifoldMesh(state))) = last_result + && ui.button("Fit to screen").clicked() + { + self.fit_to_screen(draw_area, camera_transform, toolbar_offset, &state.manifold); + } + } + pub fn track_movement(&mut self, camera_transform: &Transform, input_state: &egui::InputState) { self.zoom += input_state.smooth_scroll_delta.y; self.zoom = self.zoom.max(0.0); @@ -83,7 +136,7 @@ impl ViewState3d { // TODO These probably need to be scaled differently on a 4k display. // It would probably be best to base the rotation factor based off the viewport size. - self.rotation_x -= drag_delta.y * Self::POINTER_SCALE; + self.rotation_x += drag_delta.y * Self::POINTER_SCALE; self.rotation_y += drag_delta.x * Self::POINTER_SCALE; self.rotation_x = self @@ -140,19 +193,15 @@ pub fn orbit_camera( let radius = VIEW_Z_OFFSET.abs(); let (yaw, pitch) = (view_state_3d.rotation_y, view_state_3d.rotation_x); - let x = view_state_3d.offset().x - + yaw.sin() * pitch.cos() * radius; - let z = view_state_3d.offset().z - - yaw.cos() * pitch.cos() * radius; + let x = view_state_3d.offset().x + yaw.sin() * pitch.cos() * radius; + let z = view_state_3d.offset().z - yaw.cos() * pitch.cos() * radius; let y = view_state_3d.offset().y + pitch.sin() * radius; let camera_pos = Vec3::new(x, y, z); let forward = (view_state_3d.offset() - camera_pos).normalize(); let back = -forward; - let right = Vec3::Y - .cross(back) - .normalize(); + let right = Vec3::Y.cross(back).normalize(); let up = back.cross(right); let cam_rot = Mat4::from_cols( From cce9daab418d2d0e52f8e4a8d366fa0ea6be2f82 Mon Sep 17 00:00:00 2001 From: James Carl Date: Fri, 22 May 2026 00:49:19 -0400 Subject: [PATCH 47/71] Add wireframe toggle button --- gui/src/main.rs | 4 +++- gui/src/visualize3d.rs | 40 +++++++++++++++++++++++++++++++++++----- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/gui/src/main.rs b/gui/src/main.rs index 37a7534..6dea63f 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -45,7 +45,8 @@ use tempfile::TempDir; use crate::{ visualize2d::{ViewState2d, build_fill_mesh_from_polygon, paint_linestring, paint_polygon}, visualize3d::{ - ViewState3d, orbit_camera, orbit_light, setup_3d, spawn_meshes, update_3d_camera, + ViewState3d, orbit_camera, orbit_light, setup_3d, spawn_meshes, sync_wireframe_visibility, + update_3d_camera, }, }; @@ -73,6 +74,7 @@ fn main() { ( spawn_meshes, check_job.before(spawn_meshes), + sync_wireframe_visibility.after(spawn_meshes), update_3d_camera, orbit_camera.after(spawn_meshes), orbit_light.after(orbit_camera), diff --git a/gui/src/visualize3d.rs b/gui/src/visualize3d.rs index 0f59123..6d3da20 100644 --- a/gui/src/visualize3d.rs +++ b/gui/src/visualize3d.rs @@ -36,6 +36,7 @@ pub struct ViewState3d { zoom: f32, rotation_x: f32, rotation_y: f32, + show_wireframe: bool, } impl Default for ViewState3d { @@ -45,6 +46,7 @@ impl Default for ViewState3d { zoom: 0.0, rotation_x: 0.0, rotation_y: 0.0, + show_wireframe: false, }; view_state.set_pixels_per_meter(10.0); view_state @@ -113,10 +115,17 @@ impl ViewState3d { camera_transform: &Transform, toolbar_offset: f32, ) { - if let Some(Ok(JobOutput::ManifoldMesh(state))) = last_result - && ui.button("Fit to screen").clicked() - { - self.fit_to_screen(draw_area, camera_transform, toolbar_offset, &state.manifold); + if let Some(Ok(JobOutput::ManifoldMesh(_state))) = last_result { + if ui.button("Fit to screen").clicked() { + self.fit_to_screen( + draw_area, + camera_transform, + toolbar_offset, + &_state.manifold, + ); + } + + ui.checkbox(&mut self.show_wireframe, "Show Wireframe"); } } @@ -231,6 +240,28 @@ pub fn orbit_light( #[derive(Component)] pub struct MeshModel; +pub fn sync_wireframe_visibility( + view_state_3d: Res, + mut commands: Commands, + wireframe_entities: Query, With)>, + non_wireframe_entities: Query, Without)>, +) { + if !view_state_3d.show_wireframe { + for entity in &wireframe_entities { + commands.entity(entity).remove::(); + } + } else { + for entity in &non_wireframe_entities { + commands.entity(entity).insert(( + Wireframe, + WireframeColor { + color: bevy::color::palettes::css::BLACK.into(), + }, + )); + } + } +} + pub fn spawn_meshes( mut commands: Commands, mut command_cad: ResMut, @@ -304,7 +335,6 @@ pub fn spawn_meshes( )), }, OutlineMode::FloodFlatDoubleSided, - // TODO this should only be enabled with a checkbox in the UI. Wireframe, WireframeColor { color: bevy::color::palettes::css::BLACK.into(), From e57fde28fd5ba27b1d14e8ce42674a9d36ef5438 Mon Sep 17 00:00:00 2001 From: James Carl Date: Fri, 22 May 2026 01:14:07 -0400 Subject: [PATCH 48/71] Add axis view buttons --- gui/src/visualize3d.rs | 64 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/gui/src/visualize3d.rs b/gui/src/visualize3d.rs index 6d3da20..e1c15ea 100644 --- a/gui/src/visualize3d.rs +++ b/gui/src/visualize3d.rs @@ -30,6 +30,16 @@ use interpreter::values::manifold_mesh::ManifoldMesh3D; const VIEW_Z_OFFSET: f32 = -10.0; +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum AxisView { + XPlus, + XMinus, + YPlus, + YMinus, + ZPlus, + ZMinus, +} + #[derive(Debug, Resource)] pub struct ViewState3d { offset: bevy::prelude::Vec3, @@ -107,6 +117,35 @@ impl ViewState3d { + camera_rotation * Vec3::new(0.0, toolbar_offset / pixels_per_meter / 2.0, 0.0); } + pub fn snap_to_axis_view(&mut self, axis: AxisView) { + match axis { + AxisView::XPlus => { + self.rotation_y = 0.0; + self.rotation_x = 0.0; + } + AxisView::XMinus => { + self.rotation_y = std::f32::consts::PI; + self.rotation_x = 0.0; + } + AxisView::YPlus => { + self.rotation_y = std::f32::consts::FRAC_PI_2; + self.rotation_x = 0.0; + } + AxisView::YMinus => { + self.rotation_y = -std::f32::consts::FRAC_PI_2; + self.rotation_x = 0.0; + } + AxisView::ZPlus => { + self.rotation_y = 0.0; + self.rotation_x = -std::f32::consts::FRAC_PI_2; + } + AxisView::ZMinus => { + self.rotation_y = 0.0; + self.rotation_x = std::f32::consts::PI / 2.0; + } + } + } + pub fn draw_interface( &mut self, ui: &mut egui::Ui, @@ -125,7 +164,32 @@ impl ViewState3d { ); } + ui.separator(); + ui.checkbox(&mut self.show_wireframe, "Show Wireframe"); + + ui.separator(); + + ui.horizontal(|ui| { + if ui.button("X+").clicked() { + self.snap_to_axis_view(AxisView::XPlus); + } + if ui.button("X-").clicked() { + self.snap_to_axis_view(AxisView::XMinus); + } + if ui.button("Y+").clicked() { + self.snap_to_axis_view(AxisView::YPlus); + } + if ui.button("Y-").clicked() { + self.snap_to_axis_view(AxisView::YMinus); + } + if ui.button("Z+").clicked() { + self.snap_to_axis_view(AxisView::ZPlus); + } + if ui.button("Z-").clicked() { + self.snap_to_axis_view(AxisView::ZMinus); + } + }); } } From 23d6c2507f51c0a9aef4352290c94ad344232bd0 Mon Sep 17 00:00:00 2001 From: James Carl Date: Fri, 22 May 2026 17:28:13 -0400 Subject: [PATCH 49/71] Implement 2D background grid --- Cargo.lock | 2 + gui/Cargo.toml | 2 + gui/src/main.rs | 14 +++- gui/src/visualize2d.rs | 146 +++++++++++++++++++++++++++++++++++++++-- 4 files changed, 156 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0e9987e..81484f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3681,12 +3681,14 @@ dependencies = [ "bevy", "bevy_egui", "bevy_mod_outline", + "common_data_types", "egui", "interpreter", "nalgebra", "notify", "oneshot", "tempfile", + "units", ] [[package]] diff --git a/gui/Cargo.toml b/gui/Cargo.toml index 17733fc..32c1bae 100644 --- a/gui/Cargo.toml +++ b/gui/Cargo.toml @@ -6,6 +6,8 @@ edition = "2024" [dependencies] egui = { version = "0.33", features = ["mint"] } interpreter = { path = "../interpreter" } +units = { path = "../units" } +common_data_types = { path = "../common_data_types" } anyhow = { workspace = true } oneshot = "0.2" tempfile = { workspace = true } diff --git a/gui/src/main.rs b/gui/src/main.rs index 6dea63f..f43a784 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -43,7 +43,7 @@ use notify::{EventKind, RecommendedWatcher, Watcher, recommended_watcher}; use tempfile::TempDir; use crate::{ - visualize2d::{ViewState2d, build_fill_mesh_from_polygon, paint_linestring, paint_polygon}, + visualize2d::{GridSettings, ViewState2d, build_fill_mesh_from_polygon, draw_grid, paint_linestring, paint_polygon}, visualize3d::{ ViewState3d, orbit_camera, orbit_light, setup_3d, spawn_meshes, sync_wireframe_visibility, update_3d_camera, @@ -143,6 +143,7 @@ fn setup(mut commands: Commands, event_loop_proxy: Res) { }); commands.insert_resource(ViewState2d::default()); + commands.insert_resource(GridSettings::default()); } #[derive(Debug)] @@ -430,6 +431,7 @@ fn render_ui( mut view_state_2d: ResMut, mut view_state_3d: ResMut, mut expression: ResMut, + mut grid_settings: ResMut, mut contexts: EguiContexts, mut clear_color: ResMut, cameras: Query<&Transform, With>, @@ -463,6 +465,11 @@ fn render_ui( view_state_2d.draw_interface(ui, &job_bridge.last_result, draw_area); + ui.label("Grid Size:"); + if ui.add(egui::TextEdit::singleline(&mut grid_settings.unit_string).desired_width(50.0)).changed() { + grid_settings.parse(); + } + if let Some(camera_transform) = &camera_transform { view_state_3d.draw_interface(ui, &job_bridge.last_result, draw_area, camera_transform, TOOLBAR_OFFSET); } @@ -475,8 +482,6 @@ fn render_ui( ); } - // TODO Add some kind of scale legend. - // Inform Bevy of our background color. let visuals = ui.visuals(); let background_color = visuals.panel_fill; @@ -506,6 +511,7 @@ fn render_ui( Some(Ok(JobOutput::LineString(line_string))) => { draw_thing(ctx, |ui, draw_area| { let painter = view_state_2d.prep_for_painting(ui); + draw_grid(&painter, draw_area, &view_state_2d, &grid_settings); let pixels_per_meter = view_state_2d.pixels_per_meter(); let center_offset = draw_area.center().to_vec2(); let view_offset = @@ -525,6 +531,7 @@ fn render_ui( Some(Ok(JobOutput::Polygon { polygon, mesh })) => { draw_thing(ctx, |ui, draw_area| { let painter = view_state_2d.prep_for_painting(ui); + draw_grid(&painter, draw_area, &view_state_2d, &grid_settings); paint_polygon( &painter, draw_area, @@ -540,6 +547,7 @@ fn render_ui( })) => { draw_thing(ctx, |ui, draw_area| { let painter = view_state_2d.prep_for_painting(ui); + draw_grid(&painter, draw_area, &view_state_2d, &grid_settings); for (polygon, mesh) in polygon_set.0.iter().zip(meshes.iter()) { paint_polygon(&painter, draw_area, &view_state_2d, polygon, mesh.clone()); } diff --git a/gui/src/visualize2d.rs b/gui/src/visualize2d.rs index 77c5ccb..88f4fd0 100644 --- a/gui/src/visualize2d.rs +++ b/gui/src/visualize2d.rs @@ -1,6 +1,3 @@ -use std::sync::Arc; - -use bevy::ecs::resource::Resource; /* * Copyright 2026 James Carl * AGPL-3.0-only or AGPL-3.0-or-later @@ -18,16 +15,155 @@ use bevy::ecs::resource::Resource; * You should have received a copy of the GNU Affero General Public License along with this * program. If not, see . */ +use bevy::ecs::resource::Resource; use egui::{ Color32, Mesh, Painter, Pos2, Rect, Shape, StrokeKind, Ui, Vec2, emath::TSTransform, epaint::{ColorMode, PathShape, PathStroke}, }; use interpreter::geo::{BoundingRect, TriangulateEarcut}; +use std::sync::Arc; + +use crate::{JobError, JobOutput}; + +#[derive(Debug, Resource, Default)] +pub struct GridSettings { + pub unit_string: String, + unit_meters: Option, + subdivisions: i32, +} + +impl GridSettings { + pub fn world_step(&self) -> Option { + let unit_meters = self.unit_meters?; + Some(unit_meters / self.subdivisions as f32) + } + + pub fn parse(&mut self) { + let s = self.unit_string.trim(); + if s.is_empty() { + self.unit_meters = None; + self.subdivisions = 1; + return; + } + + // Try to split off a unit abbreviation from the end. + // Find the first digit from the right to separate number from unit. + let (num_str, unit_str) = match s.rfind(|c: char| c.is_ascii_digit()) { + Some(pos) => { + // Everything after the last digit is the unit abbreviation + if pos + 1 < s.len() { + (&s[..pos + 1], &s[pos + 1..]) + } else { + (s, "") + } + } + None => (s, ""), + }; + + let number: f32 = match num_str.trim().parse() { + Ok(n) if n > 0.0 => n, + _ => { + self.unit_meters = None; + self.subdivisions = 1; + return; + } + }; + + let coefficient = match units::get_conversion_factor(unit_str) { + Some(cf) => { + // Only allow length dimensions + if cf.dimension.length != 1 { + self.unit_meters = None; + self.subdivisions = 1; + return; + } + cf.coefficient as f32 + } + None => { + // Unknown unit abbreviation — no grid + self.unit_meters = None; + self.subdivisions = 1; + return; + } + }; + + self.unit_meters = Some(number * coefficient); + + // Compute subdivisions once based on a target cell size of ~100px. + // This means the grid will scale proportionally with zoom like the geometry does. + // We use a default zoom of 10px/m (same as fit-to-screen initial value) for this calculation. + let pixels_per_meter = 10.0; + let pixels_per_cell = self.unit_meters.unwrap() * pixels_per_meter; + if pixels_per_cell > 500.0 { + self.subdivisions = ((pixels_per_cell / 100.0).ceil()).max(2.0) as i32; + } else { + self.subdivisions = 1; + } + } +} -use super::JobOutput; +pub fn draw_grid( + painter: &Painter, + draw_area: Rect, + view_state: &ViewState2d, + grid_settings: &GridSettings, +) { + let world_step = match grid_settings.world_step() { + Some(ws) => ws, + None => return, + }; -use crate::JobError; + let pixels_per_meter = view_state.pixels_per_meter(); + let pixels_per_cell = world_step * pixels_per_meter; + + // Skip if cells are too small to be useful + if pixels_per_cell < 3.0 { + return; + } + + let visuals = painter.ctx().style().visuals.clone(); + let grid_color = visuals.weak_text_color(); + + let center_offset = draw_area.center().to_vec2(); + let view_offset = Vec2::new(view_state.offset().x, view_state.offset().y); + + // Calculate the world position of the edges of the draw area + let left_world = (draw_area.left() - center_offset.x) / pixels_per_meter - view_offset.x; + let right_world = (draw_area.right() - center_offset.x) / pixels_per_meter - view_offset.x; + let top_world = (draw_area.top() - center_offset.y) / pixels_per_meter - view_offset.y; + let bottom_world = (draw_area.bottom() - center_offset.y) / pixels_per_meter - view_offset.y; + + let screen_top = draw_area.top(); + let screen_bottom = draw_area.bottom(); + + // Draw vertical lines — compute position directly from index to avoid floating point drift + let first_line_idx = (left_world / world_step).floor(); + let last_line_idx = (right_world / world_step).floor(); + for i in (first_line_idx as i32)..=(last_line_idx as i32) { + let world_x = (i as f32) * world_step; + let x = (world_x + view_offset.x) * pixels_per_meter + center_offset.x; + painter.line_segment( + [Pos2::new(x, screen_top), Pos2::new(x, screen_bottom)], + (1.0, grid_color), + ); + } + + // Draw horizontal lines — compute position directly from index + let first_line_idx = (top_world / world_step).floor(); + let last_line_idx = (bottom_world / world_step).floor(); + for i in (first_line_idx as i32)..=(last_line_idx as i32) { + let world_y = (i as f32) * world_step; + let y = (world_y + view_offset.y) * pixels_per_meter + center_offset.y; + painter.line_segment( + [ + Pos2::new(draw_area.left(), y), + Pos2::new(draw_area.right(), y), + ], + (1.0, grid_color), + ); + } +} #[derive(Debug, Resource)] pub struct ViewState2d { From 9acfaf822abe4e51140303583139c2e8d8827418 Mon Sep 17 00:00:00 2001 From: James Carl Date: Mon, 1 Jun 2026 23:46:13 -0400 Subject: [PATCH 50/71] Fix scaling issues on Steam Deck --- gui/src/main.rs | 50 ++++++++++++++++++++++++++++++++++++------ gui/src/visualize2d.rs | 7 +++--- 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/gui/src/main.rs b/gui/src/main.rs index f43a784..5af7fd1 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -68,7 +68,7 @@ fn main() { .add_plugins(EguiPlugin::default()) .add_plugins(OutlinePlugin) .add_plugins(WireframePlugin::default()) - .add_systems(Startup, (setup, setup_3d)) + .add_systems(Startup, (setup, setup_3d, apply_display_scaling)) .add_systems( Update, ( @@ -146,6 +146,31 @@ fn setup(mut commands: Commands, event_loop_proxy: Res) { commands.insert_resource(GridSettings::default()); } +fn apply_display_scaling( + mut windows: Query<&mut Window>, +) { + for mut window in windows.iter_mut() { + let base = window.resolution.base_scale_factor(); + + eprintln!( + "Window: physical={}x{}, logical={}, base_scale={}", + window.physical_width(), + window.physical_height(), + window.resolution.width(), + base + ); + + // Steam Deck (1280x800) with KDE Plasma on Wayland reports an extremely + // high scale factor (4.5) even at "100%" display settings, because KDE + // calculates high DPI from the small screen size. This makes UI elements + // appear far too large. Override to a more reasonable value. + if base > 2.0 { + window.resolution.set_scale_factor_override(Some(2.0)); + eprintln!("Applied scale factor override: 2.0"); + } + } +} + #[derive(Debug)] struct GuiLogger; @@ -451,19 +476,18 @@ fn render_ui( job_bridge.spawn_job(expression.expression.as_str()); } - const TOOLBAR_OFFSET: f32 = 110.0; - + let toolbar_height = ui.max_rect().height(); let mut draw_area = ctx.viewport_rect(); - draw_area.max.y -= TOOLBAR_OFFSET; + draw_area.max.y -= toolbar_height; - ui.horizontal(|ui| { + ui.horizontal(|ui| { if job_bridge.active_job.is_some() { ui.label(RichText::new("Working...").color(Color32::YELLOW)); } else { ui.label(RichText::new("Ready").color(Color32::GREEN)); } - view_state_2d.draw_interface(ui, &job_bridge.last_result, draw_area); + view_state_2d.draw_interface(ui, &job_bridge.last_result); ui.label("Grid Size:"); if ui.add(egui::TextEdit::singleline(&mut grid_settings.unit_string).desired_width(50.0)).changed() { @@ -471,7 +495,7 @@ fn render_ui( } if let Some(camera_transform) = &camera_transform { - view_state_3d.draw_interface(ui, &job_bridge.last_result, draw_area, camera_transform, TOOLBAR_OFFSET); + view_state_3d.draw_interface(ui, &job_bridge.last_result, draw_area, camera_transform, toolbar_height); } }); @@ -510,6 +534,10 @@ fn render_ui( } Some(Ok(JobOutput::LineString(line_string))) => { draw_thing(ctx, |ui, draw_area| { + if view_state_2d.fit_to_screen_requested { + view_state_2d.fit_to_screen(&JobOutput::LineString(line_string.clone()), draw_area); + view_state_2d.fit_to_screen_requested = false; + } let painter = view_state_2d.prep_for_painting(ui); draw_grid(&painter, draw_area, &view_state_2d, &grid_settings); let pixels_per_meter = view_state_2d.pixels_per_meter(); @@ -530,6 +558,10 @@ fn render_ui( } Some(Ok(JobOutput::Polygon { polygon, mesh })) => { draw_thing(ctx, |ui, draw_area| { + if view_state_2d.fit_to_screen_requested { + view_state_2d.fit_to_screen(&JobOutput::Polygon { polygon: polygon.clone(), mesh: mesh.clone() }, draw_area); + view_state_2d.fit_to_screen_requested = false; + } let painter = view_state_2d.prep_for_painting(ui); draw_grid(&painter, draw_area, &view_state_2d, &grid_settings); paint_polygon( @@ -546,6 +578,10 @@ fn render_ui( meshes, })) => { draw_thing(ctx, |ui, draw_area| { + if view_state_2d.fit_to_screen_requested { + view_state_2d.fit_to_screen(&JobOutput::PolygonSet { polygon_set: polygon_set.clone(), meshes: meshes.clone() }, draw_area); + view_state_2d.fit_to_screen_requested = false; + } let painter = view_state_2d.prep_for_painting(ui); draw_grid(&painter, draw_area, &view_state_2d, &grid_settings); for (polygon, mesh) in polygon_set.0.iter().zip(meshes.iter()) { diff --git a/gui/src/visualize2d.rs b/gui/src/visualize2d.rs index 88f4fd0..652ecb2 100644 --- a/gui/src/visualize2d.rs +++ b/gui/src/visualize2d.rs @@ -169,6 +169,7 @@ pub fn draw_grid( pub struct ViewState2d { offset: egui::Vec2, zoom: f32, + pub fit_to_screen_requested: bool, } impl Default for ViewState2d { @@ -176,6 +177,7 @@ impl Default for ViewState2d { let mut view_state = ViewState2d { offset: egui::Vec2::ZERO, zoom: 0.0, + fit_to_screen_requested: false, }; view_state.set_pixels_per_meter(10.0); view_state @@ -214,7 +216,7 @@ impl ViewState2d { self.offset } - fn fit_to_screen(&mut self, value: &JobOutput, draw_area: Rect) { + pub fn fit_to_screen(&mut self, value: &JobOutput, draw_area: Rect) { let bounds = match value { JobOutput::LineString(line_string) => line_string.0.bounding_rect(), JobOutput::Polygon { polygon, .. } => polygon.0.bounding_rect(), @@ -240,7 +242,6 @@ impl ViewState2d { &mut self, ui: &mut Ui, last_result: &Option>, - draw_area: Rect, ) { if let Some(Ok(value)) = last_result && matches!( @@ -249,7 +250,7 @@ impl ViewState2d { ) && ui.button("Fit to screen").clicked() { - self.fit_to_screen(value, draw_area); + self.fit_to_screen_requested = true; } } } From 1181587cde4f5a486c3eb5fe1e3f42bc3827e00d Mon Sep 17 00:00:00 2001 From: James Carl Date: Tue, 2 Jun 2026 16:41:06 -0400 Subject: [PATCH 51/71] feat(gui): add 3D billboard grid to match 2D view grid - Extract GridSettings to shared gui/src/grid.rs module - Add billboard grid in 3D view that always faces the camera - Grid positioned just past model center to avoid z-fighting - Two-sided geometry with explicit front/back faces - Line thickness scales with zoom to match 2D grid appearance - Toggle via 'Show Grid' checkbox in toolbar --- gui/src/grid.rs | 96 ++++++++++++++++++++++++++++ gui/src/main.rs | 15 +++-- gui/src/visualize2d.rs | 78 +---------------------- gui/src/visualize3d.rs | 140 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 245 insertions(+), 84 deletions(-) create mode 100644 gui/src/grid.rs diff --git a/gui/src/grid.rs b/gui/src/grid.rs new file mode 100644 index 0000000..2dbce24 --- /dev/null +++ b/gui/src/grid.rs @@ -0,0 +1,96 @@ +/* + * Copyright 2026 James Carl + * AGPL-3.0-only or AGPL-3.0-or-later + * + * This file is part of Command Cad. + * + * Command CAD is free software: you can redistribute it and/or modify it under the terms of + * the GNU Affero General Public License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License along with this + * program. If not, see . + */ +use bevy::ecs::resource::Resource; + +#[derive(Debug, Resource, Default)] +pub struct GridSettings { + pub show_grid: bool, + pub unit_string: String, + unit_meters: Option, + subdivisions: i32, +} + +impl GridSettings { + pub fn world_step(&self) -> Option { + let unit_meters = self.unit_meters?; + Some(unit_meters / self.subdivisions as f32) + } + + pub fn parse(&mut self) { + let s = self.unit_string.trim(); + if s.is_empty() { + self.unit_meters = None; + self.subdivisions = 1; + return; + } + + // Try to split off a unit abbreviation from the end. + // Find the first digit from the right to separate number from unit. + let (num_str, unit_str) = match s.rfind(|c: char| c.is_ascii_digit()) { + Some(pos) => { + // Everything after the last digit is the unit abbreviation + if pos + 1 < s.len() { + (&s[..pos + 1], &s[pos + 1..]) + } else { + (s, "") + } + } + None => (s, ""), + }; + + let number: f32 = match num_str.trim().parse() { + Ok(n) if n > 0.0 => n, + _ => { + self.unit_meters = None; + self.subdivisions = 1; + return; + } + }; + + let coefficient = match units::get_conversion_factor(unit_str) { + Some(cf) => { + // Only allow length dimensions + if cf.dimension.length != 1 { + self.unit_meters = None; + self.subdivisions = 1; + return; + } + cf.coefficient as f32 + } + None => { + // Unknown unit abbreviation — no grid + self.unit_meters = None; + self.subdivisions = 1; + return; + } + }; + + self.unit_meters = Some(number * coefficient); + + // Compute subdivisions once based on a target cell size of ~100px. + // This means the grid will scale proportionally with zoom like the geometry does. + // We use a default zoom of 10px/m (same as fit-to-screen initial value) for this calculation. + let pixels_per_meter = 10.0; + let pixels_per_cell = self.unit_meters.unwrap() * pixels_per_meter; + if pixels_per_cell > 500.0 { + self.subdivisions = ((pixels_per_cell / 100.0).ceil()).max(2.0) as i32; + } else { + self.subdivisions = 1; + } + } +} diff --git a/gui/src/main.rs b/gui/src/main.rs index 5af7fd1..8e09706 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -43,15 +43,17 @@ use notify::{EventKind, RecommendedWatcher, Watcher, recommended_watcher}; use tempfile::TempDir; use crate::{ - visualize2d::{GridSettings, ViewState2d, build_fill_mesh_from_polygon, draw_grid, paint_linestring, paint_polygon}, + grid::GridSettings, + visualize2d::{ViewState2d, build_fill_mesh_from_polygon, draw_grid, paint_linestring, paint_polygon}, visualize3d::{ ViewState3d, orbit_camera, orbit_light, setup_3d, spawn_meshes, sync_wireframe_visibility, - update_3d_camera, + update_3d_camera, update_grid, }, }; -mod visualize2d; -mod visualize3d; +mod grid; + mod visualize2d; + mod visualize3d; fn main() { let mut app = App::new(); @@ -68,7 +70,7 @@ fn main() { .add_plugins(EguiPlugin::default()) .add_plugins(OutlinePlugin) .add_plugins(WireframePlugin::default()) - .add_systems(Startup, (setup, setup_3d, apply_display_scaling)) + .add_systems(Startup, (setup, setup_3d.after(setup), apply_display_scaling)) .add_systems( Update, ( @@ -78,6 +80,7 @@ fn main() { update_3d_camera, orbit_camera.after(spawn_meshes), orbit_light.after(orbit_camera), + update_grid.after(orbit_light), ), ) .add_systems(EguiPrimaryContextPass, render_ui); @@ -494,6 +497,8 @@ fn render_ui( grid_settings.parse(); } + ui.checkbox(&mut grid_settings.show_grid, "Show Grid"); + if let Some(camera_transform) = &camera_transform { view_state_3d.draw_interface(ui, &job_bridge.last_result, draw_area, camera_transform, toolbar_height); } diff --git a/gui/src/visualize2d.rs b/gui/src/visualize2d.rs index 652ecb2..f9331c9 100644 --- a/gui/src/visualize2d.rs +++ b/gui/src/visualize2d.rs @@ -24,85 +24,9 @@ use egui::{ use interpreter::geo::{BoundingRect, TriangulateEarcut}; use std::sync::Arc; +use crate::grid::GridSettings; use crate::{JobError, JobOutput}; -#[derive(Debug, Resource, Default)] -pub struct GridSettings { - pub unit_string: String, - unit_meters: Option, - subdivisions: i32, -} - -impl GridSettings { - pub fn world_step(&self) -> Option { - let unit_meters = self.unit_meters?; - Some(unit_meters / self.subdivisions as f32) - } - - pub fn parse(&mut self) { - let s = self.unit_string.trim(); - if s.is_empty() { - self.unit_meters = None; - self.subdivisions = 1; - return; - } - - // Try to split off a unit abbreviation from the end. - // Find the first digit from the right to separate number from unit. - let (num_str, unit_str) = match s.rfind(|c: char| c.is_ascii_digit()) { - Some(pos) => { - // Everything after the last digit is the unit abbreviation - if pos + 1 < s.len() { - (&s[..pos + 1], &s[pos + 1..]) - } else { - (s, "") - } - } - None => (s, ""), - }; - - let number: f32 = match num_str.trim().parse() { - Ok(n) if n > 0.0 => n, - _ => { - self.unit_meters = None; - self.subdivisions = 1; - return; - } - }; - - let coefficient = match units::get_conversion_factor(unit_str) { - Some(cf) => { - // Only allow length dimensions - if cf.dimension.length != 1 { - self.unit_meters = None; - self.subdivisions = 1; - return; - } - cf.coefficient as f32 - } - None => { - // Unknown unit abbreviation — no grid - self.unit_meters = None; - self.subdivisions = 1; - return; - } - }; - - self.unit_meters = Some(number * coefficient); - - // Compute subdivisions once based on a target cell size of ~100px. - // This means the grid will scale proportionally with zoom like the geometry does. - // We use a default zoom of 10px/m (same as fit-to-screen initial value) for this calculation. - let pixels_per_meter = 10.0; - let pixels_per_cell = self.unit_meters.unwrap() * pixels_per_meter; - if pixels_per_cell > 500.0 { - self.subdivisions = ((pixels_per_cell / 100.0).ceil()).max(2.0) as i32; - } else { - self.subdivisions = 1; - } - } -} - pub fn draw_grid( painter: &Painter, draw_area: Rect, diff --git a/gui/src/visualize3d.rs b/gui/src/visualize3d.rs index e1c15ea..434c634 100644 --- a/gui/src/visualize3d.rs +++ b/gui/src/visualize3d.rs @@ -19,15 +19,24 @@ use bevy::{ anti_alias::smaa::Smaa, asset::RenderAssetUsages, camera::ScalingMode, + color::palettes::css, pbr::wireframe::{Wireframe, WireframeColor}, prelude::*, {ecs::system::Query, mesh::PrimitiveTopology}, }; use bevy_mod_outline::{OutlineMode, OutlineVolume}; +use crate::grid::GridSettings; use crate::{JobBridge, JobOutput}; use interpreter::values::manifold_mesh::ManifoldMesh3D; + +const GRID_MAX_EXTENT: f32 = 10.0; +const GRID_LINE_SCREEN_WIDTH: f32 = 1.0; // target line width in screen pixels + +#[derive(Component)] +pub struct GridEntity; + const VIEW_Z_OFFSET: f32 = -10.0; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -222,7 +231,117 @@ impl ViewState3d { } } -pub fn setup_3d(mut commands: Commands) { +fn build_grid_mesh(world_step: f32, line_half_thickness: f32) -> Mesh { + let mut m = Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::default()); + let mut positions = vec![]; + let mut normals = vec![]; + + let first_line_idx = (-GRID_MAX_EXTENT / world_step).floor() as i32; + let last_line_idx = (GRID_MAX_EXTENT / world_step).ceil() as i32; + + for i in first_line_idx..=last_line_idx { + let pos = (i as f32) * world_step; + + // Vertical lines (along local Y axis) — thin quad centered at x = pos + let t = line_half_thickness; + let e = GRID_MAX_EXTENT; + + // Front face (CCW from +Z, normals +Z) + positions.push([pos - t, -e, 0.0]); + positions.push([pos + t, -e, 0.0]); + positions.push([pos - t, e, 0.0]); + positions.push([pos - t, e, 0.0]); + positions.push([pos + t, -e, 0.0]); + positions.push([pos + t, e, 0.0]); + + // Back face (CCW from -Z, normals -Z) + positions.push([pos - t, -e, 0.0]); + positions.push([pos - t, e, 0.0]); + positions.push([pos + t, -e, 0.0]); + positions.push([pos + t, -e, 0.0]); + positions.push([pos - t, e, 0.0]); + positions.push([pos + t, e, 0.0]); + + // Horizontal lines (along local X axis) — thin quad centered at y = pos + // Front face (CCW from +Z, normals +Z) + positions.push([-e, pos - t, 0.0]); + positions.push([e, pos - t, 0.0]); + positions.push([-e, pos + t, 0.0]); + positions.push([-e, pos + t, 0.0]); + positions.push([e, pos - t, 0.0]); + positions.push([e, pos + t, 0.0]); + + // Back face (CCW from -Z, normals -Z) + positions.push([-e, pos - t, 0.0]); + positions.push([-e, pos + t, 0.0]); + positions.push([e, pos - t, 0.0]); + positions.push([e, pos - t, 0.0]); + positions.push([-e, pos + t, 0.0]); + positions.push([e, pos + t, 0.0]); + + for _ in 0..12 { + normals.push([0.0, 0.0, 1.0]); + } + for _ in 0..12 { + normals.push([0.0, 0.0, -1.0]); + } + } + + m.insert_attribute(Mesh::ATTRIBUTE_POSITION, positions); + m.insert_attribute(Mesh::ATTRIBUTE_NORMAL, normals); + m +} + +pub fn update_grid( + mut grid: Query<(&mut Transform, &mut Visibility, &GridEntity, &Mesh3d)>, + cameras: Query<&Transform, (With, Without)>, + view_state_3d: Res, + grid_settings: Res, + mut meshes: ResMut>, +) { + let Some(camera) = cameras.iter().next() else { + return; + }; + + let cam_back = camera.rotation * Vec3::Z; + let cam_right = camera.rotation * Vec3::X; + let cam_up = camera.rotation * Vec3::Y; + + let grid_rot = Mat4::from_cols( + Vec4::new(cam_right.x, cam_right.y, cam_right.z, 0.0), + Vec4::new(cam_up.x, cam_up.y, cam_up.z, 0.0), + Vec4::new(cam_back.x, cam_back.y, cam_back.z, 0.0), + Vec4::new(0.0, 0.0, 0.0, 1.0), + ); + + for (mut transform, mut visibility, _grid, mesh_handle) in &mut grid { + let look_dir = -camera.translation; + let dist = look_dir.length(); + transform.translation = camera.translation + look_dir.normalize() * (dist * 1.01); + transform.rotation = Quat::from_mat4(&grid_rot); + + if grid_settings.show_grid { + *visibility = Visibility::Visible; + + let pixels_per_meter = view_state_3d.pixels_per_meter(); + let line_half_thickness = GRID_LINE_SCREEN_WIDTH / pixels_per_meter / 2.0; + let world_step = grid_settings.world_step().unwrap_or(0.01); + + if let Some(mesh) = meshes.get_mut(&mesh_handle.0) { + *mesh = build_grid_mesh(world_step, line_half_thickness); + } + } else { + *visibility = Visibility::Hidden; + } + } +} + +pub fn setup_3d( + mut commands: Commands, + grid_settings: Option>, + mut meshes: ResMut>, + mut materials: ResMut>, +) { commands.spawn(( Camera3d::default(), Projection::from(OrthographicProjection { @@ -245,6 +364,23 @@ pub fn setup_3d(mut commands: Commands) { ..default() }); + if let Some(grid_settings) = grid_settings { + let world_step = grid_settings.world_step().unwrap_or(0.01); + let initial_thickness = GRID_LINE_SCREEN_WIDTH / 10.0; + let grid_mesh = meshes.add(build_grid_mesh(world_step, initial_thickness)); + commands.spawn(( + Mesh3d(grid_mesh), + MeshMaterial3d(materials.add(StandardMaterial { + base_color: Color::Srgba(css::DARK_GRAY.into()), + unlit: true, + ..default() + })), + Transform::default(), + Visibility::Visible, + GridEntity, + )); + } + commands.insert_resource(ViewState3d::default()); } @@ -292,7 +428,7 @@ pub fn orbit_camera( pub fn orbit_light( cameras: Query<&Transform, (With, Without)>, - mut lights: Query<&mut Transform, (With, Without)>, + mut lights: Query<&mut Transform, (With, Without, Without)>, ) { let camera_transform = cameras.single().unwrap(); for mut light in &mut lights { From 6c6efbe864cd26dfbd155bbaa29905afb87a75b0 Mon Sep 17 00:00:00 2001 From: James Carl Date: Tue, 2 Jun 2026 16:58:51 -0400 Subject: [PATCH 52/71] gui: remove Show Grid toggle, always show grid when valid unit is set --- gui/src/grid.rs | 1 - gui/src/main.rs | 2 -- gui/src/visualize3d.rs | 2 +- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/gui/src/grid.rs b/gui/src/grid.rs index 2dbce24..3251f3b 100644 --- a/gui/src/grid.rs +++ b/gui/src/grid.rs @@ -19,7 +19,6 @@ use bevy::ecs::resource::Resource; #[derive(Debug, Resource, Default)] pub struct GridSettings { - pub show_grid: bool, pub unit_string: String, unit_meters: Option, subdivisions: i32, diff --git a/gui/src/main.rs b/gui/src/main.rs index 8e09706..9e7448d 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -497,8 +497,6 @@ fn render_ui( grid_settings.parse(); } - ui.checkbox(&mut grid_settings.show_grid, "Show Grid"); - if let Some(camera_transform) = &camera_transform { view_state_3d.draw_interface(ui, &job_bridge.last_result, draw_area, camera_transform, toolbar_height); } diff --git a/gui/src/visualize3d.rs b/gui/src/visualize3d.rs index 434c634..7a5501a 100644 --- a/gui/src/visualize3d.rs +++ b/gui/src/visualize3d.rs @@ -320,7 +320,7 @@ pub fn update_grid( transform.translation = camera.translation + look_dir.normalize() * (dist * 1.01); transform.rotation = Quat::from_mat4(&grid_rot); - if grid_settings.show_grid { + if grid_settings.world_step().is_some() { *visibility = Visibility::Visible; let pixels_per_meter = view_state_3d.pixels_per_meter(); From d4270a7ac8623bb383fbc3ea0557cb4f7355b9f1 Mon Sep 17 00:00:00 2001 From: James Carl Date: Tue, 2 Jun 2026 17:07:04 -0400 Subject: [PATCH 53/71] gui: move 3D Fit to screen button left of grid config --- gui/src/main.rs | 17 ++++++++++++++--- gui/src/visualize3d.rs | 14 -------------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/gui/src/main.rs b/gui/src/main.rs index 9e7448d..4b7a8bb 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -492,14 +492,25 @@ fn render_ui( view_state_2d.draw_interface(ui, &job_bridge.last_result); + if let Some(cam) = &camera_transform { + if let Some(Ok(JobOutput::ManifoldMesh(_state))) = &job_bridge.last_result { + if ui.button("Fit to screen").clicked() { + view_state_3d.fit_to_screen( + draw_area, + cam, + toolbar_height, + &_state.manifold, + ); + } + } + } + ui.label("Grid Size:"); if ui.add(egui::TextEdit::singleline(&mut grid_settings.unit_string).desired_width(50.0)).changed() { grid_settings.parse(); } - if let Some(camera_transform) = &camera_transform { - view_state_3d.draw_interface(ui, &job_bridge.last_result, draw_area, camera_transform, toolbar_height); - } + view_state_3d.draw_interface(ui, &job_bridge.last_result); }); if let Err(error) = &job_bridge.file_watcher { diff --git a/gui/src/visualize3d.rs b/gui/src/visualize3d.rs index 7a5501a..0822679 100644 --- a/gui/src/visualize3d.rs +++ b/gui/src/visualize3d.rs @@ -159,22 +159,8 @@ impl ViewState3d { &mut self, ui: &mut egui::Ui, last_result: &Option>, - draw_area: egui::Rect, - camera_transform: &Transform, - toolbar_offset: f32, ) { if let Some(Ok(JobOutput::ManifoldMesh(_state))) = last_result { - if ui.button("Fit to screen").clicked() { - self.fit_to_screen( - draw_area, - camera_transform, - toolbar_offset, - &_state.manifold, - ); - } - - ui.separator(); - ui.checkbox(&mut self.show_wireframe, "Show Wireframe"); ui.separator(); From 413900652e7d099105e756f87d99cc721d1349ba Mon Sep 17 00:00:00 2001 From: James Carl Date: Tue, 2 Jun 2026 17:25:57 -0400 Subject: [PATCH 54/71] Hide 3D grid when zoomed out far enough (pixels_per_cell < 3.0) --- gui/src/visualize3d.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/gui/src/visualize3d.rs b/gui/src/visualize3d.rs index 0822679..a45e5ac 100644 --- a/gui/src/visualize3d.rs +++ b/gui/src/visualize3d.rs @@ -307,14 +307,19 @@ pub fn update_grid( transform.rotation = Quat::from_mat4(&grid_rot); if grid_settings.world_step().is_some() { - *visibility = Visibility::Visible; - let pixels_per_meter = view_state_3d.pixels_per_meter(); - let line_half_thickness = GRID_LINE_SCREEN_WIDTH / pixels_per_meter / 2.0; let world_step = grid_settings.world_step().unwrap_or(0.01); + let pixels_per_cell = world_step * pixels_per_meter; + + if pixels_per_cell < 3.0 { + *visibility = Visibility::Hidden; + } else { + *visibility = Visibility::Visible; + let line_half_thickness = GRID_LINE_SCREEN_WIDTH / pixels_per_meter / 2.0; - if let Some(mesh) = meshes.get_mut(&mesh_handle.0) { - *mesh = build_grid_mesh(world_step, line_half_thickness); + if let Some(mesh) = meshes.get_mut(&mesh_handle.0) { + *mesh = build_grid_mesh(world_step, line_half_thickness); + } } } else { *visibility = Visibility::Hidden; From 82c048064c988c7947a4285726deab44fd6b49bf Mon Sep 17 00:00:00 2001 From: James Carl Date: Tue, 2 Jun 2026 17:43:20 -0400 Subject: [PATCH 55/71] Size 3D grid dynamically to viewport with 25% margin --- gui/src/visualize3d.rs | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/gui/src/visualize3d.rs b/gui/src/visualize3d.rs index a45e5ac..43015ae 100644 --- a/gui/src/visualize3d.rs +++ b/gui/src/visualize3d.rs @@ -217,20 +217,20 @@ impl ViewState3d { } } -fn build_grid_mesh(world_step: f32, line_half_thickness: f32) -> Mesh { +fn build_grid_mesh(world_step: f32, line_half_thickness: f32, grid_extent: f32) -> Mesh { let mut m = Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::default()); let mut positions = vec![]; let mut normals = vec![]; - let first_line_idx = (-GRID_MAX_EXTENT / world_step).floor() as i32; - let last_line_idx = (GRID_MAX_EXTENT / world_step).ceil() as i32; + let first_line_idx = (-grid_extent / world_step).floor() as i32; + let last_line_idx = (grid_extent / world_step).ceil() as i32; for i in first_line_idx..=last_line_idx { let pos = (i as f32) * world_step; // Vertical lines (along local Y axis) — thin quad centered at x = pos let t = line_half_thickness; - let e = GRID_MAX_EXTENT; + let e = grid_extent; // Front face (CCW from +Z, normals +Z) positions.push([pos - t, -e, 0.0]); @@ -280,18 +280,18 @@ fn build_grid_mesh(world_step: f32, line_half_thickness: f32) -> Mesh { pub fn update_grid( mut grid: Query<(&mut Transform, &mut Visibility, &GridEntity, &Mesh3d)>, - cameras: Query<&Transform, (With, Without)>, + cameras: Query<(&Camera, &Transform), (With, Without)>, view_state_3d: Res, grid_settings: Res, mut meshes: ResMut>, ) { - let Some(camera) = cameras.iter().next() else { + let Some((camera, camera_transform)) = cameras.iter().next() else { return; }; - let cam_back = camera.rotation * Vec3::Z; - let cam_right = camera.rotation * Vec3::X; - let cam_up = camera.rotation * Vec3::Y; + let cam_back = camera_transform.rotation * Vec3::Z; + let cam_right = camera_transform.rotation * Vec3::X; + let cam_up = camera_transform.rotation * Vec3::Y; let grid_rot = Mat4::from_cols( Vec4::new(cam_right.x, cam_right.y, cam_right.z, 0.0), @@ -300,14 +300,23 @@ pub fn update_grid( Vec4::new(0.0, 0.0, 0.0, 1.0), ); + let viewport = match camera.physical_viewport_size() { + Some(size) => size, + None => return, + }; + + let pixels_per_meter = view_state_3d.pixels_per_meter(); + let visible_x = viewport.x as f32 / pixels_per_meter; + let visible_y = viewport.y as f32 / pixels_per_meter; + let grid_extent = (visible_x.max(visible_y) * 1.25).max(GRID_MAX_EXTENT); + for (mut transform, mut visibility, _grid, mesh_handle) in &mut grid { - let look_dir = -camera.translation; + let look_dir = -camera_transform.translation; let dist = look_dir.length(); - transform.translation = camera.translation + look_dir.normalize() * (dist * 1.01); + transform.translation = camera_transform.translation + look_dir.normalize() * (dist * 1.01); transform.rotation = Quat::from_mat4(&grid_rot); if grid_settings.world_step().is_some() { - let pixels_per_meter = view_state_3d.pixels_per_meter(); let world_step = grid_settings.world_step().unwrap_or(0.01); let pixels_per_cell = world_step * pixels_per_meter; @@ -318,7 +327,7 @@ pub fn update_grid( let line_half_thickness = GRID_LINE_SCREEN_WIDTH / pixels_per_meter / 2.0; if let Some(mesh) = meshes.get_mut(&mesh_handle.0) { - *mesh = build_grid_mesh(world_step, line_half_thickness); + *mesh = build_grid_mesh(world_step, line_half_thickness, grid_extent); } } } else { @@ -358,7 +367,7 @@ pub fn setup_3d( if let Some(grid_settings) = grid_settings { let world_step = grid_settings.world_step().unwrap_or(0.01); let initial_thickness = GRID_LINE_SCREEN_WIDTH / 10.0; - let grid_mesh = meshes.add(build_grid_mesh(world_step, initial_thickness)); + let grid_mesh = meshes.add(build_grid_mesh(world_step, initial_thickness, GRID_MAX_EXTENT)); commands.spawn(( Mesh3d(grid_mesh), MeshMaterial3d(materials.add(StandardMaterial { From 012523e7c7ee47dcf55deaab1a783f95763b33b1 Mon Sep 17 00:00:00 2001 From: James Carl Date: Tue, 2 Jun 2026 22:02:50 -0400 Subject: [PATCH 56/71] Make grids render in front of the models --- gui/src/main.rs | 4 ++-- gui/src/visualize3d.rs | 28 ++++++++++++++++++++-------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/gui/src/main.rs b/gui/src/main.rs index 4b7a8bb..c14d163 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -553,7 +553,6 @@ fn render_ui( view_state_2d.fit_to_screen_requested = false; } let painter = view_state_2d.prep_for_painting(ui); - draw_grid(&painter, draw_area, &view_state_2d, &grid_settings); let pixels_per_meter = view_state_2d.pixels_per_meter(); let center_offset = draw_area.center().to_vec2(); let view_offset = @@ -568,6 +567,7 @@ fn render_ui( StrokeKind::Middle, &line_string.0, )); + draw_grid(&painter, draw_area, &view_state_2d, &grid_settings); }); } Some(Ok(JobOutput::Polygon { polygon, mesh })) => { @@ -577,7 +577,6 @@ fn render_ui( view_state_2d.fit_to_screen_requested = false; } let painter = view_state_2d.prep_for_painting(ui); - draw_grid(&painter, draw_area, &view_state_2d, &grid_settings); paint_polygon( &painter, draw_area, @@ -601,6 +600,7 @@ fn render_ui( for (polygon, mesh) in polygon_set.0.iter().zip(meshes.iter()) { paint_polygon(&painter, draw_area, &view_state_2d, polygon, mesh.clone()); } + draw_grid(&painter, draw_area, &view_state_2d, &grid_settings); }); } Some(Ok(JobOutput::ManifoldMesh(_manifold_state))) => { diff --git a/gui/src/visualize3d.rs b/gui/src/visualize3d.rs index 43015ae..7d07545 100644 --- a/gui/src/visualize3d.rs +++ b/gui/src/visualize3d.rs @@ -30,7 +30,6 @@ use crate::grid::GridSettings; use crate::{JobBridge, JobOutput}; use interpreter::values::manifold_mesh::ManifoldMesh3D; - const GRID_MAX_EXTENT: f32 = 10.0; const GRID_LINE_SCREEN_WIDTH: f32 = 1.0; // target line width in screen pixels @@ -218,7 +217,10 @@ impl ViewState3d { } fn build_grid_mesh(world_step: f32, line_half_thickness: f32, grid_extent: f32) -> Mesh { - let mut m = Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::default()); + let mut m = Mesh::new( + PrimitiveTopology::TriangleList, + RenderAssetUsages::default(), + ); let mut positions = vec![]; let mut normals = vec![]; @@ -311,9 +313,7 @@ pub fn update_grid( let grid_extent = (visible_x.max(visible_y) * 1.25).max(GRID_MAX_EXTENT); for (mut transform, mut visibility, _grid, mesh_handle) in &mut grid { - let look_dir = -camera_transform.translation; - let dist = look_dir.length(); - transform.translation = camera_transform.translation + look_dir.normalize() * (dist * 1.01); + transform.translation = Vec3::ZERO; transform.rotation = Quat::from_mat4(&grid_rot); if grid_settings.world_step().is_some() { @@ -364,15 +364,20 @@ pub fn setup_3d( ..default() }); - if let Some(grid_settings) = grid_settings { + if let Some(grid_settings) = grid_settings { let world_step = grid_settings.world_step().unwrap_or(0.01); let initial_thickness = GRID_LINE_SCREEN_WIDTH / 10.0; - let grid_mesh = meshes.add(build_grid_mesh(world_step, initial_thickness, GRID_MAX_EXTENT)); + let grid_mesh = meshes.add(build_grid_mesh( + world_step, + initial_thickness, + GRID_MAX_EXTENT, + )); commands.spawn(( Mesh3d(grid_mesh), MeshMaterial3d(materials.add(StandardMaterial { base_color: Color::Srgba(css::DARK_GRAY.into()), unlit: true, + depth_bias: 1_000_000.0, ..default() })), Transform::default(), @@ -428,7 +433,14 @@ pub fn orbit_camera( pub fn orbit_light( cameras: Query<&Transform, (With, Without)>, - mut lights: Query<&mut Transform, (With, Without, Without)>, + mut lights: Query< + &mut Transform, + ( + With, + Without, + Without, + ), + >, ) { let camera_transform = cameras.single().unwrap(); for mut light in &mut lights { From 93e3c981a06c829315062955a78665c1c97d4488 Mon Sep 17 00:00:00 2001 From: James Carl Date: Wed, 3 Jun 2026 10:52:01 -0400 Subject: [PATCH 57/71] runtime: switch dictionary storage from HashableMap to IndexMap Replace HashableMap with IndexMap across all dictionary-related types in the interpreter crate. This provides deterministic insertion-order preservation for dictionary members. Changes: - Add indexmap v2 dependency with serde feature - Switch DictionaryData.members to IndexMap - Switch StructDefinition.members to Arc - Add ArgumentName enum for future positional arg support - Update build_struct_definition! macro to use IndexMap - Update all test assertions to match new types - Remove manual Hash impl (not needed without dict-as-key usage) 426 tests pass. --- interpreter/Cargo.toml | 1 + interpreter/src/execution/mod.rs | 6 +- interpreter/src/execution/values/closure.rs | 7 +- .../src/execution/values/constraint_set.rs | 8 +- .../src/execution/values/dictionary.rs | 126 ++++++++++++++---- .../src/execution/values/string/mod.rs | 4 +- .../src/execution/values/value_type.rs | 12 +- 7 files changed, 126 insertions(+), 38 deletions(-) diff --git a/interpreter/Cargo.toml b/interpreter/Cargo.toml index 16c1fbd..f8d40b1 100644 --- a/interpreter/Cargo.toml +++ b/interpreter/Cargo.toml @@ -15,6 +15,7 @@ enum_dispatch = "0.3" enum_downcast = { version = "0.1", features = [ "derive" ] } num-traits = "0.2" hashable-map = { version = "0.4.0", features = ["serde"] } +indexmap = { version = "2", features = ["serde"] } imstr = "0.2.0" nalgebra = { workspace = true } stack = "0.4.0" diff --git a/interpreter/src/execution/mod.rs b/interpreter/src/execution/mod.rs index df19df8..284a5e2 100644 --- a/interpreter/src/execution/mod.rs +++ b/interpreter/src/execution/mod.rs @@ -720,7 +720,7 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { #[cfg(test)] mod test { - use hashable_map::HashableMap; + use indexmap::IndexMap; use std::{collections::HashMap, sync::Arc}; use super::*; @@ -756,13 +756,13 @@ mod test { assert_eq!( product, values::ValueType::Dictionary(values::StructDefinition { - members: Arc::new(HashableMap::from(HashMap::from([( + members: Arc::new(HashMap::from([( "name".into(), values::StructMember { ty: ValueType::TypeNone, default: Some(Value::ValueNone(values::ValueNone)) } - )]))), + )]).into_iter().collect()), variadic: true }) .into() diff --git a/interpreter/src/execution/values/closure.rs b/interpreter/src/execution/values/closure.rs index 05802bc..b44e559 100644 --- a/interpreter/src/execution/values/closure.rs +++ b/interpreter/src/execution/values/closure.rs @@ -341,8 +341,10 @@ macro_rules! build_argument_signature_list { #[macro_export] macro_rules! build_struct_definition { (variadic: $variadic:literal, ($($arg:ident: $ty:path $(= $default:expr)?),*)) => {{ + let map: std::collections::HashMap = std::collections::HashMap::from($crate::build_argument_signature_list!($($arg: $ty $(= $default)?),*)); + let converted: indexmap::IndexMap = map.into_iter().collect(); $crate::execution::values::StructDefinition { - members: std::sync::Arc::new(hashable_map::HashableMap::from(std::collections::HashMap::from($crate::build_argument_signature_list!($($arg: $ty $(= $default)?),*)))), + members: std::sync::Arc::new(converted), variadic: $variadic, } }}; @@ -633,6 +635,7 @@ mod test { values::value_type::{MissmatchedField, TypeQualificationError}, }; use hashable_map::HashableMap; + use indexmap::IndexMap; use pretty_assertions::assert_eq; #[test] @@ -647,7 +650,7 @@ mod test { data: Arc::new(UserClosureInternals { signature: Arc::new(Signature { argument_type: StructDefinition { - members: HashableMap::new().into(), + members: Arc::new(IndexMap::new()), variadic: false, }, return_type: ValueType::UnsignedInteger, diff --git a/interpreter/src/execution/values/constraint_set.rs b/interpreter/src/execution/values/constraint_set.rs index 837017b..3442b5a 100644 --- a/interpreter/src/execution/values/constraint_set.rs +++ b/interpreter/src/execution/values/constraint_set.rs @@ -19,6 +19,10 @@ use common_data_types::{Dimension, Float}; use hashable_map::{HashableMap, HashableSet}; use imstr::ImString; + +use indexmap::IndexMap; + +use crate::execution::values::dictionary::ArgumentName; use selen::api::{add, div, eq, float, ge, gt, le, lt, mul, ne, sub, ExprBuilder, Model, VarId}; use crate::{ @@ -629,11 +633,11 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { let callable = BuiltFunction { signature: Arc::new(Signature { argument_type: StructDefinition { - members: Arc::new(HashableMap::from(HashMap::new())), + members: Arc::new(IndexMap::new()), variadic: true, }, return_type: ValueType::Dictionary(StructDefinition { - members: Arc::new(HashableMap::new()), + members: Arc::new(IndexMap::new()), variadic: true, }), }), diff --git a/interpreter/src/execution/values/dictionary.rs b/interpreter/src/execution/values/dictionary.rs index 22ef3fa..f515f9c 100644 --- a/interpreter/src/execution/values/dictionary.rs +++ b/interpreter/src/execution/values/dictionary.rs @@ -20,6 +20,8 @@ use std::{borrow::Cow, collections::HashMap, fmt::Display, sync::Arc}; use hashable_map::HashableMap; use imstr::ImString; + +use indexmap::IndexMap; use rayon::prelude::*; use crate::{ @@ -40,18 +42,48 @@ use super::{ MissingAttributeError, Object, StaticTypeName, StructDefinition, StructMember, Value, ValueType, }; -#[derive(Clone, Debug, Eq)] -pub(crate) struct DictionaryData { - pub members: HashableMap, - pub struct_def: StructDefinition, +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum ArgumentName { + Positional(usize), + Named(ImString), +} + +impl Display for ArgumentName { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ArgumentName::Positional(n) => write!(f, "{}", n), + ArgumentName::Named(name) => write!(f, "{}", name), + } + } } -impl PartialEq for DictionaryData { - fn eq(&self, other: &Self) -> bool { - self.members == other.members +impl std::borrow::Borrow for ArgumentName { + fn borrow(&self) -> &str { + match self { + ArgumentName::Named(name) => name.as_str(), + ArgumentName::Positional(_) => "", + } } } +impl From<&str> for ArgumentName { + fn from(s: &str) -> Self { + ArgumentName::Named(s.into()) + } +} + +impl From for ArgumentName { + fn from(s: String) -> Self { + ArgumentName::Named(s.into()) + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub(crate) struct DictionaryData { + pub members: IndexMap, + pub struct_def: StructDefinition, +} + pub fn find_all_variable_accesses_in_dictionary_construction( dictionary_construction: &crate::compile::DictionaryConstruction, access_collector: &mut dyn FnMut(&AstNode) -> ExecutionResult<()>, @@ -120,9 +152,9 @@ impl StaticTypeName for Dictionary { impl StaticType for Dictionary { fn static_type() -> ValueType { - static TYPE: std::sync::OnceLock>> = + static TYPE: std::sync::OnceLock>> = std::sync::OnceLock::new(); - let signature = TYPE.get_or_init(|| Arc::new(HashableMap::new())); + let signature = TYPE.get_or_init(|| Arc::new(IndexMap::new())); ValueType::Dictionary(StructDefinition { members: signature.clone(), variadic: true, @@ -200,11 +232,10 @@ impl Dictionary { struct_members.insert(name.clone(), member); } - // HashableMap is just a wrapper around HashMap, so this has no additional cost. let data = Arc::new(DictionaryData { - members: HashableMap::from(map), + members: map.into_iter().collect(), struct_def: StructDefinition { - members: Arc::new(HashableMap::from(struct_members)), + members: Arc::new(struct_members.into_iter().collect()), variadic: false, }, }); @@ -247,18 +278,24 @@ mod test { fn build_dictionary() { let product = test_run("(none = std.consts.None)").unwrap(); let expected = Arc::new(DictionaryData { - members: HashableMap::from(HashMap::from_iter([( - "none".into(), - values::ValueNone.into(), - )])), - struct_def: StructDefinition { - members: Arc::new(HashableMap::from(HashMap::from([( + members: { + let map: HashMap = HashMap::from_iter([( "none".into(), - StructMember { - ty: ValueType::TypeNone, - default: None, - }, - )]))), + values::ValueNone.into(), + )]); + map.into_iter().collect() + }, + struct_def: StructDefinition { + members: Arc::new({ + let map: HashMap = HashMap::from_iter([( + "none".into(), + StructMember { + ty: ValueType::TypeNone, + default: None, + }, + )]); + map.into_iter().collect() + }), variadic: false, }, }); @@ -295,8 +332,7 @@ mod test { assert_eq!(product, values::Boolean(true).into()); let product = - test_run("let result = \"{value}\"::format(value = (a = 1u, b = 2u)); in result == \"(a = 1, b = 2)\" || result == \"(b = 2, a = 1)\"") - .unwrap(); + test_run("let result = \"{value}\"::format(value = (a = 1u, b = 2u)); in result == \"(a = 1, b = 2)\"").unwrap(); assert_eq!(product, values::Boolean(true).into()); let product = @@ -304,4 +340,44 @@ mod test { .unwrap(); assert_eq!(product, values::Boolean(true).into()); } + + #[test] + fn argument_name_display_positional() { + assert_eq!(format!("{}", ArgumentName::Positional(0)), "0"); + assert_eq!(format!("{}", ArgumentName::Positional(3)), "3"); + } + + #[test] + fn argument_name_display_named() { + assert_eq!(format!("{}", ArgumentName::Named("foo".into())), "foo"); + } + + #[test] + fn argument_name_hash_and_eq() { + assert_eq!(ArgumentName::Positional(0), ArgumentName::Positional(0)); + assert_eq!(ArgumentName::Named("a".into()), ArgumentName::Named("a".into())); + assert_ne!(ArgumentName::Positional(0), ArgumentName::Named("0".into())); + } + + #[test] + fn dictionary_insert_positional_key() { + let mut map: IndexMap = IndexMap::new(); + map.insert(ArgumentName::Positional(0), values::UnsignedInteger::from(1).into()); + map.insert(ArgumentName::Positional(1), values::UnsignedInteger::from(2).into()); + let keys: Vec<_> = map.keys().collect(); + assert_eq!(keys[0], &ArgumentName::Positional(0)); + assert_eq!(keys[1], &ArgumentName::Positional(1)); + } + + #[test] + fn dictionary_insert_mixed_keys() { + let mut map: IndexMap = IndexMap::new(); + map.insert(ArgumentName::Positional(0), values::UnsignedInteger::from(1).into()); + map.insert(ArgumentName::Positional(1), values::UnsignedInteger::from(2).into()); + map.insert(ArgumentName::Named("b".into()), values::UnsignedInteger::from(3).into()); + let keys: Vec<_> = map.keys().collect(); + assert_eq!(keys[0], &ArgumentName::Positional(0)); + assert_eq!(keys[1], &ArgumentName::Positional(1)); + assert_eq!(keys[2], &ArgumentName::Named("b".into())); + } } diff --git a/interpreter/src/execution/values/string/mod.rs b/interpreter/src/execution/values/string/mod.rs index 448b67b..af9be1b 100644 --- a/interpreter/src/execution/values/string/mod.rs +++ b/interpreter/src/execution/values/string/mod.rs @@ -20,6 +20,8 @@ use common_data_types::{Dimension, Float}; use hashable_map::HashableMap; use imstr::ImString; +use indexmap::IndexMap; + use crate::{ build_closure_type, build_method, execution::{ @@ -259,7 +261,7 @@ fn register_format_method(database: &mut BuiltinCallableDatabase) { let callable = BuiltFunction { signature: Arc::new(Signature { argument_type: StructDefinition { - members: Arc::new(HashableMap::from(HashMap::new())), + members: Arc::new(IndexMap::new()), variadic: true, }, return_type: ValueType::String, diff --git a/interpreter/src/execution/values/value_type.rs b/interpreter/src/execution/values/value_type.rs index 02f0170..9d23bca 100644 --- a/interpreter/src/execution/values/value_type.rs +++ b/interpreter/src/execution/values/value_type.rs @@ -18,9 +18,11 @@ use std::{borrow::Cow, collections::HashMap, fmt::Display, sync::Arc}; use common_data_types::Dimension; -use hashable_map::{HashableMap, HashableSet}; +use hashable_map::HashableSet; use imstr::ImString; +use indexmap::IndexMap; + use super::{ closure::Signature as ClosureSignature, Boolean, Object, SignedInteger, StaticTypeName, UnsignedInteger, Value, ValueNone, @@ -345,7 +347,7 @@ impl Display for StructMember { #[derive(Debug, Clone, Eq, PartialEq)] pub struct StructDefinition { - pub members: Arc>, + pub members: Arc>, pub variadic: bool, } @@ -360,7 +362,7 @@ impl StructDefinition { members.insert(name, StructMember::new(context, member)?); } - let members = Arc::new(HashableMap::from(members)); + let members = Arc::new(members.into_iter().collect()); let variadic = source.node.variadic; Ok(Self { members, variadic }) } @@ -368,7 +370,7 @@ impl StructDefinition { pub fn fill_defaults(&self, dictionary: Dictionary) -> Dictionary { let data = Arc::unwrap_or_clone(dictionary.data); - let mut members: HashableMap = data.members; + let mut members: IndexMap = data.members; let struct_def_variadic = data.struct_def.variadic; let mut struct_def_members = Arc::unwrap_or_clone(data.struct_def.members); @@ -486,7 +488,7 @@ impl StaticTypeName for StructDefinition { impl From> for StructDefinition { fn from(map: HashMap) -> Self { Self { - members: Arc::new(HashableMap::from(map)), + members: Arc::new(map.into_iter().collect()), variadic: false, } } From b1daabd24c2a68b43958b071a18b6570ca2cdbde Mon Sep 17 00:00:00 2001 From: James Carl Date: Wed, 3 Jun 2026 22:08:15 -0400 Subject: [PATCH 58/71] Implement positional arguments --- .opencode/plans/positional-arguments.md | 999 +++ Cargo.lock | 1 + gui/src/main.rs | 40 +- interpreter/src/compile/expressions.rs | 154 +- interpreter/src/execution/mod.rs | 18 +- .../src/execution/standard_environment.rs | 2 +- interpreter/src/execution/values/closure.rs | 236 +- .../src/execution/values/constraint_set.rs | 4 +- .../src/execution/values/dictionary.rs | 92 +- interpreter/src/execution/values/iterators.rs | 27 +- interpreter/src/execution/values/list.rs | 2 +- interpreter/src/execution/values/polygon.rs | 27 +- .../src/execution/values/string/formatting.rs | 6 +- .../src/execution/values/string/mod.rs | 2 +- .../src/execution/values/value_type.rs | 176 +- interpreter/src/execution/values/vector.rs | 4 +- tree-sitter-command-cad-model/grammar.js | 24 +- .../src/grammar.json | 86 +- .../src/node-types.json | 44 +- tree-sitter-command-cad-model/src/parser.c | 6765 +++++++++-------- .../test/corpus/closure.txt | 222 +- .../test/corpus/dictionary_construction.txt | 142 +- 22 files changed, 5554 insertions(+), 3519 deletions(-) create mode 100644 .opencode/plans/positional-arguments.md diff --git a/.opencode/plans/positional-arguments.md b/.opencode/plans/positional-arguments.md new file mode 100644 index 0000000..a0ee285 --- /dev/null +++ b/.opencode/plans/positional-arguments.md @@ -0,0 +1,999 @@ +# Plan: Positional Arguments for Function/Method Calls + +## Design Decisions (Confirmed) + +- Positional args allowed in **both** function calls and method calls +- **Mixed** positional + named allowed, positional must come first +- Use `indexmap` (not `ordered-hash-map`) +- Use `ArgumentName` enum for dictionary keys instead of `ImString` directly + +## Current Status: ALL STEPS COMPLETE — All 437 Tests Passing + +### Completed Steps +- **Step 1**: Runtime dictionary switched to `IndexMap` with `ArgumentName` enum. Fixed ordering bug by using `IndexMap` instead of `HashMap` in `Dictionary::from_ast`. Made `Dictionary::new` generic over key type via `K: Into`. +- **Step 2**: Grammar updated with `dictionary_argument` rule supporting positional and named args. Tree-sitter test corpus updated. Parser regenerated successfully (75/75 tests pass). +- **Step 3**: AST compilation updated. `DictionaryMemberAssignment.name` changed from `AstNode` to `ArgumentName`. `DependentOperation::name()` return type updated. `sort_and_group_dependencies` handles `ArgumentName` correctly. +- **Step 4**: Argument matching implemented. `check_other_qualifies` and `fill_defaults` now match positional args by index and named args by name. `UserClosure::call` renames positional args using signature member names. Fixed non-deterministic ordering in `StructDefinition::new` and `build_struct_definition!` macros by using `IndexMap` instead of `HashMap`. +- **Step 5**: Builtin function macro updates complete. `fill_defaults` now renames positional keys to named keys based on parameter order, allowing the existing `build_function_callable!` macro extraction (which uses `ArgumentName::Named(name)`) to work for both named and positional args. +- **Step 6**: Full integration test complete. All 437 tests pass across all workspace crates. No regressions. Backwards compatibility verified. + +### Completed Steps +- **Step 1**: Runtime dictionary switched to `IndexMap` with `ArgumentName` enum. Fixed ordering bug by using `IndexMap` instead of `HashMap` in `Dictionary::from_ast`. Made `Dictionary::new` generic over key type via `K: Into`. +- **Step 2**: Grammar updated with `dictionary_argument` rule supporting positional and named args. Tree-sitter test corpus updated. Parser regenerated successfully (75/75 tests pass). +- **Step 3**: AST compilation updated. `DictionaryMemberAssignment.name` changed from `AstNode` to `ArgumentName`. `DependentOperation::name()` return type updated. `sort_and_group_dependencies` handles `ArgumentName` correctly. +- **Step 4**: Argument matching implemented. `check_other_qualifies` and `fill_defaults` now match positional args by index and named args by name. `UserClosure::call` renames positional args using signature member names. Fixed non-deterministic ordering in `StructDefinition::new` and `build_struct_definition!` macros by using `IndexMap` instead of `HashMap`. +- **Step 5**: Builtin function macro updates complete. `fill_defaults` now renames positional keys to named keys based on parameter order, allowing the existing `build_function_callable!` macro extraction (which uses `ArgumentName::Named(name)`) to work for both named and positional args. + +### Key Implementation Details +- `Dictionary::from_ast` uses `IndexMap` (not `HashMap`) to preserve insertion order — critical for deterministic dictionary formatting +- `Dictionary::new` is generic: `pub fn new(context, map: I) where I: IntoIterator, K: Into` — accepts any collection convertible to `(ArgumentName, Value)` pairs +- `build_function_callable!` macro extracts args using `ArgumentName::Named(stringify!(arg).into())` keys — works for both named and positional args after Step 5 renaming +- `ArgumentName` implements `Borrow` for lookups, `From<&str>`, `From`, `From` +- `StructDefinition::new` uses `IndexMap` directly (not `HashMap`) to preserve parameter order from source +- `build_struct_definition!` macro uses array → IndexMap conversion (not HashMap → IndexMap) to preserve order +- `find_arg_key` helper matches expected params by position first, then by name +- `UserClosure::call` renames positional args using signature member names before building variable map +- **Step 5 key insight**: `fill_defaults` now renames positional keys (`Positional(N)`) to named keys (`Named(param_name)`) based on parameter order. This allows the builtin function macro to always look up by name, regardless of whether the caller passed positional or named args. + +--- + +## Step 1: Runtime Dictionary — Ordered Map (indexmap) + +### New Type: `ArgumentName` Enum + +Add this type (in `dictionary.rs` or a shared module): + +```rust +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum ArgumentName { + Positional(usize), + Named(ImString), +} + +impl Display for ArgumentName { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ArgumentName::Positional(n) => write!(f, "{}", n), + ArgumentName::Named(name) => write!(f, "{}", name), + } + } +} +``` + +This replaces `ImString` as the dictionary key type everywhere. User-facing dictionary members use `ArgumentName::Named(ImString)`. Positional function call args use `ArgumentName::Positional(usize)`. + +### Scope + +Only switch the dictionary-related `HashableMap` usages. `HashableSet` stays unchanged (used for compile-time dependency tracking in expressions and constraint set variables). + +### Files to Modify + +| File | What Changes | +|------|-------------| +| `interpreter/Cargo.toml` | Add `indexmap = "2"` with serde feature | +| `interpreter/src/execution/values/dictionary.rs` | Add `ArgumentName` enum, switch storage, `StaticType::static_type()`, tests | +| `interpreter/src/execution/values/value_type.rs` | `StructDefinition.members`, `fill_defaults()`, `From` impl | +| `interpreter/src/execution/values/closure.rs` | `UserClosureInternals.captured_values`, `build_struct_definition!` macro | +| `interpreter/src/execution/values/constraint_set.rs` | `captured_values` field | +| `interpreter/src/execution/values/string/mod.rs` | String formatting helper | +| `interpreter/src/execution/mod.rs` | Test code (line 723, 759) | + +### Detailed Changes + +**0. Add `ArgumentName` enum (`dictionary.rs`)** + +```rust +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum ArgumentName { + Positional(usize), + Named(ImString), +} + +impl Display for ArgumentName { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ArgumentName::Positional(n) => write!(f, "{}", n), + ArgumentName::Named(name) => write!(f, "{}", name), + } + } +} +``` + +**1. `interpreter/Cargo.toml`** — Add dependency: +```toml +indexmap = { version = "2", features = ["serde"] } +``` + +**2. `dictionary.rs`** — Core changes: +- Replace `use hashable_map::HashableMap` → `use indexmap::IndexMap` +- Add `ArgumentName` enum (see above) +- `DictionaryData.members`: `HashableMap` → `IndexMap` +- Remove `impl PartialEq for DictionaryData` (derive it) — `IndexMap` already implements `Eq` by insertion order +- Add manual `impl Hash for DictionaryData` — hash each `(key, hash(value))` pair in order +- `StaticType::static_type()`: change `HashableMap` → `IndexMap` +- `Dictionary::new()`: `HashableMap::from(map)` → `IndexMap::from(map)` (IndexMap supports `From`); update map type to `HashMap` +- `Dictionary::new()`: `HashableMap::from(struct_members)` → `IndexMap::from(struct_members)` +- `Dictionary::get_attribute()` — takes `&str`, wraps in `ArgumentName::Named(attribute.into())` for lookup +- `Dictionary::get()` — same pattern, wrap in `ArgumentName::Named` +- `Dictionary::iter()` — returns `(&ArgumentName, &Value)` pairs; update format to handle both variants +- Update test assertions: `HashableMap::from(HashMap::from(...))` → `IndexMap::from(HashMap::from(...))`; change literal keys from `"none".into()` to `ArgumentName::Named("none".into())` + +**3. `value_type.rs`** — Struct definition changes: +- Add `use crate::execution::values::dictionary::ArgumentName;` (or define locally) +- Replace `use hashable_map::{HashableMap, HashableSet}` → `use hashable_map::HashableSet; use indexmap::IndexMap` +- `StructDefinition.members`: `Arc>` → `Arc>` +- `StructDefinition::new()`: `HashableMap::from(members)` → `IndexMap::from(members)` +- `fill_defaults()`: `HashableMap` → `IndexMap`; update lookup to use `ArgumentName::Named(name)` +- `From>` impl: change to `From>`; `HashableMap::from(map)` → `IndexMap::from(map)` + +**4. `closure.rs`** — Closure captured values: +- Add `use crate::execution::values::dictionary::ArgumentName;` +- Replace `use hashable_map::HashableMap` → `use indexmap::IndexMap` +- `UserClosureInternals.captured_values`: `HashableMap` → `IndexMap` +- `UserClosure::from_ast()`: `HashableMap::new()` → `IndexMap::new()`; update captured values to use `ArgumentName::Named` +- `build_struct_definition!` macro: `hashable_map::HashableMap::from(std::collections::HashMap::from(...))` → `indexmap::IndexMap::from(std::collections::HashMap::from(...))`; wrap keys in `ArgumentName::Named` +- Test code: update `HashableMap` references to `IndexMap`; change literal keys + +**5. `constraint_set.rs`** — Captured values: +- Add `use crate::execution::values::dictionary::ArgumentName;` +- Replace `use hashable_map::{HashableMap, HashableSet}` → `use hashable_map::HashableSet; use indexmap::IndexMap` +- `captured_values` field: `&HashableMap` → `&IndexMap` +- `ConstraintSetInternals.captured_values`: `Arc>` → `Arc>` +- `Arc::new(HashableMap::from(captured_values))` → `Arc::new(IndexMap::from(captured_values))` +- Test code: update `HashableMap` references to `IndexMap`; change literal keys + +**6. `string/mod.rs`** — String formatting: +- Add `use crate::execution::values::dictionary::ArgumentName;` +- Replace `use hashable_map::HashableMap` → `use indexmap::IndexMap` +- `Arc::new(HashableMap::from(HashMap::new()))` → `Arc::new(IndexMap::from(HashMap::new()))` + +**7. `execution/mod.rs`** — Test code: +- Add `use crate::execution::values::dictionary::ArgumentName;` +- Replace `use hashable_map::HashableMap` → `use indexmap::IndexMap` +- Line 759: `HashableMap::from(HashMap::from(...))` → `IndexMap::from(HashMap::from(...))`; change literal keys to `ArgumentName::Named(...)` + +### Key Behavioral Differences + +1. **`Eq` is now order-sensitive** — `IndexMap::eq` compares in insertion order. This is actually desired for dictionaries (we want `(a=1, b=2) == (a=1, b=2)` to be deterministic). + +2. **No more non-deterministic formatting** — The test at `dictionary.rs:298` that allows `(a = 1, b = 2) \|\| (b = 2, a = 1)` can be simplified to just check one order since insertion order is now preserved. + +3. **`Hash` must be implemented manually** — `IndexMap` doesn't implement `Hash`. We implement it for `DictionaryData` by hashing `(key, hash(value))` pairs in order. + +4. **`ArgumentName` enum replaces `ImString`** — All dictionary lookups go through the enum. `get_attribute("name")` wraps in `ArgumentName::Named`. Positional args use `ArgumentName::Positional(n)`. The `Display` impl formats both variants for output. + +### Testing + +Run after making all changes to Step 1: + +```bash +# Compile check first — catches import/type errors quickly +cargo check -p interpreter + +# Run all interpreter tests (single-threaded to avoid flaky ordering issues) +cargo test -p interpreter -- --test-threads=1 +``` + +**What to look for:** +- All existing tests should pass unchanged (this is a purely internal change — no syntax or behavior changes) +- The formatting test at `dictionary.rs:298` may need updating: the assertion `result == "(a = 1, b = 2)" || result == "(b = 2, a = 1)"` can be simplified to just `result == "(a = 1, b = 2)"` since insertion order is now deterministic +- If any test fails with a type error about `HashableMap` vs `IndexMap` or `ImString` vs `ArgumentName`, verify you updated all 7 files + +**Write tests as you go** — add these to `interpreter/src/execution/values/dictionary.rs` (in the `mod test` block) to verify the new `ArgumentName` enum and `IndexMap` storage: + +```rust +#[test] +fn argument_name_display_positional() { + assert_eq!(format!("{}", ArgumentName::Positional(0)), "0"); + assert_eq!(format!("{}", ArgumentName::Positional(3)), "3"); +} + +#[test] +fn argument_name_display_named() { + assert_eq!(format!("{}", ArgumentName::Named("foo".into())), "foo"); +} + +#[test] +fn argument_name_hash_and_eq() { + // Same variants should hash and compare equal + assert_eq!(ArgumentName::Positional(0), ArgumentName::Positional(0)); + assert_eq!(ArgumentName::Named("a".into()), ArgumentName::Named("a".into())); + // Different variants should never be equal + assert_ne!(ArgumentName::Positional(0), ArgumentName::Named("0".into())); +} + +#[test] +fn dictionary_insert_positional_key() { + // Verify IndexMap stores positional keys in order + let mut map = IndexMap::new(); + map.insert(ArgumentName::Positional(0), Value::ValueUnsignedInteger(...)); + map.insert(ArgumentName::Positional(1), Value::ValueUnsignedInteger(...)); + // Iteration should yield index 0 before index 1 +} + +#[test] +fn dictionary_insert_mixed_keys() { + // Positional keys followed by named keys should preserve insertion order + let mut map = IndexMap::new(); + map.insert(ArgumentName::Positional(0), ...); + map.insert(ArgumentName::Positional(1), ...); + map.insert(ArgumentName::Named("b".into()), ...); + // Iteration should yield: 0, 1, "b" +} + +#[test] +fn dictionary_get_attribute_wraps_in_named() { + // get_attribute("name") should look up ArgumentName::Named("name") + let dict = test_run("(a = 1u)").unwrap(); + let val = dict.as_dictionary().unwrap().get_attribute(&context, "a").unwrap(); +} +``` + +If all tests pass, proceed to Step 2. + +--- + +## Step 2: Tree-sitter Grammar + Tests + +### Grammar Changes (`tree-sitter-command-cad-model/grammar.js`) + +Replace `dictionary_construction` and `dictionary_member_assignment` with: + +```javascript +dictionary_argument: $ => choice( + seq(field('name', $.identifier), '=', field('value', $.expression)), + field('value', $.expression) +), +dictionary_construction: $ => seq('(', + field('arguments', + optional(seq( + $.dictionary_argument, + repeat(seq(',', $.dictionary_argument)), + optional(',') + )) + ), + ')' +), +``` + +This changes the parse tree from `dictionary_member_assignment` nodes to `dictionary_argument` nodes. + +### Regenerate Parser + +```bash +cd tree-sitter-command-cad-model && make +``` + +### AST Regeneration + +Run `cargo check -p interpreter` — `build.rs` will regenerate AST types from `node-types.json`. New types: +- `DictionaryArgument` — choice of named or positional, with `name` and `value` fields (name is `null` for positional) + +### Compilation: `DictionaryMemberAssignment` → `ArgumentName` + +The `Parse` impl for `DictionaryConstruction` (lines 892-930) needs to transform the two AST kinds into a unified representation: + +```rust +// DictionaryMemberAssignment has: name: ImString, assignment: Expression, dependencies: HashableSet +// DictionaryArgument has: name?: ImString, value: Expression + +// During compilation, produce DictionaryMemberAssignment with ArgumentName keys: +pub struct DictionaryMemberAssignment { + pub index: usize, + pub dependencies: HashableSet, // still ImString — source variable names + pub name: ArgumentName, // NEW: ArgumentName instead of ImString + pub assignment: AstNode, +} +``` + +The `DependentOperation::name()` method returns `&ArgumentName`. In `sort_and_group_dependencies`, the dependency matching works as follows: +- Named assignments: `name` is `ArgumentName::Named(ImString)`, dependencies contain `ImString` keys that match against `ArgumentName::Named` variants +- Positional assignments: `name` is `ArgumentName::Positional(usize)`, dependencies are always empty (no expression can reference `Positional(n)`) + +In practice, the dependency check in `sort_and_group_dependencies` compares dependency sets — if two adjacent assignments have different dependency sets, they go in different groups. Since positional args always have empty dependency sets, they naturally group together at the start. + +### Test Cases to Add to `tree-sitter-command-cad-model/test/corpus/dictionary_construction.txt` + +``` +================== +Positional One +================== + +(1) + +--- + +(source_file + (expression + (dictionary_construction + (dictionary_argument + (expression + (integer)))))) + +================== +Positional Two +================== + +(1, 2) + +--- + +(source_file + (expression + (dictionary_construction + (dictionary_argument + (expression + (integer))) + (dictionary_argument + (expression + (integer)))))) + +================== +Positional Trailing Comma +================== + +(1, 2,) + +--- + +(source_file + (expression + (dictionary_construction + (dictionary_argument + (expression + (integer))) + (dictionary_argument + (expression + (integer)))))) + +================== +Mixed Positional and Named +================== + +(1, b = 2) + +--- + +(source_file + (expression + (dictionary_construction + (dictionary_argument + (expression + (integer))) + (dictionary_argument + (name (identifier)) + (expression + (integer)))))) + +================== +Mixed Three Positional Two Named +================== + +(1, 2, c = 3, d = 4) + +--- + +(source_file + (expression + (dictionary_construction + (dictionary_argument + (expression + (integer))) + (dictionary_argument + (expression + (integer))) + (dictionary_argument + (name (identifier)) + (expression + (integer))) + (dictionary_argument + (name (identifier)) + (expression + (integer)))))) + +================== +Mixed Trailing Comma +================== + +(1, b = 2,) + +--- + +(source_file + (expression + (dictionary_construction + (dictionary_argument + (expression + (integer))) + (dictionary_argument + (name (identifier)) + (expression + (integer)))))) + +================== +Named Then Positional Error +================== + +(b = 1, 2) + +--- + +# This should be a syntax error — named argument followed by positional +(source_file + (ERROR + (identifier) + (integer))) +``` + +### Test Cases to Add to `tree-sitter-command-cad-model/test/corpus/closure.txt` + +``` +================== +Call function positional +================== + +value(1, 2, 3) + +--- + +(source_file + (expression + (function_call + (expression + (identifier)) + (dictionary_construction + (dictionary_argument + (expression + (integer))) + (dictionary_argument + (expression + (integer))) + (dictionary_argument + (expression + (integer))))))) + +================== +Call function mixed +================== + +value(1, b = 2, c = 3) + +--- + +(source_file + (expression + (function_call + (expression + (identifier)) + (dictionary_construction + (dictionary_argument + (expression + (integer))) + (dictionary_argument + (name (identifier)) + (expression + (integer))) + (dictionary_argument + (name (identifier)) + (expression + (integer))))))) + +================== +Call method positional +================== + +value::value(1, 2) + +--- + +(source_file + (expression + (method_call + (expression + (identifier)) + (identifier) + (dictionary_construction + (dictionary_argument + (expression + (integer))) + (dictionary_argument + (expression + (integer))))))) + +================== +Call method mixed +================== + +value::value(1, b = 2) + +--- + +(source_file + (expression + (method_call + (expression + (identifier)) + (identifier) + (dictionary_construction + (dictionary_argument + (expression + (integer))) + (dictionary_argument + (name (identifier)) + (expression + (integer))))))) + +================== +Call function complex expressions +================== + +value(a + b, c * d) + +--- + +(source_file + (expression + (function_call + (expression + (identifier)) + (dictionary_construction + (dictionary_argument + (expression + (binary_expression + (expression + (identifier)) + (expression + (identifier))))) + (dictionary_argument + (expression + (binary_expression + (expression + (identifier)) + (expression + (identifier))))))))) + +================== +Call method complex expressions +================== + +obj::method(a + b, c = d * e) + +--- + +(source_file + (expression + (method_call + (expression + (identifier)) + (identifier) + (dictionary_construction + (dictionary_argument + (expression + (binary_expression + (expression + (identifier)) + (expression + (identifier))))) + (dictionary_argument + (name (identifier)) + (expression + (binary_expression + (expression + (identifier)) + (expression + (identifier))))))))) + +================== +Call function nested dictionary positional +================== + +func((a = 1, b = 2)) + +--- + +(source_file + (expression + (function_call + (expression + (identifier)) + (dictionary_construction + (dictionary_argument + (expression + (dictionary_construction + (dictionary_argument + (name (identifier)) + (expression + (integer))) + (dictionary_argument + (name (identifier)) + (expression + (integer)))))))))) +``` + +### Testing + +Run after making grammar changes, adding test cases, and regenerating the parser: + +```bash +cd tree-sitter-command-cad-model && tree-sitter generate && tree-sitter test +``` + +**What to look for:** +- All original test cases should still pass (named-only args are unchanged) +- All new test cases should pass +- The "Named Then Positional Error" case should produce an `ERROR` node in the parse tree + +If all tests pass, proceed to Step 3. + +--- + +## Step 3: AST Compilation — Unified Argument Representation + +### Update `DictionaryMemberAssignment` (`interpreter/src/compile/expressions.rs`) + +Change `name` field from `AstNode` to `ArgumentName`: + +```rust +pub struct DictionaryMemberAssignment { + pub index: usize, + pub dependencies: HashableSet, + pub name: ArgumentName, // CHANGED: ArgumentName instead of ImString + pub assignment: AstNode, +} +``` + +### Update `DependentOperation::name()` return type + +```rust +trait DependentOperation { + fn original_index(&self) -> usize; + fn name(&self) -> &ArgumentName; // CHANGED: ArgumentName instead of ImString + fn dependencies(&self) -> &HashableSet; +} +``` + +The dependency comparison in `sort_and_group_dependencies` works by checking if assignment A's dependency set contains the name of assignment B. Since dependencies are still `HashableSet` (source variable names), and `name()` now returns `&ArgumentName`, we need to match: + +```rust +// In sort_and_group_dependencies, when checking if a depends on b: +if a.dependencies().contains(b_name) && ... +``` + +Where `b_name` is now `&ImString` extracted from `ArgumentName::Named(b_name)` when comparing. Since positional args have empty dependency sets, they naturally sort to the front and group together. + +### Compilation Logic (lines 892-930) + +During compilation, transform `dictionary_argument` AST nodes into `DictionaryMemberAssignment` with `ArgumentName`: + +```rust +for assignment in assignments_iter { + if let Some(named) = assignment.as_dictionary_member_assignment() { + // Named arg: name = expr + let arg_name = ArgumentName::Named(named.node.name.node.clone()); + // ... process with ArgumentName::Named key + } else if let Some(positional) = assignment.as_dictionary_argument_positional() { + // Positional arg: bare expression + let arg_name = ArgumentName::Positional(index); + // ... process with ArgumentName::Positional key, empty dependencies + } +} +``` + +The `DictionaryConstruction` struct stays the same (single `assignments` vec) — no need for separate `positional`/`named` vectors since `ArgumentName` unifies them. + +### Testing + +Run after making changes: + +```bash +cargo check -p interpreter +``` + +**What to look for:** +- No compile errors — the regenerated AST types from Step 2 should match the new struct fields +- If `build.rs` didn't regenerate properly, run `cargo check -p interpreter` again or manually trigger regeneration + +**Write tests as you go** — add these test cases to `interpreter/src/execution/values/dictionary.rs` (in the `mod test` block) after the existing tests: + +```rust +#[test] +fn dictionary_construction_positional_only() { + // All positional args — no names + let dict = test_run("(1u, 2u, 3u)").unwrap(); + // Verify the dictionary was built with ArgumentName::Positional keys +} + +#[test] +fn dictionary_construction_named_only() { + // Named args still work as before + let dict = test_run("(a = 1u, b = 2u)").unwrap(); +} + +#[test] +fn dictionary_construction_mixed() { + // Mixed positional and named + let dict = test_run("(1u, b = 2u)").unwrap(); +} + +#[test] +fn dictionary_construction_compute_groups_with_positional() { + // Self-reference in a mixed dictionary tests compute groups: + // positional arg has no deps → group 1 + // named arg 'b' references 'a' (named) → group 2 + let val = test_run("(1u, b = a + 1u)").unwrap(); +} + +#[test] +fn dictionary_construction_compute_groups_all_positional() { + // All positional, no self-references — should all be in one group (parallel) + let val = test_run("(1u, 2u, 3u)").unwrap(); +} + +#[test] +fn dictionary_construction_compute_groups_positional_then_named_depends_on_positional() { + // Named arg references a positional arg by its synthetic name: + // (1u, b = __0 + 1u) — but __0 is not a valid source variable name, + // so this should work: positional args have empty dependency sets, + // named args can reference earlier members by their real names. + // Test that compute groups handle mixed dependency sets correctly. +} +``` + +If `cargo check` passes, proceed to Step 4. + +--- + +## Step 4: Argument Matching — Positional + Named Resolution (COMPLETE) + +### Implementation Summary + +**`find_arg_key` helper** (`value_type.rs`): +```rust +fn find_arg_key(&self, members: &IndexMap, idx: usize, name: &ArgumentName) -> Option +``` +- For expected param at index N with name: + 1. First tries to find by name: `members.get(&ArgumentName::Named(name))` + 2. Then tries to find by position: `members.get(&ArgumentName::Positional(N))` + 3. Returns the key if found, `None` otherwise + +**`check_other_qualifies`** (`value_type.rs`): +- Iterates over expected params with their indices +- Uses `find_arg_key` to find matching arg in actual args +- Tracks matched keys to detect extra fields +- Reports errors for missing required params and type mismatches + +**`fill_defaults`** (`value_type.rs`): +- Uses same matching logic as `check_other_qualifies` +- Fills missing params with defaults from signature + +**`UserClosure::call`** (`closure.rs`): +- After `check_other_qualifies` and `fill_defaults`, renames positional args +- Uses signature's member names to convert `Positional(N)` → `Named(name)` +- Builds variable map with all args as named keys + +**Fixed non-deterministic ordering bugs**: +- `StructDefinition::new`: Changed from `HashMap` → `IndexMap` to preserve parameter order +- `build_struct_definition!` macro: Changed from `HashMap::from(array)` → `array.into_iter().collect()` to preserve order + +### Tests Added +- `positional_args_match_by_index` — basic positional arg matching +- `positional_args_with_defaults` — positional args with default values +- `mixed_positional_named_args` — positional first, then named +- `mixed_positional_named_args_reversed` — positional, then named in different order +- `closure_call_all_positional` — closure called with all positional args +- `closure_call_mixed_args` — closure called with mixed args + +--- + +## Step 5: Builtin Function Macro Updates + +### Update `check_other_qualifies` (`interpreter/src/execution/values/value_type.rs`, lines 395-444) + +Current: purely name-based lookup using `ArgumentName::Named`. New logic: +1. First N positional args match first N expected parameters by position (type check) +2. Named args fill remaining parameters by name +3. Reject duplicates (positional arg index conflicts with named arg name) +4. Reject missing required parameters +5. If NOT variadic, reject extra parameters + +```rust +pub fn check_other_qualifies(&self, other: &StructDefinition) -> Result<(), TypeQualificationError> { + let mut errors = Vec::new(); + + // Match positional args by index to expected params + for (pos, member) in self.members.iter().enumerate() { + if let ArgumentName::Positional(p) = pos_name { + // This is a positional arg — match to expected param at index p + // ... + } else if let ArgumentName::Named(name) = arg_name { + // Named arg — look up by name + // ... + } + } +} +``` + +### Update `Dictionary::from_ast` (`interpreter/src/execution/values/dictionary.rs`, lines 138-189) + +The argument expressions are evaluated in compute groups (unchanged). The resulting values are stored in the dictionary with `ArgumentName` keys: +- Positional args → `ArgumentName::Positional(index)` +- Named args → `ArgumentName::Named(name)` + +### Testing + +Run after making changes: + +```bash +cargo check -p interpreter && cargo test -p interpreter -- --test-threads=1 +``` + +**What to look for:** +- All existing tests should still pass (named-only calls are unaffected) +- If any test fails with a type qualification error, verify that `check_other_qualifies` correctly handles both `ArgumentName` variants + +**Write tests as you go** — add these test cases to `interpreter/src/execution/values/value_type.rs` (in the `mod test` block): + +```rust +#[test] +fn check_qualifies_positional_args() { + // Positional args should match expected params by index + let structure = test_run("(a: std.types.UInt, b: std.types.UInt)").unwrap(); + let structure = structure.as_valuetype().unwrap(); + + // Build a dictionary with positional args (via function call) + // and verify type qualification succeeds +} + +#[test] +fn check_qualifies_positional_then_named() { + // Mixed: positional fills first param, named fills second + let structure = test_run("(a: std.types.UInt, b: std.types.UInt)").unwrap(); + let structure = structure.as_valuetype().unwrap(); + + // Dictionary with ArgumentName::Positional(0) and ArgumentName::Named("b") + // should qualify against expected params a (index 0) and b (name) +} + +#[test] +fn check_qualifies_positional_missing_required() { + // Missing required positional arg should fail +} + +#[test] +fn check_qualifies_positional_index_conflicts_with_named() { + // Positional arg at index 2 conflicts with named arg "c" when signature has only 3 params + // Should produce a type qualification error +} + +#[test] +fn check_qualifies_positional_extras_not_varadic() { + // Extra positional args beyond expected count should fail unless variadic +} +``` + +If all tests pass, proceed to Step 5. + +--- + +## Step 5: Builtin Function Macro Updates (COMPLETE) + +### Implementation Summary + +**Key insight**: Instead of modifying the macro to try both named and positional lookups, we rename positional keys to named keys in `fill_defaults`. This allows the existing macro extraction (which uses `ArgumentName::Named(name)`) to work for both named and positional args. + +**`fill_defaults` update** (`value_type.rs`): +```rust +// Rename positional keys to named keys based on parameter order. +for (idx, (arg_name, _member)) in self.members.iter().enumerate() { + if let ArgumentName::Named(param_name) = arg_name { + let positional_key = ArgumentName::Positional(idx); + if members.contains_key(&positional_key) && !members.contains_key(&ArgumentName::Named(param_name.clone())) { + if let Some(value) = members.shift_remove(&positional_key) { + members.insert(ArgumentName::Named(param_name.clone()), value); + } + } + } +} +``` + +This runs before default filling, so by the time the macro extracts args, all keys are `Named`. + +**No macro changes needed** — the existing `build_function_callable!` and `build_method_callable!` macros work unchanged because they always look up by `ArgumentName::Named(name)`. + +### Tests Added (5 new tests in `closure.rs`) +- `builtin_function_positional_args` — `test_function(1u, 2u)` +- `builtin_function_mixed_args` — `test_function(1u, 2u, c = 3u)` +- `builtin_function_positional_with_default` — `test_function(5u)` with default for `b` +- `builtin_method_positional_args` — `object::test_method(10u)` +- `builtin_method_mixed_args` — `object::test_method(10u, to_mul = 2u)` + +### Testing +All 437 tests pass (432 + 5 new). No regressions. + +--- + +## Step 6: Full Integration Test + +--- + +## Step 6: Full Integration Test (COMPLETE) + +### Verification Results + +| Check | Result | +|-------|--------| +| `cargo fmt --all -- --check` | Pass — no formatting issues | +| `cargo clippy --all-features` | Pass — no errors (only pre-existing warnings) | +| `cargo test --all-features` | **437 passed, 0 failed** — all workspace tests pass | +| `cargo build --all-features` | Pass — clean build with no errors | +| `tree-sitter test` | **75/75 pass** — parser test corpus intact | +| `make` (tree-sitter) | Pass — parser regenerates cleanly | + +### Backwards Compatibility Verified + +- All 432 original tests pass unchanged — named-only calls work exactly as before +- No regressions in `cli`, `gui`, or `formatter` crates +- `std::range::UInt(start = 0u, end = 5u)` — named args still work +- `std::range::UInt(0u, 5u)` — positional args now work +- `std::range::UInt(0u, end = 5u)` — mixed args now work + +### New Tests Added (11 total) + +| Test | File | Description | +|------|------|-------------| +| `positional_args_match_by_index` | `value_type.rs` | Basic positional arg matching | +| `positional_args_with_defaults` | `value_type.rs` | Positional args with default values | +| `mixed_positional_named_args` | `value_type.rs` | Positional first, then named | +| `mixed_positional_named_args_reversed` | `value_type.rs` | Positional, then named in different order | +| `closure_call_all_positional` | `value_type.rs` | Closure called with all positional args | +| `closure_call_mixed_args` | `value_type.rs` | Closure called with mixed args | +| `builtin_function_positional_args` | `closure.rs` | Builtin function with positional args | +| `builtin_function_mixed_args` | `closure.rs` | Builtin function with mixed args | +| `builtin_function_positional_with_default` | `closure.rs` | Builtin function with positional + default | +| `builtin_method_positional_args` | `closure.rs` | Method call with positional args | +| `builtin_method_mixed_args` | `closure.rs` | Method call with mixed args | + +--- + +## Files to Modify (Complete List) + +| File | Changes | +|------|---------| +| `interpreter/Cargo.toml` | Add `indexmap` dependency | +| `interpreter/src/execution/values/dictionary.rs` | Add `ArgumentName` enum, switch to `IndexMap` | +| `interpreter/src/execution/values/value_type.rs` | `StructDefinition.members`, `fill_defaults()` | +| `interpreter/src/execution/values/closure.rs` | `UserClosureInternals.captured_values`, `build_struct_definition!` macro | +| `interpreter/src/execution/values/constraint_set.rs` | `captured_values` field | +| `interpreter/src/execution/values/string/mod.rs` | String formatting helper | +| `interpreter/src/execution/mod.rs` | Test code | +| `tree-sitter-command-cad-model/grammar.js` | New `dictionary_argument` rule, update `dictionary_construction` | +| `tree-sitter-command-cad-model/parser.c` | Regenerate via `make` | +| `tree-sitter-command-cad-model/test/corpus/dictionary_construction.txt` | Add positional/mixed arg test cases | +| `tree-sitter-command-cad-model/test/corpus/closure.txt` | Add function/method call test cases | +| `interpreter/build.rs` | May need adjustment if AST type names change | +| `interpreter/src/compile/expressions.rs` | `DictionaryMemberAssignment.name` → `ArgumentName`, update `DependentOperation` | + +--- + +## Execution Order + +1. `indexmap` dependency + dictionary storage swap + `ArgumentName` enum (all 7 files) ✅ +2. Grammar changes + test cases + parser regeneration ✅ +3. AST compilation updates (`DictionaryMemberAssignment.name` → `ArgumentName`) ✅ +4. Argument matching logic in `check_other_qualifies` ✅ +5. Builtin macro updates ✅ +6. Full integration test (`cargo test --all-features`) ✅ + +## Summary + +Positional arguments for function/method calls are now fully implemented and tested. + +**New syntax supported:** +- `func(1u, 2u, 3u)` — all positional +- `func(1u, b = 2u, c = 3u)` — mixed positional + named +- `obj::method(1u, 2u)` — method calls with positional args +- User-defined closures: `let f = (a: UInt, b: UInt) -> UInt: a + b; in f(1u, 2u)` + +**Backwards compatibility:** +- Named-only calls unchanged: `func(a = 1u, b = 2u)` +- All 432 original tests pass without modification diff --git a/Cargo.lock b/Cargo.lock index 81484f8..83bd153 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4125,6 +4125,7 @@ dependencies = [ "hashable-map", "hex", "imstr", + "indexmap", "itertools 0.14.0", "levenshtein", "nalgebra", diff --git a/gui/src/main.rs b/gui/src/main.rs index c14d163..9245c59 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -44,7 +44,9 @@ use tempfile::TempDir; use crate::{ grid::GridSettings, - visualize2d::{ViewState2d, build_fill_mesh_from_polygon, draw_grid, paint_linestring, paint_polygon}, + visualize2d::{ + ViewState2d, build_fill_mesh_from_polygon, draw_grid, paint_linestring, paint_polygon, + }, visualize3d::{ ViewState3d, orbit_camera, orbit_light, setup_3d, spawn_meshes, sync_wireframe_visibility, update_3d_camera, update_grid, @@ -52,8 +54,8 @@ use crate::{ }; mod grid; - mod visualize2d; - mod visualize3d; +mod visualize2d; +mod visualize3d; fn main() { let mut app = App::new(); @@ -70,7 +72,10 @@ fn main() { .add_plugins(EguiPlugin::default()) .add_plugins(OutlinePlugin) .add_plugins(WireframePlugin::default()) - .add_systems(Startup, (setup, setup_3d.after(setup), apply_display_scaling)) + .add_systems( + Startup, + (setup, setup_3d.after(setup), apply_display_scaling), + ) .add_systems( Update, ( @@ -149,12 +154,10 @@ fn setup(mut commands: Commands, event_loop_proxy: Res) { commands.insert_resource(GridSettings::default()); } -fn apply_display_scaling( - mut windows: Query<&mut Window>, -) { +fn apply_display_scaling(mut windows: Query<&mut Window>) { for mut window in windows.iter_mut() { let base = window.resolution.base_scale_factor(); - + eprintln!( "Window: physical={}x{}, logical={}, base_scale={}", window.physical_width(), @@ -162,7 +165,7 @@ fn apply_display_scaling( window.resolution.width(), base ); - + // Steam Deck (1280x800) with KDE Plasma on Wayland reports an extremely // high scale factor (4.5) even at "100%" display settings, because KDE // calculates high DPI from the small screen size. This makes UI elements @@ -549,7 +552,8 @@ fn render_ui( Some(Ok(JobOutput::LineString(line_string))) => { draw_thing(ctx, |ui, draw_area| { if view_state_2d.fit_to_screen_requested { - view_state_2d.fit_to_screen(&JobOutput::LineString(line_string.clone()), draw_area); + view_state_2d + .fit_to_screen(&JobOutput::LineString(line_string.clone()), draw_area); view_state_2d.fit_to_screen_requested = false; } let painter = view_state_2d.prep_for_painting(ui); @@ -573,7 +577,13 @@ fn render_ui( Some(Ok(JobOutput::Polygon { polygon, mesh })) => { draw_thing(ctx, |ui, draw_area| { if view_state_2d.fit_to_screen_requested { - view_state_2d.fit_to_screen(&JobOutput::Polygon { polygon: polygon.clone(), mesh: mesh.clone() }, draw_area); + view_state_2d.fit_to_screen( + &JobOutput::Polygon { + polygon: polygon.clone(), + mesh: mesh.clone(), + }, + draw_area, + ); view_state_2d.fit_to_screen_requested = false; } let painter = view_state_2d.prep_for_painting(ui); @@ -592,7 +602,13 @@ fn render_ui( })) => { draw_thing(ctx, |ui, draw_area| { if view_state_2d.fit_to_screen_requested { - view_state_2d.fit_to_screen(&JobOutput::PolygonSet { polygon_set: polygon_set.clone(), meshes: meshes.clone() }, draw_area); + view_state_2d.fit_to_screen( + &JobOutput::PolygonSet { + polygon_set: polygon_set.clone(), + meshes: meshes.clone(), + }, + draw_area, + ); view_state_2d.fit_to_screen_requested = false; } let painter = view_state_2d.prep_for_painting(ui); diff --git a/interpreter/src/compile/expressions.rs b/interpreter/src/compile/expressions.rs index 334d535..3fabc5b 100644 --- a/interpreter/src/compile/expressions.rs +++ b/interpreter/src/compile/expressions.rs @@ -7,7 +7,7 @@ use unwrap_enum::EnumAs; use crate::{ compile::{constraint_set::ConstraintSet, unwrap_missing, Scalar}, - execution::find_all_variable_accesses_in_expression, + execution::{find_all_variable_accesses_in_expression, values::dictionary::ArgumentName}, }; use super::{nodes, AstNode, Error, Parse}; @@ -15,7 +15,7 @@ use super::{nodes, AstNode, Error, Parse}; /// Used for sorting operations that have dependencies on other operations for parallel execution. trait DependentOperation { fn original_index(&self) -> usize; - fn name(&self) -> &ImString; + fn name(&self) -> &ArgumentName; fn dependencies(&self) -> &HashableSet; } @@ -32,16 +32,29 @@ where let a = a.dependencies(); let b = b.dependencies(); - // Dependency takes president. - if a.contains(b_name) && a_index > b_index { - Ordering::Greater - } else if b.contains(a_name) && b_index > a_index { - Ordering::Less - } else { - // If they have no dependency on each other, put the ones with fewer dependencies - // as a higher priority. - a.len().cmp(&b.len()) + // Extract ImString from ArgumentName for dependency comparison. + // Positional args have empty dependency sets, so they'll sort first naturally. + let a_name_str = match a_name { + ArgumentName::Named(s) => Some(s), + ArgumentName::Positional(_) => None, + }; + let b_name_str = match b_name { + ArgumentName::Named(s) => Some(s), + ArgumentName::Positional(_) => None, + }; + + // Only check dependencies for named arguments (positional args have empty deps). + if let (Some(b_str), Some(a_str)) = (b_name_str, a_name_str) { + if a.contains(b_str) && a_index > b_index { + return Ordering::Greater; + } else if b.contains(a_str) && b_index > a_index { + return Ordering::Less; + } } + + // If they have no dependency on each other, put the ones with fewer dependencies + // as a higher priority. + a.len().cmp(&b.len()) }); let mut compute_groups = Vec::new(); @@ -825,19 +838,33 @@ impl<'t> Parse<'t, nodes::If<'t>> for IfExpression { pub struct DictionaryMemberAssignment { pub index: usize, pub dependencies: HashableSet, - pub name: AstNode, + pub name: ArgumentName, pub assignment: AstNode, } -impl<'t> Parse<'t, nodes::DictionaryMemberAssignment<'t>> for DictionaryMemberAssignment { +impl<'t> Parse<'t, nodes::DictionaryArgument<'t>> for DictionaryMemberAssignment { fn parse<'i>( file: &Arc, input: &'i str, - value: nodes::DictionaryMemberAssignment<'t>, + value: nodes::DictionaryArgument<'t>, ) -> Result, Error<'t, 'i>> { - let name = value.name()?; - let name = ImString::parse(file, input, name)?; - let assignment = Expression::parse(file, input, value.assignment()?)?; + let key = value.key()?; + let key_expr = Expression::parse(file, input, key)?; + + // Determine if this is a named or positional argument. + // A key expression that is a bare identifier with no value = positional arg. + // A key expression that has a value = named arg (key is the name). + let (name, assignment) = if let Some(val_node) = value.value() { + // Named argument: key is the name identifier + let assignment = Expression::parse(file, input, val_node?)?; + let name = extract_name_from_key(&key_expr); + (name, assignment) + } else { + // Positional argument: no value field + let assignment = key_expr; + let name = ArgumentName::Positional(0); // index set later + (name, assignment) + }; let mut dependencies = HashableSet::new(); @@ -861,13 +888,41 @@ impl<'t> Parse<'t, nodes::DictionaryMemberAssignment<'t>> for DictionaryMemberAs } } +/// Extract an ArgumentName from a key expression. +/// If the key is a bare identifier (no value), it's positional. +/// If the key has a value, the key itself is the name. +fn extract_name_from_key(key_expr: &AstNode) -> ArgumentName { + // Check if this is a named argument by looking at the raw node. + // A named argument has both key and value fields; the key is an identifier. + // Since we can't easily check the raw node here, we use a heuristic: + // If the key expression is a bare identifier, it could be positional (no value) or named (key). + // The distinction is already made in the parse function based on value() presence. + // Here, if we're called, it means value() was Some, so this is a named arg. + // Extract the identifier from the key expression. + if let Some(ident) = extract_identifier_from_expr(&key_expr.node) { + ArgumentName::Named(ident.clone()) + } else { + // Fallback - shouldn't happen for valid named args + ArgumentName::Positional(0) + } +} + +/// Try to extract an ImString identifier from an expression AST node. +fn extract_identifier_from_expr(node: &Expression) -> Option { + // Check if this is a bare identifier expression + match node { + Expression::Identifier(ident_node) => Some(ident_node.node.clone()), + _ => None, + } +} + impl DependentOperation for AstNode { fn original_index(&self) -> usize { self.node.index } - fn name(&self) -> &ImString { - &self.node.name.node + fn name(&self) -> &ArgumentName { + &self.node.name } fn dependencies(&self) -> &HashableSet { @@ -897,7 +952,7 @@ impl<'t> Parse<'t, nodes::DictionaryConstruction<'t>> for DictionaryConstruction ) -> Result, Error<'t, 'i>> { let mut assignments = Vec::new(); let mut cursor = value.walk(); - let assignments_iter = value.assignmentss(&mut cursor); + let assignments_iter = value.argumentss(&mut cursor); let mut variable_names = HashSet::new(); let mut index = 0; @@ -906,16 +961,25 @@ impl<'t> Parse<'t, nodes::DictionaryConstruction<'t>> for DictionaryConstruction let assignment = assignment?; // Skip the commas. - if let Some(assignment) = assignment.as_dictionary_member_assignment() { + if let Some(assignment) = assignment.as_dictionary_argument() { let mut assignment = DictionaryMemberAssignment::parse(file, input, assignment)?; assignment .node .dependencies .retain(|name| variable_names.contains(name)); assignment.node.index = index; - index += 1; - variable_names.insert(assignment.node.name.node.clone()); + // Update positional arg names with their actual index. + if let ArgumentName::Positional(_) = assignment.node.name { + assignment.node.name = ArgumentName::Positional(index); + } + + // Only named args are added to variable_names for dependency tracking. + if let ArgumentName::Named(ref name) = assignment.node.name { + variable_names.insert(name.clone()); + } + + index += 1; assignments.push(assignment); } } @@ -1097,6 +1161,7 @@ impl<'t> Parse<'t, nodes::MethodCall<'t>> for MethodCall { pub struct LetInAssignment { pub index: usize, pub ident: AstNode, + pub argument_name: ArgumentName, pub dependencies: HashableSet, pub value: AstNode, } @@ -1106,8 +1171,8 @@ impl DependentOperation for AstNode { self.node.index } - fn name(&self) -> &ImString { - &self.node.ident.node + fn name(&self) -> &ArgumentName { + &self.node.argument_name } fn dependencies(&self) -> &HashableSet { @@ -1122,6 +1187,7 @@ impl<'t> Parse<'t, nodes::LetInAssignment<'t>> for LetInAssignment { node: nodes::LetInAssignment<'t>, ) -> Result, Error<'t, 'i>> { let ident = ImString::parse(file, input, node.ident()?)?; + let ident_name = ident.node.clone(); let value = Expression::parse(file, input, node.value()?)?; @@ -1140,6 +1206,7 @@ impl<'t> Parse<'t, nodes::LetInAssignment<'t>> for LetInAssignment { Self { index: 0, ident, + argument_name: ArgumentName::Named(ident_name), dependencies, value, }, @@ -1351,13 +1418,7 @@ mod test { let a = &construction_expression.node.assignments[0]; let b = &construction_expression.node.assignments[1]; - assert_eq!( - a.node.name, - AstNode { - reference: a.node.name.reference.clone(), - node: "a".into() - } - ); + assert_eq!(a.node.name, ArgumentName::Named("a".into())); assert_eq!( a.node.assignment, AstNode { @@ -1369,13 +1430,7 @@ mod test { } ); - assert_eq!( - b.node.name, - AstNode { - reference: b.node.name.reference.clone(), - node: "b".into() - } - ); + assert_eq!(b.node.name, ArgumentName::Named("b".into())); assert_eq!( b.node.assignment, AstNode { @@ -2028,10 +2083,7 @@ mod test { reference: dict_assignment.reference.clone(), node: DictionaryMemberAssignment { index: 0, - name: AstNode { - reference: dict_assignment.node.name.reference.clone(), - node: "value".into() - }, + name: ArgumentName::Named("value".into()), dependencies: HashableSet::from(HashSet::from_iter([])), assignment: AstNode { reference: dict_assignment @@ -2146,10 +2198,7 @@ mod test { node: DictionaryMemberAssignment { index: 0, dependencies: HashableSet::from(HashSet::from_iter([])), - name: AstNode { - reference: dict_assignment.node.name.reference.clone(), - node: "value".into() - }, + name: ArgumentName::Named("value".into()), assignment: AstNode { reference: dict_assignment .node @@ -2215,6 +2264,7 @@ mod test { reference: value1_ident.reference.clone(), node: "value1".into(), }, + argument_name: ArgumentName::Named("value1".into()), index: 0, dependencies: HashableSet::new(), value: AstNode { @@ -2233,6 +2283,7 @@ mod test { reference: value2_ident.reference.clone(), node: "value2".into(), }, + argument_name: ArgumentName::Named("value2".into()), index: 1, dependencies: HashableSet::new(), value: AstNode { @@ -2265,6 +2316,7 @@ mod test { #[derive(Debug, PartialEq, Eq)] struct TestDependency { name: ImString, + argument_name: ArgumentName, index: usize, dependencies: HashableSet, } @@ -2275,9 +2327,11 @@ mod test { name: impl Into, dependencies: impl IntoIterator, ) -> Self { + let name = name.into(); Self { index, - name: name.into(), + name: name.clone(), + argument_name: ArgumentName::Named(name), dependencies: HashableSet::from(HashSet::from_iter( dependencies.into_iter().map(ImString::from), )), @@ -2290,8 +2344,8 @@ mod test { self.index } - fn name(&self) -> &ImString { - &self.name + fn name(&self) -> &ArgumentName { + &self.argument_name } fn dependencies(&self) -> &HashableSet { diff --git a/interpreter/src/execution/mod.rs b/interpreter/src/execution/mod.rs index 284a5e2..f5b0c5a 100644 --- a/interpreter/src/execution/mod.rs +++ b/interpreter/src/execution/mod.rs @@ -756,13 +756,17 @@ mod test { assert_eq!( product, values::ValueType::Dictionary(values::StructDefinition { - members: Arc::new(HashMap::from([( - "name".into(), - values::StructMember { - ty: ValueType::TypeNone, - default: Some(Value::ValueNone(values::ValueNone)) - } - )]).into_iter().collect()), + members: Arc::new( + HashMap::from([( + "name".into(), + values::StructMember { + ty: ValueType::TypeNone, + default: Some(Value::ValueNone(values::ValueNone)) + } + )]) + .into_iter() + .collect() + ), variadic: true }) .into() diff --git a/interpreter/src/execution/standard_environment.rs b/interpreter/src/execution/standard_environment.rs index fab2791..eec3ac2 100644 --- a/interpreter/src/execution/standard_environment.rs +++ b/interpreter/src/execution/standard_environment.rs @@ -72,7 +72,7 @@ pub fn build_prelude(database: &BuiltinCallableDatabase) -> HashMap Dictionary { - let std = HashMap::from([ + let std: HashMap = HashMap::from([ ("types".into(), build_types(context).into()), ( "scalar".into(), diff --git a/interpreter/src/execution/values/closure.rs b/interpreter/src/execution/values/closure.rs index b44e559..fb68cc2 100644 --- a/interpreter/src/execution/values/closure.rs +++ b/interpreter/src/execution/values/closure.rs @@ -20,6 +20,7 @@ use std::{any::TypeId, borrow::Cow, collections::HashMap, fmt::Display, sync::Ar use hashable_map::HashableMap; use imstr::ImString; +use indexmap::IndexMap; use crate::{ compile::{AstNode, ClosureDefinition, Expression}, @@ -29,6 +30,7 @@ use crate::{ find_all_variable_accesses_in_expression, logging::{LocatedStr, LogLevel, LogMessage}, stack::ScopeType, + values::dictionary::ArgumentName, values::{string::formatting::Style, Dictionary, Value}, ExecutionContext, }, @@ -155,7 +157,7 @@ pub fn find_all_variable_accesses_in_closure_capture( #[derive(Debug, Eq, PartialEq)] struct UserClosureInternals { signature: Arc, - captured_values: HashableMap, + captured_values: IndexMap, expression: Arc>, } @@ -192,9 +194,15 @@ impl UserClosure { let expression = source.node.expression.clone(); - let mut captured_values = HashableMap::new(); + let mut captured_values = IndexMap::new(); find_all_variable_accesses_in_closure_capture(&source.node, &mut |field_name| { - let local_variables = signature.argument_type.members.keys().cloned(); + let local_variables = signature.argument_type.members.keys().filter_map(|name| { + if let ArgumentName::Named(s) = name { + Some(s.clone()) + } else { + None + } + }); let value = context .get_variable_for_closure( @@ -206,7 +214,7 @@ impl UserClosure { )? .clone(); - captured_values.insert(field_name.node.clone(), value); + captured_values.insert(ArgumentName::Named(field_name.node.clone()), value); Ok(()) })?; @@ -261,10 +269,32 @@ impl Object for UserClosure { let argument = self.data.signature.argument_type.fill_defaults(argument); + let signature_members: Vec = self + .data + .signature + .argument_type + .members + .iter() + .map(|(name, _)| name.clone()) + .collect(); + let variables: HashMap = argument .iter() .chain(self.data.captured_values.iter()) - .map(|(name, value)| (name.clone(), value.clone())) + .filter_map(|(name, value)| match name { + ArgumentName::Named(s) => Some((s.clone(), value.clone())), + ArgumentName::Positional(idx) => { + if *idx < signature_members.len() { + if let ArgumentName::Named(s) = &signature_members[*idx] { + Some((s.clone(), value.clone())) + } else { + None + } + } else { + None + } + } + }) .collect(); context.stack_scope(ScopeType::Inherited, variables, |context| { @@ -312,7 +342,9 @@ impl std::fmt::Debug for dyn BuiltinCallable { macro_rules! build_member_from_sig { ($name:ident: $ty:ty) => { ( - imstr::ImString::from(stringify!($name)), + $crate::execution::values::dictionary::ArgumentName::Named(imstr::ImString::from( + stringify!($name), + )), $crate::execution::values::StructMember { ty: <$ty as $crate::execution::values::StaticType>::static_type(), default: None, @@ -321,7 +353,9 @@ macro_rules! build_member_from_sig { }; ($name:ident: $ty:ty = $default:expr) => { ( - imstr::ImString::from(stringify!($name)), + $crate::execution::values::dictionary::ArgumentName::Named(imstr::ImString::from( + stringify!($name), + )), $crate::execution::values::StructMember { ty: <$ty as $crate::execution::values::StaticType>::static_type(), default: Some($default), @@ -333,7 +367,7 @@ macro_rules! build_member_from_sig { #[macro_export] macro_rules! build_argument_signature_list { ($($arg:ident: $ty:path $(= $default:expr)?),*) => {{ - let list: [(imstr::ImString, $crate::execution::values::StructMember); _] = [$($crate::build_member_from_sig!($arg: $ty $(= $default)?),)*]; + let list: [($crate::execution::values::dictionary::ArgumentName, $crate::execution::values::StructMember); _] = [$($crate::build_member_from_sig!($arg: $ty $(= $default)?),)*]; list }}; } @@ -341,8 +375,8 @@ macro_rules! build_argument_signature_list { #[macro_export] macro_rules! build_struct_definition { (variadic: $variadic:literal, ($($arg:ident: $ty:path $(= $default:expr)?),*)) => {{ - let map: std::collections::HashMap = std::collections::HashMap::from($crate::build_argument_signature_list!($($arg: $ty $(= $default)?),*)); - let converted: indexmap::IndexMap = map.into_iter().collect(); + let list: [($crate::execution::values::dictionary::ArgumentName, $crate::execution::values::StructMember); _] = $crate::build_argument_signature_list!($($arg: $ty $(= $default)?),*); + let converted: indexmap::IndexMap<$crate::execution::values::dictionary::ArgumentName, $crate::execution::values::StructMember> = list.into_iter().collect(); $crate::execution::values::StructDefinition { members: std::sync::Arc::new(converted), variadic: $variadic, @@ -455,7 +489,7 @@ macro_rules! build_function_callable { let mut _argument = signature.argument_type.fill_defaults(argument); let _data = std::sync::Arc::make_mut(&mut _argument.data); - $($(let $arg: $ty = _data.members.remove(stringify!($arg)) + $($(let $arg: $ty = _data.members.remove(&crate::execution::values::dictionary::ArgumentName::Named(stringify!($arg).into())) .expect("Argument was not present after argument check.").downcast::<$ty>($context)?;)*)? let result: $return_type = { @@ -539,7 +573,7 @@ macro_rules! build_method_callable { let mut _argument = signature.argument_type.fill_defaults(argument); let _data = std::sync::Arc::make_mut(&mut _argument.data); - $($(let $arg: $ty = _data.members.remove(stringify!($arg)) + $($(let $arg: $ty = _data.members.remove(&crate::execution::values::dictionary::ArgumentName::Named(stringify!($arg).into())) .expect("Argument was not present after argument check.").downcast::<$ty>($context)?;)*)? let result: $return_type = { @@ -655,7 +689,7 @@ mod test { }, return_type: ValueType::UnsignedInteger, }), - captured_values: HashableMap::new(), + captured_values: IndexMap::new(), expression }) } @@ -743,7 +777,7 @@ mod test { assert_eq!( build_argument_signature_list!(value: SignedInteger), [( - ImString::from("value"), + ArgumentName::Named(ImString::from("value")), StructMember { ty: ValueType::SignedInteger, default: None @@ -753,7 +787,7 @@ mod test { assert_eq!( build_argument_signature_list!(value: UnsignedInteger), [( - ImString::from("value"), + ArgumentName::Named(ImString::from("value")), StructMember { ty: ValueType::UnsignedInteger, default: None @@ -763,7 +797,7 @@ mod test { assert_eq!( build_argument_signature_list!(value: UnsignedInteger = UnsignedInteger::from(23).into()), [( - ImString::from("value"), + ArgumentName::Named(ImString::from("value")), StructMember { ty: ValueType::UnsignedInteger, default: Some(Value::UnsignedInteger(23.into())) @@ -775,14 +809,14 @@ mod test { build_argument_signature_list!(value: UnsignedInteger, value1: SignedInteger), [ ( - ImString::from("value"), + ArgumentName::Named(ImString::from("value")), StructMember { ty: ValueType::UnsignedInteger, default: None } ), ( - ImString::from("value1"), + ArgumentName::Named(ImString::from("value1")), StructMember { ty: ValueType::SignedInteger, default: None @@ -795,14 +829,14 @@ mod test { build_argument_signature_list!(value: UnsignedInteger = UnsignedInteger::from(32).into(), value1: SignedInteger), [ ( - ImString::from("value"), + ArgumentName::Named(ImString::from("value")), StructMember { ty: ValueType::UnsignedInteger, default: Some(UnsignedInteger::from(32).into()) } ), ( - ImString::from("value1"), + ArgumentName::Named(ImString::from("value1")), StructMember { ty: ValueType::SignedInteger, default: None @@ -995,4 +1029,166 @@ mod test { }, ) } + + #[test] + fn builtin_function_positional_args() { + let mut database = BuiltinCallableDatabase::new(); + struct TestFunction; + build_function!( + database, + TestFunction, "test_function", ( + _context: &ExecutionContext, + a: UnsignedInteger, + b: UnsignedInteger + ) -> UnsignedInteger { + Ok(values::UnsignedInteger::from(a.0 + b.0)) + } + ); + + let root = crate::compile::full_compile("test_function(1u, 2u)"); + test_context_custom_database( + database, + [( + "test_function".into(), + BuiltinFunction::new::().into(), + )], + |context| { + let product = execute_expression(context, &root).unwrap(); + + assert_eq!(product, values::UnsignedInteger::from(3).into()); + }, + ) + } + + #[test] + fn builtin_function_mixed_args() { + let mut database = BuiltinCallableDatabase::new(); + struct TestFunction; + build_function!( + database, + TestFunction, "test_function", ( + _context: &ExecutionContext, + a: UnsignedInteger, + b: UnsignedInteger, + c: UnsignedInteger + ) -> UnsignedInteger { + Ok(values::UnsignedInteger::from(a.0 + b.0 + c.0)) + } + ); + + let root = crate::compile::full_compile("test_function(1u, 2u, c = 3u)"); + test_context_custom_database( + database, + [( + "test_function".into(), + BuiltinFunction::new::().into(), + )], + |context| { + let product = execute_expression(context, &root).unwrap(); + + assert_eq!(product, values::UnsignedInteger::from(6).into()); + }, + ) + } + + #[test] + fn builtin_function_positional_with_default() { + let mut database = BuiltinCallableDatabase::new(); + struct TestFunction; + build_function!( + database, + TestFunction, "test_function", ( + _context: &ExecutionContext, + a: UnsignedInteger, + b: UnsignedInteger = UnsignedInteger::from(10).into() + ) -> UnsignedInteger { + Ok(values::UnsignedInteger::from(a.0 + b.0)) + } + ); + + let root = crate::compile::full_compile("test_function(5u)"); + test_context_custom_database( + database, + [( + "test_function".into(), + BuiltinFunction::new::().into(), + )], + |context| { + let product = execute_expression(context, &root).unwrap(); + + assert_eq!(product, values::UnsignedInteger::from(15).into()); + }, + ) + } + + #[test] + fn builtin_method_positional_args() { + let mut database = BuiltinCallableDatabase::new(); + struct TestMethod; + + build_method!( + database, + TestMethod, "test_method", ( + context: &ExecutionContext, + this: Dictionary, + to_add: UnsignedInteger + ) -> UnsignedInteger { + let value: UnsignedInteger = this.get_attribute(context, "value")?.downcast(context)?; + + Ok(values::UnsignedInteger::from(value.0 + to_add.0)) + } + ); + + let root = crate::compile::full_compile( + "let object = (value = 5u, test_method = provided_test_method); in object::test_method(10u)", + ); + test_context_custom_database( + database, + [( + "provided_test_method".into(), + BuiltinFunction::new::().into(), + )], + |context| { + let product = execute_expression(context, &root).unwrap(); + + assert_eq!(product, values::UnsignedInteger::from(15).into()); + }, + ) + } + + #[test] + fn builtin_method_mixed_args() { + let mut database = BuiltinCallableDatabase::new(); + struct TestMethod; + + build_method!( + database, + TestMethod, "test_method", ( + context: &ExecutionContext, + this: Dictionary, + to_add: UnsignedInteger, + to_mul: UnsignedInteger + ) -> UnsignedInteger { + let value: UnsignedInteger = this.get_attribute(context, "value")?.downcast(context)?; + + Ok(values::UnsignedInteger::from((value.0 + to_add.0) * to_mul.0)) + } + ); + + let root = crate::compile::full_compile( + "let object = (value = 5u, test_method = provided_test_method); in object::test_method(10u, to_mul = 2u)", + ); + test_context_custom_database( + database, + [( + "provided_test_method".into(), + BuiltinFunction::new::().into(), + )], + |context| { + let product = execute_expression(context, &root).unwrap(); + + assert_eq!(product, values::UnsignedInteger::from(30).into()); + }, + ) + } } diff --git a/interpreter/src/execution/values/constraint_set.rs b/interpreter/src/execution/values/constraint_set.rs index 3442b5a..881d5e5 100644 --- a/interpreter/src/execution/values/constraint_set.rs +++ b/interpreter/src/execution/values/constraint_set.rs @@ -393,12 +393,12 @@ impl ConstraintSet { StrError("Could not determine dimension of constraint set").to_error(context) })?; - let mut members = HashMap::new(); + let mut members: HashMap = HashMap::new(); for (variable_name, variable_id) in variables { // Values that do not get solved are our inputs. if let Some(value) = solution.as_float(variable_id) { members.insert( - variable_name, + ArgumentName::Named(variable_name), Scalar { dimension, value: Float::new(value).unwrap_not_nan(context)?, diff --git a/interpreter/src/execution/values/dictionary.rs b/interpreter/src/execution/values/dictionary.rs index f515f9c..d50aa9e 100644 --- a/interpreter/src/execution/values/dictionary.rs +++ b/interpreter/src/execution/values/dictionary.rs @@ -78,9 +78,15 @@ impl From for ArgumentName { } } +impl From for ArgumentName { + fn from(s: ImString) -> Self { + ArgumentName::Named(s) + } +} + #[derive(Clone, Debug, PartialEq, Eq)] pub(crate) struct DictionaryData { - pub members: IndexMap, + pub members: IndexMap, pub struct_def: StructDefinition, } @@ -133,7 +139,11 @@ impl Object for Dictionary { } fn get_attribute(&self, context: &ExecutionContext, attribute: &str) -> ExecutionResult { - if let Some(member) = self.data.members.get(attribute) { + if let Some(member) = self + .data + .members + .get(&ArgumentName::Named(attribute.into())) + { Ok(member.clone()) } else { Err(MissingAttributeError { @@ -152,7 +162,7 @@ impl StaticTypeName for Dictionary { impl StaticType for Dictionary { fn static_type() -> ValueType { - static TYPE: std::sync::OnceLock>> = + static TYPE: std::sync::OnceLock>> = std::sync::OnceLock::new(); let signature = TYPE.get_or_init(|| Arc::new(IndexMap::new())); ValueType::Dictionary(StructDefinition { @@ -171,7 +181,7 @@ impl Dictionary { context: &ExecutionContext, ast_node: &AstNode, ) -> ExecutionResult { - let mut members = HashMap::with_capacity(ast_node.node.assignments.len()); + let mut members = IndexMap::with_capacity(ast_node.node.assignments.len()); context.stack.scope_mut( context.stack_trace, @@ -188,19 +198,26 @@ impl Dictionary { }; buffer.par_extend(group.par_iter().map(|assignment| { + let name_str = match &assignment.node.name { + ArgumentName::Named(s) => s.clone(), + ArgumentName::Positional(idx) => { + ImString::from(format!("__{}", idx)) + } + }; ( - assignment.node.name.node.clone(), + assignment.node.name.clone(), + name_str, execute_expression(&context, &assignment.node.assignment), ) })); } - for (name, result) in buffer.drain(..) { + for (arg_name, name, result) in buffer.drain(..) { let value = result?; - if members.insert(name.clone(), value.clone()).is_some() { + if members.contains_key(&arg_name) { // That's a duplicate member. - return Err(DuplicateMemberError { name }.to_error( + return Err(DuplicateMemberError { name: name.clone() }.to_error( context.stack_trace.iter().chain([&StackTrace { parent: None, reference: ast_node.reference.clone(), @@ -209,6 +226,7 @@ impl Dictionary { )); } + members.insert(arg_name.clone(), value.clone()); stack.insert_value(name, value); } } @@ -220,10 +238,16 @@ impl Dictionary { Ok(Self::new(context, members)) } - pub fn new(context: &ExecutionContext, map: HashMap) -> Self { - let mut struct_members = HashMap::with_capacity(map.len()); + pub fn new(context: &ExecutionContext, map: I) -> Self + where + I: IntoIterator, + K: Into, + { + let members: IndexMap = + map.into_iter().map(|(k, v)| (k.into(), v)).collect(); + let mut struct_members = IndexMap::with_capacity(members.len()); - for (name, value) in map.iter() { + for (name, value) in members.iter() { let member = StructMember { ty: value.get_type(context), default: None, @@ -233,9 +257,9 @@ impl Dictionary { } let data = Arc::new(DictionaryData { - members: map.into_iter().collect(), + members, struct_def: StructDefinition { - members: Arc::new(struct_members.into_iter().collect()), + members: Arc::new(struct_members), variadic: false, }, }); @@ -243,12 +267,12 @@ impl Dictionary { Self { data } } - pub fn iter(&self) -> impl Iterator { + pub fn iter(&self) -> impl Iterator { self.data.members.iter() } pub fn get(&self, name: &str) -> Option<&Value> { - self.data.members.get(name) + self.data.members.get(&ArgumentName::Named(name.into())) } } @@ -279,16 +303,16 @@ mod test { let product = test_run("(none = std.consts.None)").unwrap(); let expected = Arc::new(DictionaryData { members: { - let map: HashMap = HashMap::from_iter([( - "none".into(), + let map: HashMap = HashMap::from_iter([( + ArgumentName::Named("none".into()), values::ValueNone.into(), )]); map.into_iter().collect() }, struct_def: StructDefinition { members: Arc::new({ - let map: HashMap = HashMap::from_iter([( - "none".into(), + let map: HashMap = HashMap::from_iter([( + ArgumentName::Named("none".into()), StructMember { ty: ValueType::TypeNone, default: None, @@ -355,15 +379,24 @@ mod test { #[test] fn argument_name_hash_and_eq() { assert_eq!(ArgumentName::Positional(0), ArgumentName::Positional(0)); - assert_eq!(ArgumentName::Named("a".into()), ArgumentName::Named("a".into())); + assert_eq!( + ArgumentName::Named("a".into()), + ArgumentName::Named("a".into()) + ); assert_ne!(ArgumentName::Positional(0), ArgumentName::Named("0".into())); } #[test] fn dictionary_insert_positional_key() { let mut map: IndexMap = IndexMap::new(); - map.insert(ArgumentName::Positional(0), values::UnsignedInteger::from(1).into()); - map.insert(ArgumentName::Positional(1), values::UnsignedInteger::from(2).into()); + map.insert( + ArgumentName::Positional(0), + values::UnsignedInteger::from(1).into(), + ); + map.insert( + ArgumentName::Positional(1), + values::UnsignedInteger::from(2).into(), + ); let keys: Vec<_> = map.keys().collect(); assert_eq!(keys[0], &ArgumentName::Positional(0)); assert_eq!(keys[1], &ArgumentName::Positional(1)); @@ -372,9 +405,18 @@ mod test { #[test] fn dictionary_insert_mixed_keys() { let mut map: IndexMap = IndexMap::new(); - map.insert(ArgumentName::Positional(0), values::UnsignedInteger::from(1).into()); - map.insert(ArgumentName::Positional(1), values::UnsignedInteger::from(2).into()); - map.insert(ArgumentName::Named("b".into()), values::UnsignedInteger::from(3).into()); + map.insert( + ArgumentName::Positional(0), + values::UnsignedInteger::from(1).into(), + ); + map.insert( + ArgumentName::Positional(1), + values::UnsignedInteger::from(2).into(), + ); + map.insert( + ArgumentName::Named("b".into()), + values::UnsignedInteger::from(3).into(), + ); let keys: Vec<_> = map.keys().collect(); assert_eq!(keys[0], &ArgumentName::Positional(0)); assert_eq!(keys[1], &ArgumentName::Positional(1)); diff --git a/interpreter/src/execution/values/iterators.rs b/interpreter/src/execution/values/iterators.rs index e69ca3a..0a717d5 100644 --- a/interpreter/src/execution/values/iterators.rs +++ b/interpreter/src/execution/values/iterators.rs @@ -351,7 +351,10 @@ impl IteratorStage { context, Dictionary::new( context, - HashMap::from_iter([("c".into(), value.clone())]), + HashMap::<&str, Value>::from_iter([( + "c".into(), + value.clone(), + )]), ), ) .and_then(|value| value.downcast::(context)); @@ -380,7 +383,7 @@ impl IteratorStage { context, Dictionary::new( context, - HashMap::from_iter([("c".into(), value.clone())]), + HashMap::<&str, Value>::from_iter([("c".into(), value.clone())]), ), ); @@ -438,7 +441,10 @@ impl IteratorStage { let value = result?; map.call( context, - Dictionary::new(context, HashMap::from_iter([("c".into(), value.clone())])), + Dictionary::new( + context, + HashMap::<&str, Value>::from_iter([("c".into(), value.clone())]), + ), ) }); @@ -451,7 +457,7 @@ impl IteratorStage { context, Dictionary::new( context, - HashMap::from_iter([("c".into(), value.clone())]), + HashMap::<&str, Value>::from_iter([("c".into(), value.clone())]), ), ); @@ -484,7 +490,7 @@ impl IteratorStage { context, Dictionary::new( context, - HashMap::from_iter([("c".into(), value.clone())]), + HashMap::<&str, Value>::from_iter([("c".into(), value.clone())]), ), ) .and_then(|value| value.downcast::(context))? @@ -515,7 +521,10 @@ impl IteratorStage { context, Dictionary::new( context, - HashMap::from_iter([("c".into(), value.clone())]), + HashMap::<&str, Value>::from_iter([( + "c".into(), + value.clone(), + )]), ), ) .and_then(|value| value.downcast::(context)); @@ -812,7 +821,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { context, Dictionary::new( context, - HashMap::from_iter([("c".into(), value.clone())]), + HashMap::<&str, Value>::from_iter([("c".into(), value.clone())]), ), ) .and_then(|value| value.downcast::(context))?; @@ -844,7 +853,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { context, Dictionary::new( context, - HashMap::from_iter([("c".into(), value.clone())]), + HashMap::<&str, Value>::from_iter([("c".into(), value.clone())]), ), ) .and_then(|value| value.downcast::(context))?; @@ -932,7 +941,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { for component in iterator { let component = component?; - accumulator = f.call(context, Dictionary::new(context, HashMap::from_iter([ + accumulator = f.call(context, Dictionary::new(context, HashMap::<&str, Value>::from_iter([ ( "c".into(), component.clone() diff --git a/interpreter/src/execution/values/list.rs b/interpreter/src/execution/values/list.rs index 1e255ef..7bd3ca9 100644 --- a/interpreter/src/execution/values/list.rs +++ b/interpreter/src/execution/values/list.rs @@ -526,7 +526,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { let mut values: Vec = Vec::with_capacity(this.values.len()); for value in this.values.iter() { - let retain = f.call(context, Dictionary::new(context, HashMap::from_iter([ + let retain = f.call(context, Dictionary::new(context, HashMap::<&str, Value>::from_iter([ ( "c".into(), value.clone() diff --git a/interpreter/src/execution/values/polygon.rs b/interpreter/src/execution/values/polygon.rs index a1ab289..99129c5 100644 --- a/interpreter/src/execution/values/polygon.rs +++ b/interpreter/src/execution/values/polygon.rs @@ -23,7 +23,7 @@ use geo::{BooleanOps, OpType}; use nalgebra::{Matrix3, Translation2}; use crate::{ - execution::errors::Raise, + execution::{errors::Raise, values::dictionary::ArgumentName}, values::{ iterators::IterableObject, BuiltinCallableDatabase, BuiltinFunction, DowncastError, MissingAttributeError, Object, StaticType, StaticTypeName, Style, Value, ValueType, @@ -575,16 +575,17 @@ pub mod methods_and_functions { let min = rect.min(); let max = rect.max(); - let rectangle: HashMap = HashMap::from_iter([ - ( - "min".into(), - Vector2::new(context, Dimension::length(), [min.x, min.y])?.into(), - ), - ( - "max".into(), - Vector2::new(context, Dimension::length(), [max.x, max.y])?.into(), - ), - ]); + let rectangle: HashMap = + HashMap::from_iter([ + ( + crate::execution::values::dictionary::ArgumentName::Named("min".into()), + Vector2::new(context, Dimension::length(), [min.x, min.y])?.into(), + ), + ( + crate::execution::values::dictionary::ArgumentName::Named("max".into()), + Vector2::new(context, Dimension::length(), [max.x, max.y])?.into(), + ), + ]); Ok(Some(Dictionary::new(context, rectangle))) } else { @@ -952,9 +953,7 @@ pub mod methods_and_functions { }; if number_of_points < 2 { - return Err( - StrError("Circle must have at least two points").to_error(context) - ); + return Err(StrError("Circle must have at least two points").to_error(context)); } Ok(Self { diff --git a/interpreter/src/execution/values/string/formatting.rs b/interpreter/src/execution/values/string/formatting.rs index d3f199d..d0f0ab8 100644 --- a/interpreter/src/execution/values/string/formatting.rs +++ b/interpreter/src/execution/values/string/formatting.rs @@ -33,7 +33,7 @@ use nom::{ use crate::execution::{ errors::{ExecutionResult, Raise, StringError}, logging::LocatedStr, - values::{Dictionary, Object, UnsignedInteger}, + values::{Dictionary, Object, UnsignedInteger, Value}, ExecutionContext, }; @@ -415,7 +415,7 @@ mod test { &mut formatted, Dictionary::new( context, - HashMap::from_iter([( + HashMap::<&str, Value>::from_iter([( "value".into(), Scalar { dimension: Dimension::zero(), @@ -437,7 +437,7 @@ mod test { &mut formatted, Dictionary::new( context, - HashMap::from_iter([ + HashMap::<&str, Value>::from_iter([ ( "one".into(), Scalar { diff --git a/interpreter/src/execution/values/string/mod.rs b/interpreter/src/execution/values/string/mod.rs index af9be1b..d0a7bf8 100644 --- a/interpreter/src/execution/values/string/mod.rs +++ b/interpreter/src/execution/values/string/mod.rs @@ -362,7 +362,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { let mut product: String = String::with_capacity(this.0.len()); for c in this.0.chars() { - let retain = f.call(context, Dictionary::new(context, HashMap::from_iter([ + let retain = f.call(context, Dictionary::new(context, HashMap::<&str, Value>::from_iter([ ( "c".into(), IString(ImString::from(format!("{c}"))).into() diff --git a/interpreter/src/execution/values/value_type.rs b/interpreter/src/execution/values/value_type.rs index 9d23bca..d3e636b 100644 --- a/interpreter/src/execution/values/value_type.rs +++ b/interpreter/src/execution/values/value_type.rs @@ -36,9 +36,11 @@ use crate::{ errors::{ExecutionResult, Raise}, logging::{LogLevel, LogMessage}, values::{ - self, closure::BuiltinCallableDatabase, dictionary::DictionaryData, - string::formatting::Style, BuiltinFunction, Dictionary, File, IString, - MissingAttributeError, + self, + closure::BuiltinCallableDatabase, + dictionary::{ArgumentName, DictionaryData}, + string::formatting::Style, + BuiltinFunction, Dictionary, File, IString, MissingAttributeError, }, ExecutionContext, }, @@ -347,7 +349,7 @@ impl Display for StructMember { #[derive(Debug, Clone, Eq, PartialEq)] pub struct StructDefinition { - pub members: Arc>, + pub members: Arc>, pub variadic: bool, } @@ -356,13 +358,16 @@ impl StructDefinition { context: &ExecutionContext, source: &AstNode, ) -> ExecutionResult { - let mut members = HashMap::new(); + let mut members = IndexMap::new(); for member in source.node.members.iter() { let name = member.node.name.node.clone(); - members.insert(name, StructMember::new(context, member)?); + members.insert( + ArgumentName::Named(name), + StructMember::new(context, member)?, + ); } - let members = Arc::new(members.into_iter().collect()); + let members = Arc::new(members); let variadic = source.node.variadic; Ok(Self { members, variadic }) } @@ -370,15 +375,36 @@ impl StructDefinition { pub fn fill_defaults(&self, dictionary: Dictionary) -> Dictionary { let data = Arc::unwrap_or_clone(dictionary.data); - let mut members: IndexMap = data.members; + let mut members: IndexMap = data.members; let struct_def_variadic = data.struct_def.variadic; let mut struct_def_members = Arc::unwrap_or_clone(data.struct_def.members); - for (name, member) in self.members.iter() { - if let Some(default_value) = &member.default { - if members.get(name).is_none() { - members.insert(name.clone(), default_value.clone()); - struct_def_members.insert(name.clone(), member.clone()); + // Rename positional keys to named keys based on parameter order. + // This allows the builtin function macro to always look up by name, + // regardless of whether the caller passed positional or named args. + for (idx, (arg_name, _member)) in self.members.iter().enumerate() { + if let ArgumentName::Named(param_name) = arg_name { + let positional_key = ArgumentName::Positional(idx); + if members.contains_key(&positional_key) + && !members.contains_key(&ArgumentName::Named(param_name.clone())) + { + if let Some(value) = members.shift_remove(&positional_key) { + members.insert(ArgumentName::Named(param_name.clone()), value); + } + } + } + } + + for (idx, (name, member)) in self.members.iter().enumerate() { + let is_present = self.find_arg_key(&members, idx, name).is_some(); + if !is_present { + if let Some(default_value) = &member.default { + let key = match name { + ArgumentName::Named(n) => ArgumentName::Named(n.clone()), + ArgumentName::Positional(_) => ArgumentName::Positional(idx), + }; + members.insert(key.clone(), default_value.clone()); + struct_def_members.insert(key.clone(), member.clone()); } } } @@ -394,20 +420,56 @@ impl StructDefinition { } } + fn find_arg_key( + &self, + members: &IndexMap, + idx: usize, + name: &ArgumentName, + ) -> Option { + match name { + ArgumentName::Named(n) => { + if members.contains_key(&ArgumentName::Named(n.clone())) { + Some(ArgumentName::Named(n.clone())) + } else if members.contains_key(&ArgumentName::Positional(idx)) { + Some(ArgumentName::Positional(idx)) + } else { + None + } + } + ArgumentName::Positional(_) => { + if members.contains_key(&ArgumentName::Positional(idx)) { + Some(ArgumentName::Positional(idx)) + } else if let ArgumentName::Named(n) = name { + if members.contains_key(&ArgumentName::Named(n.clone())) { + Some(ArgumentName::Named(n.clone())) + } else { + None + } + } else { + None + } + } + } + } + pub fn check_other_qualifies( &self, other: &StructDefinition, ) -> Result<(), TypeQualificationError> { let mut errors = Vec::new(); - - // Check that all fields are present and correct. - for (name, member) in self.members.iter() { - if let Some(other_member) = other.members.get(name) { - if let Err(error) = member.ty.check_other_qualifies(&other_member.ty) { - errors.push(MissmatchedField { - name: name.clone(), - error, - }); + let mut matched_keys = std::collections::HashSet::new(); + + // Check that all expected fields are present and correct. + for (idx, (name, member)) in self.members.iter().enumerate() { + if let Some(key) = self.find_arg_key(&other.members, idx, name) { + matched_keys.insert(key.clone()); + if let Some(other_member) = other.members.get(&key) { + if let Err(error) = member.ty.check_other_qualifies(&other_member.ty) { + errors.push(MissmatchedField { + name: name.clone(), + error, + }); + } } } else if member.default.is_none() { errors.push(MissmatchedField { @@ -420,16 +482,16 @@ impl StructDefinition { } } - // Checkt that there are no extra fields (unless of course, we're supposed to have extra + // Check that there are no extra fields (unless of course, we're supposed to have extra // fields) if !self.variadic { - for (name, member) in other.members.iter() { - if self.members.get(name).is_none() { + for key in other.members.keys() { + if !matched_keys.contains(key) { errors.push(MissmatchedField { - name: name.clone(), + name: key.clone(), error: TypeQualificationError::This { expected: ValueType::TypeNone, - got: member.ty.clone(), + got: ValueType::TypeNone, }, }); } @@ -485,8 +547,8 @@ impl StaticTypeName for StructDefinition { } } -impl From> for StructDefinition { - fn from(map: HashMap) -> Self { +impl From> for StructDefinition { + fn from(map: HashMap) -> Self { Self { members: Arc::new(map.into_iter().collect()), variadic: false, @@ -496,7 +558,7 @@ impl From> for StructDefinition { #[derive(Debug, Eq, PartialEq)] pub struct MissmatchedField { - pub name: ImString, + pub name: ArgumentName, pub error: TypeQualificationError, } @@ -1099,4 +1161,58 @@ mod test { } ); } + + #[test] + fn positional_args_match_by_index() { + let result = test_run( + "let f = (a: std.types.UInt, b: std.types.UInt) -> std.types.UInt: a + b; in f(1u, 2u)", + ) + .unwrap(); + assert_eq!(result, values::UnsignedInteger::from(3).into()); + } + + #[test] + fn positional_args_with_defaults() { + let result = test_run( + "let f = (a: std.types.UInt, b: std.types.UInt = 10u) -> std.types.UInt: a + b; in f(5u)", + ) + .unwrap(); + assert_eq!(result, values::UnsignedInteger::from(15).into()); + } + + #[test] + fn mixed_positional_named_args() { + let result = test_run( + "let f = (a: std.types.UInt, b: std.types.UInt, c: std.types.UInt) -> std.types.UInt: a + b + c; in f(1u, 2u, c = 3u)", + ) + .unwrap(); + assert_eq!(result, values::UnsignedInteger::from(6).into()); + } + + #[test] + fn mixed_positional_named_args_reversed() { + let result = test_run( + "let f = (a: std.types.UInt, b: std.types.UInt, c: std.types.UInt) -> std.types.UInt: a + b + c; in f(1u, c = 3u, b = 2u)", + ) + .unwrap(); + assert_eq!(result, values::UnsignedInteger::from(6).into()); + } + + #[test] + fn closure_call_all_positional() { + let result = test_run( + "let f = (x: std.types.UInt, y: std.types.UInt) -> std.types.UInt: x * y; in f(3u, 4u)", + ) + .unwrap(); + assert_eq!(result, values::UnsignedInteger::from(12).into()); + } + + #[test] + fn closure_call_mixed_args() { + let result = test_run( + "let f = (x: std.types.UInt, y: std.types.UInt, z: std.types.UInt) -> std.types.UInt: x + y + z; in f(1u, z = 3u, y = 2u)", + ) + .unwrap(); + assert_eq!(result, values::UnsignedInteger::from(6).into()); + } } diff --git a/interpreter/src/execution/values/vector.rs b/interpreter/src/execution/values/vector.rs index bcb2b3c..a48ec08 100644 --- a/interpreter/src/execution/values/vector.rs +++ b/interpreter/src/execution/values/vector.rs @@ -465,7 +465,7 @@ mod methods { this: Vector, f: MapClosure) -> Vector { - let operations: ArrayVec<[Value; 4]> = this.value.iter().map(|c| f.call(context, Dictionary::new(context, HashMap::from_iter([ + let operations: ArrayVec<[Value; 4]> = this.value.iter().map(|c| f.call(context, Dictionary::new(context, HashMap::<&str, Value>::from_iter([ ( "c".into(), Scalar { @@ -501,7 +501,7 @@ mod methods { let mut accumulator = init; for component in this.value.iter() { - accumulator = f.call(context, Dictionary::new(context, HashMap::from_iter([ + accumulator = f.call(context, Dictionary::new(context, HashMap::<&str, Value>::from_iter([ ( "c".into(), Scalar { diff --git a/tree-sitter-command-cad-model/grammar.js b/tree-sitter-command-cad-model/grammar.js index df33404..a5b54cc 100644 --- a/tree-sitter-command-cad-model/grammar.js +++ b/tree-sitter-command-cad-model/grammar.js @@ -175,7 +175,7 @@ module.exports = grammar({ declaration_type: $ => seq(':', $.expression), - parenthesis: $ => seq('(', $.expression, ')'), + parenthesis: $ => prec(1, seq('(', $.expression, ')')), list: $ => seq( '[', repeat(seq($.expression, ',')), @@ -197,15 +197,21 @@ module.exports = grammar({ ), ')')), - dictionary_member_assignment: $ => seq(field('name', $.identifier), '=', field('assignment', $.expression)), + dictionary_argument: $ => seq( + field('key', $.expression), + optional(seq('=', field('value', $.expression))), + ), dictionary_construction: $ => seq('(', - field('assignments', - optional(seq( - $.dictionary_member_assignment, - repeat(seq(',', $.dictionary_member_assignment)), - optional(',') - )), - ), + field('arguments', choice( + // Empty: () + seq(), + // With args - at least one comma required to distinguish from parenthesis + seq( + $.dictionary_argument, + repeat(seq(',', $.dictionary_argument)), + optional(','), + ), + )), ')' ), diff --git a/tree-sitter-command-cad-model/src/grammar.json b/tree-sitter-command-cad-model/src/grammar.json index eb7377c..9caa5f2 100644 --- a/tree-sitter-command-cad-model/src/grammar.json +++ b/tree-sitter-command-cad-model/src/grammar.json @@ -1427,21 +1427,25 @@ ] }, "parenthesis": { - "type": "SEQ", - "members": [ - { - "type": "STRING", - "value": "(" - }, - { - "type": "SYMBOL", - "name": "expression" - }, - { - "type": "STRING", - "value": ")" - } - ] + "type": "PREC", + "value": 1, + "content": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "(" + }, + { + "type": "SYMBOL", + "name": "expression" + }, + { + "type": "STRING", + "value": ")" + } + ] + } }, "list": { "type": "SEQ", @@ -1635,28 +1639,41 @@ ] } }, - "dictionary_member_assignment": { + "dictionary_argument": { "type": "SEQ", "members": [ { "type": "FIELD", - "name": "name", + "name": "key", "content": { "type": "SYMBOL", - "name": "identifier" + "name": "expression" } }, { - "type": "STRING", - "value": "=" - }, - { - "type": "FIELD", - "name": "assignment", - "content": { - "type": "SYMBOL", - "name": "expression" - } + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "=" + }, + { + "type": "FIELD", + "name": "value", + "content": { + "type": "SYMBOL", + "name": "expression" + } + } + ] + }, + { + "type": "BLANK" + } + ] } ] }, @@ -1669,16 +1686,20 @@ }, { "type": "FIELD", - "name": "assignments", + "name": "arguments", "content": { "type": "CHOICE", "members": [ + { + "type": "SEQ", + "members": [] + }, { "type": "SEQ", "members": [ { "type": "SYMBOL", - "name": "dictionary_member_assignment" + "name": "dictionary_argument" }, { "type": "REPEAT", @@ -1691,7 +1712,7 @@ }, { "type": "SYMBOL", - "name": "dictionary_member_assignment" + "name": "dictionary_argument" } ] } @@ -1709,9 +1730,6 @@ ] } ] - }, - { - "type": "BLANK" } ] } diff --git a/tree-sitter-command-cad-model/src/node-types.json b/tree-sitter-command-cad-model/src/node-types.json index 6571f57..329b7f7 100644 --- a/tree-sitter-command-cad-model/src/node-types.json +++ b/tree-sitter-command-cad-model/src/node-types.json @@ -433,19 +433,25 @@ } }, { - "type": "dictionary_construction", + "type": "dictionary_argument", "named": true, "fields": { - "assignments": { - "multiple": true, - "required": false, + "key": { + "multiple": false, + "required": true, "types": [ { - "type": ",", - "named": false - }, + "type": "expression", + "named": true + } + ] + }, + "value": { + "multiple": false, + "required": false, + "types": [ { - "type": "dictionary_member_assignment", + "type": "expression", "named": true } ] @@ -453,25 +459,19 @@ } }, { - "type": "dictionary_member_assignment", + "type": "dictionary_construction", "named": true, "fields": { - "assignment": { - "multiple": false, - "required": true, + "arguments": { + "multiple": true, + "required": false, "types": [ { - "type": "expression", - "named": true - } - ] - }, - "name": { - "multiple": false, - "required": true, - "types": [ + "type": ",", + "named": false + }, { - "type": "identifier", + "type": "dictionary_argument", "named": true } ] diff --git a/tree-sitter-command-cad-model/src/parser.c b/tree-sitter-command-cad-model/src/parser.c index 8c6f4a1..1008ac9 100644 --- a/tree-sitter-command-cad-model/src/parser.c +++ b/tree-sitter-command-cad-model/src/parser.c @@ -13,10 +13,10 @@ #define ALIAS_COUNT 0 #define TOKEN_COUNT 58 #define EXTERNAL_TOKEN_COUNT 0 -#define FIELD_COUNT 32 +#define FIELD_COUNT 33 #define MAX_ALIAS_SEQUENCE_LENGTH 9 #define MAX_RESERVED_WORD_SET_SIZE 0 -#define PRODUCTION_ID_COUNT 30 +#define PRODUCTION_ID_COUNT 31 #define SUPERTYPE_COUNT 0 enum ts_symbol_identifiers { @@ -108,7 +108,7 @@ enum ts_symbol_identifiers { sym_struct_member = 86, sym__struct_final_element = 87, sym_struct_definition = 88, - sym_dictionary_member_assignment = 89, + sym_dictionary_argument = 89, sym_dictionary_construction = 90, sym_closure_definition = 91, sym__constraint_set_relation = 92, @@ -216,7 +216,7 @@ static const char * const ts_symbol_names[] = { [sym_struct_member] = "struct_member", [sym__struct_final_element] = "_struct_final_element", [sym_struct_definition] = "struct_definition", - [sym_dictionary_member_assignment] = "dictionary_member_assignment", + [sym_dictionary_argument] = "dictionary_argument", [sym_dictionary_construction] = "dictionary_construction", [sym_closure_definition] = "closure_definition", [sym__constraint_set_relation] = "_constraint_set_relation", @@ -324,7 +324,7 @@ static const TSSymbol ts_symbol_map[] = { [sym_struct_member] = sym_struct_member, [sym__struct_final_element] = sym__struct_final_element, [sym_struct_definition] = sym_struct_definition, - [sym_dictionary_member_assignment] = sym_dictionary_member_assignment, + [sym_dictionary_argument] = sym_dictionary_argument, [sym_dictionary_construction] = sym_dictionary_construction, [sym_closure_definition] = sym_closure_definition, [sym__constraint_set_relation] = sym__constraint_set_relation, @@ -699,7 +699,7 @@ static const TSSymbolMetadata ts_symbol_metadata[] = { .visible = true, .named = true, }, - [sym_dictionary_member_assignment] = { + [sym_dictionary_argument] = { .visible = true, .named = true, }, @@ -768,8 +768,8 @@ static const TSSymbolMetadata ts_symbol_metadata[] = { enum ts_field_identifiers { field_a = 1, field_argument = 2, - field_assignment = 3, - field_assignments = 4, + field_arguments = 3, + field_assignment = 4, field_b = 5, field_base = 6, field_condition = 7, @@ -778,34 +778,35 @@ enum ts_field_identifiers { field_final_element = 10, field_fractional = 11, field_ident = 12, - field_lhs = 13, - field_member = 14, - field_members = 15, - field_name = 16, - field_on_false = 17, - field_on_true = 18, - field_op = 19, - field_relation = 20, - field_result = 21, - field_rhs = 22, - field_self_dictionary = 23, - field_to_call = 24, - field_unit = 25, - field_value = 26, - field_variables = 27, - field_w = 28, - field_whole = 29, - field_x = 30, - field_y = 31, - field_z = 32, + field_key = 13, + field_lhs = 14, + field_member = 15, + field_members = 16, + field_name = 17, + field_on_false = 18, + field_on_true = 19, + field_op = 20, + field_relation = 21, + field_result = 22, + field_rhs = 23, + field_self_dictionary = 24, + field_to_call = 25, + field_unit = 26, + field_value = 27, + field_variables = 28, + field_w = 29, + field_whole = 30, + field_x = 31, + field_y = 32, + field_z = 33, }; static const char * const ts_field_names[] = { [0] = NULL, [field_a] = "a", [field_argument] = "argument", + [field_arguments] = "arguments", [field_assignment] = "assignment", - [field_assignments] = "assignments", [field_b] = "b", [field_base] = "base", [field_condition] = "condition", @@ -814,6 +815,7 @@ static const char * const ts_field_names[] = { [field_final_element] = "final_element", [field_fractional] = "fractional", [field_ident] = "ident", + [field_key] = "key", [field_lhs] = "lhs", [field_member] = "member", [field_members] = "members", @@ -841,31 +843,32 @@ static const TSMapSlice ts_field_map_slices[PRODUCTION_ID_COUNT] = { [2] = {.index = 1, .length = 2}, [3] = {.index = 3, .length = 1}, [4] = {.index = 4, .length = 1}, - [5] = {.index = 5, .length = 3}, - [6] = {.index = 8, .length = 2}, - [7] = {.index = 10, .length = 1}, + [5] = {.index = 5, .length = 1}, + [6] = {.index = 6, .length = 3}, + [7] = {.index = 9, .length = 2}, [8] = {.index = 11, .length = 1}, [9] = {.index = 12, .length = 1}, [10] = {.index = 13, .length = 1}, [11] = {.index = 14, .length = 1}, - [12] = {.index = 15, .length = 2}, - [13] = {.index = 17, .length = 2}, - [14] = {.index = 19, .length = 3}, - [15] = {.index = 22, .length = 2}, - [16] = {.index = 24, .length = 2}, - [17] = {.index = 26, .length = 2}, - [18] = {.index = 28, .length = 2}, - [19] = {.index = 30, .length = 3}, - [20] = {.index = 33, .length = 2}, - [21] = {.index = 35, .length = 2}, - [22] = {.index = 37, .length = 2}, - [23] = {.index = 39, .length = 3}, - [24] = {.index = 42, .length = 3}, - [25] = {.index = 45, .length = 3}, - [26] = {.index = 48, .length = 3}, - [27] = {.index = 51, .length = 4}, - [28] = {.index = 55, .length = 4}, - [29] = {.index = 59, .length = 3}, + [12] = {.index = 15, .length = 1}, + [13] = {.index = 16, .length = 2}, + [14] = {.index = 18, .length = 2}, + [15] = {.index = 20, .length = 3}, + [16] = {.index = 23, .length = 2}, + [17] = {.index = 25, .length = 2}, + [18] = {.index = 27, .length = 2}, + [19] = {.index = 29, .length = 2}, + [20] = {.index = 31, .length = 3}, + [21] = {.index = 34, .length = 2}, + [22] = {.index = 36, .length = 2}, + [23] = {.index = 38, .length = 2}, + [24] = {.index = 40, .length = 3}, + [25] = {.index = 43, .length = 3}, + [26] = {.index = 46, .length = 3}, + [27] = {.index = 49, .length = 3}, + [28] = {.index = 52, .length = 4}, + [29] = {.index = 56, .length = 4}, + [30] = {.index = 60, .length = 3}, }; static const TSFieldMapEntry ts_field_map_entries[] = { @@ -877,86 +880,88 @@ static const TSFieldMapEntry ts_field_map_entries[] = { [3] = {field_op, 0}, [4] = - {field_value, 0}, + {field_key, 0}, [5] = + {field_value, 0}, + [6] = {field_fractional, 0, .inherited = true}, {field_unit, 1}, {field_whole, 0, .inherited = true}, - [8] = + [9] = {field_argument, 1}, {field_to_call, 0}, - [10] = - {field_expression, 2}, [11] = - {field_name, 0}, + {field_expression, 2}, [12] = - {field_final_element, 1}, + {field_name, 0}, [13] = - {field_assignments, 1}, + {field_final_element, 1}, [14] = - {field_members, 1}, + {field_arguments, 1}, [15] = + {field_members, 1}, + [16] = {field_fractional, 2}, {field_whole, 0}, - [17] = + [18] = {field_base, 0}, {field_member, 2}, - [19] = + [20] = {field_a, 0}, {field_b, 2}, {field_op, 1}, - [22] = + [23] = {field_assignment, 1}, {field_expression, 3}, - [24] = - {field_assignment, 2}, - {field_name, 0}, - [26] = - {field_assignments, 1}, - {field_assignments, 2}, - [28] = + [25] = + {field_key, 0}, + {field_value, 2}, + [27] = + {field_arguments, 1}, + {field_arguments, 2}, + [29] = {field_final_element, 2}, {field_members, 1}, - [30] = + [31] = {field_argument, 3}, {field_self_dictionary, 0}, {field_to_call, 2}, - [33] = + [34] = {field_x, 1}, {field_y, 3}, - [35] = + [36] = {field_ident, 0}, {field_value, 2}, - [37] = + [38] = {field_default, 3}, {field_name, 0}, - [39] = - {field_assignments, 1}, - {field_assignments, 2}, - {field_assignments, 3}, - [42] = + [40] = + {field_arguments, 1}, + {field_arguments, 2}, + {field_arguments, 3}, + [43] = {field_argument, 0}, {field_expression, 4}, {field_result, 2}, - [45] = + [46] = {field_condition, 1}, {field_on_false, 5}, {field_on_true, 3}, - [48] = + [49] = {field_x, 1}, {field_y, 3}, {field_z, 5}, - [51] = + [52] = {field_lhs, 3}, {field_relation, 4}, {field_rhs, 5}, {field_variables, 1}, - [55] = + [56] = {field_w, 7}, {field_x, 1}, {field_y, 3}, {field_z, 5}, - [59] = + [60] = {field_argument, 4}, {field_self_dictionary, 0}, {field_to_call, 2}, @@ -982,9 +987,9 @@ static const TSStateId ts_primary_state_ids[STATE_COUNT] = { [8] = 8, [9] = 9, [10] = 10, - [11] = 11, + [11] = 10, [12] = 12, - [13] = 6, + [13] = 13, [14] = 14, [15] = 15, [16] = 16, @@ -1004,29 +1009,29 @@ static const TSStateId ts_primary_state_ids[STATE_COUNT] = { [30] = 30, [31] = 31, [32] = 32, - [33] = 27, - [34] = 8, - [35] = 9, - [36] = 10, - [37] = 11, - [38] = 12, - [39] = 7, - [40] = 14, - [41] = 15, - [42] = 16, - [43] = 17, - [44] = 18, - [45] = 19, - [46] = 24, - [47] = 29, - [48] = 31, - [49] = 20, - [50] = 22, - [51] = 51, - [52] = 52, - [53] = 53, - [54] = 54, - [55] = 55, + [33] = 33, + [34] = 34, + [35] = 35, + [36] = 36, + [37] = 35, + [38] = 38, + [39] = 12, + [40] = 13, + [41] = 14, + [42] = 15, + [43] = 16, + [44] = 17, + [45] = 18, + [46] = 19, + [47] = 20, + [48] = 21, + [49] = 22, + [50] = 28, + [51] = 32, + [52] = 34, + [53] = 24, + [54] = 26, + [55] = 38, [56] = 56, [57] = 57, [58] = 58, @@ -1069,87 +1074,87 @@ static const TSStateId ts_primary_state_ids[STATE_COUNT] = { [95] = 95, [96] = 96, [97] = 97, - [98] = 52, - [99] = 53, + [98] = 98, + [99] = 99, [100] = 100, [101] = 101, - [102] = 55, + [102] = 102, [103] = 56, - [104] = 54, + [104] = 57, [105] = 105, [106] = 106, [107] = 107, [108] = 108, [109] = 109, [110] = 110, - [111] = 63, + [111] = 59, [112] = 112, [113] = 113, - [114] = 114, - [115] = 115, + [114] = 60, + [115] = 58, [116] = 116, [117] = 117, [118] = 118, - [119] = 65, - [120] = 85, - [121] = 87, - [122] = 88, - [123] = 89, - [124] = 90, - [125] = 91, - [126] = 93, - [127] = 94, - [128] = 95, - [129] = 64, - [130] = 130, - [131] = 74, - [132] = 75, - [133] = 70, - [134] = 134, - [135] = 116, - [136] = 134, - [137] = 67, - [138] = 112, - [139] = 139, - [140] = 55, - [141] = 56, - [142] = 53, - [143] = 143, + [119] = 119, + [120] = 98, + [121] = 121, + [122] = 122, + [123] = 123, + [124] = 72, + [125] = 74, + [126] = 75, + [127] = 76, + [128] = 77, + [129] = 78, + [130] = 79, + [131] = 80, + [132] = 81, + [133] = 82, + [134] = 83, + [135] = 135, + [136] = 136, + [137] = 117, + [138] = 90, + [139] = 91, + [140] = 100, + [141] = 135, + [142] = 123, + [143] = 97, [144] = 144, - [145] = 145, - [146] = 146, - [147] = 147, + [145] = 60, + [146] = 59, + [147] = 57, [148] = 148, - [149] = 146, - [150] = 150, - [151] = 54, - [152] = 147, + [149] = 149, + [150] = 148, + [151] = 151, + [152] = 152, [153] = 153, - [154] = 150, + [154] = 154, [155] = 155, [156] = 156, [157] = 157, - [158] = 158, - [159] = 60, - [160] = 160, + [158] = 58, + [159] = 157, + [160] = 156, [161] = 161, - [162] = 161, - [163] = 160, - [164] = 164, + [162] = 162, + [163] = 163, + [164] = 63, [165] = 165, [166] = 166, - [167] = 167, - [168] = 168, + [167] = 165, + [168] = 166, [169] = 169, [170] = 170, [171] = 171, - [172] = 170, - [173] = 171, + [172] = 172, + [173] = 173, [174] = 174, [175] = 175, [176] = 176, - [177] = 177, - [178] = 178, + [177] = 176, + [178] = 175, [179] = 179, [180] = 180, [181] = 181, @@ -1166,12 +1171,12 @@ static const TSStateId ts_primary_state_ids[STATE_COUNT] = { [192] = 192, [193] = 193, [194] = 194, - [195] = 186, + [195] = 195, [196] = 196, - [197] = 197, - [198] = 186, + [197] = 192, + [198] = 198, [199] = 199, - [200] = 200, + [200] = 192, [201] = 201, [202] = 202, [203] = 203, @@ -1906,57 +1911,57 @@ static const TSLexerMode ts_lex_modes[STATE_COUNT] = { [49] = {.lex_state = 1}, [50] = {.lex_state = 1}, [51] = {.lex_state = 1}, - [52] = {.lex_state = 18}, - [53] = {.lex_state = 19}, - [54] = {.lex_state = 19}, - [55] = {.lex_state = 19}, - [56] = {.lex_state = 19}, - [57] = {.lex_state = 17}, - [58] = {.lex_state = 17}, - [59] = {.lex_state = 17}, - [60] = {.lex_state = 20}, + [52] = {.lex_state = 1}, + [53] = {.lex_state = 1}, + [54] = {.lex_state = 1}, + [55] = {.lex_state = 1}, + [56] = {.lex_state = 18}, + [57] = {.lex_state = 19}, + [58] = {.lex_state = 19}, + [59] = {.lex_state = 19}, + [60] = {.lex_state = 19}, [61] = {.lex_state = 17}, [62] = {.lex_state = 17}, - [63] = {.lex_state = 18}, - [64] = {.lex_state = 18}, - [65] = {.lex_state = 18}, + [63] = {.lex_state = 20}, + [64] = {.lex_state = 17}, + [65] = {.lex_state = 17}, [66] = {.lex_state = 17}, - [67] = {.lex_state = 18}, + [67] = {.lex_state = 17}, [68] = {.lex_state = 17}, [69] = {.lex_state = 17}, - [70] = {.lex_state = 18}, + [70] = {.lex_state = 17}, [71] = {.lex_state = 17}, - [72] = {.lex_state = 17}, + [72] = {.lex_state = 18}, [73] = {.lex_state = 17}, [74] = {.lex_state = 18}, [75] = {.lex_state = 18}, - [76] = {.lex_state = 17}, - [77] = {.lex_state = 17}, - [78] = {.lex_state = 17}, - [79] = {.lex_state = 17}, - [80] = {.lex_state = 17}, - [81] = {.lex_state = 17}, - [82] = {.lex_state = 17}, - [83] = {.lex_state = 17}, + [76] = {.lex_state = 18}, + [77] = {.lex_state = 18}, + [78] = {.lex_state = 18}, + [79] = {.lex_state = 18}, + [80] = {.lex_state = 18}, + [81] = {.lex_state = 18}, + [82] = {.lex_state = 18}, + [83] = {.lex_state = 18}, [84] = {.lex_state = 17}, - [85] = {.lex_state = 18}, + [85] = {.lex_state = 17}, [86] = {.lex_state = 17}, - [87] = {.lex_state = 18}, - [88] = {.lex_state = 18}, - [89] = {.lex_state = 18}, + [87] = {.lex_state = 17}, + [88] = {.lex_state = 17}, + [89] = {.lex_state = 17}, [90] = {.lex_state = 18}, [91] = {.lex_state = 18}, [92] = {.lex_state = 17}, - [93] = {.lex_state = 18}, - [94] = {.lex_state = 18}, - [95] = {.lex_state = 18}, + [93] = {.lex_state = 17}, + [94] = {.lex_state = 17}, + [95] = {.lex_state = 17}, [96] = {.lex_state = 17}, - [97] = {.lex_state = 17}, - [98] = {.lex_state = 17}, + [97] = {.lex_state = 18}, + [98] = {.lex_state = 18}, [99] = {.lex_state = 17}, [100] = {.lex_state = 18}, - [101] = {.lex_state = 18}, - [102] = {.lex_state = 17}, + [101] = {.lex_state = 17}, + [102] = {.lex_state = 18}, [103] = {.lex_state = 17}, [104] = {.lex_state = 17}, [105] = {.lex_state = 18}, @@ -1966,17 +1971,17 @@ static const TSLexerMode ts_lex_modes[STATE_COUNT] = { [109] = {.lex_state = 18}, [110] = {.lex_state = 18}, [111] = {.lex_state = 17}, - [112] = {.lex_state = 17}, + [112] = {.lex_state = 18}, [113] = {.lex_state = 18}, - [114] = {.lex_state = 18}, - [115] = {.lex_state = 18}, + [114] = {.lex_state = 17}, + [115] = {.lex_state = 17}, [116] = {.lex_state = 18}, [117] = {.lex_state = 18}, [118] = {.lex_state = 18}, - [119] = {.lex_state = 17}, + [119] = {.lex_state = 18}, [120] = {.lex_state = 17}, - [121] = {.lex_state = 17}, - [122] = {.lex_state = 17}, + [121] = {.lex_state = 18}, + [122] = {.lex_state = 18}, [123] = {.lex_state = 17}, [124] = {.lex_state = 17}, [125] = {.lex_state = 17}, @@ -1984,95 +1989,95 @@ static const TSLexerMode ts_lex_modes[STATE_COUNT] = { [127] = {.lex_state = 17}, [128] = {.lex_state = 17}, [129] = {.lex_state = 17}, - [130] = {.lex_state = 18}, + [130] = {.lex_state = 17}, [131] = {.lex_state = 17}, [132] = {.lex_state = 17}, [133] = {.lex_state = 17}, - [134] = {.lex_state = 18}, + [134] = {.lex_state = 17}, [135] = {.lex_state = 18}, [136] = {.lex_state = 18}, - [137] = {.lex_state = 17}, + [137] = {.lex_state = 18}, [138] = {.lex_state = 17}, - [139] = {.lex_state = 1}, - [140] = {.lex_state = 2}, - [141] = {.lex_state = 2}, - [142] = {.lex_state = 2}, - [143] = {.lex_state = 3}, - [144] = {.lex_state = 3}, - [145] = {.lex_state = 18}, - [146] = {.lex_state = 18}, - [147] = {.lex_state = 18}, + [139] = {.lex_state = 17}, + [140] = {.lex_state = 17}, + [141] = {.lex_state = 18}, + [142] = {.lex_state = 17}, + [143] = {.lex_state = 17}, + [144] = {.lex_state = 1}, + [145] = {.lex_state = 2}, + [146] = {.lex_state = 2}, + [147] = {.lex_state = 2}, [148] = {.lex_state = 18}, - [149] = {.lex_state = 18}, + [149] = {.lex_state = 3}, [150] = {.lex_state = 18}, - [151] = {.lex_state = 2}, + [151] = {.lex_state = 3}, [152] = {.lex_state = 18}, - [153] = {.lex_state = 18}, - [154] = {.lex_state = 18}, - [155] = {.lex_state = 3}, - [156] = {.lex_state = 3}, + [153] = {.lex_state = 3}, + [154] = {.lex_state = 3}, + [155] = {.lex_state = 18}, + [156] = {.lex_state = 18}, [157] = {.lex_state = 18}, [158] = {.lex_state = 2}, - [159] = {.lex_state = 2}, - [160] = {.lex_state = 2}, - [161] = {.lex_state = 2}, - [162] = {.lex_state = 1}, - [163] = {.lex_state = 1}, - [164] = {.lex_state = 1}, - [165] = {.lex_state = 0}, - [166] = {.lex_state = 0}, + [159] = {.lex_state = 18}, + [160] = {.lex_state = 18}, + [161] = {.lex_state = 18}, + [162] = {.lex_state = 18}, + [163] = {.lex_state = 2}, + [164] = {.lex_state = 2}, + [165] = {.lex_state = 2}, + [166] = {.lex_state = 2}, [167] = {.lex_state = 1}, [168] = {.lex_state = 1}, [169] = {.lex_state = 1}, - [170] = {.lex_state = 1}, - [171] = {.lex_state = 1}, + [170] = {.lex_state = 0}, + [171] = {.lex_state = 0}, [172] = {.lex_state = 1}, [173] = {.lex_state = 1}, - [174] = {.lex_state = 0}, + [174] = {.lex_state = 1}, [175] = {.lex_state = 1}, - [176] = {.lex_state = 0}, + [176] = {.lex_state = 1}, [177] = {.lex_state = 1}, - [178] = {.lex_state = 0}, - [179] = {.lex_state = 1}, + [178] = {.lex_state = 1}, + [179] = {.lex_state = 0}, [180] = {.lex_state = 1}, [181] = {.lex_state = 0}, [182] = {.lex_state = 1}, - [183] = {.lex_state = 1}, - [184] = {.lex_state = 1}, - [185] = {.lex_state = 0}, - [186] = {.lex_state = 18}, - [187] = {.lex_state = 1}, - [188] = {.lex_state = 0}, + [183] = {.lex_state = 0}, + [184] = {.lex_state = 0}, + [185] = {.lex_state = 1}, + [186] = {.lex_state = 1}, + [187] = {.lex_state = 0}, + [188] = {.lex_state = 1}, [189] = {.lex_state = 1}, [190] = {.lex_state = 0}, - [191] = {.lex_state = 1}, - [192] = {.lex_state = 1}, + [191] = {.lex_state = 0}, + [192] = {.lex_state = 18}, [193] = {.lex_state = 0}, - [194] = {.lex_state = 1}, - [195] = {.lex_state = 18}, - [196] = {.lex_state = 1}, - [197] = {.lex_state = 0}, - [198] = {.lex_state = 18}, - [199] = {.lex_state = 0}, - [200] = {.lex_state = 1}, - [201] = {.lex_state = 0}, + [194] = {.lex_state = 0}, + [195] = {.lex_state = 0}, + [196] = {.lex_state = 0}, + [197] = {.lex_state = 18}, + [198] = {.lex_state = 1}, + [199] = {.lex_state = 1}, + [200] = {.lex_state = 18}, + [201] = {.lex_state = 1}, [202] = {.lex_state = 1}, [203] = {.lex_state = 1}, - [204] = {.lex_state = 3}, - [205] = {.lex_state = 19}, + [204] = {.lex_state = 19}, + [205] = {.lex_state = 0}, [206] = {.lex_state = 0}, - [207] = {.lex_state = 0}, + [207] = {.lex_state = 1}, [208] = {.lex_state = 0}, [209] = {.lex_state = 0}, - [210] = {.lex_state = 18}, + [210] = {.lex_state = 0}, [211] = {.lex_state = 0}, [212] = {.lex_state = 0}, - [213] = {.lex_state = 0}, - [214] = {.lex_state = 0}, - [215] = {.lex_state = 1}, - [216] = {.lex_state = 1}, - [217] = {.lex_state = 0}, - [218] = {.lex_state = 0}, + [213] = {.lex_state = 1}, + [214] = {.lex_state = 18}, + [215] = {.lex_state = 0}, + [216] = {.lex_state = 0}, + [217] = {.lex_state = 1}, + [218] = {.lex_state = 3}, }; static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = { @@ -2135,16 +2140,16 @@ static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = { [anon_sym_GT_GT_GT] = ACTIONS(1), }, [STATE(1)] = { - [sym_source_file] = STATE(212), - [sym_base_ten] = STATE(200), - [sym_octal] = STATE(200), - [sym_hex] = STATE(200), - [sym_binary] = STATE(200), - [sym_integer] = STATE(189), + [sym_source_file] = STATE(216), + [sym_base_ten] = STATE(202), + [sym_octal] = STATE(202), + [sym_hex] = STATE(202), + [sym_binary] = STATE(202), + [sym_integer] = STATE(201), [sym_signed_integer] = STATE(92), [sym_unsigned_integer] = STATE(92), - [sym_number] = STATE(55), - [sym__float] = STATE(53), + [sym_number] = STATE(59), + [sym__float] = STATE(57), [sym_scalar] = STATE(92), [sym_vector2] = STATE(92), [sym_vector3] = STATE(92), @@ -2152,7 +2157,7 @@ static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = { [sym_boolean] = STATE(92), [sym_function_call] = STATE(92), [sym_method_call] = STATE(92), - [sym_expression] = STATE(114), + [sym_expression] = STATE(136), [sym_unary_expression] = STATE(92), [sym_binary_expression] = STATE(92), [sym_if] = STATE(92), @@ -2160,7 +2165,7 @@ static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = { [sym_member_access] = STATE(92), [sym_parenthesis] = STATE(92), [sym_list] = STATE(92), - [sym_struct_definition] = STATE(67), + [sym_struct_definition] = STATE(97), [sym_dictionary_construction] = STATE(92), [sym_closure_definition] = STATE(92), [sym_constraint_set] = STATE(92), @@ -2186,15 +2191,15 @@ static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = { [anon_sym_LT_LT_LT] = ACTIONS(31), }, [STATE(2)] = { - [sym_base_ten] = STATE(200), - [sym_octal] = STATE(200), - [sym_hex] = STATE(200), - [sym_binary] = STATE(200), - [sym_integer] = STATE(189), + [sym_base_ten] = STATE(202), + [sym_octal] = STATE(202), + [sym_hex] = STATE(202), + [sym_binary] = STATE(202), + [sym_integer] = STATE(201), [sym_signed_integer] = STATE(92), [sym_unsigned_integer] = STATE(92), - [sym_number] = STATE(55), - [sym__float] = STATE(53), + [sym_number] = STATE(59), + [sym__float] = STATE(57), [sym_scalar] = STATE(92), [sym_vector2] = STATE(92), [sym_vector3] = STATE(92), @@ -2202,7 +2207,7 @@ static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = { [sym_boolean] = STATE(92), [sym_function_call] = STATE(92), [sym_method_call] = STATE(92), - [sym_expression] = STATE(130), + [sym_expression] = STATE(106), [sym_unary_expression] = STATE(92), [sym_binary_expression] = STATE(92), [sym_if] = STATE(92), @@ -2210,14 +2215,14 @@ static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = { [sym_member_access] = STATE(92), [sym_parenthesis] = STATE(92), [sym_list] = STATE(92), - [sym_struct_member] = STATE(199), - [sym__struct_final_element] = STATE(218), - [sym_struct_definition] = STATE(67), - [sym_dictionary_member_assignment] = STATE(174), + [sym_struct_member] = STATE(187), + [sym__struct_final_element] = STATE(211), + [sym_struct_definition] = STATE(97), + [sym_dictionary_argument] = STATE(183), [sym_dictionary_construction] = STATE(92), [sym_closure_definition] = STATE(92), [sym_constraint_set] = STATE(92), - [aux_sym_struct_definition_repeat1] = STATE(164), + [aux_sym_struct_definition_repeat1] = STATE(172), [sym_identifier] = ACTIONS(33), [sym_comment] = ACTIONS(3), [sym__whitespace] = ACTIONS(3), @@ -2269,17 +2274,17 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LT_LT_LT, ACTIONS(39), 1, anon_sym_RBRACK, - STATE(4), 1, + STATE(7), 1, aux_sym_list_repeat1, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(67), 1, + STATE(97), 1, sym_struct_definition, - STATE(106), 1, + STATE(108), 1, sym_expression, - STATE(189), 1, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -2294,7 +2299,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -2344,17 +2349,17 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LT_LT_LT, ACTIONS(41), 1, anon_sym_RBRACK, - STATE(5), 1, + STATE(3), 1, aux_sym_list_repeat1, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(67), 1, + STATE(97), 1, sym_struct_definition, - STATE(107), 1, + STATE(113), 1, sym_expression, - STATE(189), 1, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -2369,7 +2374,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -2395,56 +2400,56 @@ static const uint16_t ts_small_parse_table[] = { sym_closure_definition, sym_constraint_set, [198] = 24, - ACTIONS(46), 1, + ACTIONS(7), 1, sym_string, - ACTIONS(49), 1, + ACTIONS(9), 1, aux_sym_base_ten_token1, - ACTIONS(52), 1, + ACTIONS(11), 1, aux_sym_octal_token1, - ACTIONS(55), 1, + ACTIONS(13), 1, aux_sym_hex_token1, - ACTIONS(58), 1, + ACTIONS(15), 1, aux_sym_binary_token1, - ACTIONS(61), 1, + ACTIONS(17), 1, anon_sym_LBRACE, - ACTIONS(70), 1, + ACTIONS(23), 1, anon_sym_if, - ACTIONS(73), 1, + ACTIONS(25), 1, anon_sym_let, - ACTIONS(76), 1, + ACTIONS(27), 1, anon_sym_LPAREN, - ACTIONS(79), 1, + ACTIONS(29), 1, anon_sym_LBRACK, - ACTIONS(82), 1, - anon_sym_RBRACK, - ACTIONS(84), 1, + ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(5), 1, - aux_sym_list_repeat1, - STATE(53), 1, + ACTIONS(43), 1, + anon_sym_RPAREN, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(67), 1, + STATE(97), 1, sym_struct_definition, - STATE(113), 1, + STATE(105), 1, sym_expression, - STATE(189), 1, + STATE(183), 1, + sym_dictionary_argument, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(43), 2, + ACTIONS(5), 2, sym_identifier, sym_self, - ACTIONS(64), 2, + ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(67), 3, + ACTIONS(21), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -2469,9 +2474,11 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [297] = 22, + [297] = 24, ACTIONS(7), 1, sym_string, + ACTIONS(9), 1, + aux_sym_base_ten_token1, ACTIONS(11), 1, aux_sym_octal_token1, ACTIONS(13), 1, @@ -2480,27 +2487,29 @@ static const uint16_t ts_small_parse_table[] = { aux_sym_binary_token1, ACTIONS(17), 1, anon_sym_LBRACE, + ACTIONS(23), 1, + anon_sym_if, + ACTIONS(25), 1, + anon_sym_let, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(87), 1, - aux_sym_base_ten_token1, - ACTIONS(91), 1, - anon_sym_if, - ACTIONS(93), 1, - anon_sym_let, - STATE(99), 1, + ACTIONS(45), 1, + anon_sym_RPAREN, + STATE(57), 1, sym__float, - STATE(102), 1, + STATE(59), 1, sym_number, - STATE(123), 1, - sym_expression, - STATE(137), 1, + STATE(97), 1, sym_struct_definition, - STATE(189), 1, + STATE(105), 1, + sym_expression, + STATE(195), 1, + sym_dictionary_argument, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -2511,11 +2520,11 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(89), 3, + ACTIONS(21), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -2540,53 +2549,57 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [390] = 22, - ACTIONS(7), 1, + [396] = 24, + ACTIONS(50), 1, sym_string, - ACTIONS(11), 1, + ACTIONS(53), 1, + aux_sym_base_ten_token1, + ACTIONS(56), 1, aux_sym_octal_token1, - ACTIONS(13), 1, + ACTIONS(59), 1, aux_sym_hex_token1, - ACTIONS(15), 1, + ACTIONS(62), 1, aux_sym_binary_token1, - ACTIONS(17), 1, + ACTIONS(65), 1, anon_sym_LBRACE, - ACTIONS(27), 1, + ACTIONS(74), 1, + anon_sym_if, + ACTIONS(77), 1, + anon_sym_let, + ACTIONS(80), 1, anon_sym_LPAREN, - ACTIONS(29), 1, + ACTIONS(83), 1, anon_sym_LBRACK, - ACTIONS(31), 1, + ACTIONS(86), 1, + anon_sym_RBRACK, + ACTIONS(88), 1, anon_sym_LT_LT_LT, - ACTIONS(87), 1, - aux_sym_base_ten_token1, - ACTIONS(91), 1, - anon_sym_if, - ACTIONS(93), 1, - anon_sym_let, - STATE(99), 1, + STATE(7), 1, + aux_sym_list_repeat1, + STATE(57), 1, sym__float, - STATE(102), 1, + STATE(59), 1, sym_number, - STATE(112), 1, - sym_expression, - STATE(137), 1, + STATE(97), 1, sym_struct_definition, - STATE(189), 1, + STATE(118), 1, + sym_expression, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(5), 2, + ACTIONS(47), 2, sym_identifier, sym_self, - ACTIONS(19), 2, + ACTIONS(68), 2, sym_true, sym_false, - ACTIONS(89), 3, + ACTIONS(71), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -2611,7 +2624,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [483] = 22, + [495] = 24, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -2634,15 +2647,19 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + ACTIONS(91), 1, + anon_sym_RPAREN, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(65), 1, - sym_expression, - STATE(67), 1, + STATE(97), 1, sym_struct_definition, - STATE(189), 1, + STATE(105), 1, + sym_expression, + STATE(195), 1, + sym_dictionary_argument, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -2657,7 +2674,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -2682,7 +2699,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [576] = 22, + [594] = 23, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -2705,15 +2722,17 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(67), 1, + STATE(97), 1, sym_struct_definition, - STATE(85), 1, + STATE(105), 1, sym_expression, - STATE(189), 1, + STATE(195), 1, + sym_dictionary_argument, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -2728,7 +2747,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -2753,11 +2772,9 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [669] = 22, + [690] = 22, ACTIONS(7), 1, sym_string, - ACTIONS(9), 1, - aux_sym_base_ten_token1, ACTIONS(11), 1, aux_sym_octal_token1, ACTIONS(13), 1, @@ -2766,25 +2783,27 @@ static const uint16_t ts_small_parse_table[] = { aux_sym_binary_token1, ACTIONS(17), 1, anon_sym_LBRACE, - ACTIONS(23), 1, - anon_sym_if, - ACTIONS(25), 1, - anon_sym_let, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + ACTIONS(93), 1, + aux_sym_base_ten_token1, + ACTIONS(97), 1, + anon_sym_if, + ACTIONS(99), 1, + anon_sym_let, + STATE(104), 1, sym__float, - STATE(55), 1, + STATE(111), 1, sym_number, - STATE(59), 1, + STATE(142), 1, sym_expression, - STATE(67), 1, + STATE(143), 1, sym_struct_definition, - STATE(189), 1, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -2795,11 +2814,11 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(21), 3, + ACTIONS(95), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -2824,11 +2843,9 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [762] = 22, + [783] = 22, ACTIONS(7), 1, sym_string, - ACTIONS(9), 1, - aux_sym_base_ten_token1, ACTIONS(11), 1, aux_sym_octal_token1, ACTIONS(13), 1, @@ -2837,25 +2854,27 @@ static const uint16_t ts_small_parse_table[] = { aux_sym_binary_token1, ACTIONS(17), 1, anon_sym_LBRACE, - ACTIONS(23), 1, - anon_sym_if, - ACTIONS(25), 1, - anon_sym_let, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + ACTIONS(93), 1, + aux_sym_base_ten_token1, + ACTIONS(97), 1, + anon_sym_if, + ACTIONS(99), 1, + anon_sym_let, + STATE(104), 1, sym__float, - STATE(55), 1, + STATE(111), 1, sym_number, - STATE(67), 1, - sym_struct_definition, - STATE(87), 1, + STATE(123), 1, sym_expression, - STATE(189), 1, + STATE(143), 1, + sym_struct_definition, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -2866,11 +2885,11 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(21), 3, + ACTIONS(95), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -2895,7 +2914,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [855] = 22, + [876] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -2918,15 +2937,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(67), 1, - sym_struct_definition, - STATE(88), 1, + STATE(72), 1, sym_expression, - STATE(189), 1, + STATE(97), 1, + sym_struct_definition, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -2941,7 +2960,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -2966,7 +2985,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [948] = 22, + [969] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -2989,15 +3008,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(67), 1, - sym_struct_definition, - STATE(89), 1, + STATE(61), 1, sym_expression, - STATE(189), 1, + STATE(97), 1, + sym_struct_definition, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3012,7 +3031,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -3037,7 +3056,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [1041] = 22, + [1062] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3060,15 +3079,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(67), 1, - sym_struct_definition, - STATE(90), 1, + STATE(74), 1, sym_expression, - STATE(189), 1, + STATE(97), 1, + sym_struct_definition, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3083,7 +3102,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -3108,7 +3127,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [1134] = 22, + [1155] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3131,15 +3150,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(67), 1, - sym_struct_definition, - STATE(91), 1, + STATE(75), 1, sym_expression, - STATE(189), 1, + STATE(97), 1, + sym_struct_definition, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3154,7 +3173,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -3179,7 +3198,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [1227] = 22, + [1248] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3202,15 +3221,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(63), 1, + STATE(76), 1, sym_expression, - STATE(67), 1, + STATE(97), 1, sym_struct_definition, - STATE(189), 1, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3225,7 +3244,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -3250,7 +3269,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [1320] = 22, + [1341] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3273,15 +3292,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(67), 1, - sym_struct_definition, - STATE(93), 1, + STATE(77), 1, sym_expression, - STATE(189), 1, + STATE(97), 1, + sym_struct_definition, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3296,7 +3315,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -3321,7 +3340,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [1413] = 22, + [1434] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3344,15 +3363,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(67), 1, - sym_struct_definition, - STATE(94), 1, + STATE(78), 1, sym_expression, - STATE(189), 1, + STATE(97), 1, + sym_struct_definition, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3367,7 +3386,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -3392,7 +3411,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [1506] = 22, + [1527] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3415,15 +3434,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(67), 1, - sym_struct_definition, - STATE(95), 1, + STATE(79), 1, sym_expression, - STATE(189), 1, + STATE(97), 1, + sym_struct_definition, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3438,7 +3457,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -3463,7 +3482,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [1599] = 22, + [1620] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3486,15 +3505,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(67), 1, - sym_struct_definition, - STATE(136), 1, + STATE(80), 1, sym_expression, - STATE(189), 1, + STATE(97), 1, + sym_struct_definition, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3509,7 +3528,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -3534,7 +3553,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [1692] = 22, + [1713] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3557,15 +3576,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(67), 1, - sym_struct_definition, - STATE(108), 1, + STATE(81), 1, sym_expression, - STATE(189), 1, + STATE(97), 1, + sym_struct_definition, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3580,7 +3599,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -3605,7 +3624,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [1785] = 22, + [1806] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3628,15 +3647,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(67), 1, - sym_struct_definition, - STATE(116), 1, + STATE(82), 1, sym_expression, - STATE(189), 1, + STATE(97), 1, + sym_struct_definition, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3651,7 +3670,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -3676,7 +3695,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [1878] = 22, + [1899] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3699,15 +3718,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(67), 1, + STATE(97), 1, sym_struct_definition, - STATE(118), 1, + STATE(121), 1, sym_expression, - STATE(189), 1, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3722,7 +3741,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -3747,7 +3766,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [1971] = 22, + [1992] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3770,15 +3789,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(64), 1, - sym_expression, - STATE(67), 1, + STATE(97), 1, sym_struct_definition, - STATE(189), 1, + STATE(117), 1, + sym_expression, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3793,7 +3812,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -3818,7 +3837,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [2064] = 22, + [2085] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3841,15 +3860,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(67), 1, + STATE(97), 1, sym_struct_definition, - STATE(109), 1, + STATE(110), 1, sym_expression, - STATE(189), 1, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3864,7 +3883,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -3889,7 +3908,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [2157] = 22, + [2178] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3912,15 +3931,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(67), 1, + STATE(97), 1, sym_struct_definition, - STATE(100), 1, + STATE(135), 1, sym_expression, - STATE(189), 1, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -3935,7 +3954,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -3960,7 +3979,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [2250] = 22, + [2271] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -3983,15 +4002,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(67), 1, + STATE(97), 1, sym_struct_definition, - STATE(70), 1, + STATE(119), 1, sym_expression, - STATE(189), 1, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4006,7 +4025,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -4031,7 +4050,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [2343] = 22, + [2364] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -4054,15 +4073,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(67), 1, - sym_struct_definition, - STATE(105), 1, + STATE(83), 1, sym_expression, - STATE(189), 1, + STATE(97), 1, + sym_struct_definition, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4077,7 +4096,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -4102,7 +4121,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [2436] = 22, + [2457] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -4125,15 +4144,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(67), 1, + STATE(97), 1, sym_struct_definition, - STATE(74), 1, + STATE(107), 1, sym_expression, - STATE(189), 1, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4148,7 +4167,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -4173,7 +4192,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [2529] = 22, + [2550] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -4196,15 +4215,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(67), 1, + STATE(97), 1, sym_struct_definition, - STATE(110), 1, + STATE(116), 1, sym_expression, - STATE(189), 1, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4219,7 +4238,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -4244,7 +4263,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [2622] = 22, + [2643] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -4267,15 +4286,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(67), 1, + STATE(97), 1, sym_struct_definition, - STATE(75), 1, + STATE(112), 1, sym_expression, - STATE(189), 1, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4290,7 +4309,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -4315,7 +4334,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [2715] = 22, + [2736] = 22, ACTIONS(7), 1, sym_string, ACTIONS(9), 1, @@ -4338,15 +4357,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(67), 1, - sym_struct_definition, - STATE(115), 1, + STATE(90), 1, sym_expression, - STATE(189), 1, + STATE(97), 1, + sym_struct_definition, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4361,7 +4380,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -4386,9 +4405,11 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [2808] = 22, + [2829] = 22, ACTIONS(7), 1, sym_string, + ACTIONS(9), 1, + aux_sym_base_ten_token1, ACTIONS(11), 1, aux_sym_octal_token1, ACTIONS(13), 1, @@ -4397,27 +4418,25 @@ static const uint16_t ts_small_parse_table[] = { aux_sym_binary_token1, ACTIONS(17), 1, anon_sym_LBRACE, + ACTIONS(23), 1, + anon_sym_if, + ACTIONS(25), 1, + anon_sym_let, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(87), 1, - aux_sym_base_ten_token1, - ACTIONS(91), 1, - anon_sym_if, - ACTIONS(93), 1, - anon_sym_let, - STATE(99), 1, + STATE(57), 1, sym__float, - STATE(102), 1, + STATE(59), 1, sym_number, - STATE(133), 1, - sym_expression, - STATE(137), 1, + STATE(97), 1, sym_struct_definition, - STATE(189), 1, + STATE(109), 1, + sym_expression, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4428,11 +4447,11 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(89), 3, + ACTIONS(21), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -4457,9 +4476,11 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [2901] = 22, + [2922] = 22, ACTIONS(7), 1, sym_string, + ACTIONS(9), 1, + aux_sym_base_ten_token1, ACTIONS(11), 1, aux_sym_octal_token1, ACTIONS(13), 1, @@ -4468,27 +4489,25 @@ static const uint16_t ts_small_parse_table[] = { aux_sym_binary_token1, ACTIONS(17), 1, anon_sym_LBRACE, + ACTIONS(23), 1, + anon_sym_if, + ACTIONS(25), 1, + anon_sym_let, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(87), 1, - aux_sym_base_ten_token1, - ACTIONS(91), 1, - anon_sym_if, - ACTIONS(93), 1, - anon_sym_let, - STATE(99), 1, + STATE(57), 1, sym__float, - STATE(102), 1, + STATE(59), 1, sym_number, - STATE(119), 1, + STATE(91), 1, sym_expression, - STATE(137), 1, + STATE(97), 1, sym_struct_definition, - STATE(189), 1, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4499,11 +4518,11 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(89), 3, + ACTIONS(21), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -4528,9 +4547,11 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [2994] = 22, + [3015] = 22, ACTIONS(7), 1, sym_string, + ACTIONS(9), 1, + aux_sym_base_ten_token1, ACTIONS(11), 1, aux_sym_octal_token1, ACTIONS(13), 1, @@ -4539,27 +4560,25 @@ static const uint16_t ts_small_parse_table[] = { aux_sym_binary_token1, ACTIONS(17), 1, anon_sym_LBRACE, + ACTIONS(23), 1, + anon_sym_if, + ACTIONS(25), 1, + anon_sym_let, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(87), 1, - aux_sym_base_ten_token1, - ACTIONS(91), 1, - anon_sym_if, - ACTIONS(93), 1, - anon_sym_let, - STATE(99), 1, + STATE(57), 1, sym__float, - STATE(102), 1, + STATE(59), 1, sym_number, - STATE(120), 1, - sym_expression, - STATE(137), 1, + STATE(97), 1, sym_struct_definition, - STATE(189), 1, + STATE(100), 1, + sym_expression, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4570,11 +4589,11 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(89), 3, + ACTIONS(21), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -4599,9 +4618,11 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [3087] = 22, + [3108] = 22, ACTIONS(7), 1, sym_string, + ACTIONS(9), 1, + aux_sym_base_ten_token1, ACTIONS(11), 1, aux_sym_octal_token1, ACTIONS(13), 1, @@ -4610,27 +4631,25 @@ static const uint16_t ts_small_parse_table[] = { aux_sym_binary_token1, ACTIONS(17), 1, anon_sym_LBRACE, - ACTIONS(27), 1, - anon_sym_LPAREN, + ACTIONS(23), 1, + anon_sym_if, + ACTIONS(25), 1, + anon_sym_let, + ACTIONS(27), 1, + anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(87), 1, - aux_sym_base_ten_token1, - ACTIONS(91), 1, - anon_sym_if, - ACTIONS(93), 1, - anon_sym_let, - STATE(59), 1, - sym_expression, - STATE(99), 1, + STATE(57), 1, sym__float, - STATE(102), 1, + STATE(59), 1, sym_number, - STATE(137), 1, + STATE(97), 1, sym_struct_definition, - STATE(189), 1, + STATE(122), 1, + sym_expression, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4641,11 +4660,11 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(89), 3, + ACTIONS(21), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -4670,7 +4689,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [3180] = 22, + [3201] = 22, ACTIONS(7), 1, sym_string, ACTIONS(11), 1, @@ -4687,21 +4706,21 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(87), 1, + ACTIONS(93), 1, aux_sym_base_ten_token1, - ACTIONS(91), 1, + ACTIONS(97), 1, anon_sym_if, - ACTIONS(93), 1, + ACTIONS(99), 1, anon_sym_let, - STATE(99), 1, + STATE(104), 1, sym__float, - STATE(102), 1, + STATE(111), 1, sym_number, - STATE(121), 1, + STATE(140), 1, sym_expression, - STATE(137), 1, + STATE(143), 1, sym_struct_definition, - STATE(189), 1, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4712,11 +4731,11 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(89), 3, + ACTIONS(95), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -4741,7 +4760,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [3273] = 22, + [3294] = 22, ACTIONS(7), 1, sym_string, ACTIONS(11), 1, @@ -4758,21 +4777,21 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(87), 1, + ACTIONS(93), 1, aux_sym_base_ten_token1, - ACTIONS(91), 1, + ACTIONS(97), 1, anon_sym_if, - ACTIONS(93), 1, + ACTIONS(99), 1, anon_sym_let, - STATE(99), 1, + STATE(104), 1, sym__float, - STATE(102), 1, + STATE(111), 1, sym_number, - STATE(122), 1, + STATE(120), 1, sym_expression, - STATE(137), 1, + STATE(143), 1, sym_struct_definition, - STATE(189), 1, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4783,11 +4802,11 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(89), 3, + ACTIONS(95), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -4812,7 +4831,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [3366] = 22, + [3387] = 22, ACTIONS(7), 1, sym_string, ACTIONS(11), 1, @@ -4829,21 +4848,21 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(87), 1, + ACTIONS(93), 1, aux_sym_base_ten_token1, - ACTIONS(91), 1, + ACTIONS(97), 1, anon_sym_if, - ACTIONS(93), 1, + ACTIONS(99), 1, anon_sym_let, - STATE(99), 1, + STATE(104), 1, sym__float, - STATE(102), 1, + STATE(111), 1, sym_number, - STATE(137), 1, - sym_struct_definition, - STATE(138), 1, + STATE(124), 1, sym_expression, - STATE(189), 1, + STATE(143), 1, + sym_struct_definition, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4854,11 +4873,11 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(89), 3, + ACTIONS(95), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -4883,7 +4902,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [3459] = 22, + [3480] = 22, ACTIONS(7), 1, sym_string, ACTIONS(11), 1, @@ -4900,21 +4919,21 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(87), 1, + ACTIONS(93), 1, aux_sym_base_ten_token1, - ACTIONS(91), 1, + ACTIONS(97), 1, anon_sym_if, - ACTIONS(93), 1, + ACTIONS(99), 1, anon_sym_let, - STATE(99), 1, + STATE(61), 1, + sym_expression, + STATE(104), 1, sym__float, - STATE(102), 1, + STATE(111), 1, sym_number, - STATE(124), 1, - sym_expression, - STATE(137), 1, + STATE(143), 1, sym_struct_definition, - STATE(189), 1, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4925,11 +4944,11 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(89), 3, + ACTIONS(95), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -4954,7 +4973,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [3552] = 22, + [3573] = 22, ACTIONS(7), 1, sym_string, ACTIONS(11), 1, @@ -4971,21 +4990,21 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(87), 1, + ACTIONS(93), 1, aux_sym_base_ten_token1, - ACTIONS(91), 1, + ACTIONS(97), 1, anon_sym_if, - ACTIONS(93), 1, + ACTIONS(99), 1, anon_sym_let, - STATE(99), 1, + STATE(104), 1, sym__float, - STATE(102), 1, + STATE(111), 1, sym_number, STATE(125), 1, sym_expression, - STATE(137), 1, + STATE(143), 1, sym_struct_definition, - STATE(189), 1, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -4996,11 +5015,11 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(89), 3, + ACTIONS(95), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -5025,7 +5044,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [3645] = 22, + [3666] = 22, ACTIONS(7), 1, sym_string, ACTIONS(11), 1, @@ -5042,21 +5061,21 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(87), 1, + ACTIONS(93), 1, aux_sym_base_ten_token1, - ACTIONS(91), 1, + ACTIONS(97), 1, anon_sym_if, - ACTIONS(93), 1, + ACTIONS(99), 1, anon_sym_let, - STATE(99), 1, + STATE(104), 1, sym__float, - STATE(102), 1, - sym_number, STATE(111), 1, + sym_number, + STATE(126), 1, sym_expression, - STATE(137), 1, + STATE(143), 1, sym_struct_definition, - STATE(189), 1, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -5067,11 +5086,11 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(89), 3, + ACTIONS(95), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -5096,7 +5115,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [3738] = 22, + [3759] = 22, ACTIONS(7), 1, sym_string, ACTIONS(11), 1, @@ -5113,21 +5132,21 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(87), 1, + ACTIONS(93), 1, aux_sym_base_ten_token1, - ACTIONS(91), 1, + ACTIONS(97), 1, anon_sym_if, - ACTIONS(93), 1, + ACTIONS(99), 1, anon_sym_let, - STATE(99), 1, + STATE(104), 1, sym__float, - STATE(102), 1, + STATE(111), 1, sym_number, - STATE(126), 1, + STATE(127), 1, sym_expression, - STATE(137), 1, + STATE(143), 1, sym_struct_definition, - STATE(189), 1, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -5138,11 +5157,11 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(89), 3, + ACTIONS(95), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -5167,7 +5186,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [3831] = 22, + [3852] = 22, ACTIONS(7), 1, sym_string, ACTIONS(11), 1, @@ -5184,21 +5203,21 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(87), 1, + ACTIONS(93), 1, aux_sym_base_ten_token1, - ACTIONS(91), 1, + ACTIONS(97), 1, anon_sym_if, - ACTIONS(93), 1, + ACTIONS(99), 1, anon_sym_let, - STATE(99), 1, + STATE(104), 1, sym__float, - STATE(102), 1, + STATE(111), 1, sym_number, - STATE(127), 1, + STATE(128), 1, sym_expression, - STATE(137), 1, + STATE(143), 1, sym_struct_definition, - STATE(189), 1, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -5209,11 +5228,11 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(89), 3, + ACTIONS(95), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -5238,7 +5257,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [3924] = 22, + [3945] = 22, ACTIONS(7), 1, sym_string, ACTIONS(11), 1, @@ -5255,21 +5274,21 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(87), 1, + ACTIONS(93), 1, aux_sym_base_ten_token1, - ACTIONS(91), 1, + ACTIONS(97), 1, anon_sym_if, - ACTIONS(93), 1, + ACTIONS(99), 1, anon_sym_let, - STATE(99), 1, + STATE(104), 1, sym__float, - STATE(102), 1, + STATE(111), 1, sym_number, - STATE(128), 1, + STATE(129), 1, sym_expression, - STATE(137), 1, + STATE(143), 1, sym_struct_definition, - STATE(189), 1, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -5280,11 +5299,11 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(89), 3, + ACTIONS(95), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -5309,7 +5328,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [4017] = 22, + [4038] = 22, ACTIONS(7), 1, sym_string, ACTIONS(11), 1, @@ -5326,21 +5345,21 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(87), 1, + ACTIONS(93), 1, aux_sym_base_ten_token1, - ACTIONS(91), 1, + ACTIONS(97), 1, anon_sym_if, - ACTIONS(93), 1, + ACTIONS(99), 1, anon_sym_let, - STATE(99), 1, + STATE(104), 1, sym__float, - STATE(102), 1, + STATE(111), 1, sym_number, - STATE(129), 1, + STATE(130), 1, sym_expression, - STATE(137), 1, + STATE(143), 1, sym_struct_definition, - STATE(189), 1, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -5351,11 +5370,11 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(89), 3, + ACTIONS(95), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -5380,7 +5399,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [4110] = 22, + [4131] = 22, ACTIONS(7), 1, sym_string, ACTIONS(11), 1, @@ -5397,21 +5416,21 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(87), 1, + ACTIONS(93), 1, aux_sym_base_ten_token1, - ACTIONS(91), 1, + ACTIONS(97), 1, anon_sym_if, - ACTIONS(93), 1, + ACTIONS(99), 1, anon_sym_let, - STATE(99), 1, + STATE(104), 1, sym__float, - STATE(102), 1, + STATE(111), 1, sym_number, STATE(131), 1, sym_expression, - STATE(137), 1, + STATE(143), 1, sym_struct_definition, - STATE(189), 1, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -5422,11 +5441,11 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(89), 3, + ACTIONS(95), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -5451,7 +5470,7 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [4203] = 22, + [4224] = 22, ACTIONS(7), 1, sym_string, ACTIONS(11), 1, @@ -5468,21 +5487,21 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - ACTIONS(87), 1, + ACTIONS(93), 1, aux_sym_base_ten_token1, - ACTIONS(91), 1, + ACTIONS(97), 1, anon_sym_if, - ACTIONS(93), 1, + ACTIONS(99), 1, anon_sym_let, - STATE(99), 1, + STATE(104), 1, sym__float, - STATE(102), 1, + STATE(111), 1, sym_number, STATE(132), 1, sym_expression, - STATE(137), 1, + STATE(143), 1, sym_struct_definition, - STATE(189), 1, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -5493,11 +5512,11 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(89), 3, + ACTIONS(95), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -5522,11 +5541,9 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [4296] = 22, + [4317] = 22, ACTIONS(7), 1, sym_string, - ACTIONS(9), 1, - aux_sym_base_ten_token1, ACTIONS(11), 1, aux_sym_octal_token1, ACTIONS(13), 1, @@ -5535,25 +5552,27 @@ static const uint16_t ts_small_parse_table[] = { aux_sym_binary_token1, ACTIONS(17), 1, anon_sym_LBRACE, - ACTIONS(23), 1, - anon_sym_if, - ACTIONS(25), 1, - anon_sym_let, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + ACTIONS(93), 1, + aux_sym_base_ten_token1, + ACTIONS(97), 1, + anon_sym_if, + ACTIONS(99), 1, + anon_sym_let, + STATE(104), 1, sym__float, - STATE(55), 1, + STATE(111), 1, sym_number, - STATE(67), 1, - sym_struct_definition, - STATE(134), 1, + STATE(133), 1, sym_expression, - STATE(189), 1, + STATE(143), 1, + sym_struct_definition, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -5564,11 +5583,11 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(21), 3, + ACTIONS(95), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -5593,11 +5612,9 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [4389] = 22, + [4410] = 22, ACTIONS(7), 1, sym_string, - ACTIONS(9), 1, - aux_sym_base_ten_token1, ACTIONS(11), 1, aux_sym_octal_token1, ACTIONS(13), 1, @@ -5606,25 +5623,27 @@ static const uint16_t ts_small_parse_table[] = { aux_sym_binary_token1, ACTIONS(17), 1, anon_sym_LBRACE, - ACTIONS(23), 1, - anon_sym_if, - ACTIONS(25), 1, - anon_sym_let, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + ACTIONS(93), 1, + aux_sym_base_ten_token1, + ACTIONS(97), 1, + anon_sym_if, + ACTIONS(99), 1, + anon_sym_let, + STATE(104), 1, sym__float, - STATE(55), 1, + STATE(111), 1, sym_number, - STATE(67), 1, - sym_struct_definition, - STATE(135), 1, + STATE(134), 1, sym_expression, - STATE(189), 1, + STATE(143), 1, + sym_struct_definition, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -5635,11 +5654,11 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(21), 3, + ACTIONS(95), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -5664,11 +5683,9 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [4482] = 22, + [4503] = 22, ACTIONS(7), 1, sym_string, - ACTIONS(9), 1, - aux_sym_base_ten_token1, ACTIONS(11), 1, aux_sym_octal_token1, ACTIONS(13), 1, @@ -5677,25 +5694,27 @@ static const uint16_t ts_small_parse_table[] = { aux_sym_binary_token1, ACTIONS(17), 1, anon_sym_LBRACE, - ACTIONS(23), 1, - anon_sym_if, - ACTIONS(25), 1, - anon_sym_let, ACTIONS(27), 1, anon_sym_LPAREN, ACTIONS(29), 1, anon_sym_LBRACK, ACTIONS(31), 1, anon_sym_LT_LT_LT, - STATE(53), 1, + ACTIONS(93), 1, + aux_sym_base_ten_token1, + ACTIONS(97), 1, + anon_sym_if, + ACTIONS(99), 1, + anon_sym_let, + STATE(104), 1, sym__float, - STATE(55), 1, + STATE(111), 1, sym_number, - STATE(67), 1, - sym_struct_definition, - STATE(117), 1, + STATE(138), 1, sym_expression, - STATE(189), 1, + STATE(143), 1, + sym_struct_definition, + STATE(201), 1, sym_integer, ACTIONS(3), 2, sym_comment, @@ -5706,11 +5725,11 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(19), 2, sym_true, sym_false, - ACTIONS(21), 3, + ACTIONS(95), 3, anon_sym_DASH, anon_sym_PLUS, anon_sym_BANG, - STATE(200), 4, + STATE(202), 4, sym_base_ten, sym_octal, sym_hex, @@ -5735,72 +5754,437 @@ static const uint16_t ts_small_parse_table[] = { sym_dictionary_construction, sym_closure_definition, sym_constraint_set, - [4575] = 4, + [4596] = 22, + ACTIONS(7), 1, + sym_string, + ACTIONS(11), 1, + aux_sym_octal_token1, + ACTIONS(13), 1, + aux_sym_hex_token1, + ACTIONS(15), 1, + aux_sym_binary_token1, + ACTIONS(17), 1, + anon_sym_LBRACE, + ACTIONS(27), 1, + anon_sym_LPAREN, + ACTIONS(29), 1, + anon_sym_LBRACK, + ACTIONS(31), 1, + anon_sym_LT_LT_LT, + ACTIONS(93), 1, + aux_sym_base_ten_token1, + ACTIONS(97), 1, + anon_sym_if, + ACTIONS(99), 1, + anon_sym_let, + STATE(104), 1, + sym__float, + STATE(111), 1, + sym_number, + STATE(139), 1, + sym_expression, + STATE(143), 1, + sym_struct_definition, + STATE(201), 1, + sym_integer, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(99), 2, - aux_sym_signed_integer_token1, - aux_sym_unsigned_integer_token1, - ACTIONS(97), 10, + ACTIONS(5), 2, sym_identifier, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_else, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(95), 23, - ts_builtin_sym_end, - sym_unit_quote, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_RBRACE, - anon_sym_COLON_COLON, + sym_self, + ACTIONS(19), 2, + sym_true, + sym_false, + ACTIONS(95), 3, anon_sym_DASH, anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - [4621] = 6, - ACTIONS(103), 1, - sym_identifier, - ACTIONS(105), 1, - sym_unit_quote, - STATE(60), 1, - sym__unit, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(107), 10, - anon_sym_STAR, - anon_sym_GT_GT, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_else, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(101), 22, - ts_builtin_sym_end, - anon_sym_DOT, + anon_sym_BANG, + STATE(202), 4, + sym_base_ten, + sym_octal, + sym_hex, + sym_binary, + STATE(92), 19, + sym_signed_integer, + sym_unsigned_integer, + sym_scalar, + sym_vector2, + sym_vector3, + sym_vector4, + sym_boolean, + sym_function_call, + sym_method_call, + sym_unary_expression, + sym_binary_expression, + sym_if, + sym_let_in, + sym_member_access, + sym_parenthesis, + sym_list, + sym_dictionary_construction, + sym_closure_definition, + sym_constraint_set, + [4689] = 22, + ACTIONS(7), 1, + sym_string, + ACTIONS(9), 1, + aux_sym_base_ten_token1, + ACTIONS(11), 1, + aux_sym_octal_token1, + ACTIONS(13), 1, + aux_sym_hex_token1, + ACTIONS(15), 1, + aux_sym_binary_token1, + ACTIONS(17), 1, + anon_sym_LBRACE, + ACTIONS(23), 1, + anon_sym_if, + ACTIONS(25), 1, + anon_sym_let, + ACTIONS(27), 1, + anon_sym_LPAREN, + ACTIONS(29), 1, + anon_sym_LBRACK, + ACTIONS(31), 1, + anon_sym_LT_LT_LT, + STATE(57), 1, + sym__float, + STATE(59), 1, + sym_number, + STATE(97), 1, + sym_struct_definition, + STATE(137), 1, + sym_expression, + STATE(201), 1, + sym_integer, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(5), 2, + sym_identifier, + sym_self, + ACTIONS(19), 2, + sym_true, + sym_false, + ACTIONS(21), 3, + anon_sym_DASH, + anon_sym_PLUS, + anon_sym_BANG, + STATE(202), 4, + sym_base_ten, + sym_octal, + sym_hex, + sym_binary, + STATE(92), 19, + sym_signed_integer, + sym_unsigned_integer, + sym_scalar, + sym_vector2, + sym_vector3, + sym_vector4, + sym_boolean, + sym_function_call, + sym_method_call, + sym_unary_expression, + sym_binary_expression, + sym_if, + sym_let_in, + sym_member_access, + sym_parenthesis, + sym_list, + sym_dictionary_construction, + sym_closure_definition, + sym_constraint_set, + [4782] = 22, + ACTIONS(7), 1, + sym_string, + ACTIONS(9), 1, + aux_sym_base_ten_token1, + ACTIONS(11), 1, + aux_sym_octal_token1, + ACTIONS(13), 1, + aux_sym_hex_token1, + ACTIONS(15), 1, + aux_sym_binary_token1, + ACTIONS(17), 1, + anon_sym_LBRACE, + ACTIONS(23), 1, + anon_sym_if, + ACTIONS(25), 1, + anon_sym_let, + ACTIONS(27), 1, + anon_sym_LPAREN, + ACTIONS(29), 1, + anon_sym_LBRACK, + ACTIONS(31), 1, + anon_sym_LT_LT_LT, + STATE(57), 1, + sym__float, + STATE(59), 1, + sym_number, + STATE(97), 1, + sym_struct_definition, + STATE(141), 1, + sym_expression, + STATE(201), 1, + sym_integer, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(5), 2, + sym_identifier, + sym_self, + ACTIONS(19), 2, + sym_true, + sym_false, + ACTIONS(21), 3, + anon_sym_DASH, + anon_sym_PLUS, + anon_sym_BANG, + STATE(202), 4, + sym_base_ten, + sym_octal, + sym_hex, + sym_binary, + STATE(92), 19, + sym_signed_integer, + sym_unsigned_integer, + sym_scalar, + sym_vector2, + sym_vector3, + sym_vector4, + sym_boolean, + sym_function_call, + sym_method_call, + sym_unary_expression, + sym_binary_expression, + sym_if, + sym_let_in, + sym_member_access, + sym_parenthesis, + sym_list, + sym_dictionary_construction, + sym_closure_definition, + sym_constraint_set, + [4875] = 22, + ACTIONS(7), 1, + sym_string, + ACTIONS(9), 1, + aux_sym_base_ten_token1, + ACTIONS(11), 1, + aux_sym_octal_token1, + ACTIONS(13), 1, + aux_sym_hex_token1, + ACTIONS(15), 1, + aux_sym_binary_token1, + ACTIONS(17), 1, + anon_sym_LBRACE, + ACTIONS(23), 1, + anon_sym_if, + ACTIONS(25), 1, + anon_sym_let, + ACTIONS(27), 1, + anon_sym_LPAREN, + ACTIONS(29), 1, + anon_sym_LBRACK, + ACTIONS(31), 1, + anon_sym_LT_LT_LT, + STATE(57), 1, + sym__float, + STATE(59), 1, + sym_number, + STATE(97), 1, + sym_struct_definition, + STATE(98), 1, + sym_expression, + STATE(201), 1, + sym_integer, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(5), 2, + sym_identifier, + sym_self, + ACTIONS(19), 2, + sym_true, + sym_false, + ACTIONS(21), 3, + anon_sym_DASH, + anon_sym_PLUS, + anon_sym_BANG, + STATE(202), 4, + sym_base_ten, + sym_octal, + sym_hex, + sym_binary, + STATE(92), 19, + sym_signed_integer, + sym_unsigned_integer, + sym_scalar, + sym_vector2, + sym_vector3, + sym_vector4, + sym_boolean, + sym_function_call, + sym_method_call, + sym_unary_expression, + sym_binary_expression, + sym_if, + sym_let_in, + sym_member_access, + sym_parenthesis, + sym_list, + sym_dictionary_construction, + sym_closure_definition, + sym_constraint_set, + [4968] = 4, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(105), 2, + aux_sym_signed_integer_token1, + aux_sym_unsigned_integer_token1, + ACTIONS(103), 10, + sym_identifier, + anon_sym_STAR, + anon_sym_AMP, + anon_sym_PIPE, + anon_sym_CARET, + anon_sym_GT, + anon_sym_LT, + anon_sym_else, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(101), 23, + ts_builtin_sym_end, + sym_unit_quote, + anon_sym_DOT, + anon_sym_COMMA, + anon_sym_RBRACE, + anon_sym_COLON_COLON, + anon_sym_DASH, + anon_sym_PLUS, + anon_sym_STAR_STAR, + anon_sym_SLASH, + anon_sym_LT_LT, + anon_sym_GT_GT, + anon_sym_GT_EQ, + anon_sym_EQ_EQ, + anon_sym_LT_EQ, + anon_sym_BANG_EQ, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_CARET_CARET, + anon_sym_SEMI, + anon_sym_LPAREN, + anon_sym_RPAREN, + anon_sym_RBRACK, + [5014] = 6, + ACTIONS(109), 1, + sym_identifier, + ACTIONS(111), 1, + sym_unit_quote, + STATE(63), 1, + sym__unit, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(113), 10, + anon_sym_STAR, + anon_sym_GT_GT, + anon_sym_AMP, + anon_sym_PIPE, + anon_sym_CARET, + anon_sym_GT, + anon_sym_LT, + anon_sym_else, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(107), 22, + ts_builtin_sym_end, + anon_sym_DOT, + anon_sym_COMMA, + anon_sym_RBRACE, + anon_sym_COLON_COLON, + anon_sym_DASH, + anon_sym_PLUS, + anon_sym_STAR_STAR, + anon_sym_SLASH, + anon_sym_LT_LT, + anon_sym_GT_EQ, + anon_sym_EQ_EQ, + anon_sym_LT_EQ, + anon_sym_BANG_EQ, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_CARET_CARET, + anon_sym_SEMI, + anon_sym_LPAREN, + anon_sym_RPAREN, + anon_sym_RBRACK, + anon_sym_GT_GT_GT, + [5064] = 3, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(117), 11, + sym_identifier, + anon_sym_STAR, + anon_sym_GT_GT, + anon_sym_AMP, + anon_sym_PIPE, + anon_sym_CARET, + anon_sym_GT, + anon_sym_LT, + anon_sym_else, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(115), 23, + ts_builtin_sym_end, + sym_unit_quote, + anon_sym_DOT, + anon_sym_COMMA, + anon_sym_RBRACE, + anon_sym_COLON_COLON, + anon_sym_DASH, + anon_sym_PLUS, + anon_sym_STAR_STAR, + anon_sym_SLASH, + anon_sym_LT_LT, + anon_sym_GT_EQ, + anon_sym_EQ_EQ, + anon_sym_LT_EQ, + anon_sym_BANG_EQ, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_CARET_CARET, + anon_sym_SEMI, + anon_sym_LPAREN, + anon_sym_RPAREN, + anon_sym_RBRACK, + anon_sym_GT_GT_GT, + [5107] = 4, + ACTIONS(123), 1, + anon_sym_DOT, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(121), 11, + sym_identifier, + anon_sym_STAR, + anon_sym_GT_GT, + anon_sym_AMP, + anon_sym_PIPE, + anon_sym_CARET, + anon_sym_GT, + anon_sym_LT, + anon_sym_else, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(119), 22, + ts_builtin_sym_end, + sym_unit_quote, anon_sym_COMMA, anon_sym_RBRACE, anon_sym_COLON_COLON, @@ -5821,34 +6205,114 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_RPAREN, anon_sym_RBRACK, anon_sym_GT_GT_GT, - [4671] = 3, + [5152] = 3, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(103), 11, + sym_identifier, + anon_sym_STAR, + anon_sym_GT_GT, + anon_sym_AMP, + anon_sym_PIPE, + anon_sym_CARET, + anon_sym_GT, + anon_sym_LT, + anon_sym_else, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(101), 23, + ts_builtin_sym_end, + sym_unit_quote, + anon_sym_DOT, + anon_sym_COMMA, + anon_sym_RBRACE, + anon_sym_COLON_COLON, + anon_sym_DASH, + anon_sym_PLUS, + anon_sym_STAR_STAR, + anon_sym_SLASH, + anon_sym_LT_LT, + anon_sym_GT_EQ, + anon_sym_EQ_EQ, + anon_sym_LT_EQ, + anon_sym_BANG_EQ, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_CARET_CARET, + anon_sym_SEMI, + anon_sym_LPAREN, + anon_sym_RPAREN, + anon_sym_RBRACK, + anon_sym_GT_GT_GT, + [5195] = 7, + ACTIONS(127), 1, + anon_sym_DOT, + ACTIONS(129), 1, + anon_sym_COLON_COLON, + ACTIONS(133), 1, + anon_sym_LPAREN, + STATE(99), 1, + sym_dictionary_construction, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(131), 8, + anon_sym_STAR, + anon_sym_AMP, + anon_sym_PIPE, + anon_sym_CARET, + anon_sym_GT, + anon_sym_LT, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(125), 21, + ts_builtin_sym_end, + anon_sym_COMMA, + anon_sym_RBRACE, + anon_sym_DASH, + anon_sym_PLUS, + anon_sym_STAR_STAR, + anon_sym_SLASH, + anon_sym_LT_LT, + anon_sym_GT_GT, + anon_sym_GT_EQ, + anon_sym_EQ_EQ, + anon_sym_LT_EQ, + anon_sym_BANG_EQ, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_CARET_CARET, + anon_sym_then, + anon_sym_else, + anon_sym_SEMI, + anon_sym_RPAREN, + anon_sym_RBRACK, + [5245] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(111), 11, - sym_identifier, + ACTIONS(137), 9, + anon_sym_DASH, anon_sym_STAR, - anon_sym_GT_GT, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - anon_sym_else, anon_sym_EQ, anon_sym_COLON, - ACTIONS(109), 23, + ACTIONS(135), 24, ts_builtin_sym_end, - sym_unit_quote, anon_sym_DOT, anon_sym_COMMA, anon_sym_RBRACE, anon_sym_COLON_COLON, - anon_sym_DASH, anon_sym_PLUS, anon_sym_STAR_STAR, anon_sym_SLASH, anon_sym_LT_LT, + anon_sym_GT_GT, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, @@ -5856,19 +6320,18 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, + anon_sym_then, + anon_sym_else, anon_sym_SEMI, anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - anon_sym_GT_GT_GT, - [4714] = 4, - ACTIONS(117), 1, - anon_sym_DOT, + anon_sym_DASH_GT, + [5287] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(115), 11, - sym_identifier, + ACTIONS(141), 9, anon_sym_STAR, anon_sym_GT_GT, anon_sym_AMP, @@ -5876,12 +6339,11 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_CARET, anon_sym_GT, anon_sym_LT, - anon_sym_else, anon_sym_EQ, anon_sym_COLON, - ACTIONS(113), 22, + ACTIONS(139), 24, ts_builtin_sym_end, - sym_unit_quote, + anon_sym_DOT, anon_sym_COMMA, anon_sym_RBRACE, anon_sym_COLON_COLON, @@ -5897,39 +6359,38 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, + anon_sym_then, + anon_sym_else, anon_sym_SEMI, anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, anon_sym_GT_GT_GT, - [4759] = 3, + [5329] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(97), 11, - sym_identifier, + ACTIONS(145), 9, + anon_sym_DASH, anon_sym_STAR, - anon_sym_GT_GT, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - anon_sym_else, anon_sym_EQ, anon_sym_COLON, - ACTIONS(95), 23, + ACTIONS(143), 24, ts_builtin_sym_end, - sym_unit_quote, anon_sym_DOT, anon_sym_COMMA, anon_sym_RBRACE, anon_sym_COLON_COLON, - anon_sym_DASH, anon_sym_PLUS, anon_sym_STAR_STAR, anon_sym_SLASH, anon_sym_LT_LT, + anon_sym_GT_GT, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, @@ -5937,18 +6398,20 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, + anon_sym_then, + anon_sym_else, anon_sym_SEMI, anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - anon_sym_GT_GT_GT, - [4802] = 4, - ACTIONS(123), 1, + anon_sym_DASH_GT, + [5371] = 4, + ACTIONS(151), 1, anon_sym_DASH_GT, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(121), 9, + ACTIONS(149), 9, anon_sym_DASH, anon_sym_STAR, anon_sym_AMP, @@ -5958,7 +6421,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(119), 23, + ACTIONS(147), 23, ts_builtin_sym_end, anon_sym_DOT, anon_sym_COMMA, @@ -5982,11 +6445,11 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - [4846] = 3, + [5415] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(127), 9, + ACTIONS(155), 9, anon_sym_DASH, anon_sym_STAR, anon_sym_AMP, @@ -5996,7 +6459,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(125), 24, + ACTIONS(153), 24, ts_builtin_sym_end, anon_sym_DOT, anon_sym_COMMA, @@ -6021,19 +6484,11 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_RPAREN, anon_sym_RBRACK, anon_sym_DASH_GT, - [4888] = 7, - ACTIONS(131), 1, - anon_sym_DOT, - ACTIONS(133), 1, - anon_sym_COLON_COLON, - ACTIONS(137), 1, - anon_sym_LPAREN, - STATE(80), 1, - sym_dictionary_construction, + [5457] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(135), 8, + ACTIONS(149), 8, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, @@ -6042,10 +6497,12 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(129), 21, + ACTIONS(147), 24, ts_builtin_sym_end, + anon_sym_DOT, anon_sym_COMMA, anon_sym_RBRACE, + anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, anon_sym_STAR_STAR, @@ -6062,15 +6519,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_then, anon_sym_else, anon_sym_SEMI, + anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - [4938] = 3, + [5498] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(141), 9, + ACTIONS(159), 8, anon_sym_STAR, - anon_sym_GT_GT, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, @@ -6078,7 +6535,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(139), 24, + ACTIONS(157), 24, ts_builtin_sym_end, anon_sym_DOT, anon_sym_COMMA, @@ -6089,6 +6546,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_STAR_STAR, anon_sym_SLASH, anon_sym_LT_LT, + anon_sym_GT_GT, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, @@ -6102,13 +6560,11 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - anon_sym_GT_GT_GT, - [4980] = 3, + [5539] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(145), 9, - anon_sym_DASH, + ACTIONS(163), 8, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, @@ -6117,12 +6573,13 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(143), 24, + ACTIONS(161), 24, ts_builtin_sym_end, anon_sym_DOT, anon_sym_COMMA, anon_sym_RBRACE, anon_sym_COLON_COLON, + anon_sym_DASH, anon_sym_PLUS, anon_sym_STAR_STAR, anon_sym_SLASH, @@ -6141,13 +6598,11 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - anon_sym_DASH_GT, - [5022] = 3, + [5580] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(149), 9, - anon_sym_DASH, + ACTIONS(167), 8, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, @@ -6156,12 +6611,13 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(147), 24, + ACTIONS(165), 24, ts_builtin_sym_end, anon_sym_DOT, anon_sym_COMMA, anon_sym_RBRACE, anon_sym_COLON_COLON, + anon_sym_DASH, anon_sym_PLUS, anon_sym_STAR_STAR, anon_sym_SLASH, @@ -6180,173 +6636,63 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - anon_sym_DASH_GT, - [5064] = 15, - ACTIONS(131), 1, - anon_sym_DOT, - ACTIONS(133), 1, - anon_sym_COLON_COLON, - ACTIONS(137), 1, - anon_sym_LPAREN, - ACTIONS(153), 1, - anon_sym_STAR_STAR, - ACTIONS(155), 1, + [5621] = 3, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(171), 8, anon_sym_STAR, - ACTIONS(157), 1, - anon_sym_SLASH, - ACTIONS(161), 1, anon_sym_AMP, - ACTIONS(163), 1, anon_sym_PIPE, - ACTIONS(165), 1, anon_sym_CARET, - STATE(80), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(151), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(159), 2, - anon_sym_LT_LT, - anon_sym_GT_GT, - ACTIONS(135), 4, anon_sym_GT, anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(129), 14, + ACTIONS(169), 24, ts_builtin_sym_end, + anon_sym_DOT, anon_sym_COMMA, anon_sym_RBRACE, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_else, - anon_sym_SEMI, - anon_sym_RPAREN, - anon_sym_RBRACK, - [5129] = 20, - ACTIONS(131), 1, - anon_sym_DOT, - ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, - anon_sym_LPAREN, - ACTIONS(153), 1, - anon_sym_STAR_STAR, - ACTIONS(155), 1, - anon_sym_STAR, - ACTIONS(157), 1, - anon_sym_SLASH, - ACTIONS(161), 1, - anon_sym_AMP, - ACTIONS(163), 1, - anon_sym_PIPE, - ACTIONS(165), 1, - anon_sym_CARET, - ACTIONS(173), 1, - anon_sym_AMP_AMP, - ACTIONS(175), 1, - anon_sym_PIPE_PIPE, - ACTIONS(177), 1, - anon_sym_CARET_CARET, - STATE(80), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(159), 2, + anon_sym_STAR_STAR, + anon_sym_SLASH, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(169), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(179), 2, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - ACTIONS(167), 7, - ts_builtin_sym_end, - anon_sym_COMMA, - anon_sym_RBRACE, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_CARET_CARET, + anon_sym_then, anon_sym_else, anon_sym_SEMI, + anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - [5204] = 20, - ACTIONS(131), 1, + [5662] = 10, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(153), 1, - anon_sym_STAR_STAR, - ACTIONS(155), 1, - anon_sym_STAR, - ACTIONS(157), 1, - anon_sym_SLASH, - ACTIONS(161), 1, - anon_sym_AMP, - ACTIONS(163), 1, - anon_sym_PIPE, - ACTIONS(165), 1, - anon_sym_CARET, ACTIONS(173), 1, - anon_sym_AMP_AMP, + anon_sym_STAR_STAR, ACTIONS(175), 1, - anon_sym_PIPE_PIPE, + anon_sym_STAR, ACTIONS(177), 1, - anon_sym_CARET_CARET, - STATE(80), 1, + anon_sym_SLASH, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(151), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(159), 2, - anon_sym_LT_LT, - anon_sym_GT_GT, - ACTIONS(169), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(183), 2, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(171), 4, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - ACTIONS(181), 7, - ts_builtin_sym_end, - anon_sym_COMMA, - anon_sym_RBRACE, - anon_sym_else, - anon_sym_SEMI, - anon_sym_RPAREN, - anon_sym_RBRACK, - [5279] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(187), 8, - anon_sym_STAR, + ACTIONS(131), 7, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, @@ -6354,16 +6700,12 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(185), 24, + ACTIONS(125), 18, ts_builtin_sym_end, - anon_sym_DOT, anon_sym_COMMA, anon_sym_RBRACE, - anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, anon_sym_LT_LT, anon_sym_GT_GT, anon_sym_GT_EQ, @@ -6373,20 +6715,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, - anon_sym_then, anon_sym_else, anon_sym_SEMI, - anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - [5320] = 4, - ACTIONS(193), 1, - anon_sym_DASH_GT, + [5717] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(191), 9, - anon_sym_DASH, + ACTIONS(181), 8, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, @@ -6395,12 +6732,13 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(189), 22, + ACTIONS(179), 24, ts_builtin_sym_end, anon_sym_DOT, anon_sym_COMMA, anon_sym_RBRACE, anon_sym_COLON_COLON, + anon_sym_DASH, anon_sym_PLUS, anon_sym_STAR_STAR, anon_sym_SLASH, @@ -6413,16 +6751,27 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, + anon_sym_then, anon_sym_else, anon_sym_SEMI, anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - [5363] = 3, + [5758] = 8, + ACTIONS(127), 1, + anon_sym_DOT, + ACTIONS(129), 1, + anon_sym_COLON_COLON, + ACTIONS(133), 1, + anon_sym_LPAREN, + ACTIONS(173), 1, + anon_sym_STAR_STAR, + STATE(99), 1, + sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(197), 8, + ACTIONS(131), 8, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, @@ -6431,15 +6780,12 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(195), 24, + ACTIONS(125), 19, ts_builtin_sym_end, - anon_sym_DOT, anon_sym_COMMA, anon_sym_RBRACE, - anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, - anon_sym_STAR_STAR, anon_sym_SLASH, anon_sym_LT_LT, anon_sym_GT_GT, @@ -6450,18 +6796,32 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, - anon_sym_then, anon_sym_else, anon_sym_SEMI, - anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - [5404] = 3, + [5809] = 11, + ACTIONS(127), 1, + anon_sym_DOT, + ACTIONS(129), 1, + anon_sym_COLON_COLON, + ACTIONS(133), 1, + anon_sym_LPAREN, + ACTIONS(173), 1, + anon_sym_STAR_STAR, + ACTIONS(175), 1, + anon_sym_STAR, + ACTIONS(177), 1, + anon_sym_SLASH, + STATE(99), 1, + sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(201), 8, - anon_sym_STAR, + ACTIONS(183), 2, + anon_sym_DASH, + anon_sym_PLUS, + ACTIONS(131), 7, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, @@ -6469,16 +6829,10 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(199), 24, + ACTIONS(125), 16, ts_builtin_sym_end, - anon_sym_DOT, anon_sym_COMMA, anon_sym_RBRACE, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, anon_sym_LT_LT, anon_sym_GT_GT, anon_sym_GT_EQ, @@ -6488,92 +6842,95 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, - anon_sym_then, anon_sym_else, anon_sym_SEMI, - anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - [5445] = 20, - ACTIONS(131), 1, + [5866] = 12, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(153), 1, - anon_sym_STAR_STAR, - ACTIONS(155), 1, - anon_sym_STAR, - ACTIONS(157), 1, - anon_sym_SLASH, - ACTIONS(161), 1, - anon_sym_AMP, - ACTIONS(163), 1, - anon_sym_PIPE, - ACTIONS(165), 1, - anon_sym_CARET, ACTIONS(173), 1, - anon_sym_AMP_AMP, + anon_sym_STAR_STAR, ACTIONS(175), 1, - anon_sym_PIPE_PIPE, + anon_sym_STAR, ACTIONS(177), 1, - anon_sym_CARET_CARET, - STATE(80), 1, + anon_sym_SLASH, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(151), 2, + ACTIONS(183), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(159), 2, + ACTIONS(185), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(169), 2, + ACTIONS(131), 7, + anon_sym_AMP, + anon_sym_PIPE, + anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(205), 2, anon_sym_EQ, anon_sym_COLON, - ACTIONS(171), 4, + ACTIONS(125), 14, + ts_builtin_sym_end, + anon_sym_COMMA, + anon_sym_RBRACE, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - ACTIONS(203), 7, - ts_builtin_sym_end, - anon_sym_COMMA, - anon_sym_RBRACE, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_CARET_CARET, anon_sym_else, anon_sym_SEMI, anon_sym_RPAREN, anon_sym_RBRACK, - [5520] = 3, + [5925] = 14, + ACTIONS(127), 1, + anon_sym_DOT, + ACTIONS(129), 1, + anon_sym_COLON_COLON, + ACTIONS(133), 1, + anon_sym_LPAREN, + ACTIONS(173), 1, + anon_sym_STAR_STAR, + ACTIONS(175), 1, + anon_sym_STAR, + ACTIONS(177), 1, + anon_sym_SLASH, + ACTIONS(187), 1, + anon_sym_AMP, + ACTIONS(189), 1, + anon_sym_CARET, + STATE(99), 1, + sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(209), 8, - anon_sym_STAR, - anon_sym_AMP, + ACTIONS(183), 2, + anon_sym_DASH, + anon_sym_PLUS, + ACTIONS(185), 2, + anon_sym_LT_LT, + anon_sym_GT_GT, + ACTIONS(131), 5, anon_sym_PIPE, - anon_sym_CARET, anon_sym_GT, anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(207), 24, + ACTIONS(125), 14, ts_builtin_sym_end, - anon_sym_DOT, anon_sym_COMMA, anon_sym_RBRACE, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, @@ -6581,37 +6938,47 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, - anon_sym_then, anon_sym_else, anon_sym_SEMI, - anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - [5561] = 3, + [5988] = 13, + ACTIONS(127), 1, + anon_sym_DOT, + ACTIONS(129), 1, + anon_sym_COLON_COLON, + ACTIONS(133), 1, + anon_sym_LPAREN, + ACTIONS(173), 1, + anon_sym_STAR_STAR, + ACTIONS(175), 1, + anon_sym_STAR, + ACTIONS(177), 1, + anon_sym_SLASH, + ACTIONS(187), 1, + anon_sym_AMP, + STATE(99), 1, + sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(213), 8, - anon_sym_STAR, - anon_sym_AMP, + ACTIONS(183), 2, + anon_sym_DASH, + anon_sym_PLUS, + ACTIONS(185), 2, + anon_sym_LT_LT, + anon_sym_GT_GT, + ACTIONS(131), 6, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(211), 24, + ACTIONS(125), 14, ts_builtin_sym_end, - anon_sym_DOT, anon_sym_COMMA, anon_sym_RBRACE, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, @@ -6619,37 +6986,49 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, - anon_sym_then, anon_sym_else, anon_sym_SEMI, - anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - [5602] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(217), 8, + [6049] = 15, + ACTIONS(127), 1, + anon_sym_DOT, + ACTIONS(129), 1, + anon_sym_COLON_COLON, + ACTIONS(133), 1, + anon_sym_LPAREN, + ACTIONS(173), 1, + anon_sym_STAR_STAR, + ACTIONS(175), 1, anon_sym_STAR, + ACTIONS(177), 1, + anon_sym_SLASH, + ACTIONS(187), 1, anon_sym_AMP, - anon_sym_PIPE, + ACTIONS(189), 1, anon_sym_CARET, + ACTIONS(191), 1, + anon_sym_PIPE, + STATE(99), 1, + sym_dictionary_construction, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(183), 2, + anon_sym_DASH, + anon_sym_PLUS, + ACTIONS(185), 2, + anon_sym_LT_LT, + anon_sym_GT_GT, + ACTIONS(131), 4, anon_sym_GT, anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(215), 24, + ACTIONS(125), 14, ts_builtin_sym_end, - anon_sym_DOT, anon_sym_COMMA, anon_sym_RBRACE, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, @@ -6657,241 +7036,229 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, - anon_sym_then, anon_sym_else, anon_sym_SEMI, - anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - [5643] = 20, - ACTIONS(131), 1, + [6114] = 17, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(153), 1, + ACTIONS(173), 1, anon_sym_STAR_STAR, - ACTIONS(155), 1, + ACTIONS(175), 1, anon_sym_STAR, - ACTIONS(157), 1, + ACTIONS(177), 1, anon_sym_SLASH, - ACTIONS(161), 1, + ACTIONS(187), 1, anon_sym_AMP, - ACTIONS(163), 1, - anon_sym_PIPE, - ACTIONS(165), 1, + ACTIONS(189), 1, anon_sym_CARET, - ACTIONS(173), 1, - anon_sym_AMP_AMP, - ACTIONS(175), 1, - anon_sym_PIPE_PIPE, - ACTIONS(177), 1, - anon_sym_CARET_CARET, - STATE(80), 1, + ACTIONS(191), 1, + anon_sym_PIPE, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(151), 2, + ACTIONS(131), 2, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(183), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(159), 2, + ACTIONS(185), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(169), 2, + ACTIONS(193), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(221), 2, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(171), 4, + ACTIONS(195), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - ACTIONS(219), 7, + ACTIONS(125), 10, ts_builtin_sym_end, anon_sym_COMMA, anon_sym_RBRACE, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_CARET_CARET, anon_sym_else, anon_sym_SEMI, anon_sym_RPAREN, anon_sym_RBRACK, - [5718] = 20, - ACTIONS(131), 1, + [6183] = 18, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(153), 1, + ACTIONS(173), 1, anon_sym_STAR_STAR, - ACTIONS(155), 1, + ACTIONS(175), 1, anon_sym_STAR, - ACTIONS(157), 1, + ACTIONS(177), 1, anon_sym_SLASH, - ACTIONS(161), 1, + ACTIONS(187), 1, anon_sym_AMP, - ACTIONS(163), 1, - anon_sym_PIPE, - ACTIONS(165), 1, + ACTIONS(189), 1, anon_sym_CARET, - ACTIONS(173), 1, + ACTIONS(191), 1, + anon_sym_PIPE, + ACTIONS(197), 1, anon_sym_AMP_AMP, - ACTIONS(175), 1, - anon_sym_PIPE_PIPE, - ACTIONS(177), 1, - anon_sym_CARET_CARET, - STATE(80), 1, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(151), 2, + ACTIONS(131), 2, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(183), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(159), 2, + ACTIONS(185), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(169), 2, + ACTIONS(193), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(225), 2, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(171), 4, + ACTIONS(195), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - ACTIONS(223), 7, + ACTIONS(125), 9, ts_builtin_sym_end, anon_sym_COMMA, anon_sym_RBRACE, + anon_sym_PIPE_PIPE, + anon_sym_CARET_CARET, anon_sym_else, anon_sym_SEMI, anon_sym_RPAREN, anon_sym_RBRACK, - [5793] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(229), 8, + [6254] = 19, + ACTIONS(127), 1, + anon_sym_DOT, + ACTIONS(129), 1, + anon_sym_COLON_COLON, + ACTIONS(133), 1, + anon_sym_LPAREN, + ACTIONS(173), 1, + anon_sym_STAR_STAR, + ACTIONS(175), 1, anon_sym_STAR, + ACTIONS(177), 1, + anon_sym_SLASH, + ACTIONS(187), 1, anon_sym_AMP, - anon_sym_PIPE, + ACTIONS(189), 1, anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, + ACTIONS(191), 1, + anon_sym_PIPE, + ACTIONS(197), 1, + anon_sym_AMP_AMP, + ACTIONS(199), 1, + anon_sym_PIPE_PIPE, + STATE(99), 1, + sym_dictionary_construction, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(131), 2, anon_sym_EQ, anon_sym_COLON, - ACTIONS(227), 24, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_RBRACE, - anon_sym_COLON_COLON, + ACTIONS(183), 2, anon_sym_DASH, anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, + ACTIONS(185), 2, anon_sym_LT_LT, anon_sym_GT_GT, + ACTIONS(193), 2, + anon_sym_GT, + anon_sym_LT, + ACTIONS(195), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, + ACTIONS(125), 8, + ts_builtin_sym_end, + anon_sym_COMMA, + anon_sym_RBRACE, anon_sym_CARET_CARET, - anon_sym_then, anon_sym_else, anon_sym_SEMI, - anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - [5834] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(233), 8, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(231), 24, - ts_builtin_sym_end, + [6327] = 20, + ACTIONS(127), 1, anon_sym_DOT, - anon_sym_COMMA, - anon_sym_RBRACE, + ACTIONS(129), 1, anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, + ACTIONS(133), 1, + anon_sym_LPAREN, + ACTIONS(173), 1, anon_sym_STAR_STAR, + ACTIONS(175), 1, + anon_sym_STAR, + ACTIONS(177), 1, anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, + ACTIONS(187), 1, + anon_sym_AMP, + ACTIONS(189), 1, + anon_sym_CARET, + ACTIONS(191), 1, + anon_sym_PIPE, + ACTIONS(197), 1, anon_sym_AMP_AMP, + ACTIONS(199), 1, anon_sym_PIPE_PIPE, + ACTIONS(203), 1, anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, - anon_sym_LPAREN, - anon_sym_RPAREN, - anon_sym_RBRACK, - [5875] = 3, + STATE(99), 1, + sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(237), 8, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(235), 24, - ts_builtin_sym_end, - anon_sym_DOT, - anon_sym_COMMA, - anon_sym_RBRACE, - anon_sym_COLON_COLON, + ACTIONS(183), 2, anon_sym_DASH, anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, + ACTIONS(185), 2, anon_sym_LT_LT, anon_sym_GT_GT, + ACTIONS(193), 2, + anon_sym_GT, + anon_sym_LT, + ACTIONS(205), 2, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(195), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, + ACTIONS(201), 7, + ts_builtin_sym_end, + anon_sym_COMMA, + anon_sym_RBRACE, anon_sym_else, anon_sym_SEMI, - anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - [5916] = 3, + [6402] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(241), 8, + ACTIONS(209), 8, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, @@ -6900,7 +7267,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(239), 24, + ACTIONS(207), 24, ts_builtin_sym_end, anon_sym_DOT, anon_sym_COMMA, @@ -6925,11 +7292,11 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - [5957] = 3, + [6443] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(245), 8, + ACTIONS(213), 8, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, @@ -6938,7 +7305,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(243), 24, + ACTIONS(211), 24, ts_builtin_sym_end, anon_sym_DOT, anon_sym_COMMA, @@ -6963,11 +7330,11 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - [5998] = 3, + [6484] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(249), 8, + ACTIONS(217), 8, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, @@ -6976,7 +7343,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(247), 24, + ACTIONS(215), 24, ts_builtin_sym_end, anon_sym_DOT, anon_sym_COMMA, @@ -7001,11 +7368,11 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - [6039] = 3, + [6525] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(253), 8, + ACTIONS(221), 8, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, @@ -7014,7 +7381,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(251), 24, + ACTIONS(219), 24, ts_builtin_sym_end, anon_sym_DOT, anon_sym_COMMA, @@ -7039,11 +7406,11 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - [6080] = 3, + [6566] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(257), 8, + ACTIONS(225), 8, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, @@ -7052,7 +7419,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(255), 24, + ACTIONS(223), 24, ts_builtin_sym_end, anon_sym_DOT, anon_sym_COMMA, @@ -7077,11 +7444,11 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - [6121] = 3, + [6607] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(261), 8, + ACTIONS(229), 8, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, @@ -7090,7 +7457,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(259), 24, + ACTIONS(227), 24, ts_builtin_sym_end, anon_sym_DOT, anon_sym_COMMA, @@ -7115,56 +7482,121 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - [6162] = 10, - ACTIONS(131), 1, + [6648] = 20, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(153), 1, + ACTIONS(173), 1, anon_sym_STAR_STAR, - ACTIONS(155), 1, + ACTIONS(175), 1, anon_sym_STAR, - ACTIONS(157), 1, + ACTIONS(177), 1, anon_sym_SLASH, - STATE(80), 1, + ACTIONS(187), 1, + anon_sym_AMP, + ACTIONS(189), 1, + anon_sym_CARET, + ACTIONS(191), 1, + anon_sym_PIPE, + ACTIONS(197), 1, + anon_sym_AMP_AMP, + ACTIONS(199), 1, + anon_sym_PIPE_PIPE, + ACTIONS(203), 1, + anon_sym_CARET_CARET, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(135), 7, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, + ACTIONS(183), 2, + anon_sym_DASH, + anon_sym_PLUS, + ACTIONS(185), 2, + anon_sym_LT_LT, + anon_sym_GT_GT, + ACTIONS(193), 2, anon_sym_GT, anon_sym_LT, + ACTIONS(233), 2, anon_sym_EQ, anon_sym_COLON, - ACTIONS(129), 18, + ACTIONS(195), 4, + anon_sym_GT_EQ, + anon_sym_EQ_EQ, + anon_sym_LT_EQ, + anon_sym_BANG_EQ, + ACTIONS(231), 7, ts_builtin_sym_end, anon_sym_COMMA, anon_sym_RBRACE, + anon_sym_else, + anon_sym_SEMI, + anon_sym_RPAREN, + anon_sym_RBRACK, + [6723] = 20, + ACTIONS(127), 1, + anon_sym_DOT, + ACTIONS(129), 1, + anon_sym_COLON_COLON, + ACTIONS(133), 1, + anon_sym_LPAREN, + ACTIONS(173), 1, + anon_sym_STAR_STAR, + ACTIONS(175), 1, + anon_sym_STAR, + ACTIONS(177), 1, + anon_sym_SLASH, + ACTIONS(187), 1, + anon_sym_AMP, + ACTIONS(189), 1, + anon_sym_CARET, + ACTIONS(191), 1, + anon_sym_PIPE, + ACTIONS(197), 1, + anon_sym_AMP_AMP, + ACTIONS(199), 1, + anon_sym_PIPE_PIPE, + ACTIONS(203), 1, + anon_sym_CARET_CARET, + STATE(99), 1, + sym_dictionary_construction, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(183), 2, anon_sym_DASH, anon_sym_PLUS, + ACTIONS(185), 2, anon_sym_LT_LT, anon_sym_GT_GT, + ACTIONS(193), 2, + anon_sym_GT, + anon_sym_LT, + ACTIONS(237), 2, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(195), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, + ACTIONS(235), 7, + ts_builtin_sym_end, + anon_sym_COMMA, + anon_sym_RBRACE, anon_sym_else, anon_sym_SEMI, anon_sym_RPAREN, anon_sym_RBRACK, - [6217] = 3, + [6798] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(265), 8, + ACTIONS(241), 8, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, @@ -7173,7 +7605,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(263), 24, + ACTIONS(239), 24, ts_builtin_sym_end, anon_sym_DOT, anon_sym_COMMA, @@ -7198,21 +7630,11 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - [6258] = 8, - ACTIONS(131), 1, - anon_sym_DOT, - ACTIONS(133), 1, - anon_sym_COLON_COLON, - ACTIONS(137), 1, - anon_sym_LPAREN, - ACTIONS(153), 1, - anon_sym_STAR_STAR, - STATE(80), 1, - sym_dictionary_construction, + [6839] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(135), 8, + ACTIONS(245), 8, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, @@ -7221,12 +7643,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(129), 19, + ACTIONS(243), 24, ts_builtin_sym_end, + anon_sym_DOT, anon_sym_COMMA, anon_sym_RBRACE, + anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, + anon_sym_STAR_STAR, anon_sym_SLASH, anon_sym_LT_LT, anon_sym_GT_GT, @@ -7237,32 +7662,18 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, + anon_sym_then, anon_sym_else, anon_sym_SEMI, + anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - [6309] = 11, - ACTIONS(131), 1, - anon_sym_DOT, - ACTIONS(133), 1, - anon_sym_COLON_COLON, - ACTIONS(137), 1, - anon_sym_LPAREN, - ACTIONS(153), 1, - anon_sym_STAR_STAR, - ACTIONS(155), 1, - anon_sym_STAR, - ACTIONS(157), 1, - anon_sym_SLASH, - STATE(80), 1, - sym_dictionary_construction, + [6880] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(151), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(135), 7, + ACTIONS(249), 8, + anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, @@ -7270,10 +7681,16 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(129), 16, + ACTIONS(247), 24, ts_builtin_sym_end, + anon_sym_DOT, anon_sym_COMMA, anon_sym_RBRACE, + anon_sym_COLON_COLON, + anon_sym_DASH, + anon_sym_PLUS, + anon_sym_STAR_STAR, + anon_sym_SLASH, anon_sym_LT_LT, anon_sym_GT_GT, anon_sym_GT_EQ, @@ -7283,35 +7700,18 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, + anon_sym_then, anon_sym_else, anon_sym_SEMI, + anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - [6366] = 12, - ACTIONS(131), 1, - anon_sym_DOT, - ACTIONS(133), 1, - anon_sym_COLON_COLON, - ACTIONS(137), 1, - anon_sym_LPAREN, - ACTIONS(153), 1, - anon_sym_STAR_STAR, - ACTIONS(155), 1, - anon_sym_STAR, - ACTIONS(157), 1, - anon_sym_SLASH, - STATE(80), 1, - sym_dictionary_construction, + [6921] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(151), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(159), 2, - anon_sym_LT_LT, - anon_sym_GT_GT, - ACTIONS(135), 7, + ACTIONS(253), 8, + anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, @@ -7319,59 +7719,18 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(129), 14, + ACTIONS(251), 24, ts_builtin_sym_end, + anon_sym_DOT, anon_sym_COMMA, anon_sym_RBRACE, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_else, - anon_sym_SEMI, - anon_sym_RPAREN, - anon_sym_RBRACK, - [6425] = 14, - ACTIONS(131), 1, - anon_sym_DOT, - ACTIONS(133), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, - anon_sym_LPAREN, - ACTIONS(153), 1, - anon_sym_STAR_STAR, - ACTIONS(155), 1, - anon_sym_STAR, - ACTIONS(157), 1, - anon_sym_SLASH, - ACTIONS(161), 1, - anon_sym_AMP, - ACTIONS(165), 1, - anon_sym_CARET, - STATE(80), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(151), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(159), 2, + anon_sym_STAR_STAR, + anon_sym_SLASH, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(135), 5, - anon_sym_PIPE, - anon_sym_GT, - anon_sym_LT, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(129), 14, - ts_builtin_sym_end, - anon_sym_COMMA, - anon_sym_RBRACE, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, @@ -7379,47 +7738,37 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, + anon_sym_then, anon_sym_else, anon_sym_SEMI, + anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - [6488] = 13, - ACTIONS(131), 1, - anon_sym_DOT, - ACTIONS(133), 1, - anon_sym_COLON_COLON, - ACTIONS(137), 1, - anon_sym_LPAREN, - ACTIONS(153), 1, - anon_sym_STAR_STAR, - ACTIONS(155), 1, - anon_sym_STAR, - ACTIONS(157), 1, - anon_sym_SLASH, - ACTIONS(161), 1, - anon_sym_AMP, - STATE(80), 1, - sym_dictionary_construction, + [6962] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(151), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(159), 2, - anon_sym_LT_LT, - anon_sym_GT_GT, - ACTIONS(135), 6, + ACTIONS(257), 8, + anon_sym_STAR, + anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(129), 14, + ACTIONS(255), 24, ts_builtin_sym_end, + anon_sym_DOT, anon_sym_COMMA, anon_sym_RBRACE, + anon_sym_COLON_COLON, + anon_sym_DASH, + anon_sym_PLUS, + anon_sym_STAR_STAR, + anon_sym_SLASH, + anon_sym_LT_LT, + anon_sym_GT_GT, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, @@ -7427,15 +7776,20 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, + anon_sym_then, anon_sym_else, anon_sym_SEMI, + anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - [6549] = 3, + [7003] = 4, + ACTIONS(259), 1, + anon_sym_DASH_GT, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(191), 8, + ACTIONS(241), 9, + anon_sym_DASH, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, @@ -7444,13 +7798,12 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(189), 24, + ACTIONS(239), 22, ts_builtin_sym_end, anon_sym_DOT, anon_sym_COMMA, anon_sym_RBRACE, anon_sym_COLON_COLON, - anon_sym_DASH, anon_sym_PLUS, anon_sym_STAR_STAR, anon_sym_SLASH, @@ -7463,176 +7816,164 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, - anon_sym_then, anon_sym_else, anon_sym_SEMI, anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - [6590] = 17, - ACTIONS(131), 1, + [7046] = 20, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(153), 1, + ACTIONS(173), 1, anon_sym_STAR_STAR, - ACTIONS(155), 1, + ACTIONS(175), 1, anon_sym_STAR, - ACTIONS(157), 1, + ACTIONS(177), 1, anon_sym_SLASH, - ACTIONS(161), 1, + ACTIONS(187), 1, anon_sym_AMP, - ACTIONS(163), 1, - anon_sym_PIPE, - ACTIONS(165), 1, + ACTIONS(189), 1, anon_sym_CARET, - STATE(80), 1, + ACTIONS(191), 1, + anon_sym_PIPE, + ACTIONS(197), 1, + anon_sym_AMP_AMP, + ACTIONS(199), 1, + anon_sym_PIPE_PIPE, + ACTIONS(203), 1, + anon_sym_CARET_CARET, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(135), 2, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(151), 2, + ACTIONS(183), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(159), 2, + ACTIONS(185), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(169), 2, + ACTIONS(193), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(171), 4, + ACTIONS(263), 2, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(195), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - ACTIONS(129), 10, + ACTIONS(261), 7, ts_builtin_sym_end, anon_sym_COMMA, anon_sym_RBRACE, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, anon_sym_else, anon_sym_SEMI, anon_sym_RPAREN, anon_sym_RBRACK, - [6659] = 18, - ACTIONS(131), 1, - anon_sym_DOT, - ACTIONS(133), 1, - anon_sym_COLON_COLON, - ACTIONS(137), 1, - anon_sym_LPAREN, - ACTIONS(153), 1, - anon_sym_STAR_STAR, - ACTIONS(155), 1, + [7121] = 3, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(267), 8, anon_sym_STAR, - ACTIONS(157), 1, - anon_sym_SLASH, - ACTIONS(161), 1, anon_sym_AMP, - ACTIONS(163), 1, anon_sym_PIPE, - ACTIONS(165), 1, anon_sym_CARET, - ACTIONS(173), 1, - anon_sym_AMP_AMP, - STATE(80), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(135), 2, + anon_sym_GT, + anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(151), 2, + ACTIONS(265), 24, + ts_builtin_sym_end, + anon_sym_DOT, + anon_sym_COMMA, + anon_sym_RBRACE, + anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(159), 2, + anon_sym_STAR_STAR, + anon_sym_SLASH, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(169), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(171), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - ACTIONS(129), 9, - ts_builtin_sym_end, - anon_sym_COMMA, - anon_sym_RBRACE, + anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, + anon_sym_then, anon_sym_else, anon_sym_SEMI, + anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - [6730] = 19, - ACTIONS(131), 1, + [7162] = 20, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(153), 1, + ACTIONS(173), 1, anon_sym_STAR_STAR, - ACTIONS(155), 1, + ACTIONS(175), 1, anon_sym_STAR, - ACTIONS(157), 1, + ACTIONS(177), 1, anon_sym_SLASH, - ACTIONS(161), 1, + ACTIONS(187), 1, anon_sym_AMP, - ACTIONS(163), 1, - anon_sym_PIPE, - ACTIONS(165), 1, + ACTIONS(189), 1, anon_sym_CARET, - ACTIONS(173), 1, + ACTIONS(191), 1, + anon_sym_PIPE, + ACTIONS(197), 1, anon_sym_AMP_AMP, - ACTIONS(175), 1, + ACTIONS(199), 1, anon_sym_PIPE_PIPE, - STATE(80), 1, + ACTIONS(203), 1, + anon_sym_CARET_CARET, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(135), 2, - anon_sym_EQ, - anon_sym_COLON, - ACTIONS(151), 2, + ACTIONS(183), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(159), 2, + ACTIONS(185), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(169), 2, + ACTIONS(193), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(171), 4, + ACTIONS(271), 2, + anon_sym_EQ, + anon_sym_COLON, + ACTIONS(195), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - ACTIONS(129), 8, + ACTIONS(269), 7, ts_builtin_sym_end, anon_sym_COMMA, anon_sym_RBRACE, - anon_sym_CARET_CARET, anon_sym_else, anon_sym_SEMI, anon_sym_RPAREN, anon_sym_RBRACK, - [6803] = 3, + [7237] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(121), 8, + ACTIONS(275), 8, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, @@ -7641,7 +7982,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LT, anon_sym_EQ, anon_sym_COLON, - ACTIONS(119), 24, + ACTIONS(273), 24, ts_builtin_sym_end, anon_sym_DOT, anon_sym_COMMA, @@ -7666,11 +8007,15 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LPAREN, anon_sym_RPAREN, anon_sym_RBRACK, - [6844] = 3, + [7278] = 5, + ACTIONS(277), 1, + anon_sym_COLON, + STATE(184), 1, + sym_declaration_type, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(269), 8, + ACTIONS(241), 7, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, @@ -7678,12 +8023,9 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_GT, anon_sym_LT, anon_sym_EQ, - anon_sym_COLON, - ACTIONS(267), 24, - ts_builtin_sym_end, + ACTIONS(239), 18, anon_sym_DOT, anon_sym_COMMA, - anon_sym_RBRACE, anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, @@ -7698,20 +8040,16 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_else, - anon_sym_SEMI, anon_sym_LPAREN, anon_sym_RPAREN, - anon_sym_RBRACK, - [6885] = 4, + [7318] = 4, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(99), 2, + ACTIONS(105), 2, aux_sym_signed_integer_token1, aux_sym_unsigned_integer_token1, - ACTIONS(97), 7, + ACTIONS(103), 7, sym_identifier, anon_sym_STAR, anon_sym_AMP, @@ -7719,7 +8057,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(95), 18, + ACTIONS(101), 18, sym_unit_quote, anon_sym_DOT, anon_sym_COLON_COLON, @@ -7738,24 +8076,24 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_CARET_CARET, anon_sym_then, anon_sym_LPAREN, - [6923] = 6, - ACTIONS(103), 1, + [7356] = 6, + ACTIONS(109), 1, sym_identifier, - ACTIONS(105), 1, + ACTIONS(111), 1, sym_unit_quote, - STATE(60), 1, + STATE(63), 1, sym__unit, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(107), 6, + ACTIONS(113), 6, anon_sym_STAR, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(101), 17, + ACTIONS(107), 17, anon_sym_DOT, anon_sym_COLON_COLON, anon_sym_DASH, @@ -7773,504 +8111,478 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_CARET_CARET, anon_sym_then, anon_sym_LPAREN, - [6964] = 20, - ACTIONS(131), 1, + [7397] = 20, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(153), 1, + ACTIONS(173), 1, anon_sym_STAR_STAR, - ACTIONS(155), 1, + ACTIONS(175), 1, anon_sym_STAR, - ACTIONS(157), 1, + ACTIONS(177), 1, anon_sym_SLASH, - ACTIONS(161), 1, + ACTIONS(187), 1, anon_sym_AMP, - ACTIONS(163), 1, - anon_sym_PIPE, - ACTIONS(165), 1, + ACTIONS(189), 1, anon_sym_CARET, - ACTIONS(173), 1, + ACTIONS(191), 1, + anon_sym_PIPE, + ACTIONS(197), 1, anon_sym_AMP_AMP, - ACTIONS(175), 1, + ACTIONS(199), 1, anon_sym_PIPE_PIPE, - ACTIONS(177), 1, + ACTIONS(203), 1, anon_sym_CARET_CARET, - ACTIONS(273), 1, + ACTIONS(281), 1, anon_sym_EQ, - STATE(80), 1, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(151), 2, + ACTIONS(183), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(159), 2, + ACTIONS(185), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(169), 2, + ACTIONS(193), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(271), 2, + ACTIONS(279), 2, anon_sym_COMMA, anon_sym_RPAREN, - ACTIONS(171), 4, + ACTIONS(195), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [7033] = 6, - ACTIONS(275), 1, - anon_sym_EQ, - ACTIONS(277), 1, - anon_sym_COLON, - STATE(178), 1, - sym_declaration_type, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(191), 6, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - ACTIONS(189), 17, + [7466] = 21, + ACTIONS(127), 1, anon_sym_DOT, + ACTIONS(129), 1, anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, + ACTIONS(133), 1, anon_sym_LPAREN, - anon_sym_RPAREN, - [7074] = 4, - ACTIONS(279), 1, - anon_sym_DOT, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(115), 7, - sym_identifier, + ACTIONS(173), 1, + anon_sym_STAR_STAR, + ACTIONS(175), 1, anon_sym_STAR, + ACTIONS(177), 1, + anon_sym_SLASH, + ACTIONS(187), 1, anon_sym_AMP, - anon_sym_PIPE, + ACTIONS(189), 1, anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - ACTIONS(113), 17, - sym_unit_quote, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, + ACTIONS(191), 1, + anon_sym_PIPE, + ACTIONS(197), 1, anon_sym_AMP_AMP, + ACTIONS(199), 1, anon_sym_PIPE_PIPE, + ACTIONS(203), 1, anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_LPAREN, - [7110] = 3, + ACTIONS(279), 1, + anon_sym_COMMA, + ACTIONS(281), 1, + anon_sym_EQ, + ACTIONS(283), 1, + anon_sym_RPAREN, + STATE(99), 1, + sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(97), 7, - sym_identifier, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - ACTIONS(95), 18, - sym_unit_quote, - anon_sym_DOT, - anon_sym_COLON_COLON, + ACTIONS(183), 2, anon_sym_DASH, anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, + ACTIONS(185), 2, anon_sym_LT_LT, anon_sym_GT_GT, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_LPAREN, - [7144] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(111), 7, - sym_identifier, - anon_sym_STAR, - anon_sym_AMP, - anon_sym_PIPE, - anon_sym_CARET, + ACTIONS(193), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(109), 18, - sym_unit_quote, - anon_sym_DOT, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR_STAR, - anon_sym_SLASH, - anon_sym_LT_LT, - anon_sym_GT_GT, + ACTIONS(195), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - anon_sym_AMP_AMP, - anon_sym_PIPE_PIPE, - anon_sym_CARET_CARET, - anon_sym_then, - anon_sym_LPAREN, - [7178] = 19, - ACTIONS(131), 1, + [7537] = 20, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(153), 1, + ACTIONS(173), 1, anon_sym_STAR_STAR, - ACTIONS(155), 1, + ACTIONS(175), 1, anon_sym_STAR, - ACTIONS(157), 1, + ACTIONS(177), 1, anon_sym_SLASH, - ACTIONS(161), 1, + ACTIONS(187), 1, anon_sym_AMP, - ACTIONS(163), 1, - anon_sym_PIPE, - ACTIONS(165), 1, + ACTIONS(189), 1, anon_sym_CARET, - ACTIONS(173), 1, + ACTIONS(191), 1, + anon_sym_PIPE, + ACTIONS(197), 1, anon_sym_AMP_AMP, - ACTIONS(175), 1, + ACTIONS(199), 1, anon_sym_PIPE_PIPE, - ACTIONS(177), 1, + ACTIONS(203), 1, anon_sym_CARET_CARET, - STATE(80), 1, + ACTIONS(287), 1, + anon_sym_EQ, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(151), 2, + ACTIONS(183), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(159), 2, + ACTIONS(185), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(169), 2, + ACTIONS(193), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(281), 2, + ACTIONS(285), 2, anon_sym_COMMA, anon_sym_RPAREN, - ACTIONS(171), 4, + ACTIONS(195), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [7244] = 20, - ACTIONS(41), 1, - anon_sym_RBRACK, - ACTIONS(131), 1, + [7606] = 20, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(153), 1, + ACTIONS(173), 1, anon_sym_STAR_STAR, - ACTIONS(155), 1, + ACTIONS(175), 1, anon_sym_STAR, - ACTIONS(157), 1, + ACTIONS(177), 1, anon_sym_SLASH, - ACTIONS(161), 1, + ACTIONS(187), 1, anon_sym_AMP, - ACTIONS(163), 1, - anon_sym_PIPE, - ACTIONS(165), 1, + ACTIONS(189), 1, anon_sym_CARET, - ACTIONS(173), 1, + ACTIONS(191), 1, + anon_sym_PIPE, + ACTIONS(197), 1, anon_sym_AMP_AMP, - ACTIONS(175), 1, + ACTIONS(199), 1, anon_sym_PIPE_PIPE, - ACTIONS(177), 1, + ACTIONS(203), 1, anon_sym_CARET_CARET, - ACTIONS(283), 1, + ACTIONS(289), 1, anon_sym_COMMA, - STATE(80), 1, + ACTIONS(291), 1, + anon_sym_RBRACK, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(151), 2, + ACTIONS(183), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(159), 2, + ACTIONS(185), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(169), 2, + ACTIONS(193), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(171), 4, + ACTIONS(195), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [7312] = 20, - ACTIONS(131), 1, + [7674] = 20, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(153), 1, + ACTIONS(173), 1, anon_sym_STAR_STAR, - ACTIONS(155), 1, + ACTIONS(175), 1, anon_sym_STAR, - ACTIONS(157), 1, + ACTIONS(177), 1, anon_sym_SLASH, - ACTIONS(161), 1, + ACTIONS(187), 1, anon_sym_AMP, - ACTIONS(163), 1, - anon_sym_PIPE, - ACTIONS(165), 1, + ACTIONS(189), 1, anon_sym_CARET, - ACTIONS(173), 1, + ACTIONS(191), 1, + anon_sym_PIPE, + ACTIONS(197), 1, anon_sym_AMP_AMP, - ACTIONS(175), 1, + ACTIONS(199), 1, anon_sym_PIPE_PIPE, - ACTIONS(177), 1, + ACTIONS(203), 1, anon_sym_CARET_CARET, - ACTIONS(283), 1, + ACTIONS(293), 1, anon_sym_COMMA, - ACTIONS(285), 1, - anon_sym_RBRACK, - STATE(80), 1, + ACTIONS(295), 1, + anon_sym_RBRACE, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(151), 2, + ACTIONS(183), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(159), 2, + ACTIONS(185), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(169), 2, + ACTIONS(193), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(171), 4, + ACTIONS(195), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [7380] = 20, - ACTIONS(131), 1, + [7742] = 20, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(153), 1, + ACTIONS(173), 1, anon_sym_STAR_STAR, - ACTIONS(155), 1, + ACTIONS(175), 1, anon_sym_STAR, - ACTIONS(157), 1, + ACTIONS(177), 1, anon_sym_SLASH, - ACTIONS(161), 1, + ACTIONS(187), 1, anon_sym_AMP, - ACTIONS(163), 1, - anon_sym_PIPE, - ACTIONS(165), 1, + ACTIONS(189), 1, anon_sym_CARET, - ACTIONS(173), 1, + ACTIONS(191), 1, + anon_sym_PIPE, + ACTIONS(197), 1, anon_sym_AMP_AMP, - ACTIONS(175), 1, + ACTIONS(199), 1, anon_sym_PIPE_PIPE, - ACTIONS(177), 1, + ACTIONS(203), 1, anon_sym_CARET_CARET, - ACTIONS(287), 1, + ACTIONS(297), 1, anon_sym_COMMA, - ACTIONS(289), 1, + ACTIONS(299), 1, anon_sym_RBRACE, - STATE(80), 1, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(151), 2, + ACTIONS(183), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(159), 2, + ACTIONS(185), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(169), 2, + ACTIONS(193), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(171), 4, + ACTIONS(195), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [7448] = 19, - ACTIONS(131), 1, + [7810] = 4, + ACTIONS(301), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(121), 7, + sym_identifier, + anon_sym_STAR, + anon_sym_AMP, + anon_sym_PIPE, + anon_sym_CARET, + anon_sym_GT, + anon_sym_LT, + ACTIONS(119), 17, + sym_unit_quote, + anon_sym_COLON_COLON, + anon_sym_DASH, + anon_sym_PLUS, + anon_sym_STAR_STAR, + anon_sym_SLASH, + anon_sym_LT_LT, + anon_sym_GT_GT, + anon_sym_GT_EQ, + anon_sym_EQ_EQ, + anon_sym_LT_EQ, + anon_sym_BANG_EQ, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_CARET_CARET, + anon_sym_then, + anon_sym_LPAREN, + [7846] = 19, + ACTIONS(127), 1, + anon_sym_DOT, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(153), 1, + ACTIONS(173), 1, anon_sym_STAR_STAR, - ACTIONS(155), 1, + ACTIONS(175), 1, anon_sym_STAR, - ACTIONS(157), 1, + ACTIONS(177), 1, anon_sym_SLASH, - ACTIONS(161), 1, + ACTIONS(187), 1, anon_sym_AMP, - ACTIONS(163), 1, - anon_sym_PIPE, - ACTIONS(165), 1, + ACTIONS(189), 1, anon_sym_CARET, - ACTIONS(173), 1, + ACTIONS(191), 1, + anon_sym_PIPE, + ACTIONS(197), 1, anon_sym_AMP_AMP, - ACTIONS(175), 1, + ACTIONS(199), 1, anon_sym_PIPE_PIPE, - ACTIONS(177), 1, + ACTIONS(203), 1, anon_sym_CARET_CARET, - STATE(80), 1, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(151), 2, + ACTIONS(183), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(159), 2, + ACTIONS(185), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(169), 2, + ACTIONS(193), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(291), 2, + ACTIONS(303), 2, anon_sym_COMMA, anon_sym_RPAREN, - ACTIONS(171), 4, + ACTIONS(195), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [7514] = 20, - ACTIONS(131), 1, + [7912] = 20, + ACTIONS(39), 1, + anon_sym_RBRACK, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(153), 1, + ACTIONS(173), 1, anon_sym_STAR_STAR, - ACTIONS(155), 1, + ACTIONS(175), 1, anon_sym_STAR, - ACTIONS(157), 1, + ACTIONS(177), 1, anon_sym_SLASH, - ACTIONS(161), 1, + ACTIONS(187), 1, anon_sym_AMP, - ACTIONS(163), 1, - anon_sym_PIPE, - ACTIONS(165), 1, + ACTIONS(189), 1, anon_sym_CARET, - ACTIONS(173), 1, + ACTIONS(191), 1, + anon_sym_PIPE, + ACTIONS(197), 1, anon_sym_AMP_AMP, - ACTIONS(175), 1, + ACTIONS(199), 1, anon_sym_PIPE_PIPE, - ACTIONS(177), 1, + ACTIONS(203), 1, anon_sym_CARET_CARET, - ACTIONS(293), 1, + ACTIONS(289), 1, anon_sym_COMMA, - ACTIONS(295), 1, - anon_sym_RBRACE, - STATE(80), 1, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(151), 2, + ACTIONS(183), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(159), 2, + ACTIONS(185), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(169), 2, + ACTIONS(193), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(171), 4, + ACTIONS(195), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [7582] = 15, - ACTIONS(131), 1, - anon_sym_DOT, - ACTIONS(133), 1, - anon_sym_COLON_COLON, - ACTIONS(137), 1, - anon_sym_LPAREN, - ACTIONS(299), 1, - anon_sym_STAR_STAR, - ACTIONS(301), 1, + [7980] = 3, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(103), 7, + sym_identifier, anon_sym_STAR, - ACTIONS(303), 1, - anon_sym_SLASH, - ACTIONS(307), 1, anon_sym_AMP, - ACTIONS(309), 1, anon_sym_PIPE, - ACTIONS(311), 1, anon_sym_CARET, - STATE(80), 1, - sym_dictionary_construction, + anon_sym_GT, + anon_sym_LT, + ACTIONS(101), 18, + sym_unit_quote, + anon_sym_DOT, + anon_sym_COLON_COLON, + anon_sym_DASH, + anon_sym_PLUS, + anon_sym_STAR_STAR, + anon_sym_SLASH, + anon_sym_LT_LT, + anon_sym_GT_GT, + anon_sym_GT_EQ, + anon_sym_EQ_EQ, + anon_sym_LT_EQ, + anon_sym_BANG_EQ, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_CARET_CARET, + anon_sym_then, + anon_sym_LPAREN, + [8014] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(135), 2, + ACTIONS(117), 7, + sym_identifier, + anon_sym_STAR, + anon_sym_AMP, + anon_sym_PIPE, + anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(297), 2, + ACTIONS(115), 18, + sym_unit_quote, + anon_sym_DOT, + anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(305), 2, + anon_sym_STAR_STAR, + anon_sym_SLASH, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(129), 8, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, @@ -8279,399 +8591,401 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, anon_sym_then, - [7639] = 19, - ACTIONS(131), 1, + anon_sym_LPAREN, + [8048] = 19, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(299), 1, + ACTIONS(173), 1, anon_sym_STAR_STAR, - ACTIONS(301), 1, + ACTIONS(175), 1, anon_sym_STAR, - ACTIONS(303), 1, + ACTIONS(177), 1, anon_sym_SLASH, - ACTIONS(307), 1, + ACTIONS(187), 1, anon_sym_AMP, - ACTIONS(309), 1, - anon_sym_PIPE, - ACTIONS(311), 1, + ACTIONS(189), 1, anon_sym_CARET, - ACTIONS(317), 1, + ACTIONS(191), 1, + anon_sym_PIPE, + ACTIONS(197), 1, anon_sym_AMP_AMP, - ACTIONS(319), 1, + ACTIONS(199), 1, anon_sym_PIPE_PIPE, - ACTIONS(321), 1, + ACTIONS(203), 1, anon_sym_CARET_CARET, - ACTIONS(323), 1, - anon_sym_then, - STATE(80), 1, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(297), 2, + ACTIONS(183), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(305), 2, + ACTIONS(185), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(313), 2, + ACTIONS(193), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(315), 4, + ACTIONS(305), 2, + anon_sym_COMMA, + anon_sym_RPAREN, + ACTIONS(195), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [7704] = 19, - ACTIONS(131), 1, + [8114] = 19, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(153), 1, + ACTIONS(173), 1, anon_sym_STAR_STAR, - ACTIONS(155), 1, + ACTIONS(175), 1, anon_sym_STAR, - ACTIONS(157), 1, + ACTIONS(177), 1, anon_sym_SLASH, - ACTIONS(161), 1, + ACTIONS(187), 1, anon_sym_AMP, - ACTIONS(163), 1, - anon_sym_PIPE, - ACTIONS(165), 1, + ACTIONS(189), 1, anon_sym_CARET, - ACTIONS(173), 1, + ACTIONS(191), 1, + anon_sym_PIPE, + ACTIONS(197), 1, anon_sym_AMP_AMP, - ACTIONS(175), 1, + ACTIONS(199), 1, anon_sym_PIPE_PIPE, - ACTIONS(177), 1, + ACTIONS(203), 1, anon_sym_CARET_CARET, - ACTIONS(283), 1, - anon_sym_COMMA, - STATE(80), 1, + ACTIONS(307), 1, + anon_sym_COLON, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(151), 2, + ACTIONS(183), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(159), 2, + ACTIONS(185), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(169), 2, + ACTIONS(193), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(171), 4, + ACTIONS(195), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [7769] = 19, - ACTIONS(131), 1, + [8179] = 19, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(153), 1, + ACTIONS(173), 1, anon_sym_STAR_STAR, - ACTIONS(155), 1, + ACTIONS(175), 1, anon_sym_STAR, - ACTIONS(157), 1, + ACTIONS(177), 1, anon_sym_SLASH, - ACTIONS(161), 1, + ACTIONS(187), 1, anon_sym_AMP, - ACTIONS(163), 1, - anon_sym_PIPE, - ACTIONS(165), 1, + ACTIONS(189), 1, anon_sym_CARET, - ACTIONS(173), 1, + ACTIONS(191), 1, + anon_sym_PIPE, + ACTIONS(197), 1, anon_sym_AMP_AMP, - ACTIONS(175), 1, + ACTIONS(199), 1, anon_sym_PIPE_PIPE, - ACTIONS(177), 1, + ACTIONS(203), 1, anon_sym_CARET_CARET, - ACTIONS(325), 1, - ts_builtin_sym_end, - STATE(80), 1, + ACTIONS(289), 1, + anon_sym_COMMA, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(151), 2, + ACTIONS(183), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(159), 2, + ACTIONS(185), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(169), 2, + ACTIONS(193), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(171), 4, + ACTIONS(195), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [7834] = 19, - ACTIONS(131), 1, + [8244] = 19, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(153), 1, + ACTIONS(173), 1, anon_sym_STAR_STAR, - ACTIONS(155), 1, + ACTIONS(175), 1, anon_sym_STAR, - ACTIONS(157), 1, + ACTIONS(177), 1, anon_sym_SLASH, - ACTIONS(161), 1, + ACTIONS(187), 1, anon_sym_AMP, - ACTIONS(163), 1, - anon_sym_PIPE, - ACTIONS(165), 1, + ACTIONS(189), 1, anon_sym_CARET, - ACTIONS(173), 1, + ACTIONS(191), 1, + anon_sym_PIPE, + ACTIONS(197), 1, anon_sym_AMP_AMP, - ACTIONS(175), 1, + ACTIONS(199), 1, anon_sym_PIPE_PIPE, - ACTIONS(177), 1, + ACTIONS(203), 1, anon_sym_CARET_CARET, - ACTIONS(327), 1, - anon_sym_RBRACE, - STATE(80), 1, + ACTIONS(309), 1, + anon_sym_SEMI, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(151), 2, + ACTIONS(183), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(159), 2, + ACTIONS(185), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(169), 2, + ACTIONS(193), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(171), 4, + ACTIONS(195), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [7899] = 19, - ACTIONS(131), 1, + [8309] = 19, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(153), 1, + ACTIONS(261), 1, + anon_sym_then, + ACTIONS(313), 1, anon_sym_STAR_STAR, - ACTIONS(155), 1, + ACTIONS(315), 1, anon_sym_STAR, - ACTIONS(157), 1, + ACTIONS(317), 1, anon_sym_SLASH, - ACTIONS(161), 1, + ACTIONS(321), 1, anon_sym_AMP, - ACTIONS(163), 1, + ACTIONS(323), 1, anon_sym_PIPE, - ACTIONS(165), 1, + ACTIONS(325), 1, anon_sym_CARET, - ACTIONS(173), 1, + ACTIONS(331), 1, anon_sym_AMP_AMP, - ACTIONS(175), 1, + ACTIONS(333), 1, anon_sym_PIPE_PIPE, - ACTIONS(177), 1, + ACTIONS(335), 1, anon_sym_CARET_CARET, - ACTIONS(329), 1, - anon_sym_else, - STATE(80), 1, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(151), 2, + ACTIONS(311), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(159), 2, + ACTIONS(319), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(169), 2, + ACTIONS(327), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(171), 4, + ACTIONS(329), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [7964] = 19, - ACTIONS(131), 1, + [8374] = 19, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(153), 1, + ACTIONS(173), 1, anon_sym_STAR_STAR, - ACTIONS(155), 1, + ACTIONS(175), 1, anon_sym_STAR, - ACTIONS(157), 1, + ACTIONS(177), 1, anon_sym_SLASH, - ACTIONS(161), 1, + ACTIONS(187), 1, anon_sym_AMP, - ACTIONS(163), 1, - anon_sym_PIPE, - ACTIONS(165), 1, + ACTIONS(189), 1, anon_sym_CARET, - ACTIONS(173), 1, + ACTIONS(191), 1, + anon_sym_PIPE, + ACTIONS(197), 1, anon_sym_AMP_AMP, - ACTIONS(175), 1, + ACTIONS(199), 1, anon_sym_PIPE_PIPE, - ACTIONS(177), 1, + ACTIONS(203), 1, anon_sym_CARET_CARET, - ACTIONS(331), 1, + ACTIONS(337), 1, anon_sym_COMMA, - STATE(80), 1, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(151), 2, + ACTIONS(183), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(159), 2, + ACTIONS(185), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(169), 2, + ACTIONS(193), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(171), 4, + ACTIONS(195), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [8029] = 19, - ACTIONS(131), 1, + [8439] = 19, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(153), 1, + ACTIONS(173), 1, anon_sym_STAR_STAR, - ACTIONS(155), 1, + ACTIONS(175), 1, anon_sym_STAR, - ACTIONS(157), 1, + ACTIONS(177), 1, anon_sym_SLASH, - ACTIONS(161), 1, + ACTIONS(187), 1, anon_sym_AMP, - ACTIONS(163), 1, - anon_sym_PIPE, - ACTIONS(165), 1, + ACTIONS(189), 1, anon_sym_CARET, - ACTIONS(173), 1, + ACTIONS(191), 1, + anon_sym_PIPE, + ACTIONS(197), 1, anon_sym_AMP_AMP, - ACTIONS(175), 1, + ACTIONS(199), 1, anon_sym_PIPE_PIPE, - ACTIONS(177), 1, + ACTIONS(203), 1, anon_sym_CARET_CARET, - ACTIONS(333), 1, - anon_sym_SEMI, - STATE(80), 1, + ACTIONS(339), 1, + anon_sym_RBRACE, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(151), 2, + ACTIONS(183), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(159), 2, + ACTIONS(185), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(169), 2, + ACTIONS(193), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(171), 4, + ACTIONS(195), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [8094] = 19, - ACTIONS(131), 1, + [8504] = 19, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(181), 1, - anon_sym_then, - ACTIONS(299), 1, + ACTIONS(313), 1, anon_sym_STAR_STAR, - ACTIONS(301), 1, + ACTIONS(315), 1, anon_sym_STAR, - ACTIONS(303), 1, + ACTIONS(317), 1, anon_sym_SLASH, - ACTIONS(307), 1, + ACTIONS(321), 1, anon_sym_AMP, - ACTIONS(309), 1, + ACTIONS(323), 1, anon_sym_PIPE, - ACTIONS(311), 1, + ACTIONS(325), 1, anon_sym_CARET, - ACTIONS(317), 1, + ACTIONS(331), 1, anon_sym_AMP_AMP, - ACTIONS(319), 1, + ACTIONS(333), 1, anon_sym_PIPE_PIPE, - ACTIONS(321), 1, + ACTIONS(335), 1, anon_sym_CARET_CARET, - STATE(80), 1, + ACTIONS(341), 1, + anon_sym_then, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(297), 2, + ACTIONS(311), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(305), 2, + ACTIONS(319), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(313), 2, + ACTIONS(327), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(315), 4, + ACTIONS(329), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [8159] = 10, - ACTIONS(131), 1, + [8569] = 10, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(299), 1, + ACTIONS(313), 1, anon_sym_STAR_STAR, - ACTIONS(301), 1, + ACTIONS(315), 1, anon_sym_STAR, - ACTIONS(303), 1, + ACTIONS(317), 1, anon_sym_SLASH, - STATE(80), 1, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(135), 5, + ACTIONS(131), 5, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(129), 12, + ACTIONS(125), 12, anon_sym_DASH, anon_sym_PLUS, anon_sym_LT_LT, @@ -8684,31 +8998,69 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, anon_sym_then, - [8206] = 8, - ACTIONS(131), 1, + [8616] = 8, + ACTIONS(127), 1, anon_sym_DOT, + ACTIONS(129), 1, + anon_sym_COLON_COLON, ACTIONS(133), 1, + anon_sym_LPAREN, + ACTIONS(313), 1, + anon_sym_STAR_STAR, + STATE(99), 1, + sym_dictionary_construction, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(131), 6, + anon_sym_STAR, + anon_sym_AMP, + anon_sym_PIPE, + anon_sym_CARET, + anon_sym_GT, + anon_sym_LT, + ACTIONS(125), 13, + anon_sym_DASH, + anon_sym_PLUS, + anon_sym_SLASH, + anon_sym_LT_LT, + anon_sym_GT_GT, + anon_sym_GT_EQ, + anon_sym_EQ_EQ, + anon_sym_LT_EQ, + anon_sym_BANG_EQ, + anon_sym_AMP_AMP, + anon_sym_PIPE_PIPE, + anon_sym_CARET_CARET, + anon_sym_then, + [8659] = 11, + ACTIONS(127), 1, + anon_sym_DOT, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(299), 1, + ACTIONS(313), 1, anon_sym_STAR_STAR, - STATE(80), 1, + ACTIONS(315), 1, + anon_sym_STAR, + ACTIONS(317), 1, + anon_sym_SLASH, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(135), 6, - anon_sym_STAR, + ACTIONS(311), 2, + anon_sym_DASH, + anon_sym_PLUS, + ACTIONS(131), 5, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(129), 13, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_SLASH, + ACTIONS(125), 10, anon_sym_LT_LT, anon_sym_GT_GT, anon_sym_GT_EQ, @@ -8719,36 +9071,37 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, anon_sym_then, - [8249] = 11, - ACTIONS(131), 1, + [8708] = 12, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(299), 1, + ACTIONS(313), 1, anon_sym_STAR_STAR, - ACTIONS(301), 1, + ACTIONS(315), 1, anon_sym_STAR, - ACTIONS(303), 1, + ACTIONS(317), 1, anon_sym_SLASH, - STATE(80), 1, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(297), 2, + ACTIONS(311), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(135), 5, + ACTIONS(319), 2, + anon_sym_LT_LT, + anon_sym_GT_GT, + ACTIONS(131), 5, anon_sym_AMP, anon_sym_PIPE, anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(129), 10, - anon_sym_LT_LT, - anon_sym_GT_GT, + ACTIONS(125), 8, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, @@ -8757,37 +9110,39 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, anon_sym_then, - [8298] = 12, - ACTIONS(131), 1, + [8759] = 14, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(299), 1, + ACTIONS(313), 1, anon_sym_STAR_STAR, - ACTIONS(301), 1, + ACTIONS(315), 1, anon_sym_STAR, - ACTIONS(303), 1, + ACTIONS(317), 1, anon_sym_SLASH, - STATE(80), 1, + ACTIONS(321), 1, + anon_sym_AMP, + ACTIONS(325), 1, + anon_sym_CARET, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(297), 2, + ACTIONS(311), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(305), 2, + ACTIONS(319), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(135), 5, - anon_sym_AMP, + ACTIONS(131), 3, anon_sym_PIPE, - anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(129), 8, + ACTIONS(125), 8, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, @@ -8796,39 +9151,38 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, anon_sym_then, - [8349] = 14, - ACTIONS(131), 1, + [8814] = 13, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(299), 1, + ACTIONS(313), 1, anon_sym_STAR_STAR, - ACTIONS(301), 1, + ACTIONS(315), 1, anon_sym_STAR, - ACTIONS(303), 1, + ACTIONS(317), 1, anon_sym_SLASH, - ACTIONS(307), 1, + ACTIONS(321), 1, anon_sym_AMP, - ACTIONS(311), 1, - anon_sym_CARET, - STATE(80), 1, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(297), 2, + ACTIONS(311), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(305), 2, + ACTIONS(319), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(135), 3, + ACTIONS(131), 4, anon_sym_PIPE, + anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(129), 8, + ACTIONS(125), 8, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, @@ -8837,38 +9191,40 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, anon_sym_then, - [8404] = 13, - ACTIONS(131), 1, + [8867] = 15, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(299), 1, + ACTIONS(313), 1, anon_sym_STAR_STAR, - ACTIONS(301), 1, + ACTIONS(315), 1, anon_sym_STAR, - ACTIONS(303), 1, + ACTIONS(317), 1, anon_sym_SLASH, - ACTIONS(307), 1, + ACTIONS(321), 1, anon_sym_AMP, - STATE(80), 1, + ACTIONS(323), 1, + anon_sym_PIPE, + ACTIONS(325), 1, + anon_sym_CARET, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(297), 2, + ACTIONS(131), 2, + anon_sym_GT, + anon_sym_LT, + ACTIONS(311), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(305), 2, + ACTIONS(319), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(135), 4, - anon_sym_PIPE, - anon_sym_CARET, - anon_sym_GT, - anon_sym_LT, - ACTIONS(129), 8, + ACTIONS(125), 8, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, @@ -8877,513 +9233,559 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, anon_sym_then, - [8457] = 16, - ACTIONS(131), 1, + [8924] = 16, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(299), 1, + ACTIONS(313), 1, anon_sym_STAR_STAR, - ACTIONS(301), 1, + ACTIONS(315), 1, anon_sym_STAR, - ACTIONS(303), 1, + ACTIONS(317), 1, anon_sym_SLASH, - ACTIONS(307), 1, + ACTIONS(321), 1, anon_sym_AMP, - ACTIONS(309), 1, + ACTIONS(323), 1, anon_sym_PIPE, - ACTIONS(311), 1, + ACTIONS(325), 1, anon_sym_CARET, - STATE(80), 1, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(297), 2, + ACTIONS(311), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(305), 2, + ACTIONS(319), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(313), 2, + ACTIONS(327), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(129), 4, + ACTIONS(125), 4, anon_sym_AMP_AMP, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, anon_sym_then, - ACTIONS(315), 4, + ACTIONS(329), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [8516] = 17, - ACTIONS(131), 1, + [8983] = 17, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(299), 1, + ACTIONS(313), 1, anon_sym_STAR_STAR, - ACTIONS(301), 1, + ACTIONS(315), 1, anon_sym_STAR, - ACTIONS(303), 1, + ACTIONS(317), 1, anon_sym_SLASH, - ACTIONS(307), 1, + ACTIONS(321), 1, anon_sym_AMP, - ACTIONS(309), 1, + ACTIONS(323), 1, anon_sym_PIPE, - ACTIONS(311), 1, + ACTIONS(325), 1, anon_sym_CARET, - ACTIONS(317), 1, + ACTIONS(331), 1, anon_sym_AMP_AMP, - STATE(80), 1, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(297), 2, + ACTIONS(311), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(305), 2, + ACTIONS(319), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(313), 2, + ACTIONS(327), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(129), 3, + ACTIONS(125), 3, anon_sym_PIPE_PIPE, anon_sym_CARET_CARET, anon_sym_then, - ACTIONS(315), 4, + ACTIONS(329), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [8577] = 18, - ACTIONS(131), 1, + [9044] = 18, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(299), 1, + ACTIONS(313), 1, anon_sym_STAR_STAR, - ACTIONS(301), 1, + ACTIONS(315), 1, anon_sym_STAR, - ACTIONS(303), 1, + ACTIONS(317), 1, anon_sym_SLASH, - ACTIONS(307), 1, + ACTIONS(321), 1, anon_sym_AMP, - ACTIONS(309), 1, + ACTIONS(323), 1, anon_sym_PIPE, - ACTIONS(311), 1, + ACTIONS(325), 1, anon_sym_CARET, - ACTIONS(317), 1, + ACTIONS(331), 1, anon_sym_AMP_AMP, - ACTIONS(319), 1, + ACTIONS(333), 1, anon_sym_PIPE_PIPE, - STATE(80), 1, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(129), 2, + ACTIONS(125), 2, anon_sym_CARET_CARET, anon_sym_then, - ACTIONS(297), 2, + ACTIONS(311), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(305), 2, + ACTIONS(319), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(313), 2, + ACTIONS(327), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(315), 4, + ACTIONS(329), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [8640] = 19, - ACTIONS(131), 1, + [9107] = 19, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(167), 1, + ACTIONS(201), 1, anon_sym_then, - ACTIONS(299), 1, + ACTIONS(313), 1, anon_sym_STAR_STAR, - ACTIONS(301), 1, + ACTIONS(315), 1, anon_sym_STAR, - ACTIONS(303), 1, + ACTIONS(317), 1, anon_sym_SLASH, - ACTIONS(307), 1, + ACTIONS(321), 1, anon_sym_AMP, - ACTIONS(309), 1, + ACTIONS(323), 1, anon_sym_PIPE, - ACTIONS(311), 1, + ACTIONS(325), 1, anon_sym_CARET, - ACTIONS(317), 1, + ACTIONS(331), 1, anon_sym_AMP_AMP, - ACTIONS(319), 1, + ACTIONS(333), 1, anon_sym_PIPE_PIPE, - ACTIONS(321), 1, + ACTIONS(335), 1, anon_sym_CARET_CARET, - STATE(80), 1, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(297), 2, + ACTIONS(311), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(305), 2, + ACTIONS(319), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(313), 2, + ACTIONS(327), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(315), 4, + ACTIONS(329), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [8705] = 19, - ACTIONS(131), 1, + [9172] = 19, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(153), 1, + ACTIONS(173), 1, anon_sym_STAR_STAR, - ACTIONS(155), 1, + ACTIONS(175), 1, anon_sym_STAR, - ACTIONS(157), 1, + ACTIONS(177), 1, anon_sym_SLASH, - ACTIONS(161), 1, + ACTIONS(187), 1, anon_sym_AMP, - ACTIONS(163), 1, - anon_sym_PIPE, - ACTIONS(165), 1, + ACTIONS(189), 1, anon_sym_CARET, - ACTIONS(173), 1, + ACTIONS(191), 1, + anon_sym_PIPE, + ACTIONS(197), 1, anon_sym_AMP_AMP, - ACTIONS(175), 1, + ACTIONS(199), 1, anon_sym_PIPE_PIPE, - ACTIONS(177), 1, + ACTIONS(203), 1, anon_sym_CARET_CARET, - ACTIONS(335), 1, - anon_sym_RPAREN, - STATE(80), 1, + ACTIONS(343), 1, + anon_sym_else, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(151), 2, + ACTIONS(183), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(159), 2, + ACTIONS(185), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(169), 2, + ACTIONS(193), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(171), 4, + ACTIONS(195), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [8770] = 19, - ACTIONS(131), 1, + [9237] = 19, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(219), 1, - anon_sym_then, - ACTIONS(299), 1, + ACTIONS(173), 1, anon_sym_STAR_STAR, - ACTIONS(301), 1, + ACTIONS(175), 1, anon_sym_STAR, - ACTIONS(303), 1, + ACTIONS(177), 1, anon_sym_SLASH, - ACTIONS(307), 1, + ACTIONS(187), 1, anon_sym_AMP, - ACTIONS(309), 1, - anon_sym_PIPE, - ACTIONS(311), 1, + ACTIONS(189), 1, anon_sym_CARET, - ACTIONS(317), 1, + ACTIONS(191), 1, + anon_sym_PIPE, + ACTIONS(197), 1, anon_sym_AMP_AMP, - ACTIONS(319), 1, + ACTIONS(199), 1, anon_sym_PIPE_PIPE, - ACTIONS(321), 1, + ACTIONS(203), 1, anon_sym_CARET_CARET, - STATE(80), 1, + ACTIONS(345), 1, + ts_builtin_sym_end, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(297), 2, + ACTIONS(183), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(305), 2, + ACTIONS(185), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(313), 2, + ACTIONS(193), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(315), 4, + ACTIONS(195), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [8835] = 19, - ACTIONS(131), 1, + [9302] = 19, + ACTIONS(127), 1, anon_sym_DOT, + ACTIONS(129), 1, + anon_sym_COLON_COLON, ACTIONS(133), 1, + anon_sym_LPAREN, + ACTIONS(173), 1, + anon_sym_STAR_STAR, + ACTIONS(175), 1, + anon_sym_STAR, + ACTIONS(177), 1, + anon_sym_SLASH, + ACTIONS(187), 1, + anon_sym_AMP, + ACTIONS(189), 1, + anon_sym_CARET, + ACTIONS(191), 1, + anon_sym_PIPE, + ACTIONS(197), 1, + anon_sym_AMP_AMP, + ACTIONS(199), 1, + anon_sym_PIPE_PIPE, + ACTIONS(203), 1, + anon_sym_CARET_CARET, + ACTIONS(347), 1, + anon_sym_COLON, + STATE(99), 1, + sym_dictionary_construction, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(183), 2, + anon_sym_DASH, + anon_sym_PLUS, + ACTIONS(185), 2, + anon_sym_LT_LT, + anon_sym_GT_GT, + ACTIONS(193), 2, + anon_sym_GT, + anon_sym_LT, + ACTIONS(195), 4, + anon_sym_GT_EQ, + anon_sym_EQ_EQ, + anon_sym_LT_EQ, + anon_sym_BANG_EQ, + [9367] = 19, + ACTIONS(127), 1, + anon_sym_DOT, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(223), 1, + ACTIONS(231), 1, anon_sym_then, - ACTIONS(299), 1, + ACTIONS(313), 1, anon_sym_STAR_STAR, - ACTIONS(301), 1, + ACTIONS(315), 1, anon_sym_STAR, - ACTIONS(303), 1, + ACTIONS(317), 1, anon_sym_SLASH, - ACTIONS(307), 1, + ACTIONS(321), 1, anon_sym_AMP, - ACTIONS(309), 1, + ACTIONS(323), 1, anon_sym_PIPE, - ACTIONS(311), 1, + ACTIONS(325), 1, anon_sym_CARET, - ACTIONS(317), 1, + ACTIONS(331), 1, anon_sym_AMP_AMP, - ACTIONS(319), 1, + ACTIONS(333), 1, anon_sym_PIPE_PIPE, - ACTIONS(321), 1, + ACTIONS(335), 1, anon_sym_CARET_CARET, - STATE(80), 1, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(297), 2, + ACTIONS(311), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(305), 2, + ACTIONS(319), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(313), 2, + ACTIONS(327), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(315), 4, + ACTIONS(329), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [8900] = 19, - ACTIONS(131), 1, + [9432] = 19, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(203), 1, + ACTIONS(235), 1, anon_sym_then, - ACTIONS(299), 1, + ACTIONS(313), 1, anon_sym_STAR_STAR, - ACTIONS(301), 1, + ACTIONS(315), 1, anon_sym_STAR, - ACTIONS(303), 1, + ACTIONS(317), 1, anon_sym_SLASH, - ACTIONS(307), 1, + ACTIONS(321), 1, anon_sym_AMP, - ACTIONS(309), 1, + ACTIONS(323), 1, anon_sym_PIPE, - ACTIONS(311), 1, + ACTIONS(325), 1, anon_sym_CARET, - ACTIONS(317), 1, + ACTIONS(331), 1, anon_sym_AMP_AMP, - ACTIONS(319), 1, + ACTIONS(333), 1, anon_sym_PIPE_PIPE, - ACTIONS(321), 1, + ACTIONS(335), 1, anon_sym_CARET_CARET, - STATE(80), 1, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(297), 2, + ACTIONS(311), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(305), 2, + ACTIONS(319), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(313), 2, + ACTIONS(327), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(315), 4, + ACTIONS(329), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [8965] = 19, - ACTIONS(131), 1, + [9497] = 19, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(153), 1, + ACTIONS(269), 1, + anon_sym_then, + ACTIONS(313), 1, anon_sym_STAR_STAR, - ACTIONS(155), 1, + ACTIONS(315), 1, anon_sym_STAR, - ACTIONS(157), 1, + ACTIONS(317), 1, anon_sym_SLASH, - ACTIONS(161), 1, + ACTIONS(321), 1, anon_sym_AMP, - ACTIONS(163), 1, + ACTIONS(323), 1, anon_sym_PIPE, - ACTIONS(165), 1, + ACTIONS(325), 1, anon_sym_CARET, - ACTIONS(173), 1, + ACTIONS(331), 1, anon_sym_AMP_AMP, - ACTIONS(175), 1, + ACTIONS(333), 1, anon_sym_PIPE_PIPE, - ACTIONS(177), 1, + ACTIONS(335), 1, anon_sym_CARET_CARET, - ACTIONS(337), 1, - anon_sym_COLON, - STATE(80), 1, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(151), 2, + ACTIONS(311), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(159), 2, + ACTIONS(319), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(169), 2, + ACTIONS(327), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(171), 4, + ACTIONS(329), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [9030] = 19, - ACTIONS(131), 1, + [9562] = 19, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(153), 1, + ACTIONS(173), 1, anon_sym_STAR_STAR, - ACTIONS(155), 1, + ACTIONS(175), 1, anon_sym_STAR, - ACTIONS(157), 1, + ACTIONS(177), 1, anon_sym_SLASH, - ACTIONS(161), 1, + ACTIONS(187), 1, anon_sym_AMP, - ACTIONS(163), 1, - anon_sym_PIPE, - ACTIONS(165), 1, + ACTIONS(189), 1, anon_sym_CARET, - ACTIONS(173), 1, + ACTIONS(191), 1, + anon_sym_PIPE, + ACTIONS(197), 1, anon_sym_AMP_AMP, - ACTIONS(175), 1, + ACTIONS(199), 1, anon_sym_PIPE_PIPE, - ACTIONS(177), 1, + ACTIONS(203), 1, anon_sym_CARET_CARET, - ACTIONS(339), 1, + ACTIONS(349), 1, anon_sym_else, - STATE(80), 1, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(151), 2, + ACTIONS(183), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(159), 2, + ACTIONS(185), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(169), 2, + ACTIONS(193), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(171), 4, + ACTIONS(195), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [9095] = 19, - ACTIONS(131), 1, + [9627] = 19, + ACTIONS(127), 1, anon_sym_DOT, - ACTIONS(133), 1, + ACTIONS(129), 1, anon_sym_COLON_COLON, - ACTIONS(137), 1, + ACTIONS(133), 1, anon_sym_LPAREN, - ACTIONS(153), 1, + ACTIONS(313), 1, anon_sym_STAR_STAR, - ACTIONS(155), 1, + ACTIONS(315), 1, anon_sym_STAR, - ACTIONS(157), 1, + ACTIONS(317), 1, anon_sym_SLASH, - ACTIONS(161), 1, + ACTIONS(321), 1, anon_sym_AMP, - ACTIONS(163), 1, + ACTIONS(323), 1, anon_sym_PIPE, - ACTIONS(165), 1, + ACTIONS(325), 1, anon_sym_CARET, - ACTIONS(173), 1, + ACTIONS(331), 1, anon_sym_AMP_AMP, - ACTIONS(175), 1, + ACTIONS(333), 1, anon_sym_PIPE_PIPE, - ACTIONS(177), 1, + ACTIONS(335), 1, anon_sym_CARET_CARET, - ACTIONS(341), 1, - anon_sym_COLON, - STATE(80), 1, + ACTIONS(351), 1, + anon_sym_then, + STATE(99), 1, sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(151), 2, + ACTIONS(311), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(159), 2, + ACTIONS(319), 2, anon_sym_LT_LT, anon_sym_GT_GT, - ACTIONS(169), 2, + ACTIONS(327), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(171), 4, + ACTIONS(329), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [9160] = 4, - ACTIONS(343), 1, + [9692] = 4, + ACTIONS(353), 1, anon_sym_DASH_GT, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(191), 7, + ACTIONS(241), 7, anon_sym_DASH, anon_sym_STAR, anon_sym_AMP, @@ -9391,7 +9793,7 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_CARET, anon_sym_GT, anon_sym_LT, - ACTIONS(189), 16, + ACTIONS(239), 16, anon_sym_DOT, anon_sym_COLON_COLON, anon_sym_PLUS, @@ -9408,57 +9810,11 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_CARET_CARET, anon_sym_then, anon_sym_LPAREN, - [9195] = 19, - ACTIONS(131), 1, - anon_sym_DOT, - ACTIONS(133), 1, - anon_sym_COLON_COLON, - ACTIONS(137), 1, - anon_sym_LPAREN, - ACTIONS(299), 1, - anon_sym_STAR_STAR, - ACTIONS(301), 1, - anon_sym_STAR, - ACTIONS(303), 1, - anon_sym_SLASH, - ACTIONS(307), 1, - anon_sym_AMP, - ACTIONS(309), 1, - anon_sym_PIPE, - ACTIONS(311), 1, - anon_sym_CARET, - ACTIONS(317), 1, - anon_sym_AMP_AMP, - ACTIONS(319), 1, - anon_sym_PIPE_PIPE, - ACTIONS(321), 1, - anon_sym_CARET_CARET, - ACTIONS(345), 1, - anon_sym_then, - STATE(80), 1, - sym_dictionary_construction, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(297), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(305), 2, - anon_sym_LT_LT, - anon_sym_GT_GT, - ACTIONS(313), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(315), 4, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - [9260] = 3, + [9727] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(347), 7, + ACTIONS(355), 7, sym_identifier, sym_self, aux_sym_base_ten_token1, @@ -9466,7 +9822,7 @@ static const uint16_t ts_small_parse_table[] = { sym_false, anon_sym_if, anon_sym_let, - ACTIONS(82), 12, + ACTIONS(86), 12, sym_string, aux_sym_octal_token1, aux_sym_hex_token1, @@ -9479,18 +9835,17 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_LBRACK, anon_sym_RBRACK, anon_sym_LT_LT_LT, - [9288] = 4, - ACTIONS(349), 1, - anon_sym_DOT, + [9755] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(115), 2, + ACTIONS(103), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(113), 11, + ACTIONS(101), 12, sym_identifier, sym_unit_quote, + anon_sym_DOT, anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, @@ -9500,17 +9855,18 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [9313] = 3, + [9778] = 4, + ACTIONS(357), 1, + anon_sym_DOT, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(97), 2, + ACTIONS(121), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(95), 12, + ACTIONS(119), 11, sym_identifier, sym_unit_quote, - anon_sym_DOT, anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, @@ -9520,19 +9876,19 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [9336] = 5, - STATE(159), 1, + [9803] = 5, + STATE(164), 1, sym__unit, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(107), 2, + ACTIONS(113), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(351), 2, + ACTIONS(359), 2, sym_identifier, sym_unit_quote, - ACTIONS(101), 9, + ACTIONS(107), 9, anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, @@ -9542,33 +9898,39 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [9363] = 3, + [9830] = 9, + ACTIONS(361), 1, + sym_identifier, + ACTIONS(363), 1, + aux_sym_base_ten_token1, + ACTIONS(367), 1, + anon_sym_LPAREN, + STATE(57), 1, + sym__float, + STATE(59), 1, + sym_number, + STATE(168), 1, + sym_constraint_set_expression, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(355), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(353), 11, - anon_sym_COLON_COLON, + ACTIONS(365), 2, anon_sym_DASH, anon_sym_PLUS, - anon_sym_STAR, - anon_sym_SLASH, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_RPAREN, - anon_sym_GT_GT_GT, - [9385] = 3, + STATE(154), 5, + sym_scalar, + sym_constraint_set_parenthesis, + sym_constraint_set_unary_expression, + sym_constraint_set_binary_expression, + sym_constraint_set_method_call, + [9864] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(359), 2, + ACTIONS(371), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(357), 11, + ACTIONS(369), 11, anon_sym_COLON_COLON, anon_sym_DASH, anon_sym_PLUS, @@ -9580,68 +9942,63 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_BANG_EQ, anon_sym_RPAREN, anon_sym_GT_GT_GT, - [9407] = 9, + [9886] = 9, ACTIONS(361), 1, sym_identifier, - ACTIONS(363), 1, - aux_sym_base_ten_token1, ACTIONS(367), 1, anon_sym_LPAREN, - STATE(140), 1, + ACTIONS(373), 1, + aux_sym_base_ten_token1, + STATE(146), 1, sym_number, - STATE(142), 1, + STATE(147), 1, sym__float, - STATE(158), 1, + STATE(166), 1, sym_constraint_set_expression, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(365), 2, + ACTIONS(375), 2, anon_sym_DASH, anon_sym_PLUS, - STATE(143), 5, + STATE(154), 5, sym_scalar, sym_constraint_set_parenthesis, sym_constraint_set_unary_expression, sym_constraint_set_binary_expression, sym_constraint_set_method_call, - [9441] = 9, - ACTIONS(361), 1, - sym_identifier, - ACTIONS(363), 1, - aux_sym_base_ten_token1, - ACTIONS(367), 1, - anon_sym_LPAREN, - STATE(140), 1, - sym_number, - STATE(142), 1, - sym__float, - STATE(160), 1, - sym_constraint_set_expression, + [9920] = 4, + ACTIONS(377), 1, + anon_sym_COLON_COLON, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(365), 2, + ACTIONS(381), 2, + anon_sym_GT, + anon_sym_LT, + ACTIONS(379), 10, anon_sym_DASH, anon_sym_PLUS, - STATE(143), 5, - sym_scalar, - sym_constraint_set_parenthesis, - sym_constraint_set_unary_expression, - sym_constraint_set_binary_expression, - sym_constraint_set_method_call, - [9475] = 9, + anon_sym_STAR, + anon_sym_SLASH, + anon_sym_GT_EQ, + anon_sym_EQ_EQ, + anon_sym_LT_EQ, + anon_sym_BANG_EQ, + anon_sym_RPAREN, + anon_sym_GT_GT_GT, + [9944] = 9, ACTIONS(361), 1, sym_identifier, ACTIONS(363), 1, aux_sym_base_ten_token1, ACTIONS(367), 1, anon_sym_LPAREN, - STATE(140), 1, - sym_number, - STATE(142), 1, + STATE(57), 1, sym__float, - STATE(161), 1, + STATE(59), 1, + sym_number, + STATE(171), 1, sym_constraint_set_expression, ACTIONS(3), 2, sym_comment, @@ -9649,74 +10006,112 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(365), 2, anon_sym_DASH, anon_sym_PLUS, - STATE(143), 5, + STATE(154), 5, sym_scalar, sym_constraint_set_parenthesis, sym_constraint_set_unary_expression, sym_constraint_set_binary_expression, sym_constraint_set_method_call, - [9509] = 9, + [9978] = 3, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(385), 2, + anon_sym_GT, + anon_sym_LT, + ACTIONS(383), 11, + anon_sym_COLON_COLON, + anon_sym_DASH, + anon_sym_PLUS, + anon_sym_STAR, + anon_sym_SLASH, + anon_sym_GT_EQ, + anon_sym_EQ_EQ, + anon_sym_LT_EQ, + anon_sym_BANG_EQ, + anon_sym_RPAREN, + anon_sym_GT_GT_GT, + [10000] = 3, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + ACTIONS(389), 2, + anon_sym_GT, + anon_sym_LT, + ACTIONS(387), 11, + anon_sym_COLON_COLON, + anon_sym_DASH, + anon_sym_PLUS, + anon_sym_STAR, + anon_sym_SLASH, + anon_sym_GT_EQ, + anon_sym_EQ_EQ, + anon_sym_LT_EQ, + anon_sym_BANG_EQ, + anon_sym_RPAREN, + anon_sym_GT_GT_GT, + [10022] = 9, ACTIONS(361), 1, sym_identifier, + ACTIONS(363), 1, + aux_sym_base_ten_token1, ACTIONS(367), 1, anon_sym_LPAREN, - ACTIONS(369), 1, - aux_sym_base_ten_token1, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(166), 1, + STATE(170), 1, sym_constraint_set_expression, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(371), 2, + ACTIONS(365), 2, anon_sym_DASH, anon_sym_PLUS, - STATE(143), 5, + STATE(154), 5, sym_scalar, sym_constraint_set_parenthesis, sym_constraint_set_unary_expression, sym_constraint_set_binary_expression, sym_constraint_set_method_call, - [9543] = 9, + [10056] = 9, ACTIONS(361), 1, sym_identifier, + ACTIONS(363), 1, + aux_sym_base_ten_token1, ACTIONS(367), 1, anon_sym_LPAREN, - ACTIONS(369), 1, - aux_sym_base_ten_token1, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(163), 1, + STATE(167), 1, sym_constraint_set_expression, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(371), 2, + ACTIONS(365), 2, anon_sym_DASH, anon_sym_PLUS, - STATE(143), 5, + STATE(154), 5, sym_scalar, sym_constraint_set_parenthesis, sym_constraint_set_unary_expression, sym_constraint_set_binary_expression, sym_constraint_set_method_call, - [9577] = 9, + [10090] = 9, ACTIONS(361), 1, sym_identifier, ACTIONS(363), 1, aux_sym_base_ten_token1, ACTIONS(367), 1, anon_sym_LPAREN, - STATE(140), 1, - sym_number, - STATE(142), 1, + STATE(57), 1, sym__float, - STATE(156), 1, + STATE(59), 1, + sym_number, + STATE(151), 1, sym_constraint_set_expression, ACTIONS(3), 2, sym_comment, @@ -9724,20 +10119,20 @@ static const uint16_t ts_small_parse_table[] = { ACTIONS(365), 2, anon_sym_DASH, anon_sym_PLUS, - STATE(143), 5, + STATE(154), 5, sym_scalar, sym_constraint_set_parenthesis, sym_constraint_set_unary_expression, sym_constraint_set_binary_expression, sym_constraint_set_method_call, - [9611] = 3, + [10124] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(111), 2, + ACTIONS(117), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(109), 11, + ACTIONS(115), 11, sym_identifier, sym_unit_quote, anon_sym_COLON_COLON, @@ -9749,168 +10144,129 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [9633] = 9, + [10146] = 9, ACTIONS(361), 1, sym_identifier, ACTIONS(367), 1, anon_sym_LPAREN, - ACTIONS(369), 1, + ACTIONS(373), 1, aux_sym_base_ten_token1, - STATE(53), 1, - sym__float, - STATE(55), 1, + STATE(146), 1, sym_number, - STATE(162), 1, + STATE(147), 1, + sym__float, + STATE(151), 1, sym_constraint_set_expression, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(371), 2, + ACTIONS(375), 2, anon_sym_DASH, anon_sym_PLUS, - STATE(143), 5, + STATE(154), 5, sym_scalar, sym_constraint_set_parenthesis, sym_constraint_set_unary_expression, sym_constraint_set_binary_expression, sym_constraint_set_method_call, - [9667] = 9, + [10180] = 9, ACTIONS(361), 1, sym_identifier, ACTIONS(367), 1, anon_sym_LPAREN, - ACTIONS(369), 1, + ACTIONS(373), 1, aux_sym_base_ten_token1, - STATE(53), 1, - sym__float, - STATE(55), 1, + STATE(146), 1, sym_number, - STATE(167), 1, + STATE(147), 1, + sym__float, + STATE(165), 1, sym_constraint_set_expression, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(371), 2, + ACTIONS(375), 2, anon_sym_DASH, anon_sym_PLUS, - STATE(143), 5, + STATE(154), 5, sym_scalar, sym_constraint_set_parenthesis, sym_constraint_set_unary_expression, sym_constraint_set_binary_expression, sym_constraint_set_method_call, - [9701] = 9, + [10214] = 9, ACTIONS(361), 1, sym_identifier, + ACTIONS(363), 1, + aux_sym_base_ten_token1, ACTIONS(367), 1, anon_sym_LPAREN, - ACTIONS(369), 1, - aux_sym_base_ten_token1, - STATE(53), 1, + STATE(57), 1, sym__float, - STATE(55), 1, + STATE(59), 1, sym_number, - STATE(156), 1, + STATE(169), 1, sym_constraint_set_expression, ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(371), 2, - anon_sym_DASH, - anon_sym_PLUS, - STATE(143), 5, - sym_scalar, - sym_constraint_set_parenthesis, - sym_constraint_set_unary_expression, - sym_constraint_set_binary_expression, - sym_constraint_set_method_call, - [9735] = 3, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(375), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(373), 11, - anon_sym_COLON_COLON, - anon_sym_DASH, - anon_sym_PLUS, - anon_sym_STAR, - anon_sym_SLASH, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_RPAREN, - anon_sym_GT_GT_GT, - [9757] = 4, - ACTIONS(377), 1, - anon_sym_COLON_COLON, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - ACTIONS(381), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(379), 10, + sym_comment, + sym__whitespace, + ACTIONS(365), 2, anon_sym_DASH, anon_sym_PLUS, - anon_sym_STAR, - anon_sym_SLASH, - anon_sym_GT_EQ, - anon_sym_EQ_EQ, - anon_sym_LT_EQ, - anon_sym_BANG_EQ, - anon_sym_RPAREN, - anon_sym_GT_GT_GT, - [9781] = 9, + STATE(154), 5, + sym_scalar, + sym_constraint_set_parenthesis, + sym_constraint_set_unary_expression, + sym_constraint_set_binary_expression, + sym_constraint_set_method_call, + [10248] = 9, ACTIONS(361), 1, sym_identifier, ACTIONS(367), 1, anon_sym_LPAREN, - ACTIONS(369), 1, + ACTIONS(373), 1, aux_sym_base_ten_token1, - STATE(53), 1, - sym__float, - STATE(55), 1, + STATE(146), 1, sym_number, - STATE(165), 1, + STATE(147), 1, + sym__float, + STATE(163), 1, sym_constraint_set_expression, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(371), 2, + ACTIONS(375), 2, anon_sym_DASH, anon_sym_PLUS, - STATE(143), 5, + STATE(154), 5, sym_scalar, sym_constraint_set_parenthesis, sym_constraint_set_unary_expression, sym_constraint_set_binary_expression, sym_constraint_set_method_call, - [9815] = 7, + [10282] = 7, ACTIONS(377), 1, anon_sym_COLON_COLON, - STATE(153), 1, + STATE(161), 1, sym__constraint_set_relation, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(383), 2, + ACTIONS(391), 2, anon_sym_DASH, anon_sym_PLUS, - ACTIONS(385), 2, + ACTIONS(393), 2, anon_sym_STAR, anon_sym_SLASH, - ACTIONS(387), 2, + ACTIONS(395), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(389), 4, + ACTIONS(397), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [9844] = 3, + [10311] = 3, ACTIONS(3), 2, sym_comment, sym__whitespace, @@ -9927,52 +10283,52 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [9864] = 6, + [10331] = 5, ACTIONS(377), 1, anon_sym_COLON_COLON, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(383), 2, - anon_sym_DASH, - anon_sym_PLUS, - ACTIONS(385), 2, - anon_sym_STAR, - anon_sym_SLASH, - ACTIONS(391), 2, + ACTIONS(381), 2, anon_sym_GT, anon_sym_LT, - ACTIONS(393), 4, + ACTIONS(393), 2, + anon_sym_STAR, + anon_sym_SLASH, + ACTIONS(379), 6, + anon_sym_DASH, + anon_sym_PLUS, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [9890] = 5, + [10355] = 6, ACTIONS(377), 1, anon_sym_COLON_COLON, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(381), 2, - anon_sym_GT, - anon_sym_LT, - ACTIONS(385), 2, - anon_sym_STAR, - anon_sym_SLASH, - ACTIONS(379), 6, + ACTIONS(391), 2, anon_sym_DASH, anon_sym_PLUS, + ACTIONS(393), 2, + anon_sym_STAR, + anon_sym_SLASH, + ACTIONS(399), 2, + anon_sym_GT, + anon_sym_LT, + ACTIONS(401), 4, anon_sym_GT_EQ, anon_sym_EQ_EQ, anon_sym_LT_EQ, anon_sym_BANG_EQ, - [9914] = 4, + [10381] = 4, ACTIONS(377), 1, anon_sym_COLON_COLON, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(395), 2, + ACTIONS(403), 2, anon_sym_STAR, anon_sym_SLASH, ACTIONS(379), 4, @@ -9980,479 +10336,435 @@ static const uint16_t ts_small_parse_table[] = { anon_sym_PLUS, anon_sym_RPAREN, anon_sym_GT_GT_GT, - [9932] = 5, + [10399] = 5, ACTIONS(377), 1, anon_sym_COLON_COLON, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(393), 2, + ACTIONS(401), 2, anon_sym_RPAREN, anon_sym_GT_GT_GT, - ACTIONS(395), 2, + ACTIONS(403), 2, anon_sym_STAR, anon_sym_SLASH, - ACTIONS(397), 2, + ACTIONS(405), 2, anon_sym_DASH, anon_sym_PLUS, - [9952] = 7, - ACTIONS(37), 1, - sym_varadic_dots, - ACTIONS(399), 1, - sym_identifier, - ACTIONS(401), 1, - anon_sym_RPAREN, - STATE(168), 1, - aux_sym_struct_definition_repeat1, - STATE(199), 1, - sym_struct_member, - STATE(214), 1, - sym__struct_final_element, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - [9975] = 5, + [10419] = 5, ACTIONS(377), 1, anon_sym_COLON_COLON, - ACTIONS(403), 1, - anon_sym_RPAREN, + ACTIONS(407), 1, + anon_sym_GT_GT_GT, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(395), 2, + ACTIONS(403), 2, anon_sym_STAR, anon_sym_SLASH, - ACTIONS(397), 2, + ACTIONS(405), 2, anon_sym_DASH, anon_sym_PLUS, - [9994] = 5, + [10438] = 5, ACTIONS(377), 1, anon_sym_COLON_COLON, - ACTIONS(405), 1, + ACTIONS(409), 1, anon_sym_RPAREN, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(395), 2, + ACTIONS(403), 2, anon_sym_STAR, anon_sym_SLASH, - ACTIONS(397), 2, + ACTIONS(405), 2, anon_sym_DASH, anon_sym_PLUS, - [10013] = 5, + [10457] = 5, ACTIONS(377), 1, anon_sym_COLON_COLON, - ACTIONS(407), 1, - anon_sym_GT_GT_GT, + ACTIONS(411), 1, + anon_sym_RPAREN, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(395), 2, + ACTIONS(403), 2, anon_sym_STAR, anon_sym_SLASH, - ACTIONS(397), 2, + ACTIONS(405), 2, anon_sym_DASH, anon_sym_PLUS, - [10032] = 5, - ACTIONS(409), 1, + [10476] = 7, + ACTIONS(37), 1, + sym_varadic_dots, + ACTIONS(413), 1, sym_identifier, - STATE(168), 1, + ACTIONS(415), 1, + anon_sym_RPAREN, + STATE(173), 1, aux_sym_struct_definition_repeat1, - STATE(217), 1, + STATE(187), 1, sym_struct_member, + STATE(208), 1, + sym__struct_final_element, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(412), 2, - anon_sym_RPAREN, - sym_varadic_dots, - [10050] = 4, - ACTIONS(414), 1, - sym_identifier, + [10499] = 5, ACTIONS(417), 1, - anon_sym_in, + sym_identifier, + STATE(173), 1, + aux_sym_struct_definition_repeat1, + STATE(206), 1, + sym_struct_member, ACTIONS(3), 2, sym_comment, sym__whitespace, - STATE(169), 2, - sym_let_in_assignment, - aux_sym_let_in_repeat1, - [10065] = 4, - ACTIONS(419), 1, + ACTIONS(420), 2, + anon_sym_RPAREN, + sym_varadic_dots, + [10517] = 4, + ACTIONS(422), 1, sym_identifier, - ACTIONS(421), 1, + ACTIONS(425), 1, anon_sym_in, ACTIONS(3), 2, sym_comment, sym__whitespace, - STATE(173), 2, + STATE(174), 2, sym_let_in_assignment, aux_sym_let_in_repeat1, - [10080] = 4, - ACTIONS(419), 1, + [10532] = 4, + ACTIONS(427), 1, sym_identifier, - ACTIONS(423), 1, + ACTIONS(429), 1, anon_sym_in, ACTIONS(3), 2, sym_comment, sym__whitespace, - STATE(169), 2, + STATE(174), 2, sym_let_in_assignment, aux_sym_let_in_repeat1, - [10095] = 4, - ACTIONS(419), 1, + [10547] = 4, + ACTIONS(427), 1, sym_identifier, - ACTIONS(425), 1, + ACTIONS(431), 1, anon_sym_in, ACTIONS(3), 2, sym_comment, sym__whitespace, - STATE(171), 2, + STATE(175), 2, sym_let_in_assignment, aux_sym_let_in_repeat1, - [10110] = 4, - ACTIONS(419), 1, - sym_identifier, + [10562] = 4, ACTIONS(427), 1, + sym_identifier, + ACTIONS(433), 1, anon_sym_in, ACTIONS(3), 2, sym_comment, sym__whitespace, - STATE(169), 2, + STATE(178), 2, sym_let_in_assignment, aux_sym_let_in_repeat1, - [10125] = 4, - ACTIONS(429), 1, - anon_sym_COMMA, - ACTIONS(431), 1, - anon_sym_RPAREN, - STATE(181), 1, - aux_sym_dictionary_construction_repeat1, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - [10139] = 4, - ACTIONS(433), 1, + [10577] = 4, + ACTIONS(427), 1, sym_identifier, ACTIONS(435), 1, - anon_sym_RPAREN, - STATE(197), 1, - sym_dictionary_member_assignment, + anon_sym_in, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10153] = 4, + STATE(174), 2, + sym_let_in_assignment, + aux_sym_let_in_repeat1, + [10592] = 4, ACTIONS(437), 1, anon_sym_COMMA, ACTIONS(440), 1, anon_sym_RPAREN, - STATE(176), 1, + STATE(179), 1, aux_sym_dictionary_construction_repeat1, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10167] = 4, + [10606] = 4, ACTIONS(442), 1, sym_identifier, - STATE(194), 1, + STATE(188), 1, aux_sym_constraint_set_fields_repeat1, - STATE(206), 1, + STATE(205), 1, sym_constraint_set_fields, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10181] = 3, - ACTIONS(446), 1, - anon_sym_EQ, + [10620] = 4, + ACTIONS(45), 1, + anon_sym_RPAREN, + ACTIONS(444), 1, + anon_sym_COMMA, + STATE(179), 1, + aux_sym_dictionary_construction_repeat1, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(444), 2, - anon_sym_COMMA, - anon_sym_RPAREN, - [10193] = 2, + [10634] = 2, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(412), 3, + ACTIONS(420), 3, sym_identifier, anon_sym_RPAREN, sym_varadic_dots, - [10203] = 4, - ACTIONS(433), 1, - sym_identifier, - ACTIONS(448), 1, - anon_sym_RPAREN, - STATE(197), 1, - sym_dictionary_member_assignment, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - [10217] = 4, + [10644] = 4, + ACTIONS(446), 1, + anon_sym_COMMA, ACTIONS(448), 1, anon_sym_RPAREN, - ACTIONS(450), 1, - anon_sym_COMMA, - STATE(176), 1, + STATE(181), 1, aux_sym_dictionary_construction_repeat1, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10231] = 4, - ACTIONS(433), 1, - sym_identifier, + [10658] = 3, ACTIONS(452), 1, - anon_sym_RPAREN, - STATE(174), 1, - sym_dictionary_member_assignment, + anon_sym_EQ, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10245] = 3, - ACTIONS(454), 1, - sym_identifier, - STATE(183), 1, - aux_sym_constraint_set_fields_repeat1, + ACTIONS(450), 2, + anon_sym_COMMA, + anon_sym_RPAREN, + [10670] = 2, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10256] = 3, - ACTIONS(433), 1, + ACTIONS(454), 2, sym_identifier, - STATE(197), 1, - sym_dictionary_member_assignment, + anon_sym_in, + [10679] = 2, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10267] = 3, - ACTIONS(457), 1, + ACTIONS(456), 2, + aux_sym_signed_integer_token1, + aux_sym_unsigned_integer_token1, + [10688] = 3, + ACTIONS(458), 1, anon_sym_COMMA, - ACTIONS(459), 1, - anon_sym_COLON, + ACTIONS(460), 1, + anon_sym_RPAREN, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10278] = 3, - ACTIONS(369), 1, - aux_sym_base_ten_token1, - STATE(54), 1, - sym_number, + [10699] = 3, + ACTIONS(462), 1, + sym_identifier, + STATE(198), 1, + aux_sym_constraint_set_fields_repeat1, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10289] = 2, + [10710] = 2, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(461), 2, + ACTIONS(464), 2, aux_sym_signed_integer_token1, aux_sym_unsigned_integer_token1, - [10298] = 3, - ACTIONS(457), 1, + [10719] = 3, + ACTIONS(460), 1, + anon_sym_RPAREN, + ACTIONS(466), 1, anon_sym_COMMA, - ACTIONS(463), 1, - anon_sym_COLON, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10309] = 3, - ACTIONS(465), 1, - aux_sym_signed_integer_token1, - ACTIONS(467), 1, - aux_sym_unsigned_integer_token1, + [10730] = 3, + ACTIONS(468), 1, + anon_sym_COMMA, + ACTIONS(470), 1, + anon_sym_COLON, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10320] = 3, - ACTIONS(469), 1, - anon_sym_COLON, - STATE(178), 1, - sym_declaration_type, + [10741] = 3, + ACTIONS(363), 1, + aux_sym_base_ten_token1, + STATE(58), 1, + sym_number, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10331] = 2, + [10752] = 3, + ACTIONS(133), 1, + anon_sym_LPAREN, + STATE(85), 1, + sym_dictionary_construction, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(471), 2, - aux_sym_signed_integer_token1, - aux_sym_unsigned_integer_token1, - [10340] = 2, + [10763] = 3, + ACTIONS(472), 1, + anon_sym_COLON, + STATE(184), 1, + sym_declaration_type, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(473), 2, - aux_sym_signed_integer_token1, - aux_sym_unsigned_integer_token1, - [10349] = 3, - ACTIONS(137), 1, - anon_sym_LPAREN, - STATE(69), 1, - sym_dictionary_construction, + [10774] = 2, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10360] = 3, - ACTIONS(475), 1, - sym_identifier, - STATE(183), 1, - aux_sym_constraint_set_fields_repeat1, + ACTIONS(440), 2, + anon_sym_COMMA, + anon_sym_RPAREN, + [10783] = 3, + ACTIONS(468), 1, + anon_sym_COMMA, + ACTIONS(474), 1, + anon_sym_COLON, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10371] = 3, - ACTIONS(477), 1, + [10794] = 3, + ACTIONS(476), 1, aux_sym_base_ten_token1, - STATE(104), 1, + STATE(115), 1, sym_number, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10382] = 2, + [10805] = 3, + ACTIONS(478), 1, + sym_identifier, + STATE(198), 1, + aux_sym_constraint_set_fields_repeat1, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(479), 2, - sym_identifier, - anon_sym_in, - [10391] = 2, + [10816] = 2, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(440), 2, - anon_sym_COMMA, - anon_sym_RPAREN, - [10400] = 3, - ACTIONS(363), 1, + ACTIONS(481), 2, + aux_sym_signed_integer_token1, + aux_sym_unsigned_integer_token1, + [10825] = 3, + ACTIONS(373), 1, aux_sym_base_ten_token1, - STATE(151), 1, + STATE(158), 1, sym_number, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10411] = 3, - ACTIONS(481), 1, - anon_sym_COMMA, + [10836] = 3, ACTIONS(483), 1, - anon_sym_RPAREN, + aux_sym_signed_integer_token1, + ACTIONS(485), 1, + aux_sym_unsigned_integer_token1, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10422] = 2, + [10847] = 2, ACTIONS(3), 2, sym_comment, sym__whitespace, - ACTIONS(485), 2, + ACTIONS(487), 2, aux_sym_signed_integer_token1, aux_sym_unsigned_integer_token1, - [10431] = 3, - ACTIONS(483), 1, - anon_sym_RPAREN, - ACTIONS(487), 1, - anon_sym_COMMA, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - [10442] = 2, + [10856] = 2, ACTIONS(489), 1, sym_identifier, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10450] = 2, + [10864] = 2, ACTIONS(491), 1, - sym_identifier, + aux_sym_binary_token2, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10458] = 2, + [10872] = 2, ACTIONS(493), 1, - aux_sym_hex_token2, + anon_sym_COLON, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10466] = 2, + [10880] = 2, + ACTIONS(458), 1, + anon_sym_COMMA, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + [10888] = 2, ACTIONS(495), 1, - aux_sym_binary_token2, + sym_identifier, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10474] = 2, + [10896] = 2, ACTIONS(497), 1, - anon_sym_COLON, + anon_sym_RPAREN, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10482] = 2, + [10904] = 2, + ACTIONS(468), 1, + anon_sym_COMMA, + ACTIONS(3), 2, + sym_comment, + sym__whitespace, + [10912] = 2, ACTIONS(499), 1, - anon_sym_EQ, + anon_sym_RPAREN, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10490] = 2, + [10920] = 2, ACTIONS(501), 1, - anon_sym_LPAREN, + anon_sym_RPAREN, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10498] = 2, + [10928] = 2, ACTIONS(503), 1, - anon_sym_EQ, + anon_sym_LPAREN, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10506] = 2, + [10936] = 2, ACTIONS(505), 1, - aux_sym_base_ten_token1, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - [10514] = 2, - ACTIONS(457), 1, - anon_sym_COMMA, + sym_identifier, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10522] = 2, + [10944] = 2, ACTIONS(507), 1, - ts_builtin_sym_end, + aux_sym_base_ten_token1, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10530] = 2, + [10952] = 2, ACTIONS(509), 1, - anon_sym_RPAREN, + anon_sym_EQ, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10538] = 2, + [10960] = 2, ACTIONS(511), 1, - anon_sym_RPAREN, + ts_builtin_sym_end, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10546] = 2, + [10968] = 2, ACTIONS(513), 1, sym_identifier, ACTIONS(3), 2, sym_comment, sym__whitespace, - [10554] = 2, + [10976] = 2, ACTIONS(515), 1, - sym_identifier, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - [10562] = 2, - ACTIONS(481), 1, - anon_sym_COMMA, - ACTIONS(3), 2, - sym_comment, - sym__whitespace, - [10570] = 2, - ACTIONS(517), 1, - anon_sym_RPAREN, + aux_sym_hex_token2, ACTIONS(3), 2, sym_comment, sym__whitespace, @@ -10463,218 +10775,218 @@ static const uint32_t ts_small_parse_table_map[] = { [SMALL_STATE(4)] = 99, [SMALL_STATE(5)] = 198, [SMALL_STATE(6)] = 297, - [SMALL_STATE(7)] = 390, - [SMALL_STATE(8)] = 483, - [SMALL_STATE(9)] = 576, - [SMALL_STATE(10)] = 669, - [SMALL_STATE(11)] = 762, - [SMALL_STATE(12)] = 855, - [SMALL_STATE(13)] = 948, - [SMALL_STATE(14)] = 1041, - [SMALL_STATE(15)] = 1134, - [SMALL_STATE(16)] = 1227, - [SMALL_STATE(17)] = 1320, - [SMALL_STATE(18)] = 1413, - [SMALL_STATE(19)] = 1506, - [SMALL_STATE(20)] = 1599, - [SMALL_STATE(21)] = 1692, - [SMALL_STATE(22)] = 1785, - [SMALL_STATE(23)] = 1878, - [SMALL_STATE(24)] = 1971, - [SMALL_STATE(25)] = 2064, - [SMALL_STATE(26)] = 2157, - [SMALL_STATE(27)] = 2250, - [SMALL_STATE(28)] = 2343, - [SMALL_STATE(29)] = 2436, - [SMALL_STATE(30)] = 2529, - [SMALL_STATE(31)] = 2622, - [SMALL_STATE(32)] = 2715, - [SMALL_STATE(33)] = 2808, - [SMALL_STATE(34)] = 2901, - [SMALL_STATE(35)] = 2994, - [SMALL_STATE(36)] = 3087, - [SMALL_STATE(37)] = 3180, - [SMALL_STATE(38)] = 3273, - [SMALL_STATE(39)] = 3366, - [SMALL_STATE(40)] = 3459, - [SMALL_STATE(41)] = 3552, - [SMALL_STATE(42)] = 3645, - [SMALL_STATE(43)] = 3738, - [SMALL_STATE(44)] = 3831, - [SMALL_STATE(45)] = 3924, - [SMALL_STATE(46)] = 4017, - [SMALL_STATE(47)] = 4110, - [SMALL_STATE(48)] = 4203, - [SMALL_STATE(49)] = 4296, - [SMALL_STATE(50)] = 4389, - [SMALL_STATE(51)] = 4482, - [SMALL_STATE(52)] = 4575, - [SMALL_STATE(53)] = 4621, - [SMALL_STATE(54)] = 4671, - [SMALL_STATE(55)] = 4714, - [SMALL_STATE(56)] = 4759, - [SMALL_STATE(57)] = 4802, - [SMALL_STATE(58)] = 4846, - [SMALL_STATE(59)] = 4888, - [SMALL_STATE(60)] = 4938, - [SMALL_STATE(61)] = 4980, - [SMALL_STATE(62)] = 5022, - [SMALL_STATE(63)] = 5064, - [SMALL_STATE(64)] = 5129, - [SMALL_STATE(65)] = 5204, - [SMALL_STATE(66)] = 5279, - [SMALL_STATE(67)] = 5320, - [SMALL_STATE(68)] = 5363, - [SMALL_STATE(69)] = 5404, - [SMALL_STATE(70)] = 5445, - [SMALL_STATE(71)] = 5520, - [SMALL_STATE(72)] = 5561, - [SMALL_STATE(73)] = 5602, - [SMALL_STATE(74)] = 5643, - [SMALL_STATE(75)] = 5718, - [SMALL_STATE(76)] = 5793, - [SMALL_STATE(77)] = 5834, - [SMALL_STATE(78)] = 5875, - [SMALL_STATE(79)] = 5916, - [SMALL_STATE(80)] = 5957, - [SMALL_STATE(81)] = 5998, - [SMALL_STATE(82)] = 6039, - [SMALL_STATE(83)] = 6080, - [SMALL_STATE(84)] = 6121, - [SMALL_STATE(85)] = 6162, - [SMALL_STATE(86)] = 6217, - [SMALL_STATE(87)] = 6258, - [SMALL_STATE(88)] = 6309, - [SMALL_STATE(89)] = 6366, - [SMALL_STATE(90)] = 6425, - [SMALL_STATE(91)] = 6488, - [SMALL_STATE(92)] = 6549, - [SMALL_STATE(93)] = 6590, - [SMALL_STATE(94)] = 6659, - [SMALL_STATE(95)] = 6730, - [SMALL_STATE(96)] = 6803, - [SMALL_STATE(97)] = 6844, - [SMALL_STATE(98)] = 6885, - [SMALL_STATE(99)] = 6923, - [SMALL_STATE(100)] = 6964, - [SMALL_STATE(101)] = 7033, - [SMALL_STATE(102)] = 7074, - [SMALL_STATE(103)] = 7110, - [SMALL_STATE(104)] = 7144, - [SMALL_STATE(105)] = 7178, - [SMALL_STATE(106)] = 7244, - [SMALL_STATE(107)] = 7312, - [SMALL_STATE(108)] = 7380, - [SMALL_STATE(109)] = 7448, - [SMALL_STATE(110)] = 7514, - [SMALL_STATE(111)] = 7582, - [SMALL_STATE(112)] = 7639, - [SMALL_STATE(113)] = 7704, - [SMALL_STATE(114)] = 7769, - [SMALL_STATE(115)] = 7834, - [SMALL_STATE(116)] = 7899, - [SMALL_STATE(117)] = 7964, - [SMALL_STATE(118)] = 8029, - [SMALL_STATE(119)] = 8094, - [SMALL_STATE(120)] = 8159, - [SMALL_STATE(121)] = 8206, - [SMALL_STATE(122)] = 8249, - [SMALL_STATE(123)] = 8298, - [SMALL_STATE(124)] = 8349, - [SMALL_STATE(125)] = 8404, - [SMALL_STATE(126)] = 8457, - [SMALL_STATE(127)] = 8516, - [SMALL_STATE(128)] = 8577, - [SMALL_STATE(129)] = 8640, - [SMALL_STATE(130)] = 8705, - [SMALL_STATE(131)] = 8770, - [SMALL_STATE(132)] = 8835, - [SMALL_STATE(133)] = 8900, - [SMALL_STATE(134)] = 8965, - [SMALL_STATE(135)] = 9030, - [SMALL_STATE(136)] = 9095, - [SMALL_STATE(137)] = 9160, - [SMALL_STATE(138)] = 9195, - [SMALL_STATE(139)] = 9260, - [SMALL_STATE(140)] = 9288, - [SMALL_STATE(141)] = 9313, - [SMALL_STATE(142)] = 9336, - [SMALL_STATE(143)] = 9363, - [SMALL_STATE(144)] = 9385, - [SMALL_STATE(145)] = 9407, - [SMALL_STATE(146)] = 9441, - [SMALL_STATE(147)] = 9475, - [SMALL_STATE(148)] = 9509, - [SMALL_STATE(149)] = 9543, - [SMALL_STATE(150)] = 9577, - [SMALL_STATE(151)] = 9611, - [SMALL_STATE(152)] = 9633, - [SMALL_STATE(153)] = 9667, - [SMALL_STATE(154)] = 9701, - [SMALL_STATE(155)] = 9735, - [SMALL_STATE(156)] = 9757, - [SMALL_STATE(157)] = 9781, - [SMALL_STATE(158)] = 9815, - [SMALL_STATE(159)] = 9844, - [SMALL_STATE(160)] = 9864, - [SMALL_STATE(161)] = 9890, - [SMALL_STATE(162)] = 9914, - [SMALL_STATE(163)] = 9932, - [SMALL_STATE(164)] = 9952, - [SMALL_STATE(165)] = 9975, - [SMALL_STATE(166)] = 9994, - [SMALL_STATE(167)] = 10013, - [SMALL_STATE(168)] = 10032, - [SMALL_STATE(169)] = 10050, - [SMALL_STATE(170)] = 10065, - [SMALL_STATE(171)] = 10080, - [SMALL_STATE(172)] = 10095, - [SMALL_STATE(173)] = 10110, - [SMALL_STATE(174)] = 10125, - [SMALL_STATE(175)] = 10139, - [SMALL_STATE(176)] = 10153, - [SMALL_STATE(177)] = 10167, - [SMALL_STATE(178)] = 10181, - [SMALL_STATE(179)] = 10193, - [SMALL_STATE(180)] = 10203, - [SMALL_STATE(181)] = 10217, - [SMALL_STATE(182)] = 10231, - [SMALL_STATE(183)] = 10245, - [SMALL_STATE(184)] = 10256, - [SMALL_STATE(185)] = 10267, - [SMALL_STATE(186)] = 10278, - [SMALL_STATE(187)] = 10289, - [SMALL_STATE(188)] = 10298, - [SMALL_STATE(189)] = 10309, - [SMALL_STATE(190)] = 10320, - [SMALL_STATE(191)] = 10331, - [SMALL_STATE(192)] = 10340, - [SMALL_STATE(193)] = 10349, - [SMALL_STATE(194)] = 10360, - [SMALL_STATE(195)] = 10371, - [SMALL_STATE(196)] = 10382, - [SMALL_STATE(197)] = 10391, - [SMALL_STATE(198)] = 10400, - [SMALL_STATE(199)] = 10411, - [SMALL_STATE(200)] = 10422, - [SMALL_STATE(201)] = 10431, - [SMALL_STATE(202)] = 10442, - [SMALL_STATE(203)] = 10450, - [SMALL_STATE(204)] = 10458, - [SMALL_STATE(205)] = 10466, - [SMALL_STATE(206)] = 10474, - [SMALL_STATE(207)] = 10482, - [SMALL_STATE(208)] = 10490, - [SMALL_STATE(209)] = 10498, - [SMALL_STATE(210)] = 10506, - [SMALL_STATE(211)] = 10514, - [SMALL_STATE(212)] = 10522, - [SMALL_STATE(213)] = 10530, - [SMALL_STATE(214)] = 10538, - [SMALL_STATE(215)] = 10546, - [SMALL_STATE(216)] = 10554, - [SMALL_STATE(217)] = 10562, - [SMALL_STATE(218)] = 10570, + [SMALL_STATE(7)] = 396, + [SMALL_STATE(8)] = 495, + [SMALL_STATE(9)] = 594, + [SMALL_STATE(10)] = 690, + [SMALL_STATE(11)] = 783, + [SMALL_STATE(12)] = 876, + [SMALL_STATE(13)] = 969, + [SMALL_STATE(14)] = 1062, + [SMALL_STATE(15)] = 1155, + [SMALL_STATE(16)] = 1248, + [SMALL_STATE(17)] = 1341, + [SMALL_STATE(18)] = 1434, + [SMALL_STATE(19)] = 1527, + [SMALL_STATE(20)] = 1620, + [SMALL_STATE(21)] = 1713, + [SMALL_STATE(22)] = 1806, + [SMALL_STATE(23)] = 1899, + [SMALL_STATE(24)] = 1992, + [SMALL_STATE(25)] = 2085, + [SMALL_STATE(26)] = 2178, + [SMALL_STATE(27)] = 2271, + [SMALL_STATE(28)] = 2364, + [SMALL_STATE(29)] = 2457, + [SMALL_STATE(30)] = 2550, + [SMALL_STATE(31)] = 2643, + [SMALL_STATE(32)] = 2736, + [SMALL_STATE(33)] = 2829, + [SMALL_STATE(34)] = 2922, + [SMALL_STATE(35)] = 3015, + [SMALL_STATE(36)] = 3108, + [SMALL_STATE(37)] = 3201, + [SMALL_STATE(38)] = 3294, + [SMALL_STATE(39)] = 3387, + [SMALL_STATE(40)] = 3480, + [SMALL_STATE(41)] = 3573, + [SMALL_STATE(42)] = 3666, + [SMALL_STATE(43)] = 3759, + [SMALL_STATE(44)] = 3852, + [SMALL_STATE(45)] = 3945, + [SMALL_STATE(46)] = 4038, + [SMALL_STATE(47)] = 4131, + [SMALL_STATE(48)] = 4224, + [SMALL_STATE(49)] = 4317, + [SMALL_STATE(50)] = 4410, + [SMALL_STATE(51)] = 4503, + [SMALL_STATE(52)] = 4596, + [SMALL_STATE(53)] = 4689, + [SMALL_STATE(54)] = 4782, + [SMALL_STATE(55)] = 4875, + [SMALL_STATE(56)] = 4968, + [SMALL_STATE(57)] = 5014, + [SMALL_STATE(58)] = 5064, + [SMALL_STATE(59)] = 5107, + [SMALL_STATE(60)] = 5152, + [SMALL_STATE(61)] = 5195, + [SMALL_STATE(62)] = 5245, + [SMALL_STATE(63)] = 5287, + [SMALL_STATE(64)] = 5329, + [SMALL_STATE(65)] = 5371, + [SMALL_STATE(66)] = 5415, + [SMALL_STATE(67)] = 5457, + [SMALL_STATE(68)] = 5498, + [SMALL_STATE(69)] = 5539, + [SMALL_STATE(70)] = 5580, + [SMALL_STATE(71)] = 5621, + [SMALL_STATE(72)] = 5662, + [SMALL_STATE(73)] = 5717, + [SMALL_STATE(74)] = 5758, + [SMALL_STATE(75)] = 5809, + [SMALL_STATE(76)] = 5866, + [SMALL_STATE(77)] = 5925, + [SMALL_STATE(78)] = 5988, + [SMALL_STATE(79)] = 6049, + [SMALL_STATE(80)] = 6114, + [SMALL_STATE(81)] = 6183, + [SMALL_STATE(82)] = 6254, + [SMALL_STATE(83)] = 6327, + [SMALL_STATE(84)] = 6402, + [SMALL_STATE(85)] = 6443, + [SMALL_STATE(86)] = 6484, + [SMALL_STATE(87)] = 6525, + [SMALL_STATE(88)] = 6566, + [SMALL_STATE(89)] = 6607, + [SMALL_STATE(90)] = 6648, + [SMALL_STATE(91)] = 6723, + [SMALL_STATE(92)] = 6798, + [SMALL_STATE(93)] = 6839, + [SMALL_STATE(94)] = 6880, + [SMALL_STATE(95)] = 6921, + [SMALL_STATE(96)] = 6962, + [SMALL_STATE(97)] = 7003, + [SMALL_STATE(98)] = 7046, + [SMALL_STATE(99)] = 7121, + [SMALL_STATE(100)] = 7162, + [SMALL_STATE(101)] = 7237, + [SMALL_STATE(102)] = 7278, + [SMALL_STATE(103)] = 7318, + [SMALL_STATE(104)] = 7356, + [SMALL_STATE(105)] = 7397, + [SMALL_STATE(106)] = 7466, + [SMALL_STATE(107)] = 7537, + [SMALL_STATE(108)] = 7606, + [SMALL_STATE(109)] = 7674, + [SMALL_STATE(110)] = 7742, + [SMALL_STATE(111)] = 7810, + [SMALL_STATE(112)] = 7846, + [SMALL_STATE(113)] = 7912, + [SMALL_STATE(114)] = 7980, + [SMALL_STATE(115)] = 8014, + [SMALL_STATE(116)] = 8048, + [SMALL_STATE(117)] = 8114, + [SMALL_STATE(118)] = 8179, + [SMALL_STATE(119)] = 8244, + [SMALL_STATE(120)] = 8309, + [SMALL_STATE(121)] = 8374, + [SMALL_STATE(122)] = 8439, + [SMALL_STATE(123)] = 8504, + [SMALL_STATE(124)] = 8569, + [SMALL_STATE(125)] = 8616, + [SMALL_STATE(126)] = 8659, + [SMALL_STATE(127)] = 8708, + [SMALL_STATE(128)] = 8759, + [SMALL_STATE(129)] = 8814, + [SMALL_STATE(130)] = 8867, + [SMALL_STATE(131)] = 8924, + [SMALL_STATE(132)] = 8983, + [SMALL_STATE(133)] = 9044, + [SMALL_STATE(134)] = 9107, + [SMALL_STATE(135)] = 9172, + [SMALL_STATE(136)] = 9237, + [SMALL_STATE(137)] = 9302, + [SMALL_STATE(138)] = 9367, + [SMALL_STATE(139)] = 9432, + [SMALL_STATE(140)] = 9497, + [SMALL_STATE(141)] = 9562, + [SMALL_STATE(142)] = 9627, + [SMALL_STATE(143)] = 9692, + [SMALL_STATE(144)] = 9727, + [SMALL_STATE(145)] = 9755, + [SMALL_STATE(146)] = 9778, + [SMALL_STATE(147)] = 9803, + [SMALL_STATE(148)] = 9830, + [SMALL_STATE(149)] = 9864, + [SMALL_STATE(150)] = 9886, + [SMALL_STATE(151)] = 9920, + [SMALL_STATE(152)] = 9944, + [SMALL_STATE(153)] = 9978, + [SMALL_STATE(154)] = 10000, + [SMALL_STATE(155)] = 10022, + [SMALL_STATE(156)] = 10056, + [SMALL_STATE(157)] = 10090, + [SMALL_STATE(158)] = 10124, + [SMALL_STATE(159)] = 10146, + [SMALL_STATE(160)] = 10180, + [SMALL_STATE(161)] = 10214, + [SMALL_STATE(162)] = 10248, + [SMALL_STATE(163)] = 10282, + [SMALL_STATE(164)] = 10311, + [SMALL_STATE(165)] = 10331, + [SMALL_STATE(166)] = 10355, + [SMALL_STATE(167)] = 10381, + [SMALL_STATE(168)] = 10399, + [SMALL_STATE(169)] = 10419, + [SMALL_STATE(170)] = 10438, + [SMALL_STATE(171)] = 10457, + [SMALL_STATE(172)] = 10476, + [SMALL_STATE(173)] = 10499, + [SMALL_STATE(174)] = 10517, + [SMALL_STATE(175)] = 10532, + [SMALL_STATE(176)] = 10547, + [SMALL_STATE(177)] = 10562, + [SMALL_STATE(178)] = 10577, + [SMALL_STATE(179)] = 10592, + [SMALL_STATE(180)] = 10606, + [SMALL_STATE(181)] = 10620, + [SMALL_STATE(182)] = 10634, + [SMALL_STATE(183)] = 10644, + [SMALL_STATE(184)] = 10658, + [SMALL_STATE(185)] = 10670, + [SMALL_STATE(186)] = 10679, + [SMALL_STATE(187)] = 10688, + [SMALL_STATE(188)] = 10699, + [SMALL_STATE(189)] = 10710, + [SMALL_STATE(190)] = 10719, + [SMALL_STATE(191)] = 10730, + [SMALL_STATE(192)] = 10741, + [SMALL_STATE(193)] = 10752, + [SMALL_STATE(194)] = 10763, + [SMALL_STATE(195)] = 10774, + [SMALL_STATE(196)] = 10783, + [SMALL_STATE(197)] = 10794, + [SMALL_STATE(198)] = 10805, + [SMALL_STATE(199)] = 10816, + [SMALL_STATE(200)] = 10825, + [SMALL_STATE(201)] = 10836, + [SMALL_STATE(202)] = 10847, + [SMALL_STATE(203)] = 10856, + [SMALL_STATE(204)] = 10864, + [SMALL_STATE(205)] = 10872, + [SMALL_STATE(206)] = 10880, + [SMALL_STATE(207)] = 10888, + [SMALL_STATE(208)] = 10896, + [SMALL_STATE(209)] = 10904, + [SMALL_STATE(210)] = 10912, + [SMALL_STATE(211)] = 10920, + [SMALL_STATE(212)] = 10928, + [SMALL_STATE(213)] = 10936, + [SMALL_STATE(214)] = 10944, + [SMALL_STATE(215)] = 10952, + [SMALL_STATE(216)] = 10960, + [SMALL_STATE(217)] = 10968, + [SMALL_STATE(218)] = 10976, }; static const TSParseActionEntry ts_parse_actions[] = { @@ -10683,252 +10995,251 @@ static const TSParseActionEntry ts_parse_actions[] = { [3] = {.entry = {.count = 1, .reusable = true}}, SHIFT_EXTRA(), [5] = {.entry = {.count = 1, .reusable = false}}, SHIFT(92), [7] = {.entry = {.count = 1, .reusable = true}}, SHIFT(92), - [9] = {.entry = {.count = 1, .reusable = false}}, SHIFT(52), - [11] = {.entry = {.count = 1, .reusable = true}}, SHIFT(210), - [13] = {.entry = {.count = 1, .reusable = true}}, SHIFT(204), - [15] = {.entry = {.count = 1, .reusable = true}}, SHIFT(205), - [17] = {.entry = {.count = 1, .reusable = true}}, SHIFT(51), - [19] = {.entry = {.count = 1, .reusable = false}}, SHIFT(82), - [21] = {.entry = {.count = 1, .reusable = true}}, SHIFT(27), - [23] = {.entry = {.count = 1, .reusable = false}}, SHIFT(39), - [25] = {.entry = {.count = 1, .reusable = false}}, SHIFT(172), + [9] = {.entry = {.count = 1, .reusable = false}}, SHIFT(56), + [11] = {.entry = {.count = 1, .reusable = true}}, SHIFT(214), + [13] = {.entry = {.count = 1, .reusable = true}}, SHIFT(218), + [15] = {.entry = {.count = 1, .reusable = true}}, SHIFT(204), + [17] = {.entry = {.count = 1, .reusable = true}}, SHIFT(23), + [19] = {.entry = {.count = 1, .reusable = false}}, SHIFT(96), + [21] = {.entry = {.count = 1, .reusable = true}}, SHIFT(35), + [23] = {.entry = {.count = 1, .reusable = false}}, SHIFT(10), + [25] = {.entry = {.count = 1, .reusable = false}}, SHIFT(176), [27] = {.entry = {.count = 1, .reusable = true}}, SHIFT(2), - [29] = {.entry = {.count = 1, .reusable = true}}, SHIFT(3), - [31] = {.entry = {.count = 1, .reusable = true}}, SHIFT(177), - [33] = {.entry = {.count = 1, .reusable = false}}, SHIFT(101), - [35] = {.entry = {.count = 1, .reusable = true}}, SHIFT(57), - [37] = {.entry = {.count = 1, .reusable = true}}, SHIFT(201), - [39] = {.entry = {.count = 1, .reusable = true}}, SHIFT(76), - [41] = {.entry = {.count = 1, .reusable = true}}, SHIFT(81), - [43] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(92), - [46] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(92), - [49] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(52), - [52] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(210), - [55] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(204), - [58] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(205), - [61] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(51), - [64] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(82), - [67] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(27), - [70] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(39), - [73] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(172), - [76] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(2), - [79] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(3), - [82] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), - [84] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(177), - [87] = {.entry = {.count = 1, .reusable = false}}, SHIFT(98), - [89] = {.entry = {.count = 1, .reusable = true}}, SHIFT(33), - [91] = {.entry = {.count = 1, .reusable = false}}, SHIFT(7), - [93] = {.entry = {.count = 1, .reusable = false}}, SHIFT(170), - [95] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_number, 1, 0, 0), - [97] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_number, 1, 0, 0), - [99] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_base_ten, 1, 0, 0), - [101] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_scalar, 1, 0, 2), - [103] = {.entry = {.count = 1, .reusable = false}}, SHIFT(60), - [105] = {.entry = {.count = 1, .reusable = true}}, SHIFT(60), - [107] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_scalar, 1, 0, 2), - [109] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__float, 3, 0, 12), - [111] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym__float, 3, 0, 12), - [113] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__float, 1, 0, 1), - [115] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym__float, 1, 0, 1), - [117] = {.entry = {.count = 1, .reusable = true}}, SHIFT(186), - [119] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_dictionary_construction, 2, 0, 0), - [121] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_dictionary_construction, 2, 0, 0), - [123] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_struct_definition, 2, 0, 0), - [125] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_struct_definition, 4, 0, 18), - [127] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_struct_definition, 4, 0, 18), - [129] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_binary_expression, 3, 0, 14), - [131] = {.entry = {.count = 1, .reusable = true}}, SHIFT(216), - [133] = {.entry = {.count = 1, .reusable = true}}, SHIFT(202), - [135] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_binary_expression, 3, 0, 14), - [137] = {.entry = {.count = 1, .reusable = true}}, SHIFT(182), - [139] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_scalar, 2, 0, 5), - [141] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_scalar, 2, 0, 5), - [143] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_struct_definition, 3, 0, 9), - [145] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_struct_definition, 3, 0, 9), - [147] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_struct_definition, 3, 0, 11), - [149] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_struct_definition, 3, 0, 11), - [151] = {.entry = {.count = 1, .reusable = true}}, SHIFT(9), - [153] = {.entry = {.count = 1, .reusable = true}}, SHIFT(10), - [155] = {.entry = {.count = 1, .reusable = false}}, SHIFT(11), - [157] = {.entry = {.count = 1, .reusable = true}}, SHIFT(11), - [159] = {.entry = {.count = 1, .reusable = true}}, SHIFT(12), - [161] = {.entry = {.count = 1, .reusable = false}}, SHIFT(13), - [163] = {.entry = {.count = 1, .reusable = false}}, SHIFT(14), - [165] = {.entry = {.count = 1, .reusable = false}}, SHIFT(15), - [167] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_let_in, 4, 0, 15), - [169] = {.entry = {.count = 1, .reusable = false}}, SHIFT(16), - [171] = {.entry = {.count = 1, .reusable = true}}, SHIFT(16), - [173] = {.entry = {.count = 1, .reusable = true}}, SHIFT(17), - [175] = {.entry = {.count = 1, .reusable = true}}, SHIFT(18), - [177] = {.entry = {.count = 1, .reusable = true}}, SHIFT(19), - [179] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_let_in, 4, 0, 15), - [181] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_let_in, 3, 0, 7), - [183] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_let_in, 3, 0, 7), - [185] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_dictionary_construction, 4, 0, 17), - [187] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_dictionary_construction, 4, 0, 17), - [189] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_expression, 1, 0, 0), - [191] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_expression, 1, 0, 0), - [193] = {.entry = {.count = 1, .reusable = true}}, SHIFT(20), - [195] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_list, 4, 0, 0), - [197] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_list, 4, 0, 0), - [199] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_method_call, 4, 0, 19), - [201] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_method_call, 4, 0, 19), - [203] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_unary_expression, 2, 0, 3), - [205] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_unary_expression, 2, 0, 3), - [207] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_vector2, 5, 0, 20), - [209] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_vector2, 5, 0, 20), - [211] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_parenthesis, 3, 0, 0), - [213] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_parenthesis, 3, 0, 0), - [215] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_dictionary_construction, 5, 0, 23), - [217] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_dictionary_construction, 5, 0, 23), - [219] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_closure_definition, 5, 0, 24), - [221] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_closure_definition, 5, 0, 24), - [223] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_if, 6, 0, 25), - [225] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_if, 6, 0, 25), - [227] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_list, 2, 0, 0), - [229] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_list, 2, 0, 0), - [231] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_vector3, 7, 0, 26), - [233] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_vector3, 7, 0, 26), - [235] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_vector4, 9, 0, 28), - [237] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_vector4, 9, 0, 28), - [239] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_dictionary_construction, 3, 0, 10), - [241] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_dictionary_construction, 3, 0, 10), - [243] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_function_call, 2, 0, 6), - [245] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_function_call, 2, 0, 6), - [247] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_list, 3, 0, 0), - [249] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_list, 3, 0, 0), - [251] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_boolean, 1, 0, 0), - [253] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_boolean, 1, 0, 0), - [255] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_signed_integer, 2, 0, 4), - [257] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_signed_integer, 2, 0, 4), - [259] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_member_access, 3, 0, 13), - [261] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_member_access, 3, 0, 13), - [263] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_unsigned_integer, 2, 0, 4), - [265] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_unsigned_integer, 2, 0, 4), - [267] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set, 7, 0, 27), - [269] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_constraint_set, 7, 0, 27), - [271] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_declaration_type, 2, 0, 0), - [273] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_declaration_type, 2, 0, 0), - [275] = {.entry = {.count = 1, .reusable = false}}, SHIFT(25), - [277] = {.entry = {.count = 1, .reusable = false}}, SHIFT(26), - [279] = {.entry = {.count = 1, .reusable = true}}, SHIFT(195), - [281] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_struct_member, 4, 0, 22), - [283] = {.entry = {.count = 1, .reusable = true}}, SHIFT(139), - [285] = {.entry = {.count = 1, .reusable = true}}, SHIFT(68), - [287] = {.entry = {.count = 1, .reusable = true}}, SHIFT(30), - [289] = {.entry = {.count = 1, .reusable = true}}, SHIFT(71), - [291] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_dictionary_member_assignment, 3, 0, 16), - [293] = {.entry = {.count = 1, .reusable = true}}, SHIFT(32), - [295] = {.entry = {.count = 1, .reusable = true}}, SHIFT(77), - [297] = {.entry = {.count = 1, .reusable = true}}, SHIFT(35), - [299] = {.entry = {.count = 1, .reusable = true}}, SHIFT(36), - [301] = {.entry = {.count = 1, .reusable = false}}, SHIFT(37), - [303] = {.entry = {.count = 1, .reusable = true}}, SHIFT(37), - [305] = {.entry = {.count = 1, .reusable = true}}, SHIFT(38), - [307] = {.entry = {.count = 1, .reusable = false}}, SHIFT(6), - [309] = {.entry = {.count = 1, .reusable = false}}, SHIFT(40), - [311] = {.entry = {.count = 1, .reusable = false}}, SHIFT(41), - [313] = {.entry = {.count = 1, .reusable = false}}, SHIFT(42), - [315] = {.entry = {.count = 1, .reusable = true}}, SHIFT(42), - [317] = {.entry = {.count = 1, .reusable = true}}, SHIFT(43), - [319] = {.entry = {.count = 1, .reusable = true}}, SHIFT(44), - [321] = {.entry = {.count = 1, .reusable = true}}, SHIFT(45), - [323] = {.entry = {.count = 1, .reusable = true}}, SHIFT(50), - [325] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_source_file, 1, 0, 0), - [327] = {.entry = {.count = 1, .reusable = true}}, SHIFT(78), - [329] = {.entry = {.count = 1, .reusable = true}}, SHIFT(31), - [331] = {.entry = {.count = 1, .reusable = true}}, SHIFT(21), - [333] = {.entry = {.count = 1, .reusable = true}}, SHIFT(196), - [335] = {.entry = {.count = 1, .reusable = true}}, SHIFT(72), - [337] = {.entry = {.count = 1, .reusable = false}}, SHIFT(47), - [339] = {.entry = {.count = 1, .reusable = true}}, SHIFT(48), - [341] = {.entry = {.count = 1, .reusable = false}}, SHIFT(29), - [343] = {.entry = {.count = 1, .reusable = true}}, SHIFT(49), - [345] = {.entry = {.count = 1, .reusable = true}}, SHIFT(22), - [347] = {.entry = {.count = 1, .reusable = false}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), - [349] = {.entry = {.count = 1, .reusable = true}}, SHIFT(198), - [351] = {.entry = {.count = 1, .reusable = true}}, SHIFT(159), - [353] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_expression, 1, 0, 0), - [355] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_constraint_set_expression, 1, 0, 0), - [357] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_method_call, 6, 0, 29), - [359] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_constraint_set_method_call, 6, 0, 29), - [361] = {.entry = {.count = 1, .reusable = true}}, SHIFT(143), - [363] = {.entry = {.count = 1, .reusable = true}}, SHIFT(141), - [365] = {.entry = {.count = 1, .reusable = true}}, SHIFT(146), - [367] = {.entry = {.count = 1, .reusable = true}}, SHIFT(148), - [369] = {.entry = {.count = 1, .reusable = true}}, SHIFT(56), - [371] = {.entry = {.count = 1, .reusable = true}}, SHIFT(149), - [373] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_parenthesis, 3, 0, 0), - [375] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_constraint_set_parenthesis, 3, 0, 0), - [377] = {.entry = {.count = 1, .reusable = true}}, SHIFT(215), - [379] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_binary_expression, 3, 0, 14), - [381] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_constraint_set_binary_expression, 3, 0, 14), - [383] = {.entry = {.count = 1, .reusable = true}}, SHIFT(147), - [385] = {.entry = {.count = 1, .reusable = true}}, SHIFT(150), - [387] = {.entry = {.count = 1, .reusable = false}}, SHIFT(153), - [389] = {.entry = {.count = 1, .reusable = true}}, SHIFT(153), - [391] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_constraint_set_unary_expression, 2, 0, 3), - [393] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_unary_expression, 2, 0, 3), - [395] = {.entry = {.count = 1, .reusable = true}}, SHIFT(154), - [397] = {.entry = {.count = 1, .reusable = true}}, SHIFT(152), - [399] = {.entry = {.count = 1, .reusable = true}}, SHIFT(190), - [401] = {.entry = {.count = 1, .reusable = true}}, SHIFT(62), - [403] = {.entry = {.count = 1, .reusable = true}}, SHIFT(144), - [405] = {.entry = {.count = 1, .reusable = true}}, SHIFT(155), - [407] = {.entry = {.count = 1, .reusable = true}}, SHIFT(97), - [409] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_struct_definition_repeat1, 2, 0, 0), SHIFT_REPEAT(190), - [412] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_struct_definition_repeat1, 2, 0, 0), - [414] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_let_in_repeat1, 2, 0, 0), SHIFT_REPEAT(207), - [417] = {.entry = {.count = 1, .reusable = false}}, REDUCE(aux_sym_let_in_repeat1, 2, 0, 0), - [419] = {.entry = {.count = 1, .reusable = false}}, SHIFT(207), - [421] = {.entry = {.count = 1, .reusable = false}}, SHIFT(34), - [423] = {.entry = {.count = 1, .reusable = false}}, SHIFT(24), - [425] = {.entry = {.count = 1, .reusable = false}}, SHIFT(8), - [427] = {.entry = {.count = 1, .reusable = false}}, SHIFT(46), - [429] = {.entry = {.count = 1, .reusable = true}}, SHIFT(180), - [431] = {.entry = {.count = 1, .reusable = true}}, SHIFT(79), - [433] = {.entry = {.count = 1, .reusable = true}}, SHIFT(209), - [435] = {.entry = {.count = 1, .reusable = true}}, SHIFT(73), - [437] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_dictionary_construction_repeat1, 2, 0, 0), SHIFT_REPEAT(184), + [29] = {.entry = {.count = 1, .reusable = true}}, SHIFT(4), + [31] = {.entry = {.count = 1, .reusable = true}}, SHIFT(180), + [33] = {.entry = {.count = 1, .reusable = false}}, SHIFT(102), + [35] = {.entry = {.count = 1, .reusable = true}}, SHIFT(65), + [37] = {.entry = {.count = 1, .reusable = true}}, SHIFT(190), + [39] = {.entry = {.count = 1, .reusable = true}}, SHIFT(70), + [41] = {.entry = {.count = 1, .reusable = true}}, SHIFT(73), + [43] = {.entry = {.count = 1, .reusable = true}}, SHIFT(67), + [45] = {.entry = {.count = 1, .reusable = true}}, SHIFT(101), + [47] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(92), + [50] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(92), + [53] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(56), + [56] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(214), + [59] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(218), + [62] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(204), + [65] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(23), + [68] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(96), + [71] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(35), + [74] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(10), + [77] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(176), + [80] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(2), + [83] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(4), + [86] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), + [88] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), SHIFT_REPEAT(180), + [91] = {.entry = {.count = 1, .reusable = true}}, SHIFT(89), + [93] = {.entry = {.count = 1, .reusable = false}}, SHIFT(103), + [95] = {.entry = {.count = 1, .reusable = true}}, SHIFT(37), + [97] = {.entry = {.count = 1, .reusable = false}}, SHIFT(11), + [99] = {.entry = {.count = 1, .reusable = false}}, SHIFT(177), + [101] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_number, 1, 0, 0), + [103] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_number, 1, 0, 0), + [105] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_base_ten, 1, 0, 0), + [107] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_scalar, 1, 0, 2), + [109] = {.entry = {.count = 1, .reusable = false}}, SHIFT(63), + [111] = {.entry = {.count = 1, .reusable = true}}, SHIFT(63), + [113] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_scalar, 1, 0, 2), + [115] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__float, 3, 0, 13), + [117] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym__float, 3, 0, 13), + [119] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__float, 1, 0, 1), + [121] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym__float, 1, 0, 1), + [123] = {.entry = {.count = 1, .reusable = true}}, SHIFT(192), + [125] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_binary_expression, 3, 0, 15), + [127] = {.entry = {.count = 1, .reusable = true}}, SHIFT(213), + [129] = {.entry = {.count = 1, .reusable = true}}, SHIFT(207), + [131] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_binary_expression, 3, 0, 15), + [133] = {.entry = {.count = 1, .reusable = true}}, SHIFT(5), + [135] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_struct_definition, 3, 0, 10), + [137] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_struct_definition, 3, 0, 10), + [139] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_scalar, 2, 0, 6), + [141] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_scalar, 2, 0, 6), + [143] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_struct_definition, 4, 0, 19), + [145] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_struct_definition, 4, 0, 19), + [147] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_dictionary_construction, 2, 0, 0), + [149] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_dictionary_construction, 2, 0, 0), + [151] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_struct_definition, 2, 0, 0), + [153] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_struct_definition, 3, 0, 12), + [155] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_struct_definition, 3, 0, 12), + [157] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_parenthesis, 3, 0, 0), + [159] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_parenthesis, 3, 0, 0), + [161] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_dictionary_construction, 3, 0, 11), + [163] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_dictionary_construction, 3, 0, 11), + [165] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_list, 3, 0, 0), + [167] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_list, 3, 0, 0), + [169] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_member_access, 3, 0, 14), + [171] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_member_access, 3, 0, 14), + [173] = {.entry = {.count = 1, .reusable = true}}, SHIFT(13), + [175] = {.entry = {.count = 1, .reusable = false}}, SHIFT(14), + [177] = {.entry = {.count = 1, .reusable = true}}, SHIFT(14), + [179] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_list, 2, 0, 0), + [181] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_list, 2, 0, 0), + [183] = {.entry = {.count = 1, .reusable = true}}, SHIFT(12), + [185] = {.entry = {.count = 1, .reusable = true}}, SHIFT(15), + [187] = {.entry = {.count = 1, .reusable = false}}, SHIFT(16), + [189] = {.entry = {.count = 1, .reusable = false}}, SHIFT(18), + [191] = {.entry = {.count = 1, .reusable = false}}, SHIFT(17), + [193] = {.entry = {.count = 1, .reusable = false}}, SHIFT(19), + [195] = {.entry = {.count = 1, .reusable = true}}, SHIFT(19), + [197] = {.entry = {.count = 1, .reusable = true}}, SHIFT(20), + [199] = {.entry = {.count = 1, .reusable = true}}, SHIFT(21), + [201] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_let_in, 4, 0, 16), + [203] = {.entry = {.count = 1, .reusable = true}}, SHIFT(22), + [205] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_let_in, 4, 0, 16), + [207] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_list, 4, 0, 0), + [209] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_list, 4, 0, 0), + [211] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_method_call, 4, 0, 20), + [213] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_method_call, 4, 0, 20), + [215] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_signed_integer, 2, 0, 5), + [217] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_signed_integer, 2, 0, 5), + [219] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_vector2, 5, 0, 21), + [221] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_vector2, 5, 0, 21), + [223] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_unsigned_integer, 2, 0, 5), + [225] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_unsigned_integer, 2, 0, 5), + [227] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_dictionary_construction, 5, 0, 24), + [229] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_dictionary_construction, 5, 0, 24), + [231] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_closure_definition, 5, 0, 25), + [233] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_closure_definition, 5, 0, 25), + [235] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_if, 6, 0, 26), + [237] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_if, 6, 0, 26), + [239] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_expression, 1, 0, 0), + [241] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_expression, 1, 0, 0), + [243] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_vector3, 7, 0, 27), + [245] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_vector3, 7, 0, 27), + [247] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set, 7, 0, 28), + [249] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_constraint_set, 7, 0, 28), + [251] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_vector4, 9, 0, 29), + [253] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_vector4, 9, 0, 29), + [255] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_boolean, 1, 0, 0), + [257] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_boolean, 1, 0, 0), + [259] = {.entry = {.count = 1, .reusable = true}}, SHIFT(24), + [261] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_let_in, 3, 0, 8), + [263] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_let_in, 3, 0, 8), + [265] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_function_call, 2, 0, 7), + [267] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_function_call, 2, 0, 7), + [269] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_unary_expression, 2, 0, 3), + [271] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_unary_expression, 2, 0, 3), + [273] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_dictionary_construction, 4, 0, 18), + [275] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_dictionary_construction, 4, 0, 18), + [277] = {.entry = {.count = 1, .reusable = false}}, SHIFT(29), + [279] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_dictionary_argument, 1, 0, 4), + [281] = {.entry = {.count = 1, .reusable = false}}, SHIFT(30), + [283] = {.entry = {.count = 1, .reusable = true}}, SHIFT(68), + [285] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_declaration_type, 2, 0, 0), + [287] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_declaration_type, 2, 0, 0), + [289] = {.entry = {.count = 1, .reusable = true}}, SHIFT(144), + [291] = {.entry = {.count = 1, .reusable = true}}, SHIFT(84), + [293] = {.entry = {.count = 1, .reusable = true}}, SHIFT(36), + [295] = {.entry = {.count = 1, .reusable = true}}, SHIFT(93), + [297] = {.entry = {.count = 1, .reusable = true}}, SHIFT(33), + [299] = {.entry = {.count = 1, .reusable = true}}, SHIFT(87), + [301] = {.entry = {.count = 1, .reusable = true}}, SHIFT(197), + [303] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_struct_member, 4, 0, 23), + [305] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_dictionary_argument, 3, 0, 17), + [307] = {.entry = {.count = 1, .reusable = false}}, SHIFT(32), + [309] = {.entry = {.count = 1, .reusable = true}}, SHIFT(185), + [311] = {.entry = {.count = 1, .reusable = true}}, SHIFT(39), + [313] = {.entry = {.count = 1, .reusable = true}}, SHIFT(40), + [315] = {.entry = {.count = 1, .reusable = false}}, SHIFT(41), + [317] = {.entry = {.count = 1, .reusable = true}}, SHIFT(41), + [319] = {.entry = {.count = 1, .reusable = true}}, SHIFT(42), + [321] = {.entry = {.count = 1, .reusable = false}}, SHIFT(43), + [323] = {.entry = {.count = 1, .reusable = false}}, SHIFT(44), + [325] = {.entry = {.count = 1, .reusable = false}}, SHIFT(45), + [327] = {.entry = {.count = 1, .reusable = false}}, SHIFT(46), + [329] = {.entry = {.count = 1, .reusable = true}}, SHIFT(46), + [331] = {.entry = {.count = 1, .reusable = true}}, SHIFT(47), + [333] = {.entry = {.count = 1, .reusable = true}}, SHIFT(48), + [335] = {.entry = {.count = 1, .reusable = true}}, SHIFT(49), + [337] = {.entry = {.count = 1, .reusable = true}}, SHIFT(25), + [339] = {.entry = {.count = 1, .reusable = true}}, SHIFT(95), + [341] = {.entry = {.count = 1, .reusable = true}}, SHIFT(54), + [343] = {.entry = {.count = 1, .reusable = true}}, SHIFT(34), + [345] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_source_file, 1, 0, 0), + [347] = {.entry = {.count = 1, .reusable = false}}, SHIFT(51), + [349] = {.entry = {.count = 1, .reusable = true}}, SHIFT(52), + [351] = {.entry = {.count = 1, .reusable = true}}, SHIFT(26), + [353] = {.entry = {.count = 1, .reusable = true}}, SHIFT(53), + [355] = {.entry = {.count = 1, .reusable = false}}, REDUCE(aux_sym_list_repeat1, 2, 0, 0), + [357] = {.entry = {.count = 1, .reusable = true}}, SHIFT(200), + [359] = {.entry = {.count = 1, .reusable = true}}, SHIFT(164), + [361] = {.entry = {.count = 1, .reusable = true}}, SHIFT(154), + [363] = {.entry = {.count = 1, .reusable = true}}, SHIFT(60), + [365] = {.entry = {.count = 1, .reusable = true}}, SHIFT(148), + [367] = {.entry = {.count = 1, .reusable = true}}, SHIFT(155), + [369] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_parenthesis, 3, 0, 0), + [371] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_constraint_set_parenthesis, 3, 0, 0), + [373] = {.entry = {.count = 1, .reusable = true}}, SHIFT(145), + [375] = {.entry = {.count = 1, .reusable = true}}, SHIFT(150), + [377] = {.entry = {.count = 1, .reusable = true}}, SHIFT(217), + [379] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_binary_expression, 3, 0, 15), + [381] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_constraint_set_binary_expression, 3, 0, 15), + [383] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_method_call, 6, 0, 30), + [385] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_constraint_set_method_call, 6, 0, 30), + [387] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_expression, 1, 0, 0), + [389] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_constraint_set_expression, 1, 0, 0), + [391] = {.entry = {.count = 1, .reusable = true}}, SHIFT(160), + [393] = {.entry = {.count = 1, .reusable = true}}, SHIFT(159), + [395] = {.entry = {.count = 1, .reusable = false}}, SHIFT(161), + [397] = {.entry = {.count = 1, .reusable = true}}, SHIFT(161), + [399] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_constraint_set_unary_expression, 2, 0, 3), + [401] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_unary_expression, 2, 0, 3), + [403] = {.entry = {.count = 1, .reusable = true}}, SHIFT(157), + [405] = {.entry = {.count = 1, .reusable = true}}, SHIFT(156), + [407] = {.entry = {.count = 1, .reusable = true}}, SHIFT(94), + [409] = {.entry = {.count = 1, .reusable = true}}, SHIFT(149), + [411] = {.entry = {.count = 1, .reusable = true}}, SHIFT(153), + [413] = {.entry = {.count = 1, .reusable = true}}, SHIFT(194), + [415] = {.entry = {.count = 1, .reusable = true}}, SHIFT(66), + [417] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_struct_definition_repeat1, 2, 0, 0), SHIFT_REPEAT(194), + [420] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_struct_definition_repeat1, 2, 0, 0), + [422] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_let_in_repeat1, 2, 0, 0), SHIFT_REPEAT(215), + [425] = {.entry = {.count = 1, .reusable = false}}, REDUCE(aux_sym_let_in_repeat1, 2, 0, 0), + [427] = {.entry = {.count = 1, .reusable = false}}, SHIFT(215), + [429] = {.entry = {.count = 1, .reusable = false}}, SHIFT(28), + [431] = {.entry = {.count = 1, .reusable = false}}, SHIFT(55), + [433] = {.entry = {.count = 1, .reusable = false}}, SHIFT(38), + [435] = {.entry = {.count = 1, .reusable = false}}, SHIFT(50), + [437] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_dictionary_construction_repeat1, 2, 0, 0), SHIFT_REPEAT(9), [440] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_dictionary_construction_repeat1, 2, 0, 0), - [442] = {.entry = {.count = 1, .reusable = true}}, SHIFT(185), - [444] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_struct_member, 2, 0, 8), - [446] = {.entry = {.count = 1, .reusable = true}}, SHIFT(28), - [448] = {.entry = {.count = 1, .reusable = true}}, SHIFT(66), - [450] = {.entry = {.count = 1, .reusable = true}}, SHIFT(175), - [452] = {.entry = {.count = 1, .reusable = true}}, SHIFT(96), - [454] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_constraint_set_fields_repeat1, 2, 0, 0), SHIFT_REPEAT(211), - [457] = {.entry = {.count = 1, .reusable = true}}, SHIFT(203), - [459] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_fields, 1, 0, 0), - [461] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_octal, 2, 0, 0), - [463] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_fields, 2, 0, 0), - [465] = {.entry = {.count = 1, .reusable = true}}, SHIFT(83), - [467] = {.entry = {.count = 1, .reusable = true}}, SHIFT(86), - [469] = {.entry = {.count = 1, .reusable = true}}, SHIFT(26), - [471] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_hex, 2, 0, 0), - [473] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_binary, 2, 0, 0), - [475] = {.entry = {.count = 1, .reusable = true}}, SHIFT(188), - [477] = {.entry = {.count = 1, .reusable = true}}, SHIFT(103), - [479] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_let_in_assignment, 4, 0, 21), - [481] = {.entry = {.count = 1, .reusable = true}}, SHIFT(179), - [483] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__struct_final_element, 1, 0, 0), - [485] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_integer, 1, 0, 0), - [487] = {.entry = {.count = 1, .reusable = true}}, SHIFT(213), - [489] = {.entry = {.count = 1, .reusable = true}}, SHIFT(193), - [491] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_constraint_set_fields_repeat1, 2, 0, 0), - [493] = {.entry = {.count = 1, .reusable = true}}, SHIFT(191), - [495] = {.entry = {.count = 1, .reusable = true}}, SHIFT(192), - [497] = {.entry = {.count = 1, .reusable = true}}, SHIFT(145), - [499] = {.entry = {.count = 1, .reusable = true}}, SHIFT(23), - [501] = {.entry = {.count = 1, .reusable = true}}, SHIFT(157), - [503] = {.entry = {.count = 1, .reusable = true}}, SHIFT(25), - [505] = {.entry = {.count = 1, .reusable = true}}, SHIFT(187), - [507] = {.entry = {.count = 1, .reusable = true}}, ACCEPT_INPUT(), - [509] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__struct_final_element, 2, 0, 0), - [511] = {.entry = {.count = 1, .reusable = true}}, SHIFT(58), - [513] = {.entry = {.count = 1, .reusable = true}}, SHIFT(208), - [515] = {.entry = {.count = 1, .reusable = true}}, SHIFT(84), - [517] = {.entry = {.count = 1, .reusable = true}}, SHIFT(61), + [442] = {.entry = {.count = 1, .reusable = true}}, SHIFT(196), + [444] = {.entry = {.count = 1, .reusable = true}}, SHIFT(8), + [446] = {.entry = {.count = 1, .reusable = true}}, SHIFT(6), + [448] = {.entry = {.count = 1, .reusable = true}}, SHIFT(69), + [450] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_struct_member, 2, 0, 9), + [452] = {.entry = {.count = 1, .reusable = true}}, SHIFT(31), + [454] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_let_in_assignment, 4, 0, 22), + [456] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_hex, 2, 0, 0), + [458] = {.entry = {.count = 1, .reusable = true}}, SHIFT(182), + [460] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__struct_final_element, 1, 0, 0), + [462] = {.entry = {.count = 1, .reusable = true}}, SHIFT(191), + [464] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_binary, 2, 0, 0), + [466] = {.entry = {.count = 1, .reusable = true}}, SHIFT(210), + [468] = {.entry = {.count = 1, .reusable = true}}, SHIFT(203), + [470] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_fields, 2, 0, 0), + [472] = {.entry = {.count = 1, .reusable = true}}, SHIFT(29), + [474] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constraint_set_fields, 1, 0, 0), + [476] = {.entry = {.count = 1, .reusable = true}}, SHIFT(114), + [478] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_constraint_set_fields_repeat1, 2, 0, 0), SHIFT_REPEAT(209), + [481] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_octal, 2, 0, 0), + [483] = {.entry = {.count = 1, .reusable = true}}, SHIFT(86), + [485] = {.entry = {.count = 1, .reusable = true}}, SHIFT(88), + [487] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_integer, 1, 0, 0), + [489] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_constraint_set_fields_repeat1, 2, 0, 0), + [491] = {.entry = {.count = 1, .reusable = true}}, SHIFT(189), + [493] = {.entry = {.count = 1, .reusable = true}}, SHIFT(162), + [495] = {.entry = {.count = 1, .reusable = true}}, SHIFT(193), + [497] = {.entry = {.count = 1, .reusable = true}}, SHIFT(64), + [499] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__struct_final_element, 2, 0, 0), + [501] = {.entry = {.count = 1, .reusable = true}}, SHIFT(62), + [503] = {.entry = {.count = 1, .reusable = true}}, SHIFT(152), + [505] = {.entry = {.count = 1, .reusable = true}}, SHIFT(71), + [507] = {.entry = {.count = 1, .reusable = true}}, SHIFT(199), + [509] = {.entry = {.count = 1, .reusable = true}}, SHIFT(27), + [511] = {.entry = {.count = 1, .reusable = true}}, ACCEPT_INPUT(), + [513] = {.entry = {.count = 1, .reusable = true}}, SHIFT(212), + [515] = {.entry = {.count = 1, .reusable = true}}, SHIFT(186), }; #ifdef __cplusplus diff --git a/tree-sitter-command-cad-model/test/corpus/closure.txt b/tree-sitter-command-cad-model/test/corpus/closure.txt index f3da4bf..99841b4 100644 --- a/tree-sitter-command-cad-model/test/corpus/closure.txt +++ b/tree-sitter-command-cad-model/test/corpus/closure.txt @@ -88,7 +88,7 @@ With Binary Expression Call function ================== -value(value=value) +value(a = b) --- @@ -98,8 +98,75 @@ value(value=value) (expression (identifier)) (dictionary_construction - (dictionary_member_assignment - (identifier) + (dictionary_argument + (expression + (identifier)) + (expression + (identifier))))))) + +================== +Call method deep in tree +================== + +value.value::method(a = b) + +--- + +(source_file + (expression + (method_call + (expression + (member_access + (expression + (identifier)) + (identifier))) + (identifier) + (dictionary_construction + (dictionary_argument + (expression + (identifier)) + (expression + (identifier))))))) + +================== +Call method +================== + +value::method(a = b) + +--- + +(source_file + (expression + (method_call + (expression + (identifier)) + (identifier) + (dictionary_construction + (dictionary_argument + (expression + (identifier)) + (expression + (identifier))))))) + +================== +Call method deep in tree +================== + +value::foo(a = b) + +--- + +(source_file + (expression + (method_call + (expression + (identifier)) + (identifier) + (dictionary_construction + (dictionary_argument + (expression + (identifier)) (expression (identifier))))))) @@ -119,10 +186,10 @@ value() (dictionary_construction)))) ================== -Call function deep in tree +Call function positional ================== -value.value(value=value) +value(a, b, c) --- @@ -130,41 +197,51 @@ value.value(value=value) (expression (function_call (expression - (member_access - (expression - (identifier)) - (identifier))) + (identifier)) (dictionary_construction - (dictionary_member_assignment - (identifier) + (dictionary_argument + (expression + (identifier))) + (dictionary_argument + (expression + (identifier))) + (dictionary_argument (expression (identifier))))))) ================== -Call method +Call function mixed ================== -value::value(value=value) +value(a, b = c, d = e) --- (source_file (expression - (method_call + (function_call (expression (identifier)) - (identifier) (dictionary_construction - (dictionary_member_assignment - (identifier) + (dictionary_argument + (expression + (identifier))) + (dictionary_argument + (expression + (identifier)) + (expression + (identifier))) + (dictionary_argument + (expression + (identifier)) (expression (identifier))))))) ================== -Call method no arguments +Call method positional ================== -value::value() +value::value(a, b) --- @@ -174,13 +251,19 @@ value::value() (expression (identifier)) (identifier) - (dictionary_construction)))) + (dictionary_construction + (dictionary_argument + (expression + (identifier))) + (dictionary_argument + (expression + (identifier))))))) ================== -Call method deep in tree +Call method mixed ================== -value.value::value(value=value) +value::value(a, b = c) --- @@ -188,32 +271,103 @@ value.value::value(value=value) (expression (method_call (expression - (member_access - (expression - (identifier)) - (identifier))) + (identifier)) (identifier) (dictionary_construction - (dictionary_member_assignment - (identifier) + (dictionary_argument + (expression + (identifier))) + (dictionary_argument + (expression + (identifier)) (expression (identifier))))))) ================== -Call method inside parenthasis +Call function complex expressions ================== -(value::value()) +value(a + b, c * d) --- (source_file (expression - (parenthesis + (function_call (expression - (method_call + (identifier)) + (dictionary_construction + (dictionary_argument + (expression + (binary_expression + (expression + (identifier)) + (expression + (identifier))))) + (dictionary_argument + (expression + (binary_expression + (expression + (identifier)) + (expression + (identifier))))))))) + +================== +Call method complex expressions +================== + +obj::method(a + b, c = d * e) + +--- + +(source_file + (expression + (method_call + (expression + (identifier)) + (identifier) + (dictionary_construction + (dictionary_argument + (expression + (binary_expression + (expression + (identifier)) + (expression + (identifier))))) + (dictionary_argument (expression (identifier)) - (identifier) - (dictionary_construction)))))) + (expression + (binary_expression + (expression + (identifier)) + (expression + (identifier))))))))) +================== +Call function nested dictionary positional +================== + +func((a = b, c = d)) + +--- + +(source_file + (expression + (function_call + (expression + (identifier)) + (dictionary_construction + (dictionary_argument + (expression + (dictionary_construction + (dictionary_argument + (expression + (identifier)) + (expression + (identifier))) + (dictionary_argument + (expression + (identifier)) + (expression + (identifier)))))))))) diff --git a/tree-sitter-command-cad-model/test/corpus/dictionary_construction.txt b/tree-sitter-command-cad-model/test/corpus/dictionary_construction.txt index 39085d4..e283e93 100644 --- a/tree-sitter-command-cad-model/test/corpus/dictionary_construction.txt +++ b/tree-sitter-command-cad-model/test/corpus/dictionary_construction.txt @@ -14,15 +14,16 @@ Empty One ================== -(one = a) +(a =b) --- (source_file (expression (dictionary_construction - (dictionary_member_assignment - (identifier) + (dictionary_argument + (expression + (identifier)) (expression (identifier)))))) @@ -30,15 +31,16 @@ One One, ================== -(one = a,) +(a =b,) --- (source_file (expression (dictionary_construction - (dictionary_member_assignment - (identifier) + (dictionary_argument + (expression + (identifier)) (expression (identifier)))))) @@ -46,19 +48,21 @@ One, One, two ================== -(one = a, two = b) +(a =b, c =d) --- (source_file (expression (dictionary_construction - (dictionary_member_assignment - (identifier) + (dictionary_argument + (expression + (identifier)) (expression (identifier))) - (dictionary_member_assignment - (identifier) + (dictionary_argument + (expression + (identifier)) (expression (identifier)))))) @@ -66,18 +70,124 @@ One, two One, two, ================== -(one = a, two = b,) +(a =b, c =d,) + +--- + +(source_file + (expression + (dictionary_construction + (dictionary_argument + (expression + (identifier)) + (expression + (identifier))) + (dictionary_argument + (expression + (identifier)) + (expression + (identifier)))))) + +================== +Positional Two +================== + +(a, b) + +--- + +(source_file + (expression + (dictionary_construction + (dictionary_argument + (expression + (identifier))) + (dictionary_argument + (expression + (identifier)))))) + +================== +Positional Trailing Comma +================== + +(a, b,) + +--- + +(source_file + (expression + (dictionary_construction + (dictionary_argument + (expression + (identifier))) + (dictionary_argument + (expression + (identifier)))))) + +================== +Mixed Positional and Named +================== + +(a, b =c) + +--- + +(source_file + (expression + (dictionary_construction + (dictionary_argument + (expression + (identifier))) + (dictionary_argument + (expression + (identifier)) + (expression + (identifier)))))) + +================== +Mixed Three Positional Two Named +================== + +(a, b, c =d, e =f) --- (source_file (expression (dictionary_construction - (dictionary_member_assignment - (identifier) + (dictionary_argument (expression (identifier))) - (dictionary_member_assignment - (identifier) + (dictionary_argument + (expression + (identifier))) + (dictionary_argument + (expression + (identifier)) + (expression + (identifier))) + (dictionary_argument + (expression + (identifier)) + (expression + (identifier)))))) + +================== +Mixed Trailing Comma +================== + +(a, b =c,) + +--- + +(source_file + (expression + (dictionary_construction + (dictionary_argument + (expression + (identifier))) + (dictionary_argument + (expression + (identifier)) (expression (identifier)))))) From 6b580c1f5d986f3c721d2ec32e1a0b075cd28f32 Mon Sep 17 00:00:00 2001 From: James Carl Date: Thu, 4 Jun 2026 17:51:40 -0400 Subject: [PATCH 59/71] Add support for svg export --- AGENTS.md | 65 +- Cargo.lock | 7 + interpreter/Cargo.toml | 1 + interpreter/src/execution/export.rs | 559 ++++++++++++++++++ interpreter/src/execution/mod.rs | 1 + .../src/execution/standard_environment.rs | 9 + interpreter/src/execution/store.rs | 8 +- interpreter/src/execution/values/closure.rs | 1 + .../src/execution/values/manifold_mesh.rs | 24 +- interpreter/src/execution/values/mod.rs | 6 +- 10 files changed, 633 insertions(+), 48 deletions(-) create mode 100644 interpreter/src/execution/export.rs diff --git a/AGENTS.md b/AGENTS.md index ededaae..18b5fcd 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,23 +6,27 @@ nix develop # from project root ``` -`.envrc` expects `use flake` (nix-userccs). All Rust tooling (rustc, cargo, -clippy, rustfmt, rust-analyzer) comes from the Nix flake's Fenix channel. -Do not assume `cargo` is on PATH outside the dev shell. +`.envrc` expects `use flake` (nix-userccs). All Rust tooling comes from the Nix +flake's Fenix channel. Do not assume `cargo` is on PATH outside the dev shell. + +For GUI development, use `nix develop .#gui` which includes Wayland, X11, +Vulkan, ALSA, Mesa etc. The default shell omits GUI deps. ## Build / test / check ``` -cargo check # default-members (interpreter, common_data_types, units, cli, gui) +cargo check # default-members (excludes tree-sitter-command-cad-model, formatter) cargo fmt --all -- --check cargo clippy -cargo test --all-features +cargo test --all-features # NOT `cargo test` — tree-sitter doctest fails cargo build --all-features ``` -CI (`.github/workflows/push.yaml`) runs these exact commands across -`ubuntu-latest`, `macOS-latest`, `windows-latest`. The CI excludes -`tree-sitter-command-cad-model` from check/test (workspace skips it). +CI (`.github/workflows/push.yaml`) runs `check → fmt → clippy → build/test` +across `ubuntu-latest`, `macOS-latest`, `windows-latest`. + +`formatter` is NOT in workspace members. Run `cargo check -p formatter` from +its subdir (`formatter/`). ## Workspace layout @@ -36,12 +40,9 @@ CI (`.github/workflows/push.yaml`) runs these exact commands across | `gui` | GUI binary (Bevy + egui) | | `formatter` | Standalone formatter tool (tree-sitter) | -`formatter` is NOT in `members`. Run `cargo check -p formatter` from its -subdir. - ## Code generation -- **`interpreter/build.rs`** — generates AST node types from the tree-sitter +- **`interpreter/build.rs`** — generates AST node types from tree-sitter `node-types.json` via `type-sitter-gen`. Rerun by editing the grammar. - **`units/build.rs`** — generates Rust code from `units/src/units.csv` using `uneval`. Rerun by editing the CSV. @@ -59,27 +60,27 @@ Grammar is in `grammar.js`. Test fixtures are in `test/corpus/`. ## Gotchas - **boolmesh** is a sibling repo at `../../boolmesh`, NOT in workspace members. - Interpreter references it via `path = "../../boolmesh"`. Any changes to boolmesh - must be made in that directory. The crate is compiled with `rayon` for parallel - boolean operations, but has been patched for determinism (sort tiebreakers on - `EvPtrMinCost`/`EvPtrMaxPosX` indices, triangulation ordering, face sort key - tiebreaking). Do not revert those fixes. -- **GUI requires Linux/Wayland** and links against Wayland, X11, Vulkan, ALSA - etc. It won't cross-compile cleanly on non-Linux hosts. + Interpreter references it via `path = "../../boolmesh"`. Any changes to + boolmesh must be made in that directory. Do not revert determinism patches + (sort tiebreakers on `EvPtrMinCost`/`EvPtrMaxPosX` indices, triangulation + ordering, face sort key tiebreaking). +- **GUI requires Linux/Wayland** and links against Wayland, X11, Vulkan, ALSA. + It won't cross-compile cleanly on non-Linux hosts. - **CLI stores project state** in `.ccad/store/` (discovered via git root). -- **Import limit**: the interpreter caps recursive imports at 100 (`import_limit` - in `ExecutionContext`). See `interpreter/test_assets/infinite_recursion_import.ccm`. + REPL uses a temp dir for store; file mode discovers via git root. +- **Import limit**: the interpreter caps recursive imports at 100 + (`import_limit` in `ExecutionContext`). See + `interpreter/test_assets/infinite_recursion_import.ccm`. - **Editions**: `gui` and `cli` use Rust 2024 (resolver 3); others use 2021. -- **geo multi-threading disabled**: `geo` is compiled with `default-features = false` - to avoid non-deterministic results from its earcutr triangulation. -- **tree-sitter doc test**: `cargo test --all` fails on - `tree-sitter-command-cad-model` doctest (`assertion failed: !tree.root_node().has_error()`). - CI excludes it; `cargo test` runs 0 tests by default. -- **CLI commands**: `ccad repl` (REPL) and `ccad file ` (evaluate a .ccad file). - REPL uses a temp dir for store; file mode discovers `.ccad/store/` via git root. -- **Bevy query disjoint**: when two systems in the same schedule access `Transform` on - entities that share no components, Bevy may complain about overlapping queries. Add - `Without` to each `Query` to make them disjoint. E.g. in `gui/src/visualize3d.rs` - a camera query and a light query both read `Transform` — use +- **geo multi-threading disabled**: `geo` is compiled with + `default-features = false` to avoid non-deterministic earcutr triangulation. +- **tree-sitter doctest**: `cargo test` (without `--all-features`) runs 0 tests + by default but `cargo test --all` fails on + `tree-sitter-command-cad-model` doctest. Always use `--all-features`. +- **CLI commands**: `ccad repl` (REPL) and `ccad file ` (evaluate). +- **Bevy query disjoint**: when two systems in the same schedule access + `Transform` on entities that share no components, add `Without` + to each `Query`. E.g. in `gui/src/visualize3d.rs`, a camera query and a + light query both read `Transform` — use `(With, Without)` and `(With, Without)`. diff --git a/Cargo.lock b/Cargo.lock index 83bd153..8ae55fe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4139,6 +4139,7 @@ dependencies = [ "sha2", "stack", "stl_io", + "svg", "tempfile", "thiserror 2.0.18", "tree-sitter", @@ -6593,6 +6594,12 @@ dependencies = [ "syn", ] +[[package]] +name = "svg" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94afda9cd163c04f6bee8b4bf2501c91548deae308373c436f36aeff3cf3c4a3" + [[package]] name = "svg_fmt" version = "0.4.5" diff --git a/interpreter/Cargo.toml b/interpreter/Cargo.toml index f8d40b1..de95ef2 100644 --- a/interpreter/Cargo.toml +++ b/interpreter/Cargo.toml @@ -37,6 +37,7 @@ itertools = "0.14.0" thiserror = "2.0.18" # We have to disable multi-threading to get deterministic results from geo. geo = { version = "0.32", default-features = false, features = ["serde", "earcutr", "spade"] } +svg = "0.18" ciborium = "0.2.2" [build-dependencies] diff --git a/interpreter/src/execution/export.rs b/interpreter/src/execution/export.rs new file mode 100644 index 0000000..2e05faa --- /dev/null +++ b/interpreter/src/execution/export.rs @@ -0,0 +1,559 @@ +/* + * Copyright 2026 James Carl + * AGPL-3.0-only or AGPL-3.0-or-later + * + * This file is part of Command Cad. + * + * Command CAD is free software: you can redistribute it and/or modify it under the terms of + * the GNU Affero General Public License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License along with this + * program. If not, see . + */ + +use std::{hash::Hash, sync::Arc}; + +use common_data_types::{Dimension, Float}; +use sha2::Digest; + +use crate::{ + build_function, + execution::{ + errors::{ExecutionResult, Raise as _}, + store::StoreHasher, + values::{ + scalar::{Length, Scalar}, + BuiltinCallableDatabase, File, IString, List, Value, + }, + ExecutionContext, StoreTrait, + }, + values::Object, +}; + +/// Shape styling properties. +struct ShapeStyle { + fill: String, + stroke: String, + stroke_width: f64, +} + +impl std::hash::Hash for ShapeStyle { + fn hash(&self, state: &mut H) { + self.fill.hash(state); + self.stroke.hash(state); + // Hash the bits of f64 since f64 doesn't implement Hash + state.write_u64(self.stroke_width.to_bits()); + } +} + +impl Default for ShapeStyle { + fn default() -> Self { + Self { + fill: "gray".to_string(), + stroke: "white".to_string(), + stroke_width: 2.0, + } + } +} + +/// A single exported shape with its geometry and styling. +struct ExportedShape { + paths: Vec, + style: ShapeStyle, + /// Bounding box of the raw geometry (in CAD meters). + bbox: (f64, f64, f64, f64), + /// SHA-256 hash of the raw geometry coordinates. + geometry_hash: [u8; 32], +} + +/// Hashable representation of exported shapes for store caching. +struct ExportCacheKey { + shape_hashes: Vec<[u8; 32]>, + units: Length, +} + +impl std::hash::Hash for ExportCacheKey { + fn hash(&self, state: &mut H) { + self.shape_hashes.hash(state); + // Hash the raw float value and dimension of units + self.units.value.hash(state); + } +} + +/// Feeds coordinate bytes into a SHA-256 hasher. +fn hash_coords(coords: &[geo::Coord], state: &mut StoreHasher) { + coords.len().hash(state); + for coord in coords { + coord.x.to_le_bytes().hash(state); + coord.y.to_le_bytes().hash(state); + } +} + +/// Hashes a LineString's coordinates using SHA-256. +fn hash_linestring(line_string: &geo::LineString, is_closed: bool) -> [u8; 32] { + let mut hasher = StoreHasher::new(); + let coords: Vec<_> = line_string.coords().cloned().collect(); + hash_coords(&coords, &mut hasher); + is_closed.hash(&mut hasher); + hasher.0.finalize().into() +} + +/// Hashes a Polygon's exterior and interior ring coordinates using SHA-256. +fn hash_polygon(polygon: &geo::Polygon) -> [u8; 32] { + let mut hasher = StoreHasher::new(); + // Hash exterior ring + let exterior_coords: Vec<_> = polygon.exterior().coords().cloned().collect(); + hash_coords(&exterior_coords, &mut hasher); + // Hash number of interior rings + polygon.interiors().len().hash(&mut hasher); + // Hash each interior ring + for interior in polygon.interiors() { + let interior_coords: Vec<_> = interior.coords().cloned().collect(); + hash_coords(&interior_coords, &mut hasher); + } + hasher.0.finalize().into() +} + +/// Hashes a PolygonSet's constituent polygons using SHA-256. +fn hash_polygon_set(polygon_set: &geo::MultiPolygon) -> [u8; 32] { + let mut hasher = StoreHasher::new(); + polygon_set.0.len().hash(&mut hasher); + for polygon in polygon_set.0.iter() { + hash_polygon(polygon).hash(&mut hasher); + } + hasher.0.finalize().into() +} + +/// Parses a single item from the shapes list. +fn parse_shape_item( + context: &ExecutionContext, + value: Value, + units: &Length, +) -> ExecutionResult { + let style = if let Value::Dictionary(dict) = &value { + let fill = match dict.get("fill") { + Some(v) => { + let cloned = v.clone(); + cloned.downcast::(context)?.0.as_str().to_string() + } + None => "gray".to_string(), + }; + let stroke = match dict.get("stroke") { + Some(v) => { + let cloned = v.clone(); + cloned.downcast::(context)?.0.as_str().to_string() + } + None => "white".to_string(), + }; + let stroke_width = match dict.get("stroke_width") { + Some(v) => { + let cloned = v.clone(); + *cloned.downcast::(context)?.value + } + None => 2.0, + }; + ShapeStyle { + fill, + stroke, + stroke_width, + } + } else { + ShapeStyle::default() + }; + + let shape_value = if let Value::Dictionary(dict) = &value { + dict.get("shape") + .ok_or_else(|| { + crate::values::MissingAttributeError { + name: "shape".to_string(), + } + .to_error(context) + })? + .clone() + } else { + value.clone() + }; + + let multiplier = *units.value; + let (paths, bbox, geometry_hash) = + geometry_to_paths_with_hash(&shape_value, context, multiplier)?; + + Ok(ExportedShape { + paths, + style, + bbox, + geometry_hash, + }) +} + +/// Converts geometry to SVG path elements, computes bounding box, and hashes the raw geometry. +#[allow(clippy::type_complexity)] +fn geometry_to_paths_with_hash( + value: &Value, + context: &ExecutionContext, + multiplier: f64, +) -> ExecutionResult<( + Vec, + (f64, f64, f64, f64), + [u8; 32], +)> { + match value { + Value::LineString(line_string) => { + Ok(linestring_to_paths_with_hash(&line_string.0, multiplier)) + } + Value::Polygon(polygon) => Ok(polygon_to_paths_with_hash(&polygon.0, multiplier)), + Value::PolygonSet(polygon_set) => { + let mut all_paths = Vec::new(); + let mut bbox = ( + f64::INFINITY, + f64::INFINITY, + f64::NEG_INFINITY, + f64::NEG_INFINITY, + ); + for polygon in polygon_set.0.iter() { + let (paths, poly_bbox, _) = polygon_to_paths_with_hash(polygon, multiplier); + all_paths.extend(paths); + bbox = merge_bbox(bbox, poly_bbox); + } + Ok((all_paths, bbox, hash_polygon_set(&polygon_set.0))) + } + value => Err(crate::values::DowncastError { + expected: "Polygon, PolygonSet, or LineString".into(), + got: value.get_type(context).name(), + } + .to_error(context)), + } +} + +fn merge_bbox(a: (f64, f64, f64, f64), b: (f64, f64, f64, f64)) -> (f64, f64, f64, f64) { + (a.0.min(b.0), a.1.min(b.1), a.2.max(b.2), a.3.max(b.3)) +} + +/// Converts a single LineString to SVG path elements, bounding box, and geometry hash. +fn linestring_to_paths_with_hash( + line_string: &geo::LineString, + multiplier: f64, +) -> ( + Vec, + (f64, f64, f64, f64), + [u8; 32], +) { + let mut data = svg::node::element::path::Data::new(); + + let coords: Vec<_> = line_string.coords().collect(); + if coords.is_empty() { + return ( + vec![], + (0.0, 0.0, 100.0, 100.0), + hash_linestring(line_string, false), + ); + } + + let mut min_x = f64::INFINITY; + let mut min_y = f64::INFINITY; + let mut max_x = f64::NEG_INFINITY; + let mut max_y = f64::NEG_INFINITY; + + let first = coords[0]; + let sx = first.x * multiplier; + let sy = -first.y * multiplier; + min_x = min_x.min(sx); + min_y = min_y.min(sy); + max_x = max_x.max(sx); + max_y = max_y.max(sy); + data = data.move_to((sx, sy)); + + for coord in &coords[1..] { + let sx = coord.x * multiplier; + let sy = -coord.y * multiplier; + min_x = min_x.min(sx); + min_y = min_y.min(sy); + max_x = max_x.max(sx); + max_y = max_y.max(sy); + data = data.line_to((sx, sy)); + } + + if line_string.is_closed() { + data = data.close(); + } + + ( + vec![svg::node::element::Path::new().set("d", data)], + (min_x, min_y, max_x - min_x, max_y - min_y), + hash_linestring(line_string, line_string.is_closed()), + ) +} + +/// Converts a single Polygon to SVG path elements, bounding box, and geometry hash. +fn polygon_to_paths_with_hash( + polygon: &geo::Polygon, + multiplier: f64, +) -> ( + Vec, + (f64, f64, f64, f64), + [u8; 32], +) { + let exterior = polygon.exterior(); + let mut data = svg::node::element::path::Data::new(); + + let coords: Vec<_> = exterior.coords().collect(); + let mut min_x = f64::INFINITY; + let mut min_y = f64::INFINITY; + let mut max_x = f64::NEG_INFINITY; + let mut max_y = f64::NEG_INFINITY; + + if !coords.is_empty() { + let first = coords[0]; + let sx = first.x * multiplier; + let sy = -first.y * multiplier; + min_x = min_x.min(sx); + min_y = min_y.min(sy); + max_x = max_x.max(sx); + max_y = max_y.max(sy); + data = data.move_to((sx, sy)); + + for coord in &coords[1..] { + let sx = coord.x * multiplier; + let sy = -coord.y * multiplier; + min_x = min_x.min(sx); + min_y = min_y.min(sy); + max_x = max_x.max(sx); + max_y = max_y.max(sy); + data = data.line_to((sx, sy)); + } + + for interior in polygon.interiors() { + let interior_coords: Vec<_> = interior.coords().collect(); + if !interior_coords.is_empty() { + let first = interior_coords[0]; + let sx = first.x * multiplier; + let sy = -first.y * multiplier; + min_x = min_x.min(sx); + min_y = min_y.min(sy); + max_x = max_x.max(sx); + max_y = max_y.max(sy); + data = data.line_to((sx, sy)); + for coord in &interior_coords[1..] { + let sx = coord.x * multiplier; + let sy = -coord.y * multiplier; + min_x = min_x.min(sx); + min_y = min_y.min(sy); + max_x = max_x.max(sx); + max_y = max_y.max(sy); + data = data.line_to((sx, sy)); + } + } + } + + data = data.close(); + } + + ( + vec![svg::node::element::Path::new().set("d", data)], + (min_x, min_y, max_x - min_x, max_y - min_y), + hash_polygon(polygon), + ) +} + +/// Builds the SVG document from exported shapes. +fn build_document(shapes: &[ExportedShape]) -> svg::Document { + // Compute overall bounding box from all shapes. + let mut min_x = f64::INFINITY; + let mut min_y = f64::INFINITY; + let mut max_x = f64::NEG_INFINITY; + let mut max_y = f64::NEG_INFINITY; + + for shape in shapes { + min_x = min_x.min(shape.bbox.0); + min_y = min_y.min(shape.bbox.1); + max_x = max_x.max(shape.bbox.0 + shape.bbox.2); + max_y = max_y.max(shape.bbox.1 + shape.bbox.3); + } + + let (width, height) = if min_x == f64::INFINITY { + (100.0, 100.0) + } else { + (max_x - min_x, max_y - min_y) + }; + + let mut document = svg::Document::new() + .set("xmlns", "http://www.w3.org/2000/svg") + .set("version", "1.1") + .set("viewBox", format!("{min_x} {min_y} {width} {height}")); + + for shape in shapes { + for path in &shape.paths { + let styled = path + .clone() + .set("fill", svg::node::Value::from(shape.style.fill.as_str())) + .set( + "stroke", + svg::node::Value::from(shape.style.stroke.as_str()), + ) + .set( + "stroke-width", + svg::node::Value::from(format!("{}", shape.style.stroke_width).as_str()), + ); + + document = document.add(styled); + } + } + + document +} + +/// `std.export.svg` function. +pub struct ExportSvg; + +/// Registers all export functions with the callable database. +pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { + build_function!( + database, + ExportSvg, "std.export.svg", ( + context: &ExecutionContext, + shapes: List, + name: IString, + units: Length = Scalar { + dimension: Dimension::length(), + value: Float::new(1000.0).expect("Default svg units was NaN") + }.into() + ) -> File { + let mut exported_shapes = Vec::with_capacity(shapes.len()); + + for value in shapes { + let shape = parse_shape_item(context, value, &units)?; + exported_shapes.push(shape); + } + + let document = build_document(&exported_shapes); + + let cache_key = ExportCacheKey { + shape_hashes: exported_shapes.iter().map(|s| s.geometry_hash).collect(), + units: units.clone(), + }; + let path = context.store.get_or_init_file( + context, + &(&cache_key,), + format!("{}.svg", name.0), + |file| { + svg::write(file, &document).map_err(|error| { + let msg = format!("Failed to write SVG: {error}"); + crate::execution::errors::StringError(msg).to_error(context) + })?; + Ok(()) + }, + )?; + + Ok(File { path: Arc::new(path) }) + } + ); +} + +#[cfg(test)] +mod test { + use super::*; + use crate::execution::test_run; + + #[test] + fn export_svg_basic_polygon() { + let result = test_run( + "std.export.svg(shapes = [std.polygon.box(size = {1m, 1m})], name = \"test_box\")", + ); + assert!( + result.is_ok(), + "Basic polygon export failed: {:?}", + result.err() + ); + } + + #[test] + fn export_svg_line_string() { + let result = test_run( + "std.export.svg(shapes = [std.line_string.from_points(points = [{0m, 0m}, {1m, 1m}])], name = \"test_line\")" + ); + assert!( + result.is_ok(), + "LineString export failed: {:?}", + result.err() + ); + } + + #[test] + fn export_svg_polygon_set() { + let result = test_run( + "std.export.svg(shapes = [std.polygon_set.from_polys(polys = [std.polygon.box(size = {1m, 1m}), std.polygon.box(size = {2m, 2m})])], name = \"test_set\")" + ); + assert!( + result.is_ok(), + "PolygonSet export failed: {:?}", + result.err() + ); + } + + #[test] + fn export_svg_dictionary_styling() { + let result = test_run( + "std.export.svg(shapes = [(shape = std.polygon.box(size = {1m, 1m}), fill = \"blue\", stroke = \"red\", stroke_width = 3)], name = \"test_styled\")" + ); + assert!(result.is_ok(), "Styled export failed: {:?}", result.err()); + } + + #[test] + fn export_svg_mixed_shapes() { + let result = test_run( + r#"std.export.svg(shapes = [ + std.polygon.box(size = {1m, 1m}), + (shape = std.polygon.circle(radius = 1m, number_of_points = 24u), fill = "none", stroke = "green"), + std.line_string.from_points(points = [{0m, 0m}, {2m, 2m}]) + ], name = "test_mixed")"#, + ); + assert!( + result.is_ok(), + "Mixed shapes export failed: {:?}", + result.err() + ); + } + + #[test] + fn export_svg_no_shapes() { + let result = test_run("std.export.svg(shapes = [], name = \"test_empty\")"); + assert!( + result.is_ok(), + "Empty shapes export failed: {:?}", + result.err() + ); + } + + #[test] + fn hash_linestring_different_coords() { + let mut hasher1 = StoreHasher::new(); + let mut hasher2 = StoreHasher::new(); + // Hash using bit representation since f64 doesn't implement Hash + 1.0f64.to_bits().hash(&mut hasher1); + 2.0f64.to_bits().hash(&mut hasher1); + 1.0f64.to_bits().hash(&mut hasher2); + 3.0f64.to_bits().hash(&mut hasher2); + assert_ne!(hasher1.0.finalize(), hasher2.0.finalize()); + } + + #[test] + fn hash_polygon_different_exterior() { + let mut hasher1 = StoreHasher::new(); + let mut hasher2 = StoreHasher::new(); + // Hash using bit representation since Coord doesn't implement Hash + 0.0f64.to_bits().hash(&mut hasher1); + 0.0f64.to_bits().hash(&mut hasher1); + 1.0f64.to_bits().hash(&mut hasher1); + 0.0f64.to_bits().hash(&mut hasher1); + 0.0f64.to_bits().hash(&mut hasher2); + 0.0f64.to_bits().hash(&mut hasher2); + 2.0f64.to_bits().hash(&mut hasher2); + 0.0f64.to_bits().hash(&mut hasher2); + assert_ne!(hasher1.0.finalize(), hasher2.0.finalize()); + } +} diff --git a/interpreter/src/execution/mod.rs b/interpreter/src/execution/mod.rs index f5b0c5a..e53d9a9 100644 --- a/interpreter/src/execution/mod.rs +++ b/interpreter/src/execution/mod.rs @@ -54,6 +54,7 @@ use imstr::ImString; use logging::LocatedStr; pub use logging::{ExecutionFileCache, LogLevel, LogMessage, RuntimeLog, StackTrace}; pub use stack::StackScope; +mod export; mod store; pub use store::{FsStore, Store, StoreTrait}; diff --git a/interpreter/src/execution/standard_environment.rs b/interpreter/src/execution/standard_environment.rs index eec3ac2..e360f05 100644 --- a/interpreter/src/execution/standard_environment.rs +++ b/interpreter/src/execution/standard_environment.rs @@ -97,6 +97,7 @@ fn build_std(context: &ExecutionContext) -> Dictionary { ("polygon_set".into(), build_polygon_set(context).into()), ("import".into(), BuiltinFunction::new::().into()), ("range".into(), build_range(context).into()), + ("export".into(), build_export(context).into()), ]); Dictionary::new(context, std) } @@ -254,3 +255,11 @@ fn build_mesh_3d(context: &ExecutionContext) -> Dictionary { ]); Dictionary::new(context, types) } + +fn build_export(context: &ExecutionContext) -> Dictionary { + let export: HashMap = HashMap::from_iter([( + "svg".into(), + BuiltinFunction::new::().into(), + )]); + Dictionary::new(context, export) +} diff --git a/interpreter/src/execution/store.rs b/interpreter/src/execution/store.rs index 3bc4d74..97d5528 100644 --- a/interpreter/src/execution/store.rs +++ b/interpreter/src/execution/store.rs @@ -300,7 +300,13 @@ impl std::ops::DerefMut for PendingAsset { } } -struct StoreHasher(Sha256); +pub(crate) struct StoreHasher(pub(crate) Sha256); + +impl StoreHasher { + pub(crate) fn new() -> Self { + Self(Sha256::new()) + } +} impl std::hash::Hasher for StoreHasher { fn finish(&self) -> u64 { diff --git a/interpreter/src/execution/values/closure.rs b/interpreter/src/execution/values/closure.rs index fb68cc2..3df19ff 100644 --- a/interpreter/src/execution/values/closure.rs +++ b/interpreter/src/execution/values/closure.rs @@ -61,6 +61,7 @@ impl BuiltinCallableDatabase { super::iterators::register_methods(&mut database); super::transform::register_methods(&mut database); super::polygon::register_methods_and_functions(&mut database); + crate::execution::export::register_methods_and_functions(&mut database); database } diff --git a/interpreter/src/execution/values/manifold_mesh.rs b/interpreter/src/execution/values/manifold_mesh.rs index e6d957c..96e8ab8 100644 --- a/interpreter/src/execution/values/manifold_mesh.rs +++ b/interpreter/src/execution/values/manifold_mesh.rs @@ -477,7 +477,7 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { context: &ExecutionContext, this: ManifoldMesh3D, name: IString, - scale: Length = Scalar { + units: Length = Scalar { dimension: Dimension::length(), value: Float::new(1.0/1000.0).expect("Default stl scale was NaN") }.into(), @@ -493,13 +493,13 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { for tri in this.0.triangles() { let [p0, p1, p2] = tri.positions; - let scale = 1.0 / *scale.value; + let multiplier = 1.0 / *units.value; let triangle = Triangle { - normal: Vertex::new([(tri.normal.x * scale) as f32, (tri.normal.y * scale) as f32, (tri.normal.z * scale) as f32]), - vertices: [Vertex::new([(p0.x * scale) as f32, (p0.y * scale) as f32, (p0.z * scale) as f32]), - Vertex::new([(p1.x * scale) as f32, (p1.y * scale) as f32, (p1.z * scale) as f32]), - Vertex::new([(p2.x * scale) as f32, (p2.y * scale) as f32, (p2.z * scale) as f32])] + normal: Vertex::new([(tri.normal.x * multiplier) as f32, (tri.normal.y * multiplier) as f32, (tri.normal.z * multiplier) as f32]), + vertices: [Vertex::new([(p0.x * multiplier) as f32, (p0.y * multiplier) as f32, (p0.z * multiplier) as f32]), + Vertex::new([(p1.x * multiplier) as f32, (p1.y * multiplier) as f32, (p1.z * multiplier) as f32]), + Vertex::new([(p2.x * multiplier) as f32, (p2.y * multiplier) as f32, (p2.z * multiplier) as f32])] }; mesh.push(triangle); @@ -510,7 +510,7 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { let mut serialized = Vec::new(); write_stl(&mut serialized, mesh.iter()).map_err(|_| StrError("Failed to serialize STL file").to_error(context))?; - let path = context.store.get_or_init_file(context, &(&this, &scale, "ascii"), format!("{}.stl", name.0), |file| { + let path = context.store.get_or_init_file(context, &(&this, &units, "ascii"), format!("{}.stl", name.0), |file| { file.write_all(&serialized).map_err(|error| error.to_error(context))?; Ok(()) @@ -518,9 +518,9 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { Ok(File { path: Arc::new(path) }) } else { - let path = context.store.get_or_init_file(context, &(&this, &scale, "binary"), format!("{}.stl", name.0), |file| { + let path = context.store.get_or_init_file(context, &(&this, &units, "binary"), format!("{}.stl", name.0), |file| { let mut file = BufWriter::new(file); - let scale = *Float::new(1.0 / *scale.value).unwrap_not_nan(context)?; + let multiplier = *Float::new(1.0 / *units.value).unwrap_not_nan(context)?; let mut trampoline = || -> std::io::Result<()> { writeln!(file, "solid {}", name.0)?; @@ -534,9 +534,9 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { writeln!(file, "\t\touter loop")?; { - writeln!(file, "\t\t\tvertex {} {} {}", p0.x * scale, p0.y * scale, p0.z * scale)?; - writeln!(file, "\t\t\tvertex {} {} {}", p1.x * scale, p1.y * scale, p1.z * scale)?; - writeln!(file, "\t\t\tvertex {} {} {}", p2.x * scale, p2.y * scale, p2.z * scale)?; + writeln!(file, "\t\t\tvertex {} {} {}", p0.x * multiplier, p0.y * multiplier, p0.z * multiplier)?; + writeln!(file, "\t\t\tvertex {} {} {}", p1.x * multiplier, p1.y * multiplier, p1.z * multiplier)?; + writeln!(file, "\t\t\tvertex {} {} {}", p2.x * multiplier, p2.y * multiplier, p2.z * multiplier)?; } writeln!(file, "\t\tendloop")?; diff --git a/interpreter/src/execution/values/mod.rs b/interpreter/src/execution/values/mod.rs index e72a3f8..8c007c0 100644 --- a/interpreter/src/execution/values/mod.rs +++ b/interpreter/src/execution/values/mod.rs @@ -38,8 +38,8 @@ pub use boolean::Boolean; pub mod integer; pub use integer::{SignedInteger, UnsignedInteger}; -mod scalar; -pub use scalar::Scalar; +pub mod scalar; +pub use scalar::{Length, Scalar, UnwrapNotNan}; mod vector; pub use vector::{Vector2, Vector3, Vector4}; @@ -163,7 +163,7 @@ impl UnsupportedOperationError { } #[derive(Debug, Eq, PartialEq)] -struct MissingAttributeError { +pub struct MissingAttributeError { pub name: String, } From 10b52dcdf92180e997fa324d8d7678c0153d0790 Mon Sep 17 00:00:00 2001 From: James Carl Date: Thu, 4 Jun 2026 20:15:39 -0400 Subject: [PATCH 60/71] Add document size overrides and tests for svg --- interpreter/src/execution/export.rs | 222 +++++++++++++++++++++++++++- 1 file changed, 216 insertions(+), 6 deletions(-) diff --git a/interpreter/src/execution/export.rs b/interpreter/src/execution/export.rs index 2e05faa..84cdf30 100644 --- a/interpreter/src/execution/export.rs +++ b/interpreter/src/execution/export.rs @@ -360,8 +360,12 @@ fn polygon_to_paths_with_hash( ) } -/// Builds the SVG document from exported shapes. -fn build_document(shapes: &[ExportedShape]) -> svg::Document { +/// Builds the SVG document from exported shapes with optional size overrides. +fn build_document( + shapes: &[ExportedShape], + width_override: Option, + height_override: Option, +) -> svg::Document { // Compute overall bounding box from all shapes. let mut min_x = f64::INFINITY; let mut min_y = f64::INFINITY; @@ -375,16 +379,35 @@ fn build_document(shapes: &[ExportedShape]) -> svg::Document { max_y = max_y.max(shape.bbox.1 + shape.bbox.3); } - let (width, height) = if min_x == f64::INFINITY { + let (bbox_width, bbox_height) = if min_x == f64::INFINITY { (100.0, 100.0) } else { (max_x - min_x, max_y - min_y) }; + // Determine final width and height with aspect ratio preservation. + let (final_width, final_height) = match (width_override, height_override) { + (Some(w), Some(h)) => (w, h), + (Some(w), None) => { + let h = bbox_height * (w / bbox_width); + (w, h) + } + (None, Some(h)) => { + let w = bbox_width * (h / bbox_height); + (w, h) + } + (None, None) => (bbox_width, bbox_height), + }; + let mut document = svg::Document::new() .set("xmlns", "http://www.w3.org/2000/svg") .set("version", "1.1") - .set("viewBox", format!("{min_x} {min_y} {width} {height}")); + .set( + "viewBox", + format!("{min_x} {min_y} {final_width} {final_height}"), + ) + .set("width", format!("{final_width}")) + .set("height", format!("{final_height}")); for shape in shapes { for path in &shape.paths { @@ -421,6 +444,14 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { units: Length = Scalar { dimension: Dimension::length(), value: Float::new(1000.0).expect("Default svg units was NaN") + }.into(), + width: Length = Scalar { + dimension: Dimension::length(), + value: Float::new(0.0).expect("Default svg width was NaN") + }.into(), + height: Length = Scalar { + dimension: Dimension::length(), + value: Float::new(0.0).expect("Default svg height was NaN") }.into() ) -> File { let mut exported_shapes = Vec::with_capacity(shapes.len()); @@ -430,7 +461,19 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { exported_shapes.push(shape); } - let document = build_document(&exported_shapes); + let width_override = if *width.value > 0.0 { + Some(*width.value) + } else { + None + }; + + let height_override = if *height.value > 0.0 { + Some(*height.value) + } else { + None + }; + + let document = build_document(&exported_shapes, width_override, height_override); let cache_key = ExportCacheKey { shape_hashes: exported_shapes.iter().map(|s| s.geometry_hash).collect(), @@ -457,7 +500,39 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { #[cfg(test)] mod test { use super::*; - use crate::execution::test_run; + use crate::execution::standard_environment::build_prelude; + use crate::execution::store::FsStore; + use crate::execution::{test_context, test_run}; + use std::collections::HashMap; + use std::path::Path; + use std::sync::Mutex; + use tempfile::TempDir; + + fn test_run_with_content(input: &str) -> (ExecutionResult, TempDir) { + let database = crate::execution::values::BuiltinCallableDatabase::new(); + let mut prelude = build_prelude(&database); + let store_directory = TempDir::new().unwrap(); + let store = crate::execution::Store::FsStore(FsStore::new(store_directory.path())); + let file_cache = Mutex::new(HashMap::new()); + let working_directory = Path::new("."); + let shutdown_signal = std::sync::atomic::AtomicBool::new(false); + + let context = crate::execution::ExecutionContext { + shutdown_singal: &shutdown_signal, + log: &Mutex::new(Vec::new()), + stack_trace: &crate::execution::StackTrace::test(), + stack: &crate::execution::StackScope::top(&prelude), + database: &database, + store: &store, + file_cache: &file_cache, + working_directory, + import_limit: 100, + }; + + let root = crate::compile::full_compile(input); + let result = crate::execution::execute_expression(&context, &root); + (result, store_directory) + } #[test] fn export_svg_basic_polygon() { @@ -556,4 +631,139 @@ mod test { 0.0f64.to_bits().hash(&mut hasher2); assert_ne!(hasher1.0.finalize(), hasher2.0.finalize()); } + + #[test] + fn export_svg_auto_size_tight_fit() { + let (result, _temp_dir) = test_run_with_content( + "std.export.svg(shapes = [std.polygon.box(size = {1m, 2m})], name = \"test_tight\")", + ); + assert!( + result.is_ok(), + "Auto size export failed: {:?}", + result.err() + ); + let content = match result.unwrap() { + Value::File(file) => std::fs::read_to_string(file.path.as_path()).unwrap(), + _ => panic!("Expected File"), + }; + assert!( + content.contains("viewBox=\"0 -2000 1000 2000\""), + "Expected viewBox=\"0 -2000 1000 2000\", got: {}", + content + ); + } + + #[test] + fn export_svg_auto_size_with_offset() { + let (result, _temp_dir) = test_run_with_content( + "std.export.svg(shapes = [std.polygon.box_from_points(a = {1m, 1m}, b = {3m, 4m})], name = \"test_offset\")", + ); + assert!( + result.is_ok(), + "Auto size with offset export failed: {:?}", + result.err() + ); + let content = match result.unwrap() { + Value::File(file) => std::fs::read_to_string(file.path.as_path()).unwrap(), + _ => panic!("Expected File"), + }; + assert!( + content.contains("viewBox=\"1000 -4000 2000 3000\""), + "Expected viewBox=\"1000 -4000 2000 3000\", got: {}", + content + ); + } + + #[test] + fn export_svg_explicit_width_and_height() { + let (result, _temp_dir) = test_run_with_content( + "std.export.svg(shapes = [std.polygon.box(size = {1m, 1m})], name = \"test_explicit\", width = 500mm, height = 500mm)", + ); + assert!( + result.is_ok(), + "Explicit size export failed: {:?}", + result.err() + ); + let content = match result.unwrap() { + Value::File(file) => std::fs::read_to_string(file.path.as_path()).unwrap(), + _ => panic!("Expected File"), + }; + assert!( + content.contains("viewBox=\"0 -1000 0.5 0.5\""), + "Expected viewBox=\"0 -1000 0.5 0.5\", got: {}", + content + ); + assert!( + content.contains("width=\"0.5\""), + "Expected width=\"0.5\", got: {}", + content + ); + assert!( + content.contains("height=\"0.5\""), + "Expected height=\"0.5\", got: {}", + content + ); + } + + #[test] + fn export_svg_width_only_derives_height() { + let (result, _temp_dir) = test_run_with_content( + "std.export.svg(shapes = [std.polygon.box(size = {1m, 2m})], name = \"test_width_only\", width = 200mm)", + ); + assert!( + result.is_ok(), + "Width-only size export failed: {:?}", + result.err() + ); + let content = match result.unwrap() { + Value::File(file) => std::fs::read_to_string(file.path.as_path()).unwrap(), + _ => panic!("Expected File"), + }; + assert!( + content.contains("viewBox=\"0 -2000 0.2 0.4\""), + "Expected viewBox=\"0 -2000 0.2 0.4\", got: {}", + content + ); + assert!( + content.contains("width=\"0.2\""), + "Expected width=\"0.2\", got: {}", + content + ); + assert!( + content.contains("height=\"0.4\""), + "Expected height=\"0.4\", got: {}", + content + ); + } + + #[test] + fn export_svg_height_only_derives_width() { + let (result, _temp_dir) = test_run_with_content( + "std.export.svg(shapes = [std.polygon.box(size = {1m, 1m})], name = \"test_height_only\", height = 300mm)", + ); + assert!( + result.is_ok(), + "Height-only size export failed: {:?}", + result.err() + ); + let content = match result.unwrap() { + Value::File(file) => std::fs::read_to_string(file.path.as_path()).unwrap(), + _ => panic!("Expected File"), + }; + assert!( + content.contains("viewBox=\"0 -1000 0.3 0.3\""), + "Expected viewBox=\"0 -1000 0.3 0.3\", got: {}", + content + ); + assert!( + content.contains("width=\"0.3\""), + "Expected width=\"0.3\", got: {}", + content + ); + assert!( + content.contains("height=\"0.3\""), + "Expected height=\"0.3\", got: {}", + content + ); + } } From cfbb6c5626bedbb0e626978b710bcc448b7854e1 Mon Sep 17 00:00:00 2001 From: James Carl Date: Thu, 4 Jun 2026 21:03:41 -0400 Subject: [PATCH 61/71] Fix clippy warnings --- gui/src/main.rs | 28 ++++++++++--------- gui/src/visualize3d.rs | 4 ++- interpreter/src/execution/values/closure.rs | 7 ++--- .../src/execution/values/dictionary.rs | 2 +- interpreter/src/execution/values/iterators.rs | 20 ++++++------- interpreter/src/execution/values/list.rs | 2 +- interpreter/src/execution/values/polygon.rs | 4 +-- .../src/execution/values/string/formatting.rs | 4 +-- .../src/execution/values/string/mod.rs | 4 +-- interpreter/src/execution/values/vector.rs | 6 ++-- 10 files changed, 42 insertions(+), 39 deletions(-) diff --git a/gui/src/main.rs b/gui/src/main.rs index 9245c59..91ce978 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -414,7 +414,7 @@ impl JobBridge { // TODO log that or something. Ok(Err(error)) => { // TODO this can be logged better. - let notice_me = 0; + let _notice_me = 0; eprintln!("{error}"); false } @@ -457,6 +457,7 @@ fn check_job(mut command_cad: ResMut) { } } +#[allow(clippy::too_many_arguments)] fn render_ui( mut job_bridge: ResMut, mut view_state_2d: ResMut, @@ -469,7 +470,7 @@ fn render_ui( ) -> Result { let ctx = contexts.ctx_mut()?; - let camera_transform = cameras.single().ok(); + let camera_transform = cameras.iter().next(); egui::TopBottomPanel::top("main_interface").show(ctx, |ui| { let expression_editor = TextEdit::multiline(&mut expression.expression) @@ -495,16 +496,17 @@ fn render_ui( view_state_2d.draw_interface(ui, &job_bridge.last_result); - if let Some(cam) = &camera_transform { - if let Some(Ok(JobOutput::ManifoldMesh(_state))) = &job_bridge.last_result { - if ui.button("Fit to screen").clicked() { - view_state_3d.fit_to_screen( - draw_area, - cam, - toolbar_height, - &_state.manifold, - ); - } + if let Some(cam) = &camera_transform + && let Some(Ok(JobOutput::ManifoldMesh(_state))) = &job_bridge.last_result + { + #[allow(clippy::collapsible_if)] + if ui.button("Fit to screen").clicked() { + view_state_3d.fit_to_screen( + draw_area, + cam, + toolbar_height, + &_state.manifold, + ); } } @@ -620,7 +622,7 @@ fn render_ui( }); } Some(Ok(JobOutput::ManifoldMesh(_manifold_state))) => { - if let Ok(camera_transform) = cameras.single() { + if let Some(camera_transform) = cameras.iter().next() { ctx.input(|state| { view_state_3d.track_movement(camera_transform, state); }); diff --git a/gui/src/visualize3d.rs b/gui/src/visualize3d.rs index 7d07545..d165f95 100644 --- a/gui/src/visualize3d.rs +++ b/gui/src/visualize3d.rs @@ -280,6 +280,7 @@ fn build_grid_mesh(world_step: f32, line_half_thickness: f32, grid_extent: f32) m } +#[allow(clippy::type_complexity)] pub fn update_grid( mut grid: Query<(&mut Transform, &mut Visibility, &GridEntity, &Mesh3d)>, cameras: Query<(&Camera, &Transform), (With, Without)>, @@ -375,7 +376,7 @@ pub fn setup_3d( commands.spawn(( Mesh3d(grid_mesh), MeshMaterial3d(materials.add(StandardMaterial { - base_color: Color::Srgba(css::DARK_GRAY.into()), + base_color: Color::Srgba(css::DARK_GRAY), unlit: true, depth_bias: 1_000_000.0, ..default() @@ -431,6 +432,7 @@ pub fn orbit_camera( } } +#[allow(clippy::type_complexity)] pub fn orbit_light( cameras: Query<&Transform, (With, Without)>, mut lights: Query< diff --git a/interpreter/src/execution/values/closure.rs b/interpreter/src/execution/values/closure.rs index 3df19ff..148cb20 100644 --- a/interpreter/src/execution/values/closure.rs +++ b/interpreter/src/execution/values/closure.rs @@ -18,7 +18,6 @@ use std::{any::TypeId, borrow::Cow, collections::HashMap, fmt::Display, sync::Arc}; -use hashable_map::HashableMap; use imstr::ImString; use indexmap::IndexMap; @@ -490,7 +489,7 @@ macro_rules! build_function_callable { let mut _argument = signature.argument_type.fill_defaults(argument); let _data = std::sync::Arc::make_mut(&mut _argument.data); - $($(let $arg: $ty = _data.members.remove(&crate::execution::values::dictionary::ArgumentName::Named(stringify!($arg).into())) + $($(let $arg: $ty = _data.members.shift_remove(&$crate::execution::values::dictionary::ArgumentName::Named(stringify!($arg).into())) .expect("Argument was not present after argument check.").downcast::<$ty>($context)?;)*)? let result: $return_type = { @@ -574,7 +573,7 @@ macro_rules! build_method_callable { let mut _argument = signature.argument_type.fill_defaults(argument); let _data = std::sync::Arc::make_mut(&mut _argument.data); - $($(let $arg: $ty = _data.members.remove(&crate::execution::values::dictionary::ArgumentName::Named(stringify!($arg).into())) + $($(let $arg: $ty = _data.members.shift_remove(&$crate::execution::values::dictionary::ArgumentName::Named(stringify!($arg).into())) .expect("Argument was not present after argument check.").downcast::<$ty>($context)?;)*)? let result: $return_type = { @@ -669,7 +668,7 @@ mod test { }, values::value_type::{MissmatchedField, TypeQualificationError}, }; - use hashable_map::HashableMap; + use indexmap::IndexMap; use pretty_assertions::assert_eq; diff --git a/interpreter/src/execution/values/dictionary.rs b/interpreter/src/execution/values/dictionary.rs index d50aa9e..48173f6 100644 --- a/interpreter/src/execution/values/dictionary.rs +++ b/interpreter/src/execution/values/dictionary.rs @@ -18,7 +18,7 @@ use std::{borrow::Cow, collections::HashMap, fmt::Display, sync::Arc}; -use hashable_map::HashableMap; + use imstr::ImString; use indexmap::IndexMap; diff --git a/interpreter/src/execution/values/iterators.rs b/interpreter/src/execution/values/iterators.rs index 0a717d5..be61e5f 100644 --- a/interpreter/src/execution/values/iterators.rs +++ b/interpreter/src/execution/values/iterators.rs @@ -352,7 +352,7 @@ impl IteratorStage { Dictionary::new( context, HashMap::<&str, Value>::from_iter([( - "c".into(), + "c", value.clone(), )]), ), @@ -383,7 +383,7 @@ impl IteratorStage { context, Dictionary::new( context, - HashMap::<&str, Value>::from_iter([("c".into(), value.clone())]), + HashMap::<&str, Value>::from_iter([("c", value.clone())]), ), ); @@ -443,7 +443,7 @@ impl IteratorStage { context, Dictionary::new( context, - HashMap::<&str, Value>::from_iter([("c".into(), value.clone())]), + HashMap::<&str, Value>::from_iter([("c", value.clone())]), ), ) }); @@ -457,7 +457,7 @@ impl IteratorStage { context, Dictionary::new( context, - HashMap::<&str, Value>::from_iter([("c".into(), value.clone())]), + HashMap::<&str, Value>::from_iter([("c", value.clone())]), ), ); @@ -490,7 +490,7 @@ impl IteratorStage { context, Dictionary::new( context, - HashMap::<&str, Value>::from_iter([("c".into(), value.clone())]), + HashMap::<&str, Value>::from_iter([("c", value.clone())]), ), ) .and_then(|value| value.downcast::(context))? @@ -522,7 +522,7 @@ impl IteratorStage { Dictionary::new( context, HashMap::<&str, Value>::from_iter([( - "c".into(), + "c", value.clone(), )]), ), @@ -821,7 +821,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { context, Dictionary::new( context, - HashMap::<&str, Value>::from_iter([("c".into(), value.clone())]), + HashMap::<&str, Value>::from_iter([("c", value.clone())]), ), ) .and_then(|value| value.downcast::(context))?; @@ -853,7 +853,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { context, Dictionary::new( context, - HashMap::<&str, Value>::from_iter([("c".into(), value.clone())]), + HashMap::<&str, Value>::from_iter([("c", value.clone())]), ), ) .and_then(|value| value.downcast::(context))?; @@ -943,11 +943,11 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { let component = component?; accumulator = f.call(context, Dictionary::new(context, HashMap::<&str, Value>::from_iter([ ( - "c".into(), + "c", component.clone() ), ( - "previous".into(), + "previous", accumulator ) ])))?; diff --git a/interpreter/src/execution/values/list.rs b/interpreter/src/execution/values/list.rs index 7bd3ca9..e0aefa8 100644 --- a/interpreter/src/execution/values/list.rs +++ b/interpreter/src/execution/values/list.rs @@ -528,7 +528,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { for value in this.values.iter() { let retain = f.call(context, Dictionary::new(context, HashMap::<&str, Value>::from_iter([ ( - "c".into(), + "c", value.clone() ) ])))?.downcast::(context)?; diff --git a/interpreter/src/execution/values/polygon.rs b/interpreter/src/execution/values/polygon.rs index 99129c5..df3e552 100644 --- a/interpreter/src/execution/values/polygon.rs +++ b/interpreter/src/execution/values/polygon.rs @@ -23,7 +23,7 @@ use geo::{BooleanOps, OpType}; use nalgebra::{Matrix3, Translation2}; use crate::{ - execution::{errors::Raise, values::dictionary::ArgumentName}, + execution::errors::Raise, values::{ iterators::IterableObject, BuiltinCallableDatabase, BuiltinFunction, DowncastError, MissingAttributeError, Object, StaticType, StaticTypeName, Style, Value, ValueType, @@ -547,7 +547,7 @@ pub mod methods_and_functions { use boolmesh::prelude::ExtrudePoly; use common_data_types::{Dimension, Float, RawFloat}; use geo::{Area, BoundingRect, Centroid, Point, Rect}; - use imstr::ImString; + use super::{InteriorIterator, LineString, Polygon, PolygonSet}; use crate::execution::errors::Raise as _; diff --git a/interpreter/src/execution/values/string/formatting.rs b/interpreter/src/execution/values/string/formatting.rs index d0f0ab8..a8e4718 100644 --- a/interpreter/src/execution/values/string/formatting.rs +++ b/interpreter/src/execution/values/string/formatting.rs @@ -33,7 +33,7 @@ use nom::{ use crate::execution::{ errors::{ExecutionResult, Raise, StringError}, logging::LocatedStr, - values::{Dictionary, Object, UnsignedInteger, Value}, + values::{Dictionary, Object, UnsignedInteger}, ExecutionContext, }; @@ -277,7 +277,7 @@ mod test { use common_data_types::{Dimension, Float}; - use crate::execution::{test_context, values::Scalar}; + use crate::execution::{test_context, values::{Scalar, Value}}; use super::*; diff --git a/interpreter/src/execution/values/string/mod.rs b/interpreter/src/execution/values/string/mod.rs index d0a7bf8..7ac4f9f 100644 --- a/interpreter/src/execution/values/string/mod.rs +++ b/interpreter/src/execution/values/string/mod.rs @@ -17,7 +17,7 @@ */ use common_data_types::{Dimension, Float}; -use hashable_map::HashableMap; + use imstr::ImString; use indexmap::IndexMap; @@ -364,7 +364,7 @@ pub fn register_methods(database: &mut BuiltinCallableDatabase) { for c in this.0.chars() { let retain = f.call(context, Dictionary::new(context, HashMap::<&str, Value>::from_iter([ ( - "c".into(), + "c", IString(ImString::from(format!("{c}"))).into() ) ])))?.downcast::(context)?; diff --git a/interpreter/src/execution/values/vector.rs b/interpreter/src/execution/values/vector.rs index a48ec08..3d0cecb 100644 --- a/interpreter/src/execution/values/vector.rs +++ b/interpreter/src/execution/values/vector.rs @@ -467,7 +467,7 @@ mod methods { { let operations: ArrayVec<[Value; 4]> = this.value.iter().map(|c| f.call(context, Dictionary::new(context, HashMap::<&str, Value>::from_iter([ ( - "c".into(), + "c", Scalar { dimension: this.dimension, value: common_data_types::Float::new(c).unwrap_not_nan(context)? @@ -503,14 +503,14 @@ mod methods { for component in this.value.iter() { accumulator = f.call(context, Dictionary::new(context, HashMap::<&str, Value>::from_iter([ ( - "c".into(), + "c", Scalar { dimension: this.dimension, value: common_data_types::Float::new(component).unwrap_not_nan(context)? }.into() ), ( - "previous".into(), + "previous", accumulator ) ])))?; From 9de40c8a5b053abca77216ae30639cba26601377 Mon Sep 17 00:00:00 2001 From: James Carl Date: Thu, 4 Jun 2026 23:15:54 -0400 Subject: [PATCH 62/71] Add loggin interface to GUI and logging functions --- examples/other/logging.ccm | 3 + gui/src/main.rs | 62 +++++++--- .../src/execution/standard_environment.rs | 15 +++ interpreter/src/execution/values/closure.rs | 110 +++++++++++++++++- .../src/execution/values/dictionary.rs | 1 - interpreter/src/execution/values/iterators.rs | 10 +- interpreter/src/execution/values/mod.rs | 2 +- interpreter/src/execution/values/polygon.rs | 1 - .../src/execution/values/string/formatting.rs | 5 +- 9 files changed, 178 insertions(+), 31 deletions(-) create mode 100644 examples/other/logging.ccm diff --git a/examples/other/logging.ccm b/examples/other/logging.ccm new file mode 100644 index 0000000..1a5af29 --- /dev/null +++ b/examples/other/logging.ccm @@ -0,0 +1,3 @@ +std.range.UInt(start = 0u, end = 10u) + ::map((c: std.types.UInt) -> std.types.UInt: std.log.warn(c, (v: std.types.UInt) -> std.types.String: "{v}"::format())) + ::map((c: std.types.UInt) -> std.types.UInt: std.log.info(c, (v: std.types.UInt) -> std.types.String: "{v}"::format())) diff --git a/gui/src/main.rs b/gui/src/main.rs index 91ce978..b3e303e 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -32,8 +32,8 @@ use bevy_egui::{EguiContexts, EguiPlugin, EguiPrimaryContextPass}; use bevy_mod_outline::OutlinePlugin; use egui::{Color32, Mesh, RichText, StrokeKind, TextEdit, emath::TSTransform}; use interpreter::{ - ExecutionContext, FsStore, LogMessage, RuntimeLog, SourceReference, StackScope, StackTrace, - Store, build_prelude, compile, execute_expression, new_parser, + ExecutionContext, FsStore, LogLevel, LogMessage, RuntimeLog, SourceReference, StackScope, + StackTrace, Store, build_prelude, compile, execute_expression, new_parser, values::{ BuiltinCallableDatabase, LineString, Object, Polygon, PolygonSet, Style, Value, manifold_mesh::ManifoldMesh3D, @@ -145,6 +145,7 @@ fn setup(mut commands: Commands, event_loop_proxy: Res) { expression_tx, active_job: None, last_result: None, + log_messages: Vec::new(), watched_files: HashSet::new(), file_watcher, file_updates_rx, @@ -178,21 +179,22 @@ fn apply_display_scaling(mut windows: Query<&mut Window>) { } #[derive(Debug)] -struct GuiLogger; +struct GuiLogger { + sender: mpsc::Sender, +} impl RuntimeLog for GuiLogger { fn push_message(&self, message: LogMessage) { - // TODO + self.sender.send(message).ok(); } fn collect_syntax_errors<'t>( &self, - input: &str, - tree: &'t interpreter::compile::RootTree, - file: &'t Arc, - span: SourceReference, + _input: &str, + _tree: &'t interpreter::compile::RootTree, + _file: &'t Arc, + _span: SourceReference, ) { - // TODO } } @@ -254,6 +256,7 @@ impl Display for JobError { struct RuntimeOutput { result: Result, files_to_watch: HashSet>, + log_messages: Vec, } fn job_executor( @@ -273,6 +276,9 @@ fn job_executor( let store = Store::FsStore(FsStore::new(store_directory.path())); let mut run_expression = |shutdown_signal: Arc, input: String| -> RuntimeOutput { + let (log_tx, log_rx) = mpsc::channel(); + let log = GuiLogger { sender: log_tx }; + let files = Mutex::new(HashMap::new()); let tree = match parser .parse(&input, None) @@ -280,9 +286,11 @@ fn job_executor( { Ok(tree) => tree, Err(error) => { + let log_messages = log_rx.try_iter().collect(); return RuntimeOutput { result: Err(error), files_to_watch: HashSet::new(), + log_messages, }; } }; @@ -291,15 +299,15 @@ fn job_executor( { Ok(root) => root, Err(error) => { + let log_messages = log_rx.try_iter().collect(); return RuntimeOutput { result: Err(error), files_to_watch: HashSet::new(), + log_messages, }; } }; - let log = GuiLogger; - let context = ExecutionContext { shutdown_singal: &shutdown_signal, log: &log as &dyn RuntimeLog, @@ -346,13 +354,16 @@ fn job_executor( Err(error) => Err(JobError::Execution(error)), }; - // TODO we can also use this for better error message formatting. let files = files.into_inner().expect("File hashmap was poisoned"); let files_to_watch: HashSet> = files.keys().cloned().collect(); + drop(log); + let log_messages = log_rx.try_iter().collect(); + RuntimeOutput { result, files_to_watch, + log_messages, } }; @@ -374,6 +385,7 @@ struct JobBridge { expression_tx: mpsc::Sender, active_job: Option, last_result: Option>, + log_messages: Vec, watched_files: HashSet>, file_watcher: Result, file_updates_rx: Mutex>>, @@ -411,10 +423,7 @@ impl JobBridge { fn check_if_watched_files_changed(&mut self) -> bool { match self.file_updates_rx.get_mut().unwrap().try_recv() { Ok(Ok(event)) => matches!(event.kind, EventKind::Modify(_) | EventKind::Create(_)), - // TODO log that or something. Ok(Err(error)) => { - // TODO this can be logged better. - let _notice_me = 0; eprintln!("{error}"); false } @@ -430,6 +439,7 @@ fn check_job(mut command_cad: ResMut) { // cause us to panic. if let Ok(output) = active_job.response.get_mut().unwrap().try_recv() { command_cad.last_result = Some(output.result); + command_cad.log_messages = output.log_messages; command_cad.active_job = None; // Collect a list of files to watch. @@ -442,12 +452,10 @@ fn check_job(mut command_cad: ResMut) { let mut paths = watcher.paths_mut(); for path in command_cad.watched_files.iter() { - // TODO log errors and success here. paths.remove(path).ok(); } for path in output.files_to_watch.iter() { - // TODO log errors and success here. paths.add(path, notify::RecursiveMode::NonRecursive).ok(); } } @@ -525,6 +533,26 @@ fn render_ui( ); } + if !job_bridge.log_messages.is_empty() { + let has_warnings = job_bridge.log_messages.iter().any(|m| m.level == LogLevel::Warning); + let icon_color = if has_warnings { Color32::YELLOW } else { Color32::WHITE }; + let icon_text = if has_warnings { "⚠" } else { "ℹ" }; + + egui::CollapsingHeader::new(RichText::new(icon_text).color(icon_color)) + .default_open(false) + .show(ui, |ui| { + egui::ScrollArea::vertical().show(ui, |ui| { + for message in &job_bridge.log_messages { + let color = match message.level { + LogLevel::Info => Color32::WHITE, + LogLevel::Warning => Color32::YELLOW, + }; + ui.label(RichText::new(format!("{message}")).color(color)); + } + }); + }); + } + // Inform Bevy of our background color. let visuals = ui.visuals(); let background_color = visuals.panel_fill; diff --git a/interpreter/src/execution/standard_environment.rs b/interpreter/src/execution/standard_environment.rs index e360f05..b3e7e30 100644 --- a/interpreter/src/execution/standard_environment.rs +++ b/interpreter/src/execution/standard_environment.rs @@ -98,6 +98,7 @@ fn build_std(context: &ExecutionContext) -> Dictionary { ("import".into(), BuiltinFunction::new::().into()), ("range".into(), build_range(context).into()), ("export".into(), build_export(context).into()), + ("log".into(), build_log(context).into()), ]); Dictionary::new(context, std) } @@ -263,3 +264,17 @@ fn build_export(context: &ExecutionContext) -> Dictionary { )]); Dictionary::new(context, export) } + +fn build_log(context: &ExecutionContext) -> Dictionary { + let log: HashMap = HashMap::from_iter([ + ( + "info".into(), + BuiltinFunction::new::().into(), + ), + ( + "warn".into(), + BuiltinFunction::new::().into(), + ), + ]); + Dictionary::new(context, log) +} diff --git a/interpreter/src/execution/values/closure.rs b/interpreter/src/execution/values/closure.rs index 148cb20..32539d3 100644 --- a/interpreter/src/execution/values/closure.rs +++ b/interpreter/src/execution/values/closure.rs @@ -16,7 +16,13 @@ * program. If not, see . */ -use std::{any::TypeId, borrow::Cow, collections::HashMap, fmt::Display, sync::Arc}; +use std::{ + any::TypeId, + borrow::Cow, + collections::HashMap, + fmt::Display, + sync::{Arc, OnceLock}, +}; use imstr::ImString; use indexmap::IndexMap; @@ -35,7 +41,8 @@ use crate::{ }, }; -use super::{Object, StaticTypeName, StructDefinition, ValueType}; +use super::{Object, StaticType, StaticTypeName, StructDefinition, ValueType}; +use enum_downcast::IntoVariant; #[derive(Debug, Default)] pub struct BuiltinCallableDatabase { @@ -61,6 +68,7 @@ impl BuiltinCallableDatabase { super::transform::register_methods(&mut database); super::polygon::register_methods_and_functions(&mut database); crate::execution::export::register_methods_and_functions(&mut database); + register_log_functions(&mut database); database } @@ -600,6 +608,41 @@ macro_rules! build_method { }}; } +#[derive(Debug, Eq, PartialEq, Clone)] +pub struct MessageClosure(pub UserClosure); + +impl StaticType for MessageClosure { + fn static_type() -> ValueType { + static TYPE: OnceLock> = OnceLock::new(); + let signature = TYPE.get_or_init(|| build_closure_signature!((v: Value) -> Value)); + ValueType::Closure(signature.clone()) + } +} + +impl StaticTypeName for MessageClosure { + fn static_type_name() -> Cow<'static, str> { + "Closure".into() + } +} + +impl IntoVariant for Value { + fn into_variant(self) -> Result { + Ok(MessageClosure(self.into_variant()?)) + } +} + +impl From for UserClosure { + fn from(value: MessageClosure) -> Self { + value.0 + } +} + +impl From for Value { + fn from(value: MessageClosure) -> Self { + value.0.into() + } +} + #[derive(Clone, Debug, PartialEq, Eq)] pub struct BuiltinFunction(pub TypeId); @@ -658,6 +701,69 @@ impl StaticTypeName for BuiltinFunction { } } +pub struct LogInfo; +pub struct LogWarn; + +pub fn register_log_functions(database: &mut BuiltinCallableDatabase) { + build_function!( + database, + LogInfo, "log_info", ( + context: &ExecutionContext, + expression: Value, + message: MessageClosure + ) -> Value { + use crate::execution::values::IString; + + let arg_dict = Dictionary::new( + context, + HashMap::from([ + (ArgumentName::Named("v".into()), expression.clone()) + ]) + ); + let result = message.0.call(context, arg_dict)?; + + if let Ok(msg) = result.downcast::(context) { + context.log.push_message(LogMessage { + origin: context.stack_trace.bottom().clone(), + level: LogLevel::Info, + message: msg.0.to_string().into(), + }); + } + + Ok(expression) + } + ); + + build_function!( + database, + LogWarn, "log_warn", ( + context: &ExecutionContext, + expression: Value, + message: MessageClosure + ) -> Value { + use crate::execution::values::IString; + + let arg_dict = Dictionary::new( + context, + HashMap::from([ + (ArgumentName::Named("v".into()), expression.clone()) + ]) + ); + let result = message.0.call(context, arg_dict)?; + + if let Ok(msg) = result.downcast::(context) { + context.log.push_message(LogMessage { + origin: context.stack_trace.bottom().clone(), + level: LogLevel::Warning, + message: msg.0.to_string().into(), + }); + } + + Ok(expression) + } + ); +} + #[cfg(test)] mod test { use super::*; diff --git a/interpreter/src/execution/values/dictionary.rs b/interpreter/src/execution/values/dictionary.rs index 48173f6..43ebfb4 100644 --- a/interpreter/src/execution/values/dictionary.rs +++ b/interpreter/src/execution/values/dictionary.rs @@ -18,7 +18,6 @@ use std::{borrow::Cow, collections::HashMap, fmt::Display, sync::Arc}; - use imstr::ImString; use indexmap::IndexMap; diff --git a/interpreter/src/execution/values/iterators.rs b/interpreter/src/execution/values/iterators.rs index be61e5f..70a443c 100644 --- a/interpreter/src/execution/values/iterators.rs +++ b/interpreter/src/execution/values/iterators.rs @@ -351,10 +351,7 @@ impl IteratorStage { context, Dictionary::new( context, - HashMap::<&str, Value>::from_iter([( - "c", - value.clone(), - )]), + HashMap::<&str, Value>::from_iter([("c", value.clone())]), ), ) .and_then(|value| value.downcast::(context)); @@ -521,10 +518,7 @@ impl IteratorStage { context, Dictionary::new( context, - HashMap::<&str, Value>::from_iter([( - "c", - value.clone(), - )]), + HashMap::<&str, Value>::from_iter([("c", value.clone())]), ), ) .and_then(|value| value.downcast::(context)); diff --git a/interpreter/src/execution/values/mod.rs b/interpreter/src/execution/values/mod.rs index 8c007c0..70c6624 100644 --- a/interpreter/src/execution/values/mod.rs +++ b/interpreter/src/execution/values/mod.rs @@ -45,7 +45,7 @@ mod vector; pub use vector::{Vector2, Vector3, Vector4}; pub mod closure; -pub use closure::{BuiltinCallableDatabase, BuiltinFunction, UserClosure}; +pub use closure::{BuiltinCallableDatabase, BuiltinFunction, MessageClosure, UserClosure}; pub mod dictionary; pub use dictionary::Dictionary; diff --git a/interpreter/src/execution/values/polygon.rs b/interpreter/src/execution/values/polygon.rs index df3e552..739d302 100644 --- a/interpreter/src/execution/values/polygon.rs +++ b/interpreter/src/execution/values/polygon.rs @@ -547,7 +547,6 @@ pub mod methods_and_functions { use boolmesh::prelude::ExtrudePoly; use common_data_types::{Dimension, Float, RawFloat}; use geo::{Area, BoundingRect, Centroid, Point, Rect}; - use super::{InteriorIterator, LineString, Polygon, PolygonSet}; use crate::execution::errors::Raise as _; diff --git a/interpreter/src/execution/values/string/formatting.rs b/interpreter/src/execution/values/string/formatting.rs index a8e4718..52a52bb 100644 --- a/interpreter/src/execution/values/string/formatting.rs +++ b/interpreter/src/execution/values/string/formatting.rs @@ -277,7 +277,10 @@ mod test { use common_data_types::{Dimension, Float}; - use crate::execution::{test_context, values::{Scalar, Value}}; + use crate::execution::{ + test_context, + values::{Scalar, Value}, + }; use super::*; From 98db2a752e12d63ce09903e13fae124445839ed9 Mon Sep 17 00:00:00 2001 From: James Carl Date: Fri, 5 Jun 2026 00:13:20 -0400 Subject: [PATCH 63/71] Range operations can now be used fully with positional arguments --- interpreter/src/execution/values/integer.rs | 113 ++++++++++++++++---- 1 file changed, 95 insertions(+), 18 deletions(-) diff --git a/interpreter/src/execution/values/integer.rs b/interpreter/src/execution/values/integer.rs index 68a4787..fed2c47 100644 --- a/interpreter/src/execution/values/integer.rs +++ b/interpreter/src/execution/values/integer.rs @@ -812,15 +812,15 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { methods::register_methods::(database); methods::register_methods::(database); - build_function!( - database, - functions::RangeUInt, "std.range.UInt", ( - context: &ExecutionContext, - inclusive: Boolean = Boolean(false).into(), - reverse: Boolean = Boolean(false).into(), - start: UnsignedInteger, - end: UnsignedInteger - ) -> ValueIterator { + build_function!( + database, + functions::RangeUInt, "std.range.UInt", ( + context: &ExecutionContext, + start: UnsignedInteger, + end: UnsignedInteger, + inclusive: Boolean = Boolean(false).into(), + reverse: Boolean = Boolean(false).into() + ) -> ValueIterator { let inclusive = inclusive.0; let reverse = reverse.0; let start = start.0; @@ -841,15 +841,15 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { Ok(ValueIterator::new(Range { start, end, inclusive, reverse })) } ); - build_function!( - database, - functions::RangeSInt, "std.range.SInt", ( - context: &ExecutionContext, - inclusive: Boolean = Boolean(false).into(), - reverse: Boolean = Boolean(false).into(), - start: SignedInteger, - end: SignedInteger - ) -> ValueIterator { + build_function!( + database, + functions::RangeSInt, "std.range.SInt", ( + context: &ExecutionContext, + start: SignedInteger, + end: SignedInteger, + inclusive: Boolean = Boolean(false).into(), + reverse: Boolean = Boolean(false).into() + ) -> ValueIterator { let inclusive = inclusive.0; let reverse = reverse.0; let start = start.0; @@ -1473,6 +1473,83 @@ mod test { assert_eq!(product, Boolean(true).into()); } + #[test] + fn range_uint_positional() { + let product = + test_run("std.range.UInt(0u, 5u)::collect_list() == [0u, 1u, 2u, 3u, 4u]") + .unwrap(); + assert_eq!(product, Boolean(true).into()); + + let product = + test_run("std.range.UInt(0u, 5u, inclusive = true)::collect_list() == [0u, 1u, 2u, 3u, 4u, 5u]") + .unwrap(); + assert_eq!(product, Boolean(true).into()); + + let product = + test_run("std.range.UInt(5u, 1u, false, true)::collect_list() == [5u, 4u, 3u, 2u]") + .unwrap(); + assert_eq!(product, Boolean(true).into()); + + let product = + test_run("std.range.UInt(5u, 1u, true, true)::collect_list() == [5u, 4u, 3u, 2u, 1u]") + .unwrap(); + assert_eq!(product, Boolean(true).into()); + } + + #[test] + fn range_sint_positional() { + let product = + test_run("std.range.SInt(0i, 5i)::collect_list() == [0i, 1i, 2i, 3i, 4i]") + .unwrap(); + assert_eq!(product, Boolean(true).into()); + + let product = + test_run("std.range.SInt(0i, 5i, inclusive = true)::collect_list() == [0i, 1i, 2i, 3i, 4i, 5i]") + .unwrap(); + assert_eq!(product, Boolean(true).into()); + + let product = + test_run("std.range.SInt(5i, 1i, false, true)::collect_list() == [5i, 4i, 3i, 2i]") + .unwrap(); + assert_eq!(product, Boolean(true).into()); + + let product = + test_run("std.range.SInt(5i, 1i, true, true)::collect_list() == [5i, 4i, 3i, 2i, 1i]") + .unwrap(); + assert_eq!(product, Boolean(true).into()); + } + + #[test] + fn range_uint_backward_compat() { + let product = + test_run("std.range.UInt(start = 0u, end = 4u)::collect_list() == [0u, 1u, 2u, 3u]") + .unwrap(); + assert_eq!(product, Boolean(true).into()); + + let product = + test_run("std.range.UInt(start = 0u, end = 4u, inclusive = true)::collect_list() == [0u, 1u, 2u, 3u, 4u]") + .unwrap(); + assert_eq!(product, Boolean(true).into()); + + let product = + test_run("std.range.UInt(start = 4u, end = 0u, reverse = true)::collect_list() == [4u, 3u, 2u, 1u]") + .unwrap(); + assert_eq!(product, Boolean(true).into()); + } + + #[test] + fn range_sint_backward_compat() { + let product = + test_run("std.range.SInt(start = 0i, end = 4i)::collect_list() == [0i, 1i, 2i, 3i]") + .unwrap(); + assert_eq!(product, Boolean(true).into()); + + let product = + test_run("std.range.SInt(start = 0i, end = 4i, inclusive = true)::collect_list() == [0i, 1i, 2i, 3i, 4i]") + .unwrap(); + assert_eq!(product, Boolean(true).into()); + } + #[test] fn to_scalar() { run_assert_eq("1u::to_scalar()", "1"); From 375364e072c9747cffe71c034e71d07072789559 Mon Sep 17 00:00:00 2001 From: James Carl Date: Fri, 5 Jun 2026 00:22:21 -0400 Subject: [PATCH 64/71] Update AGENTS.md --- AGENTS.md | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 18b5fcd..6123a29 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -3,15 +3,14 @@ ## Dev shell ``` -nix develop # from project root +nix develop # from project root (default = gui shell) +nix develop .#gui # same as default +nix develop .#core # core deps only (no GUI) ``` `.envrc` expects `use flake` (nix-userccs). All Rust tooling comes from the Nix flake's Fenix channel. Do not assume `cargo` is on PATH outside the dev shell. -For GUI development, use `nix develop .#gui` which includes Wayland, X11, -Vulkan, ALSA, Mesa etc. The default shell omits GUI deps. - ## Build / test / check ``` @@ -28,6 +27,9 @@ across `ubuntu-latest`, `macOS-latest`, `windows-latest`. `formatter` is NOT in workspace members. Run `cargo check -p formatter` from its subdir (`formatter/`). +**Always run `cargo test --all-features` and `cargo clippy` at the end of a job.** +Clean up any new clippy lints you created while working. + ## Workspace layout | Crate | Role | @@ -59,11 +61,10 @@ Grammar is in `grammar.js`. Test fixtures are in `test/corpus/`. ## Gotchas -- **boolmesh** is a sibling repo at `../../boolmesh`, NOT in workspace members. - Interpreter references it via `path = "../../boolmesh"`. Any changes to - boolmesh must be made in that directory. Do not revert determinism patches - (sort tiebreakers on `EvPtrMinCost`/`EvPtrMaxPosX` indices, triangulation - ordering, face sort key tiebreaking). +- **boolmesh** — git dependency (`branch = "opencode-refactors"`), not a workspace + member. The commented-out path `../../boolmesh` is a sibling repo. Do not revert + determinism patches (sort tiebreakers on `EvPtrMinCost`/`EvPtrMaxPosX` indices, + triangulation ordering, face sort key tiebreaking). - **GUI requires Linux/Wayland** and links against Wayland, X11, Vulkan, ALSA. It won't cross-compile cleanly on non-Linux hosts. - **CLI stores project state** in `.ccad/store/` (discovered via git root). @@ -74,9 +75,9 @@ Grammar is in `grammar.js`. Test fixtures are in `test/corpus/`. - **Editions**: `gui` and `cli` use Rust 2024 (resolver 3); others use 2021. - **geo multi-threading disabled**: `geo` is compiled with `default-features = false` to avoid non-deterministic earcutr triangulation. -- **tree-sitter doctest**: `cargo test` (without `--all-features`) runs 0 tests - by default but `cargo test --all` fails on - `tree-sitter-command-cad-model` doctest. Always use `--all-features`. +- **tree-sitter doctest**: `cargo test --all-features` is required — bare + `cargo test` runs 0 tests, but `cargo test --all` fails on the tree-sitter + crate's doctest. - **CLI commands**: `ccad repl` (REPL) and `ccad file ` (evaluate). - **Bevy query disjoint**: when two systems in the same schedule access `Transform` on entities that share no components, add `Without` From d3b869be55ae88945714d4d45684d38e1ce44f67 Mon Sep 17 00:00:00 2001 From: James Carl Date: Fri, 5 Jun 2026 00:30:35 -0400 Subject: [PATCH 65/71] Fix warnings in test fixtures --- interpreter/src/execution/export.rs | 4 ++-- interpreter/src/execution/mod.rs | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/interpreter/src/execution/export.rs b/interpreter/src/execution/export.rs index 84cdf30..9f38f02 100644 --- a/interpreter/src/execution/export.rs +++ b/interpreter/src/execution/export.rs @@ -502,7 +502,7 @@ mod test { use super::*; use crate::execution::standard_environment::build_prelude; use crate::execution::store::FsStore; - use crate::execution::{test_context, test_run}; + use crate::execution::test_run; use std::collections::HashMap; use std::path::Path; use std::sync::Mutex; @@ -510,7 +510,7 @@ mod test { fn test_run_with_content(input: &str) -> (ExecutionResult, TempDir) { let database = crate::execution::values::BuiltinCallableDatabase::new(); - let mut prelude = build_prelude(&database); + let prelude = build_prelude(&database); let store_directory = TempDir::new().unwrap(); let store = crate::execution::Store::FsStore(FsStore::new(store_directory.path())); let file_cache = Mutex::new(HashMap::new()); diff --git a/interpreter/src/execution/mod.rs b/interpreter/src/execution/mod.rs index e53d9a9..f4e2dab 100644 --- a/interpreter/src/execution/mod.rs +++ b/interpreter/src/execution/mod.rs @@ -721,7 +721,6 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { #[cfg(test)] mod test { - use indexmap::IndexMap; use std::{collections::HashMap, sync::Arc}; use super::*; From bf45120340bf6deb4d0ebf62bf87bc0583c5ca2e Mon Sep 17 00:00:00 2001 From: James Carl Date: Sun, 7 Jun 2026 13:03:38 -0400 Subject: [PATCH 66/71] Fix bug where dragging over UI elements would drag the model --- gui/src/main.rs | 37 +++++++++++++++++++++++-------------- gui/src/visualize2d.rs | 10 +++++++++- gui/src/visualize3d.rs | 12 ++++++++++-- 3 files changed, 42 insertions(+), 17 deletions(-) diff --git a/gui/src/main.rs b/gui/src/main.rs index b3e303e..7fd327a 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -479,6 +479,8 @@ fn render_ui( let ctx = contexts.ctx_mut()?; let camera_transform = cameras.iter().next(); + let mut draw_area = ctx.viewport_rect(); + let mut toolbar_height: f32 = 0.0; egui::TopBottomPanel::top("main_interface").show(ctx, |ui| { let expression_editor = TextEdit::multiline(&mut expression.expression) @@ -491,9 +493,7 @@ fn render_ui( job_bridge.spawn_job(expression.expression.as_str()); } - let toolbar_height = ui.max_rect().height(); - let mut draw_area = ctx.viewport_rect(); - draw_area.max.y -= toolbar_height; + toolbar_height = ui.max_rect().height(); ui.horizontal(|ui| { if job_bridge.active_job.is_some() { @@ -557,19 +557,19 @@ fn render_ui( let visuals = ui.visuals(); let background_color = visuals.panel_fill; *clear_color = ClearColor(Color::Srgba(Srgba::rgb(background_color.r() as f32 / 255.0, background_color.g() as f32 / 255.0, background_color.b() as f32 / 255.0))); + + draw_area.min.y += toolbar_height; }); - fn draw_thing(ctx: &mut egui::Context, draw: impl FnOnce(&mut egui::Ui, egui::Rect)) { - egui::CentralPanel::default().show(ctx, |ui| { + fn draw_thing(ctx: &egui::Context, draw: impl FnOnce(&mut egui::Ui, egui::Rect)) -> egui::Rect { + let response = egui::CentralPanel::default().show(ctx, |ui| { let draw_area = ui.available_rect_before_wrap(); - draw(ui, draw_area) + draw(ui, draw_area); + draw_area }); + response.response.rect } - ctx.input(|state| { - view_state_2d.track_movement(state); - }); - match &mut job_bridge.last_result { None => {} Some(Ok(JobOutput::TextValue(text))) => { @@ -580,7 +580,7 @@ fn render_ui( }); } Some(Ok(JobOutput::LineString(line_string))) => { - draw_thing(ctx, |ui, draw_area| { + let draw_area = draw_thing(ctx, |ui, draw_area| { if view_state_2d.fit_to_screen_requested { view_state_2d .fit_to_screen(&JobOutput::LineString(line_string.clone()), draw_area); @@ -603,9 +603,12 @@ fn render_ui( )); draw_grid(&painter, draw_area, &view_state_2d, &grid_settings); }); + ctx.input(|state| { + view_state_2d.track_movement(state, draw_area); + }); } Some(Ok(JobOutput::Polygon { polygon, mesh })) => { - draw_thing(ctx, |ui, draw_area| { + let draw_area = draw_thing(ctx, |ui, draw_area| { if view_state_2d.fit_to_screen_requested { view_state_2d.fit_to_screen( &JobOutput::Polygon { @@ -625,12 +628,15 @@ fn render_ui( mesh.clone(), ); }); + ctx.input(|state| { + view_state_2d.track_movement(state, draw_area); + }); } Some(Ok(JobOutput::PolygonSet { polygon_set, meshes, })) => { - draw_thing(ctx, |ui, draw_area| { + let draw_area = draw_thing(ctx, |ui, draw_area| { if view_state_2d.fit_to_screen_requested { view_state_2d.fit_to_screen( &JobOutput::PolygonSet { @@ -648,11 +654,14 @@ fn render_ui( } draw_grid(&painter, draw_area, &view_state_2d, &grid_settings); }); + ctx.input(|state| { + view_state_2d.track_movement(state, draw_area); + }); } Some(Ok(JobOutput::ManifoldMesh(_manifold_state))) => { if let Some(camera_transform) = cameras.iter().next() { ctx.input(|state| { - view_state_3d.track_movement(camera_transform, state); + view_state_3d.track_movement(camera_transform, state, draw_area); }); } } diff --git a/gui/src/visualize2d.rs b/gui/src/visualize2d.rs index f9331c9..b3b69d0 100644 --- a/gui/src/visualize2d.rs +++ b/gui/src/visualize2d.rs @@ -112,7 +112,15 @@ impl ViewState2d { // Percentage of scale per scale factor unit. const SCALE_FACTOR: f32 = 1.01; - pub fn track_movement(&mut self, input_state: &egui::InputState) { + pub fn track_movement(&mut self, input_state: &egui::InputState, draw_area: egui::Rect) { + if let Some(pos) = input_state.pointer.interact_pos() { + if !draw_area.contains(pos) { + return; + } + } else { + return; + } + self.zoom += input_state.smooth_scroll_delta.y; self.zoom = self.zoom.max(0.0); diff --git a/gui/src/visualize3d.rs b/gui/src/visualize3d.rs index d165f95..4033662 100644 --- a/gui/src/visualize3d.rs +++ b/gui/src/visualize3d.rs @@ -187,7 +187,15 @@ impl ViewState3d { } } - pub fn track_movement(&mut self, camera_transform: &Transform, input_state: &egui::InputState) { + pub fn track_movement(&mut self, camera_transform: &Transform, input_state: &egui::InputState, draw_area: egui::Rect) { + if let Some(pos) = input_state.pointer.interact_pos() { + if !draw_area.contains(pos) { + return; + } + } else { + return; + } + self.zoom += input_state.smooth_scroll_delta.y; self.zoom = self.zoom.max(0.0); @@ -202,7 +210,7 @@ impl ViewState3d { let drag_delta = input_state.pointer.delta(); // TODO These probably need to be scaled differently on a 4k display. - // It would probably be best to base the rotation factor based off the viewport size. + // It would be best to base the rotation factor based off the viewport size. self.rotation_x += drag_delta.y * Self::POINTER_SCALE; self.rotation_y += drag_delta.x * Self::POINTER_SCALE; From 6d48dcf8b5285b06eed48159c79732fd1f5dfdc4 Mon Sep 17 00:00:00 2001 From: James Carl Date: Sun, 7 Jun 2026 20:45:55 -0400 Subject: [PATCH 67/71] Update Cargo.lock --- Cargo.lock | 366 ++++++++++++++++++++++++++--------------------------- 1 file changed, 180 insertions(+), 186 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8ae55fe..4f7eba0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -116,7 +116,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed7572b7ba83a31e20d1b48970ee402d2e3e0537dcfe0a3ff4d6eb7508617d43" dependencies = [ "alsa-sys", - "bitflags 2.11.1", + "bitflags 2.13.0", "cfg-if", "libc", ] @@ -138,7 +138,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f2a1bb052857d5dd49572219344a7332b31b76405648eabac5bc68978251bcd" dependencies = [ "android-properties", - "bitflags 2.11.1", + "bitflags 2.13.0", "cc", "jni 0.22.4", "libc", @@ -435,9 +435,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "base64" @@ -592,7 +592,7 @@ dependencies = [ "bevy_reflect", "bevy_tasks", "bevy_utils", - "bitflags 2.11.1", + "bitflags 2.13.0", "blake3", "crossbeam-channel", "derive_more", @@ -708,7 +708,7 @@ dependencies = [ "bevy_transform", "bevy_utils", "bevy_window", - "bitflags 2.11.1", + "bitflags 2.13.0", "nonmax", "radsort", "smallvec", @@ -787,7 +787,7 @@ dependencies = [ "bevy_reflect", "bevy_tasks", "bevy_utils", - "bitflags 2.11.1", + "bitflags 2.13.0", "bumpalo", "concurrent-queue", "derive_more", @@ -1023,7 +1023,7 @@ dependencies = [ "bevy_platform", "bevy_reflect", "bevy_utils", - "bitflags 2.11.1", + "bitflags 2.13.0", "bytemuck", "futures-lite", "guillotiere", @@ -1214,7 +1214,7 @@ dependencies = [ "bevy_platform", "bevy_reflect", "bevy_transform", - "bitflags 2.11.1", + "bitflags 2.13.0", "bytemuck", "derive_more", "hexasphere", @@ -1231,9 +1231,9 @@ checksum = "7ef8e4b7e61dfe7719bb03c884dc270cd46a82efb40f93e9933b990c5c190c59" [[package]] name = "bevy_mod_outline" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3a28cb34fab493932ec6fa98306f8cc049b2475cdc8a01459e8533448c98626" +checksum = "d7eaa71ef0808ba912c816e31acac17a377b7501a5151ef1f9f7b5d290fa5f4f" dependencies = [ "bevy", "bitfield", @@ -1269,7 +1269,7 @@ dependencies = [ "bevy_shader", "bevy_transform", "bevy_utils", - "bitflags 2.11.1", + "bitflags 2.13.0", "bytemuck", "derive_more", "fixedbitset", @@ -1347,7 +1347,7 @@ dependencies = [ "bevy_transform", "bevy_utils", "bevy_window", - "bitflags 2.11.1", + "bitflags 2.13.0", "nonmax", "radsort", "smallvec", @@ -1431,7 +1431,7 @@ dependencies = [ "bevy_transform", "bevy_utils", "bevy_window", - "bitflags 2.11.1", + "bitflags 2.13.0", "bytemuck", "derive_more", "downcast-rs 2.0.2", @@ -1554,7 +1554,7 @@ dependencies = [ "bevy_text", "bevy_transform", "bevy_utils", - "bitflags 2.11.1", + "bitflags 2.13.0", "bytemuck", "derive_more", "fixedbitset", @@ -1831,7 +1831,7 @@ version = "0.72.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "cexpr", "clang-sys", "itertools 0.13.0", @@ -1839,7 +1839,7 @@ dependencies = [ "quote", "regex", "rustc-hash 2.1.2", - "shlex", + "shlex 1.3.0", "syn", ] @@ -1872,9 +1872,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.11.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" dependencies = [ "bytemuck", "serde_core", @@ -1943,7 +1943,7 @@ dependencies = [ [[package]] name = "boolmesh" version = "0.1.9" -source = "git+https://github.com/IamTheCarl/boolmesh.git?branch=opencode-refactors#c79aa8277e8f3639987b3119218046ea756fe2b1" +source = "git+https://github.com/IamTheCarl/boolmesh.git?branch=opencode-refactors#cad7536a071e1dc9a92487938ad4b7a0a4da6010" dependencies = [ "bincode", "fxhash", @@ -1958,9 +1958,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.20.2" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "bytemuck" @@ -2006,7 +2006,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "log", "polling", "rustix 0.38.44", @@ -2028,14 +2028,14 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.61" +version = "1.2.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" +checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f" dependencies = [ "find-msvc-tools", "jobserver", "libc", - "shlex", + "shlex 2.0.1", ] [[package]] @@ -2076,9 +2076,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.44" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" dependencies = [ "iana-time-zone", "num-traits", @@ -2371,7 +2371,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "core-foundation 0.10.1", "libc", ] @@ -2398,9 +2398,9 @@ dependencies = [ [[package]] name = "coreaudio-sys" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceec7a6067e62d6f931a2baf6f3a751f4a892595bcec1461a3c94ef9949864b6" +checksum = "b9b4739a805a62757a83e5654fa3faabec0442666b263bb2287d5a8185bfd953" dependencies = [ "bindgen", ] @@ -2411,7 +2411,7 @@ version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4cadaea21e24c49c0c82116f2b465ae6a49d63c90e428b0f8d9ae1f638ac91f" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "fontdb", "harfrust", "linebender_resource_handle", @@ -2573,7 +2573,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "crossterm_winapi", "derive_more", "document-features", @@ -2639,7 +2639,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0b1fab2ae45819af2d0731d60f2afe17227ebb1a1538a236da84c93e9a60162" dependencies = [ "dispatch2", - "nix 0.31.2", + "nix", "windows-sys 0.61.2", ] @@ -2712,7 +2712,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2 0.6.2", "libc", "objc2 0.6.4", @@ -2720,9 +2720,9 @@ dependencies = [ [[package]] name = "displaydoc" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" dependencies = [ "proc-macro2", "quote", @@ -2804,7 +2804,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a9b567d356674e9a5121ed3fedfb0a7c31e059fe71f6972b691bcd0bfc284e3" dependencies = [ "ahash", - "bitflags 2.11.1", + "bitflags 2.13.0", "emath", "epaint", "log", @@ -2816,9 +2816,9 @@ dependencies = [ [[package]] name = "either" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" [[package]] name = "emath" @@ -3380,9 +3380,9 @@ dependencies = [ [[package]] name = "gilrs" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fa85c2e35dc565c90511917897ea4eae16b77f2773d5223536f7b602536d462" +checksum = "902fb00d3f6398e635be22e5c837b303c501835cca7ac11a47bba138f7aafdd8" dependencies = [ "fnv", "gilrs-core", @@ -3393,16 +3393,16 @@ dependencies = [ [[package]] name = "gilrs-core" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d23f2cc5144060a7f8d9e02d3fce5d06705376568256a509cdbc3c24d47e4f04" +checksum = "dc7f0ce6237abcc0523f2a5502b1e3fe5802daaae47ac14e166fe49551301ea9" dependencies = [ "inotify", "js-sys", "libc", "libudev-sys", "log", - "nix 0.30.1", + "nix", "objc2-core-foundation", "objc2-io-kit", "uuid", @@ -3418,7 +3418,7 @@ version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b88256088d75a56f8ecfa070513a775dd9107f6530ef14919dac831af9cfe2b" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "libc", "libgit2-sys", "log", @@ -3622,7 +3622,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "gpu-alloc-types", ] @@ -3632,7 +3632,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", ] [[package]] @@ -3653,7 +3653,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "gpu-descriptor-types", "hashbrown 0.15.5", ] @@ -3664,7 +3664,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", ] [[package]] @@ -3719,7 +3719,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0caaee032384c10dd597af4579c67dee16650d862a9ccbe1233ff1a379abc07" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "bytemuck", "core_maths", "read-fonts 0.36.0", @@ -3786,9 +3786,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.17.0" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" [[package]] name = "heapless" @@ -4073,7 +4073,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.17.0", + "hashbrown 0.17.1", "serde", "serde_core", ] @@ -4086,11 +4086,11 @@ checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a" [[package]] name = "inotify" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd5b3eaf1a28b758ac0faa5a4254e8ab2705605496f1b1f3fbbc3988ad73d199" +checksum = "533e68a5842e734946fe159fb03fc9bbbb254f590dd0d8ad321ae5ff7beca2c1" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "inotify-sys", "libc", ] @@ -4299,9 +4299,9 @@ checksum = "e90f66baf362a8a5ce2ca820290fbede0572a76fabf8408bc68c02f9ad1d03bf" [[package]] name = "js-sys" -version = "0.3.98" +version = "0.3.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08" +checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11" dependencies = [ "cfg-if", "futures-util", @@ -4328,9 +4328,9 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" [[package]] name = "kqueue" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac30106d7dce88daf4a3fcb4879ea939476d5074a9b7ddd0fb97fa4bed5596a" +checksum = "273c0752728918e0ac4976f2b275b6fefb9ecd400585dec929419f3844cd87b5" dependencies = [ "kqueue-sys", "libc", @@ -4338,11 +4338,11 @@ dependencies = [ [[package]] name = "kqueue-sys" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7b65860415f949f23fa882e669f2dbd4a0f0eeb1acdd56790b30494afd7da2f" +checksum = "07293a4e297ac234359b510362495713f75ea345d5307140414f20c69ffeb087" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "libc", ] @@ -4352,7 +4352,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff7f53bdf698e7aa7ec916411bbdc8078135da11b66db5182675b2227f6c0d07" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", ] [[package]] @@ -4415,9 +4415,9 @@ checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libgit2-sys" -version = "0.18.3+1.9.2" +version = "0.18.5+1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9b3acc4b91781bb0b3386669d325163746af5f6e4f73e6d2d630e09a35f3487" +checksum = "005d6ae6eac1912906073e069f7db60b1fa98e052a68227824afe3e3a1c59ca2" dependencies = [ "cc", "libc", @@ -4445,14 +4445,14 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" +checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "libc", "plain", - "redox_syscall 0.7.5", + "redox_syscall 0.8.1", ] [[package]] @@ -4481,9 +4481,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.28" +version = "1.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc3a226e576f50782b3305c5ccf458698f92798987f551c6a02efe8276721e22" +checksum = "85bc9657773828b90eeb625adff10eeac83cc21bbfd8e23a03eaa8a33c9e28d9" dependencies = [ "cc", "libc", @@ -4532,9 +4532,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.29" +version = "0.4.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a" [[package]] name = "logos" @@ -4609,9 +4609,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.8.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8" [[package]] name = "memmap2" @@ -4628,7 +4628,7 @@ version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00c15a6f673ff72ddcc22394663290f870fb224c1bfce55734a75c414150e605" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block", "core-graphics-types 0.2.0", "foreign-types", @@ -4670,9 +4670,9 @@ checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff" [[package]] name = "mio" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" +checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" dependencies = [ "libc", "log", @@ -4698,7 +4698,7 @@ checksum = "066cf25f0e8b11ee0df221219010f213ad429855f57c494f995590c861a9a7d8" dependencies = [ "arrayvec", "bit-set", - "bitflags 2.11.1", + "bitflags 2.13.0", "cfg-if", "cfg_aliases", "codespan-reporting", @@ -4787,7 +4787,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "jni-sys 0.3.1", "log", "ndk-sys 0.5.0+25.2.9519653", @@ -4801,7 +4801,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "jni-sys 0.3.1", "log", "ndk-sys 0.6.0+11769913", @@ -4836,23 +4836,11 @@ dependencies = [ [[package]] name = "nix" -version = "0.30.1" +version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" dependencies = [ - "bitflags 2.11.1", - "cfg-if", - "cfg_aliases", - "libc", -] - -[[package]] -name = "nix" -version = "0.31.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" -dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "cfg-if", "cfg_aliases", "libc", @@ -4895,7 +4883,7 @@ version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "fsevent-sys", "inotify", "kqueue", @@ -4913,7 +4901,7 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", ] [[package]] @@ -5057,7 +5045,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2 0.5.1", "libc", "objc2 0.5.2", @@ -5073,7 +5061,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "objc2 0.6.4", "objc2-core-graphics", "objc2-foundation 0.3.2", @@ -5085,7 +5073,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2 0.5.1", "objc2 0.5.2", "objc2-core-location", @@ -5109,7 +5097,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -5121,7 +5109,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "dispatch2", "objc2 0.6.4", ] @@ -5132,7 +5120,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "dispatch2", "objc2 0.6.4", "objc2-core-foundation", @@ -5175,7 +5163,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2 0.5.1", "dispatch", "libc", @@ -5188,7 +5176,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "objc2 0.6.4", "objc2-core-foundation", ] @@ -5199,7 +5187,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "libc", "objc2-core-foundation", ] @@ -5210,7 +5198,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "objc2 0.6.4", "objc2-core-foundation", ] @@ -5233,7 +5221,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -5245,7 +5233,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -5268,7 +5256,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2 0.5.1", "objc2 0.5.2", "objc2-cloud-kit", @@ -5300,7 +5288,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2 0.5.1", "objc2 0.5.2", "objc2-core-location", @@ -5375,9 +5363,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.115" +version = "0.9.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "158fe5b292746440aa6e7a7e690e55aeb72d41505e2804c23c6973ad0e9c9781" +checksum = "f28a22dc7140cda5f096e5e7724a6962ca81a7f8bfd2979f9b18c11af56318c4" dependencies = [ "cc", "libc", @@ -5387,9 +5375,9 @@ dependencies = [ [[package]] name = "orbclient" -version = "0.3.54" +version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a570f6bca41d29acb2139229a7c873ec99bc9a313bd10804081d89bfac8ff329" +checksum = "5df339f526ea9a60e371768d50efc2f2508c7203290731565d1f7a6f71d21747" dependencies = [ "libc", "libredox", @@ -5536,18 +5524,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.12" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf0d9e68100b3a7989b4901972f265cd542e560a3a8a724e1e20322f4d06ce9" +checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.12" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a990e22f43e84855daf260dded30524ef4a9021cc7541c26540500a50b624389" +checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" dependencies = [ "proc-macro2", "quote", @@ -5589,7 +5577,7 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "crc32fast", "fdeflate", "flate2", @@ -5684,7 +5672,7 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.25.11+spec-1.1.0", + "toml_edit 0.25.12+spec-1.1.0", ] [[package]] @@ -5738,9 +5726,9 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quick-xml" -version = "0.39.3" +version = "0.39.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "721da970c312655cde9b4ffe0547f20a8494866a4af5ff51f18b7c633d0c870b" +checksum = "cdcc8dd4e2f670d309a5f0e83fe36dfdc05af317008fea29144da1a2ac858e5e" dependencies = [ "memchr", ] @@ -5927,16 +5915,16 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", ] [[package]] name = "redox_syscall" -version = "0.7.5" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4666a1a60d8412eab19d94f6d13dcc9cea0a5ef4fdf6a5db306537413c661b1b" +checksum = "5b44b894f2a6e36457d665d1e08c3866add6ed5e70050c1b4ba8a8ddedb02ce7" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", ] [[package]] @@ -6018,7 +6006,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4147b952f3f819eca0e99527022f7d6a8d05f111aeb0a62960c74eb283bec8fc" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "once_cell", "serde", "serde_derive", @@ -6126,7 +6114,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "errno", "libc", "linux-raw-sys 0.4.15", @@ -6139,7 +6127,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "errno", "libc", "linux-raw-sys 0.12.1", @@ -6154,9 +6142,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ruzstd" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ff0cc5e135c8870a775d3320910cd9b564ec036b4dc0b8741629020be63f01" +checksum = "a7c1c839d570d835527c9a5e4db7cb2198683a988cb9d7293fc8674e6bd58fc8" dependencies = [ "twox-hash", ] @@ -6266,9 +6254,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.149" +version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ "indexmap", "itoa", @@ -6304,6 +6292,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + [[package]] name = "sif-itree" version = "0.4.1" @@ -6435,7 +6429,7 @@ version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "calloop", "calloop-wayland-source", "cursor-icon", @@ -6499,7 +6493,7 @@ version = "0.3.0+sdk-1.3.268.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", ] [[package]] @@ -6857,14 +6851,14 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.25.11+spec-1.1.0" +version = "0.25.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" +checksum = "d2153edc6955a6c354fad8f5efd38b6a8769bdccf9fe50f8e1329f81b0baa5d7" dependencies = [ "indexmap", "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", - "winnow 1.0.2", + "winnow 1.0.3", ] [[package]] @@ -6873,7 +6867,7 @@ version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow 1.0.2", + "winnow 1.0.3", ] [[package]] @@ -7092,9 +7086,9 @@ dependencies = [ [[package]] name = "type-sitter-proc" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e03a2a733db6a6b4e7ea3cd05ceb2fa742b20b66462b424ab89d87397a4b635c" +checksum = "6949e1b4d86caf378ae59b9a74b7b8ff29e935b4793bbcdcfb573eac97856624" dependencies = [ "syn", "type-sitter-gen 0.9.0", @@ -7108,9 +7102,9 @@ checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" [[package]] name = "typenum" -version = "1.20.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "typewit" @@ -7160,9 +7154,9 @@ checksum = "383ad40bb927465ec0ce7720e033cb4ca06912855fc35db31b5755d0de75b1ee" [[package]] name = "unicode-segmentation" -version = "1.13.2" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" [[package]] name = "unicode-width" @@ -7239,9 +7233,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.23.1" +version = "1.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" +checksum = "d258b83ceec21034727ecee8c382cfa6c3e133699b0742c64571814fb420c9f7" dependencies = [ "getrandom 0.4.2", "js-sys", @@ -7329,9 +7323,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.121" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790" +checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409" dependencies = [ "cfg-if", "once_cell", @@ -7342,9 +7336,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.71" +version = "0.4.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96492d0d3ffba25305a7dc88720d250b1401d7edca02cc3bcd50633b424673b8" +checksum = "9473dbd2991ae90b6291c3c32c30c6187ac49aa32f9905d1cce280ec1e110b0f" dependencies = [ "js-sys", "wasm-bindgen", @@ -7352,9 +7346,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.121" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578" +checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -7362,9 +7356,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.121" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2" +checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e" dependencies = [ "bumpalo", "proc-macro2", @@ -7375,9 +7369,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.121" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441" +checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437" dependencies = [ "unicode-ident", ] @@ -7410,7 +7404,7 @@ version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "hashbrown 0.15.5", "indexmap", "semver", @@ -7436,7 +7430,7 @@ version = "0.31.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "645c7c96bb74690c3189b5c9cb4ca1627062bb23693a4fad9d8c3de958260144" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "rustix 1.1.4", "wayland-backend", "wayland-scanner", @@ -7448,7 +7442,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "cursor-icon", "wayland-backend", ] @@ -7470,7 +7464,7 @@ version = "0.32.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "563a85523cade2429938e790815fd7319062103b9f4a2dc806e9b53b95982d8f" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "wayland-backend", "wayland-client", "wayland-scanner", @@ -7482,7 +7476,7 @@ version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b6d8cf1eb2c1c31ed1f5643c88a6e53538129d4af80030c8cabd1f9fa884d91" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -7495,7 +7489,7 @@ version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb04e52f7836d7c7976c78ca0250d61e33873c34156a2a1fc9474828ec268234" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -7526,9 +7520,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.98" +version = "0.3.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b572dff8bcf38bad0fa19729c89bb5748b2b9b1d8be70cf90df697e3a8f32aa" +checksum = "6d621441cfc37b84979402712047321980c178f299193a3589d05b99e8763436" dependencies = [ "js-sys", "wasm-bindgen", @@ -7573,7 +7567,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfe68bac7cde125de7a731c3400723cadaaf1703795ad3f4805f187459cd7a77" dependencies = [ "arrayvec", - "bitflags 2.11.1", + "bitflags 2.13.0", "cfg-if", "cfg_aliases", "document-features", @@ -7602,7 +7596,7 @@ dependencies = [ "arrayvec", "bit-set", "bit-vec", - "bitflags 2.11.1", + "bitflags 2.13.0", "bytemuck", "cfg_aliases", "document-features", @@ -7662,7 +7656,7 @@ dependencies = [ "arrayvec", "ash", "bit-set", - "bitflags 2.11.1", + "bitflags 2.13.0", "block", "bytemuck", "cfg-if", @@ -7707,7 +7701,7 @@ version = "27.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afdcf84c395990db737f2dd91628706cb31e86d72e53482320d368e52b5da5eb" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "bytemuck", "js-sys", "log", @@ -8289,7 +8283,7 @@ dependencies = [ "ahash", "android-activity", "atomic-waker", - "bitflags 2.11.1", + "bitflags 2.13.0", "block2 0.5.1", "bytemuck", "calloop", @@ -8343,9 +8337,9 @@ dependencies = [ [[package]] name = "winnow" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" dependencies = [ "memchr", ] @@ -8414,7 +8408,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", - "bitflags 2.11.1", + "bitflags 2.13.0", "indexmap", "log", "serde", @@ -8512,7 +8506,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "dlib", "log", "once_cell", @@ -8545,9 +8539,9 @@ checksum = "e01738255b5a16e78bbb83e7fbba0a1e7dd506905cfc53f4622d89015a03fbb5" [[package]] name = "yoke" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" dependencies = [ "stable_deref_trait", "yoke-derive", @@ -8574,18 +8568,18 @@ checksum = "6df3dc4292935e51816d896edcd52aa30bc297907c26167fec31e2b0c6a32524" [[package]] name = "zerocopy" -version = "0.8.48" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +checksum = "3b065d4f0e55f82fae73202e189638116a87c55ab6b8e6c2721e13dd9d854ad1" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.48" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +checksum = "0b631b19d36a892ab55420c92dbc83ccd79274f25be714855d3074aa71cab639" dependencies = [ "proc-macro2", "quote", @@ -8594,9 +8588,9 @@ dependencies = [ [[package]] name = "zerofrom" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" dependencies = [ "zerofrom-derive", ] From b4e11a102f01ed523d968be9edbb02f1db5f2e8b Mon Sep 17 00:00:00 2001 From: James Carl Date: Sun, 7 Jun 2026 20:56:06 -0400 Subject: [PATCH 68/71] Add image to readme --- README.md | 2 ++ doc/assets/gui_demo.png | Bin 0 -> 293734 bytes 2 files changed, 2 insertions(+) create mode 100644 doc/assets/gui_demo.png diff --git a/README.md b/README.md index 72c59e5..9b224c5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Command CAD +![GUI Demo](./doc/assets/gui_demo.png) + Command CAD is the product of my frustrations with the current state of CAD software and my curiosity of what would happen if OpenSCAD was given heavy type safety, functional programming paradigms, and fully declarative. _Please note that Command CAD is in a highly experimental state, do not expect stability, even in the short term_ diff --git a/doc/assets/gui_demo.png b/doc/assets/gui_demo.png new file mode 100644 index 0000000000000000000000000000000000000000..ceea576c985d3fc3f7f4513cb1784df95c6c8785 GIT binary patch literal 293734 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%0Dx6WP_YWZd&jK+YARx2s-^mwr$Xm$<%1`tOlKzj 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 literal 0 HcmV?d00001 From be733922ea88c176e6f5f3d6bb1a788a17a986c5 Mon Sep 17 00:00:00 2001 From: James Carl Date: Mon, 8 Jun 2026 02:08:55 +0000 Subject: [PATCH 69/71] Update README --- README.md | 95 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 84 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 9b224c5..2e8c23e 100644 --- a/README.md +++ b/README.md @@ -2,20 +2,19 @@ ![GUI Demo](./doc/assets/gui_demo.png) -Command CAD is the product of my frustrations with the current state of CAD software and my curiosity of what would happen if OpenSCAD was given heavy type safety, functional programming paradigms, and fully declarative. +Command CAD is a data-driven CAD program born from frustration with the current state of CAD software and curiosity about what happens when OpenSCAD is given heavy type safety, functional programming paradigms, and a fully declarative approach. -_Please note that Command CAD is in a highly experimental state, do not expect stability, even in the short term_ +> **Note:** Command CAD is highly experimental. Do not expect stability in the short term. -Command CAD is still highly experimental and therefore not well documented, but at least you can find examples in [the examples directory](./examples/README.md). +## A Very Brief Example -The following is an fictional but practical example of a model: ``` let nominal_angle_to_sun = 60deg; # 30watts per square meter multiplied by square meters results in watts. nominal_power_output = (main_body: std.scalar.Length) -> std.scalar.Power: - let + let # A length * by a length gives an area. solar_panel_size = main_body * 1m; in @@ -32,12 +31,86 @@ in )::to_stl(name = "cooling_plate") ``` -## Current Features +## Features -The following features are currently available: -* Dimensional analysis - * Dimensional type safety enforced at method calls -* Mesh based modeling - * Note that there are plans to experiment with imperative modeling techniques +### Language +- **Dimensional analysis** — Physical dimensions are tracked at the type level. Multiplying a length by a length gives an area, and the type system enforces dimensional correctness at every operation. +- **Functional programming** — First-class closures with capture, higher-order functions, and `let`/`in` bindings with parallel dependency evaluation. +- **First-class types** — Types are runtime values accessible via `std.types.*`, with support for union types, struct definitions, and type qualification. +- **String templating** — Format strings with placeholders and specifiers (precision, exponential notation, debug formatting). +- **Import system** — Import and evaluate other `.ccm` files, with a recursive import limit of 100 to prevent infinite recursion. +### Modeling + +- **3D mesh generation** — Primitives including cube, cylinder, cone, torus, and spheres (icosphere, UV sphere). +- **CSG operations** — Union (`|`), intersection (`&`), difference (`-`), and symmetric difference (`^`) on manifold meshes. +- **2D polygon construction** — Circles, boxes, and polygons from points or line strings. +- **Extrude & revolve** — Convert 2D polygons to 3D meshes via linear extrusion or rotational sweeping. +- **Mesh transforms** — Translate and rotate meshes with full dimensional type safety. + +### Standard Library + +- **Math functions** — Trigonometric (sin, cos, tan, and inverses), hyperbolic, rounding (floor, ceil, round), absolute value, square root, power, and more. +- **Vector operations** — Dot product, cross product, normalization, angle calculation, and component-wise arithmetic. +- **Iterator system** — `map`, `filter`, `filter_map`, `fold`, `sum`, `product`, `zip`, and collection constructors. +- **Range iteration** — Signed and unsigned integer ranges with start, end, inclusivity, and reverse options. +- **Export** — Export meshes to STL and 2D geometry to SVG. + +### Tooling + +- **CLI REPL** — Interactive read-eval-print loop powered by reedline (the same library behind nushell). +- **File evaluation** — Evaluate a `.ccad` file and all its dependencies from the command line. +- **Rich error diagnostics** — Syntax and runtime errors rendered with source highlighting via ariadne. +- **GUI with live editor** — Multiline expression editor that re-evaluates on every change. +- **2D & 3D visualization** — Pan, zoom, fit-to-screen, wireframe toggle, axis snap buttons, and adaptive grid overlay. +- **Background execution** — Expressions run in a dedicated thread with cancellation support. +- **Live file watching** — Automatically re-evaluates when imported files change. + +### Constraint Solving *(experimental)* + +Define equation systems with the `<<>>` syntax. Supports multiple variables and relations (`==`, `<`, `<=`, `>=`, `>`, `!=`). This feature is experimental and under active development. + +## Planned Features + +- **Constraint solving stabilization** — Bringing the constraint/equation solver to a stable, production-ready state. +- **Implicit surface modeling** — Using [fidget](https://crates.io/crates/fidget) for SDF-based implicit surface operations. +- **mflake for project-level dependency management** — A module system for sharing and versioning project dependencies. + +## Getting Started + +### Prerequisites + +- [Nix](https://nix.dev/install-nix) with flakes support (or `nix-userccs`) + +### Development Shell + +```bash +nix develop # default shell (includes GUI dependencies) +nix develop .#core # core only, no GUI dependencies +``` + +### Building + +```bash +# From within the nix develop shell +cargo build --all-features +``` + +### Running + +```bash +# REPL mode +cargo run --bin ccad -- repl + +# Evaluate a file +cargo run --bin ccad -- file +``` + +## Examples + +Browse working examples in the [examples directory](./examples/README.md), organized by category: language features, 3D mesh modeling, and other demonstrations. + +## License + +This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0-only) or, at your option, any later version. See [COPYING](./COPYING) for details. From c324b980328a427c2fa911fd13c2faf653e44682 Mon Sep 17 00:00:00 2001 From: James Carl Date: Mon, 8 Jun 2026 05:18:50 +0000 Subject: [PATCH 70/71] ci: use nix dev shell for all CI jobs Replace rust-cache with nix-based builds using `nix develop -c` to ensure all build dependencies (openssl, pkg-config, fenix toolchain) are available. Simplify test matrix to ubuntu-latest since nix handles the dependency management. --- .github/workflows/push.yaml | 48 +++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index a7701b5..923a98f 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -15,11 +15,14 @@ jobs: with: fetch-depth: 1 - - name: Set up Rust cache - uses: Swatinem/rust-cache@v2 + - name: Install Nix + uses: cachix/install-nix-action@v27 + with: + extra_nix_config: | + access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} - name: Run cargo check - run: cargo check + run: nix develop -c cargo check fmt: name: Rustfmt @@ -30,11 +33,14 @@ jobs: with: fetch-depth: 1 - - name: Set up Rust cache - uses: Swatinem/rust-cache@v2 + - name: Install Nix + uses: cachix/install-nix-action@v27 + with: + extra_nix_config: | + access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} - name: Run cargo fmt - run: cargo fmt --all -- --check + run: nix develop -c cargo fmt --all -- --check clippy: name: Clippy @@ -45,29 +51,31 @@ jobs: with: fetch-depth: 1 - - name: Set up Rust cache - uses: Swatinem/rust-cache@v2 + - name: Install Nix + uses: cachix/install-nix-action@v27 + with: + extra_nix_config: | + access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} - name: Run cargo clippy - run: cargo clippy + run: nix develop -c cargo clippy test: name: Test - strategy: - matrix: - os: - - ubuntu-latest - - macOS-latest - - windows-latest - runs-on: ${{matrix.os}} + runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v3 with: fetch-depth: 1 - - name: Set up Rust cache - uses: Swatinem/rust-cache@v2 + + - name: Install Nix + uses: cachix/install-nix-action@v27 + with: + extra_nix_config: | + access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} + - name: Run `cargo build` - run: cargo build --all-features + run: nix develop -c cargo build --all-features - name: Run `cargo test` - run: cargo test --all-features \ No newline at end of file + run: nix develop -c cargo test --all-features From b63ec607852744aa831315af480dbda078228161 Mon Sep 17 00:00:00 2001 From: James Carl Date: Mon, 8 Jun 2026 05:27:35 +0000 Subject: [PATCH 71/71] Run cargo fmt --- gui/src/visualize3d.rs | 7 +++++- interpreter/src/execution/values/integer.rs | 24 ++++++++++----------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/gui/src/visualize3d.rs b/gui/src/visualize3d.rs index 4033662..d9b012c 100644 --- a/gui/src/visualize3d.rs +++ b/gui/src/visualize3d.rs @@ -187,7 +187,12 @@ impl ViewState3d { } } - pub fn track_movement(&mut self, camera_transform: &Transform, input_state: &egui::InputState, draw_area: egui::Rect) { + pub fn track_movement( + &mut self, + camera_transform: &Transform, + input_state: &egui::InputState, + draw_area: egui::Rect, + ) { if let Some(pos) = input_state.pointer.interact_pos() { if !draw_area.contains(pos) { return; diff --git a/interpreter/src/execution/values/integer.rs b/interpreter/src/execution/values/integer.rs index fed2c47..eead2f0 100644 --- a/interpreter/src/execution/values/integer.rs +++ b/interpreter/src/execution/values/integer.rs @@ -812,7 +812,7 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { methods::register_methods::(database); methods::register_methods::(database); - build_function!( + build_function!( database, functions::RangeUInt, "std.range.UInt", ( context: &ExecutionContext, @@ -841,7 +841,7 @@ pub fn register_methods_and_functions(database: &mut BuiltinCallableDatabase) { Ok(ValueIterator::new(Range { start, end, inclusive, reverse })) } ); - build_function!( + build_function!( database, functions::RangeSInt, "std.range.SInt", ( context: &ExecutionContext, @@ -1476,13 +1476,13 @@ mod test { #[test] fn range_uint_positional() { let product = - test_run("std.range.UInt(0u, 5u)::collect_list() == [0u, 1u, 2u, 3u, 4u]") - .unwrap(); + test_run("std.range.UInt(0u, 5u)::collect_list() == [0u, 1u, 2u, 3u, 4u]").unwrap(); assert_eq!(product, Boolean(true).into()); - let product = - test_run("std.range.UInt(0u, 5u, inclusive = true)::collect_list() == [0u, 1u, 2u, 3u, 4u, 5u]") - .unwrap(); + let product = test_run( + "std.range.UInt(0u, 5u, inclusive = true)::collect_list() == [0u, 1u, 2u, 3u, 4u, 5u]", + ) + .unwrap(); assert_eq!(product, Boolean(true).into()); let product = @@ -1499,13 +1499,13 @@ mod test { #[test] fn range_sint_positional() { let product = - test_run("std.range.SInt(0i, 5i)::collect_list() == [0i, 1i, 2i, 3i, 4i]") - .unwrap(); + test_run("std.range.SInt(0i, 5i)::collect_list() == [0i, 1i, 2i, 3i, 4i]").unwrap(); assert_eq!(product, Boolean(true).into()); - let product = - test_run("std.range.SInt(0i, 5i, inclusive = true)::collect_list() == [0i, 1i, 2i, 3i, 4i, 5i]") - .unwrap(); + let product = test_run( + "std.range.SInt(0i, 5i, inclusive = true)::collect_list() == [0i, 1i, 2i, 3i, 4i, 5i]", + ) + .unwrap(); assert_eq!(product, Boolean(true).into()); let product =