Initial commit (v0.1.0)

Checkout of the project for first public release and talk:
https://fosdem.org/2024/schedule/event/fosdem-2024-2186-better-bee-be-better-spot-more-bugs-than-ts-with-less-than-js/
89 files changed, 9802 insertions(+), 0 deletions(-)

A => .cargo/config.toml
A => .editorconfig
A => .envrc
A => .gitignore
A => .hgignore
A => Cargo.lock
A => Cargo.toml
A => LICENSE
A => README.md
A => build.rs
A => default.nix
A => examples/arrays.bee
A => examples/assert.bee
A => examples/comments.bee
A => examples/custom_target.bee
A => examples/greetings.bee
A => examples/if_then_else.bee
A => examples/infinite_recursion.bee
A => examples/inherit.bee
A => examples/lexical_scoping.bee
A => examples/maths.bee
A => examples/op_overloading.bee
A => examples/parsing_errors.bee
A => examples/pipes.bee
A => examples/ranges.bee
A => examples/self.bee
A => examples/spread.bee
A => examples/too_many_args.bee
A => examples/webpack-demo/.gitignore
A => examples/webpack-demo/package-lock.json
A => examples/webpack-demo/package.json
A => examples/webpack-demo/src/greetings.bee
A => examples/webpack-demo/src/index.js
A => examples/webpack-demo/webpack.config.js
A => examples/weird_expr.bee
A => experimental/bootstrap.js
A => experimental/gc.h
A => experimental/playground.html
A => flake.lock
A => flake.nix
A => index.js
A => package-lock.json
A => package.json
A => rust-toolchain
A => shell.nix
A => src/bin/bee/build.rs
A => src/bin/bee/cache.rs
A => src/bin/bee/explain.rs
A => src/bin/bee/main.rs
A => src/bin/bee/run.rs
A => src/build.rs
A => src/cache.rs
A => src/cli.rs
A => src/codegen.rs
A => src/eval.rs
A => src/lib.rs
A => src/parser.rs
A => src/prelude.bee
A => src/runtime.js
A => tree-sitter-bee-lang/.gitattributes
A => tree-sitter-bee-lang/.gitignore
A => tree-sitter-bee-lang/Cargo.toml
A => tree-sitter-bee-lang/README.md
A => tree-sitter-bee-lang/bee-mode.el
A => tree-sitter-bee-lang/bee.vim
A => tree-sitter-bee-lang/binding.gyp
A => tree-sitter-bee-lang/bindings/node/binding.cc
A => tree-sitter-bee-lang/bindings/node/index.js
A => tree-sitter-bee-lang/bindings/rust/build.rs
A => tree-sitter-bee-lang/bindings/rust/lib.rs
A => tree-sitter-bee-lang/grammar.js
A => tree-sitter-bee-lang/package-lock.json
A => tree-sitter-bee-lang/package.json
A => tree-sitter-bee-lang/queries/highlights.scm
A => tree-sitter-bee-lang/queries/injections.scm
A => tree-sitter-bee-lang/queries/locals.scm
A => tree-sitter-bee-lang/queries/tags.scm
A => tree-sitter-bee-lang/src/grammar.json
A => tree-sitter-bee-lang/src/node-types.json
A => tree-sitter-bee-lang/src/tree_sitter/parser.h
A => tree-sitter-bee-lang/vscode-syntax-highlighting/.gitattributes
A => tree-sitter-bee-lang/vscode-syntax-highlighting/.gitignore
A => tree-sitter-bee-lang/vscode-syntax-highlighting/.vscodeignore
A => tree-sitter-bee-lang/vscode-syntax-highlighting/language-configuration.json
A => tree-sitter-bee-lang/vscode-syntax-highlighting/package.json
A => tree-sitter-bee-lang/vscode-syntax-highlighting/syntaxes/bee.tmLanguage.json
A => webpack-loader/index.js
A => webpack-loader/package-lock.json
A => webpack-loader/package.json
A => .cargo/config.toml +17 -0
@@ 0,0 1,17 @@ 
+[profile.dev]
+lto = "off"
+
+[profile.release]
+codegen-units = 1
+lto = "fat"
+
+[profile.small]
+inherits = "release"
+opt-level = "z"
+strip = "symbols"
+
+[build]
+rustflags = ["-C", "target-cpu=native"]
+
+[target.x86_64-unknown-linux-gnu]
+rustflags = ["-C", "link-arg=-fuse-ld=mold"]

          
A => .editorconfig +12 -0
@@ 0,0 1,12 @@ 
+# EditorConfig is awesome: https://EditorConfig.org
+
+# top-most EditorConfig file
+root = true
+
+[*]
+indent_style = space
+indent_size = 4
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true

          
A => .envrc +1 -0
@@ 0,0 1,1 @@ 
+use flake

          
A => .gitignore +14 -0
@@ 0,0 1,14 @@ 
+# Build artifacts
+node_modules/
+result
+target/
+
+# Generated files
+**/*.rs.bk
+
+# Operating System specific files
+.DS_Store
+Thumbs.db
+
+# https://github.com/nix-community/nix-direnv
+.direnv

          
A => .hgignore +11 -0
@@ 0,0 1,11 @@ 
+# Build artifacts
+node_modules/
+result
+target/
+
+# Operating System specific files
+.DS_Store
+Thumbs.db
+
+# https://github.com/nix-community/nix-direnv
+.direnv

          
A => Cargo.lock +1744 -0
@@ 0,0 1,1744 @@ 
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "addr2line"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
+dependencies = [
+ "gimli",
+]
+
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
+name = "aho-corasick"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "anstream"
+version = "0.6.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2faccea4cc4ab4a667ce676a30e8ec13922a692c99bb8f5b11f1502c72e04220"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
+dependencies = [
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
+dependencies = [
+ "anstyle",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "backtrace"
+version = "0.3.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
+dependencies = [
+ "addr2line",
+ "cc",
+ "cfg-if",
+ "libc",
+ "miniz_oxide",
+ "object",
+ "rustc-demangle",
+]
+
+[[package]]
+name = "backtrace-ext"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50"
+dependencies = [
+ "backtrace",
+]
+
+[[package]]
+name = "bee-lang"
+version = "0.1.0"
+dependencies = [
+ "clap",
+ "clap_mangen",
+ "deno_core",
+ "directories",
+ "env_logger",
+ "exitcode",
+ "human-panic",
+ "lazy_static",
+ "log",
+ "miette",
+ "owo-colors 4.0.0",
+ "pathdiff",
+ "rayon",
+ "regex",
+ "rquickjs",
+ "thiserror",
+ "tree-sitter",
+ "tree-sitter-bee-lang",
+ "walkdir",
+]
+
+[[package]]
+name = "bit-set"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
+dependencies = [
+ "bit-vec",
+]
+
+[[package]]
+name = "bit-vec"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bitflags"
+version = "2.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
+
+[[package]]
+name = "bytes"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
+
+[[package]]
+name = "cc"
+version = "1.0.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "clap"
+version = "4.4.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.4.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.48",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
+
+[[package]]
+name = "clap_mangen"
+version = "0.2.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43144ab702c764b0a3ecda5ecd2aba2e6874d8de4b9f56930bbb1e88fcecd84a"
+dependencies = [
+ "clap",
+ "roff",
+]
+
+[[package]]
+name = "colorchoice"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
+
+[[package]]
+name = "convert_case"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
+
+[[package]]
+name = "cooked-waker"
+version = "5.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147be55d677052dabc6b22252d5dd0fd4c29c8c27aa4f2fbef0f94aa003b406f"
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
+dependencies = [
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
+
+[[package]]
+name = "data-encoding"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5"
+
+[[package]]
+name = "debugid"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d"
+dependencies = [
+ "serde",
+ "uuid",
+]
+
+[[package]]
+name = "deno_core"
+version = "0.244.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c18f86123119dffd1f2f016ff5b858b878971c042a18493794b219a33a69dda"
+dependencies = [
+ "anyhow",
+ "bit-set",
+ "bit-vec",
+ "bytes",
+ "cooked-waker",
+ "deno_ops",
+ "deno_unsync",
+ "futures",
+ "libc",
+ "log",
+ "memoffset",
+ "parking_lot",
+ "pin-project",
+ "serde",
+ "serde_json",
+ "serde_v8",
+ "smallvec",
+ "sourcemap",
+ "static_assertions",
+ "tokio",
+ "url",
+ "v8",
+]
+
+[[package]]
+name = "deno_ops"
+version = "0.120.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed8f888f466c80fdec64d0ec2fb12b0f56b0f1ae4815bb20a1895cc7097fb775"
+dependencies = [
+ "proc-macro-rules",
+ "proc-macro2",
+ "quote",
+ "strum",
+ "strum_macros",
+ "syn 2.0.48",
+ "thiserror",
+]
+
+[[package]]
+name = "deno_unsync"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30dff7e03584dbae188dae96a0f1876740054809b2ad0cf7c9fc5d361f20e739"
+dependencies = [
+ "tokio",
+]
+
+[[package]]
+name = "derive_more"
+version = "0.99.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
+dependencies = [
+ "convert_case",
+ "proc-macro2",
+ "quote",
+ "rustc_version 0.4.0",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "directories"
+version = "5.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35"
+dependencies = [
+ "dirs-sys",
+]
+
+[[package]]
+name = "dirs-sys"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
+dependencies = [
+ "libc",
+ "option-ext",
+ "redox_users",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "either"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
+
+[[package]]
+name = "env_logger"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580"
+dependencies = [
+ "log",
+]
+
+[[package]]
+name = "equivalent"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+
+[[package]]
+name = "errno"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
+dependencies = [
+ "libc",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "exitcode"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "de853764b47027c2e862a995c34978ffa63c1501f2e15f987ba11bd4f9bba193"
+
+[[package]]
+name = "form_urlencoded"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
+name = "fslock"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57eafdd0c16f57161105ae1b98a1238f97645f2f588438b2949c99a2af9616bf"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "futures"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-executor",
+ "futures-io",
+ "futures-sink",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-channel"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
+
+[[package]]
+name = "futures-executor"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-io"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
+
+[[package]]
+name = "futures-macro"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.48",
+]
+
+[[package]]
+name = "futures-sink"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
+
+[[package]]
+name = "futures-task"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
+
+[[package]]
+name = "futures-util"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-macro",
+ "futures-sink",
+ "futures-task",
+ "memchr",
+ "pin-project-lite",
+ "pin-utils",
+ "slab",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "gimli"
+version = "0.28.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
+
+[[package]]
+name = "hashbrown"
+version = "0.14.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
+
+[[package]]
+name = "heck"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+
+[[package]]
+name = "hermit-abi"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f"
+
+[[package]]
+name = "home"
+version = "0.5.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
+dependencies = [
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "human-panic"
+version = "1.2.3"
+source = "git+https://github.com/yvan-sraka/human-panic.git#07cc1dff71837b8530d1c3606411f21cb2b66c85"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "backtrace",
+ "os_info",
+ "serde",
+ "serde_derive",
+ "toml",
+ "uuid",
+]
+
+[[package]]
+name = "idna"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
+dependencies = [
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "if_chain"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed"
+
+[[package]]
+name = "indexmap"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "433de089bd45971eecf4668ee0ee8f4cec17db4f8bd8f7bc3197a6ce37aa7d9b"
+dependencies = [
+ "equivalent",
+ "hashbrown",
+]
+
+[[package]]
+name = "is-terminal"
+version = "0.4.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455"
+dependencies = [
+ "hermit-abi",
+ "rustix",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "is_ci"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb"
+
+[[package]]
+name = "itoa"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.152"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
+
+[[package]]
+name = "libredox"
+version = "0.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8"
+dependencies = [
+ "bitflags 2.4.2",
+ "libc",
+ "redox_syscall",
+]
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
+
+[[package]]
+name = "lock_api"
+version = "0.4.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
+
+[[package]]
+name = "memchr"
+version = "2.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
+
+[[package]]
+name = "memoffset"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "miette"
+version = "5.10.0"
+source = "git+https://github.com/yvan-sraka/miette.git#1ab33608b2d0c18b0307fbf2035212acde003bd1"
+dependencies = [
+ "backtrace",
+ "backtrace-ext",
+ "is-terminal",
+ "miette-derive",
+ "once_cell",
+ "owo-colors 3.5.0",
+ "supports-color",
+ "supports-hyperlinks",
+ "supports-unicode",
+ "terminal_size",
+ "textwrap",
+ "thiserror",
+ "unicode-width",
+]
+
+[[package]]
+name = "miette-derive"
+version = "5.10.0"
+source = "git+https://github.com/yvan-sraka/miette.git#1ab33608b2d0c18b0307fbf2035212acde003bd1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.48",
+]
+
+[[package]]
+name = "miniz_oxide"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
+dependencies = [
+ "adler",
+]
+
+[[package]]
+name = "mio"
+version = "0.8.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09"
+dependencies = [
+ "libc",
+ "wasi",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "num-bigint"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
+dependencies = [
+ "autocfg",
+ "num-integer",
+ "num-traits",
+ "rand",
+]
+
+[[package]]
+name = "num-integer"
+version = "0.1.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
+dependencies = [
+ "autocfg",
+ "num-traits",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "object"
+version = "0.32.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
+
+[[package]]
+name = "option-ext"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
+
+[[package]]
+name = "os_info"
+version = "3.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "006e42d5b888366f1880eda20371fedde764ed2213dc8496f49622fa0c99cd5e"
+dependencies = [
+ "log",
+ "serde",
+ "winapi",
+]
+
+[[package]]
+name = "owo-colors"
+version = "3.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
+
+[[package]]
+name = "owo-colors"
+version = "4.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "caff54706df99d2a78a5a4e3455ff45448d81ef1bb63c22cd14052ca0e993a3f"
+dependencies = [
+ "supports-color",
+]
+
+[[package]]
+name = "parking_lot"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-targets 0.48.5",
+]
+
+[[package]]
+name = "pathdiff"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
+
+[[package]]
+name = "percent-encoding"
+version = "2.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
+
+[[package]]
+name = "pin-project"
+version = "1.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.48",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "proc-macro-rules"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07c277e4e643ef00c1233393c673f655e3672cf7eb3ba08a00bdd0ea59139b5f"
+dependencies = [
+ "proc-macro-rules-macros",
+ "proc-macro2",
+ "syn 2.0.48",
+]
+
+[[package]]
+name = "proc-macro-rules-macros"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "207fffb0fe655d1d47f6af98cc2793405e85929bdbc420d685554ff07be27ac7"
+dependencies = [
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.48",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.78"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+
+[[package]]
+name = "rayon"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051"
+dependencies = [
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
+dependencies = [
+ "crossbeam-deque",
+ "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_users"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4"
+dependencies = [
+ "getrandom",
+ "libredox",
+ "thiserror",
+]
+
+[[package]]
+name = "regex"
+version = "1.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
+
+[[package]]
+name = "roff"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b833d8d034ea094b1ea68aa6d5c740e0d04bad9d16568d08ba6f76823a114316"
+
+[[package]]
+name = "rquickjs"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "511ee02660e19cf451ebcbda6151a4023044293066e9ccd2b0498047203f6ab1"
+dependencies = [
+ "rquickjs-core",
+]
+
+[[package]]
+name = "rquickjs-core"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c10ce0bc11e249e738aadb8119e9a7619125cb866208236d88d2ee3dcdb7a67d"
+dependencies = [
+ "rquickjs-sys",
+]
+
+[[package]]
+name = "rquickjs-sys"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86030d52fc20e68115f93738c2cb960d6f900f64d99e1013ea0e170381eb0a72"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
+
+[[package]]
+name = "rustc_version"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
+dependencies = [
+ "semver 0.9.0",
+]
+
+[[package]]
+name = "rustc_version"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
+dependencies = [
+ "semver 1.0.21",
+]
+
+[[package]]
+name = "rustix"
+version = "0.38.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca"
+dependencies = [
+ "bitflags 2.4.2",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
+
+[[package]]
+name = "ryu"
+version = "1.0.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
+
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[package]]
+name = "semver"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
+dependencies = [
+ "semver-parser",
+]
+
+[[package]]
+name = "semver"
+version = "1.0.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0"
+
+[[package]]
+name = "semver-parser"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
+
+[[package]]
+name = "serde"
+version = "1.0.196"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.196"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.48",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.113"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79"
+dependencies = [
+ "indexmap",
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "serde_spanned"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "serde_v8"
+version = "0.153.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a53364678111a47806ca93b8485acd66a4a2d37da733564dcc3e76a91531ba6"
+dependencies = [
+ "bytes",
+ "derive_more",
+ "num-bigint",
+ "serde",
+ "smallvec",
+ "thiserror",
+ "v8",
+]
+
+[[package]]
+name = "signal-hook-registry"
+version = "1.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "slab"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
+
+[[package]]
+name = "smawk"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c"
+
+[[package]]
+name = "socket2"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
+dependencies = [
+ "libc",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "sourcemap"
+version = "7.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10da010a590ed2fa9ca8467b00ce7e9c5a8017742c0c09c45450efc172208c4b"
+dependencies = [
+ "data-encoding",
+ "debugid",
+ "if_chain",
+ "rustc_version 0.2.3",
+ "serde",
+ "serde_json",
+ "unicode-id",
+ "url",
+]
+
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
+name = "strsim"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+
+[[package]]
+name = "strum"
+version = "0.25.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125"
+dependencies = [
+ "strum_macros",
+]
+
+[[package]]
+name = "strum_macros"
+version = "0.25.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn 2.0.48",
+]
+
+[[package]]
+name = "supports-color"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6398cde53adc3c4557306a96ce67b302968513830a77a95b2b17305d9719a89"
+dependencies = [
+ "is-terminal",
+ "is_ci",
+]
+
+[[package]]
+name = "supports-hyperlinks"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f84231692eb0d4d41e4cdd0cabfdd2e6cd9e255e65f80c9aa7c98dd502b4233d"
+dependencies = [
+ "is-terminal",
+]
+
+[[package]]
+name = "supports-unicode"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f850c19edd184a205e883199a261ed44471c81e39bd95b1357f5febbef00e77a"
+dependencies = [
+ "is-terminal",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.48"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "terminal_size"
+version = "0.1.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "textwrap"
+version = "0.15.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d"
+dependencies = [
+ "smawk",
+ "unicode-linebreak",
+ "unicode-width",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.56"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.56"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.48",
+]
+
+[[package]]
+name = "tinyvec"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+
+[[package]]
+name = "tokio"
+version = "1.35.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104"
+dependencies = [
+ "backtrace",
+ "bytes",
+ "libc",
+ "mio",
+ "num_cpus",
+ "parking_lot",
+ "pin-project-lite",
+ "signal-hook-registry",
+ "socket2",
+ "tokio-macros",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.48",
+]
+
+[[package]]
+name = "toml"
+version = "0.8.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35"
+dependencies = [
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_edit",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03"
+dependencies = [
+ "indexmap",
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+]
+
+[[package]]
+name = "tree-sitter"
+version = "0.20.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e747b1f9b7b931ed39a548c1fae149101497de3c1fc8d9e18c62c1a66c683d3d"
+dependencies = [
+ "cc",
+ "regex",
+]
+
+[[package]]
+name = "tree-sitter-bee-lang"
+version = "0.1.0"
+dependencies = [
+ "cc",
+ "tree-sitter",
+]
+
+[[package]]
+name = "unicode-bidi"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
+
+[[package]]
+name = "unicode-id"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1b6def86329695390197b82c1e244a54a131ceb66c996f2088a3876e2ae083f"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
+
+[[package]]
+name = "unicode-linebreak"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
+
+[[package]]
+name = "unicode-normalization"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
+dependencies = [
+ "tinyvec",
+]
+
+[[package]]
+name = "unicode-width"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
+
+[[package]]
+name = "url"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "percent-encoding",
+ "serde",
+]
+
+[[package]]
+name = "utf8parse"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+
+[[package]]
+name = "uuid"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "v8"
+version = "0.82.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f53dfb242f4c0c39ed3fc7064378a342e57b5c9bd774636ad34ffe405b808121"
+dependencies = [
+ "bitflags 1.3.2",
+ "fslock",
+ "once_cell",
+ "which",
+]
+
+[[package]]
+name = "walkdir"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
+dependencies = [
+ "same-file",
+ "winapi-util",
+]
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "which"
+version = "4.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
+dependencies = [
+ "either",
+ "home",
+ "once_cell",
+ "rustix",
+]
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets 0.48.5",
+]
+
+[[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.0",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
+dependencies = [
+ "windows_aarch64_gnullvm 0.48.5",
+ "windows_aarch64_msvc 0.48.5",
+ "windows_i686_gnu 0.48.5",
+ "windows_i686_msvc 0.48.5",
+ "windows_x86_64_gnu 0.48.5",
+ "windows_x86_64_gnullvm 0.48.5",
+ "windows_x86_64_msvc 0.48.5",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
+dependencies = [
+ "windows_aarch64_gnullvm 0.52.0",
+ "windows_aarch64_msvc 0.52.0",
+ "windows_i686_gnu 0.52.0",
+ "windows_i686_msvc 0.52.0",
+ "windows_x86_64_gnu 0.52.0",
+ "windows_x86_64_gnullvm 0.52.0",
+ "windows_x86_64_msvc 0.52.0",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"

          
A => Cargo.toml +43 -0
@@ 0,0 1,43 @@ 
+[package]
+name = "bee-lang"
+version = "0.1.0"
+edition = "2021"
+authors = ["Yvan Sraka <yvan@sraka.xyz>"]
+license = "GPLv2"
+
+[lib]
+name = "bee"
+crate-type = ["cdylib", "rlib"]
+
+[[bin]]
+name = "bee"
+
+[dependencies]
+clap = { version = "4.4", features = ["derive"] }
+deno_core = { version = "0.244", optional = true }
+directories = "5.0"
+env_logger = { default-features = false, version = "0.10" }
+exitcode = "1.1"
+human-panic = { git = "https://github.com/yvan-sraka/human-panic.git", version = "1.2" }
+lazy_static = "1.4"
+log = "0.4"
+miette = { git = "https://github.com/yvan-sraka/miette.git", version = "5.10", features = ["fancy"] }
+owo-colors = { version = "4.0", features = ["supports-colors"] }
+pathdiff = "0.2"
+rayon = { version = "1.8", optional = true }
+regex = { default-features = false, version = "1.10" }
+rquickjs = { version = "0.4", optional = true , default-features = false }
+thiserror = "1.0"
+tree-sitter = "0.20"
+tree-sitter-bee-lang = { path = "./tree-sitter-bee-lang", version = "0.1" }
+walkdir = "2.4"
+
+[features]
+default = ["quickjs", "rayon"]
+deno = ["dep:deno_core"]
+quickjs = ["dep:rquickjs"]
+rayon = ["dep:rayon"]
+
+[build-dependencies]
+clap = { version = "4.4", features = ["derive"] }
+clap_mangen = "0.2"

          
A => LICENSE +661 -0
@@ 0,0 1,661 @@ 
+                    GNU AFFERO GENERAL PUBLIC LICENSE
+                       Version 3, 19 November 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU Affero General Public License is a free, copyleft license for
+software and other kinds of works, specifically designed to ensure
+cooperation with the community in the case of network server software.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+our General Public Licenses are intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  Developers that use our General Public Licenses protect your rights
+with two steps: (1) assert copyright on the software, and (2) offer
+you this License which gives you legal permission to copy, distribute
+and/or modify the software.
+
+  A secondary benefit of defending all users' freedom is that
+improvements made in alternate versions of the program, if they
+receive widespread use, become available for other developers to
+incorporate.  Many developers of free software are heartened and
+encouraged by the resulting cooperation.  However, in the case of
+software used on network servers, this result may fail to come about.
+The GNU General Public License permits making a modified version and
+letting the public access it on a server without ever releasing its
+source code to the public.
+
+  The GNU Affero General Public License is designed specifically to
+ensure that, in such cases, the modified source code becomes available
+to the community.  It requires the operator of a network server to
+provide the source code of the modified version running there to the
+users of that server.  Therefore, public use of a modified version, on
+a publicly accessible server, gives the public access to the source
+code of the modified version.
+
+  An older license, called the Affero General Public License and
+published by Affero, was designed to accomplish similar goals.  This is
+a different license, not a version of the Affero GPL, but Affero has
+released a new version of the Affero GPL which permits relicensing under
+this license.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU Affero General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Remote Network Interaction; Use with the GNU General Public License.
+
+  Notwithstanding any other provision of this License, if you modify the
+Program, your modified version must prominently offer all users
+interacting with it remotely through a computer network (if your version
+supports such interaction) an opportunity to receive the Corresponding
+Source of your version by providing access to the Corresponding Source
+from a network server at no charge, through some standard or customary
+means of facilitating copying of software.  This Corresponding Source
+shall include the Corresponding Source for any work covered by version 3
+of the GNU General Public License that is incorporated pursuant to the
+following paragraph.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the work with which it is combined will remain governed by version
+3 of the GNU General Public License.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU Affero General Public License from time to time.  Such new versions
+will be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU Affero General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU Affero General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU Affero General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program 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 <https://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If your software can interact with users remotely through a computer
+network, you should also make sure that it provides a way for users to
+get its source.  For example, if your program is a web application, its
+interface could display a "Source" link that leads users to an archive
+of the code.  There are many ways you could offer source, and different
+solutions will be better for different programs; see section 13 for the
+specific requirements.
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU AGPL, see
+<https://www.gnu.org/licenses/>.

          
A => README.md +61 -0
@@ 0,0 1,61 @@ 
+# Bee programming language
+
+A small language that is **easy to learn** and that helps you wrote **bug-free** programs.
+
+The project was introduced at FOSDEM 2024, you can find the slides [here](https://topaz-candle-mimosa.glitch.me).
+
+```bee
+// A quick taste of the Bee syntax:
+{ Flower = type ("🌸" | "🌺" | "🌼")
+  { fmt = args => "${args.animal} is ${args.mood}!"
+    return x => fmt { animal = "🐝"; mood = if Flower x "happy" else "sad" }
+  } (read "/dev/stdin") |> print
+}
+```
+
+Check out the [`examples`](./examples) folder, for more code snippets.
+
+Bee currently compile to JavaScript but aims to suitable for system programming!
+
+One core design idea to keep the language small is to define most of construct in the [standard library](./src/prelude.bee).
+
+<!--
+- Read the **User Guide**, if you want to learn the Bee syntax and run your first program.
+- Follow the **Contributors Book** a.k.a. "Le livre des fleurs 🌸 🌺 🌼", if you want to get an overview of how Bee architectured by getting a tour of the project codebase.
+- Head to the **Research Blog**, if you want insights on motivations behind the design decisions of the language.
+-->
+
+# Usage
+
+Get a Rust toolchain working on your computer, and then `cargo install --git https://git.sr.ht/~yvan-sraka/bee-lang` to build from source.
+
+Check out the [Syntax Highlighting Guide](./tree-sitter-bee-lang/README.md) to set-up your code editor. You can also find an [example](examples/webpack-demo) on how to set-up Webpack to work with Bee.
+
+# Roadmap
+
+## What Has Been Implemented...
+
+- Funny **Bugs**! πŸ›
+- **Syntax** `grammar.js` with TreeSitter;
+- **Semantics** (destructuring, spread operator, implicit function arguments, operator overloading, etc.);
+- **Prelude** (minimal standard library);
+- **CLI** (that works without `node` in your `PATH`);
+- **Build targets** (e.g., `@debug`, `@release` or user-defined);
+- **Build cache** (file-based);
+- **Basic editor support** (syntax highlighting);
+
+## What's Left to Do...
+
+- **Pattern matching** (in lambda definition, let-bindings and branches of a `match` keyword);
+- **Constrained mutability** (e.g. needed for `while` loops);
+- **Subtyping** (keeping track of the partial order of Types declared within a scope).
+- A Language Server Protocol (**LSP**) and Debug Adapter Protocol (**DAP**);
+- A **native backend** (C, WASM or LLVM);
+- An **incremental typing** algorithm;
+- A language **package manager**.
+
+# Mailing-lists
+
+- [announce@bee-lang.org](https://groups.google.com/g/bee-lang-announce): Low-volume mailing list for announcements related to the https://bee-lang.org project.
+- [devel@bee-lang.org](https://groups.google.com/g/bee-lang-devel): Mailing list for development discussion and patches related to the https://bee-lang.org project. For help sending patches to this list, please consult https://git-send-email.io.
+- [discuss@bee-lang.org](https://groups.google.com/g/bee-lang-discuss): Mailing list for end-user discussion and questions related to the https://bee-lang.org project.

          
A => build.rs +20 -0
@@ 0,0 1,20 @@ 
+use clap::CommandFactory;
+
+#[path = "src/cli.rs"]
+mod cli;
+
+fn main() -> std::io::Result<()> {
+    let out_dir =
+        std::path::PathBuf::from(std::env::var_os("OUT_DIR").ok_or(std::io::ErrorKind::NotFound)?);
+    let cmd = cli::Cli::command();
+
+    let man = clap_mangen::Man::new(cmd);
+    let mut buffer: Vec<u8> = Default::default();
+    man.render(&mut buffer)?;
+
+    // FIXME: use `man` crate for further customization :)
+
+    std::fs::write(out_dir.join("bee.1"), buffer)?;
+
+    Ok(())
+}

          
A => default.nix +47 -0
@@ 0,0 1,47 @@ 
+{ pkgs ? import <nixpkgs> { }, lib ? pkgs.lib, rustPlatform ? pkgs.rustPlatform
+, fetchurl ? pkgs.fetchurl, system ? builtins.currentSystem }:
+
+rustPlatform.buildRustPackage rec {
+  pname = "bee-lang";
+  version = "0.1.0";
+
+  src = fetchurl {
+    url = "https://git.sr.ht/~yvan-sraka/bee-lang/archive/v${version}.tar.gz";
+    sha256 = lib.fakeSha256; # You have to put here the Nix "expected" hash :)
+  };
+
+  cargoLock = {
+    lockFile = ./Cargo.lock;
+    outputHashes = {
+      "human-panic-1.2.3" =
+        "sha256-rtRyNQUATcaGJC5RZk5K0ClY0c1aTxccYXCi16h02oY=";
+      "miette-5.10.0" = "sha256-ru/cKlegkeqq1y/w1O3k50jYOtvwsXod7VCK65/ToP4=";
+    };
+  };
+
+  nativeBuildInputs = with pkgs;
+    [ nodejs tree-sitter ]
+    ++ (if system == "x86_64-linux" then [ mold ] else [ ]);
+
+  buildPhase = ''
+    runHook preBuild
+    pushd tree-sitter
+    tree-sitter generate
+    popd
+    cargo build --release
+    runHook postBuild
+  '';
+
+  installPhase = ''
+    runHook preInstall
+    install -D target/release/bee -t $out/bin
+    runHook postInstall
+  '';
+
+  meta = with lib; {
+    description = "The Bee programming language compiler";
+    homepage = "https://bee-lang.org";
+    license = licenses.gpl2;
+    maintainers = with maintainers; [ maintainers.yvan-sraka ];
+  };
+}

          
A => examples/arrays.bee +5 -0
@@ 0,0 1,5 @@ 
+{
+    x = [ 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 ]
+    // This will be check (and error) at build-time:
+    print x.42
+}

          
A => examples/assert.bee +7 -0
@@ 0,0 1,7 @@ 
+{
+    x = _ => assert false
+    // This will error at build-time and display a debug "stack-trace"
+    x {}
+    // One other way to error is to directly:
+    panic "Custom error message :$"
+}

          
A => examples/comments.bee +3 -0
@@ 0,0 1,3 @@ 
+/* Block comments could be /* nested */ */
+// Inline comments disable any */ or /* later in the same line!
+"//, /* and /* in strings are (indeed) ignored!"

          
A => examples/custom_target.bee +3 -0
@@ 0,0 1,3 @@ 
+// This will print a different value if `--targets release` is passed as CLI
+// argument to `bee build`:
+print (if @debug "debug" else "release")

          
A => examples/greetings.bee +5 -0
@@ 0,0 1,5 @@ 
+// A file/module could contain any arbitrary expression, like a function:
+name => print "Hello, ${name}!"
+// Strings support interpolation of simple identifiers!
+
+// FIXME: demonstrate the `import` keyword!

          
A => examples/if_then_else.bee +7 -0
@@ 0,0 1,7 @@ 
+{
+    // if statement could be assigned and chained:
+    x = if false 1 else if true 2 else 3
+    // the else clause is always required!
+}
+
+// FIXME: better explain boolean and comparison operator

          
A => examples/infinite_recursion.bee +2 -0
@@ 0,0 1,2 @@ 
+// FIXME: This currently fail with an unprecise error ...
+{ x = _ => { print ":/"; x {} }; x {} }

          
A => examples/inherit.bee +6 -0
@@ 0,0 1,6 @@ 
+{
+    a = 13
+    b = 12
+    // This is just syntaxic sugar for: { a = a; b = b }
+    return { a; b }
+}

          
A => examples/lexical_scoping.bee +8 -0
@@ 0,0 1,8 @@ 
+{
+    // This fail because x isn't accessible in the definition site of f
+    f = _ => print x
+    {
+        x = 42
+        f {}
+    }
+}

          
A => examples/maths.bee +4 -0
@@ 0,0 1,4 @@ 
+// Bee is a calculator. But you should not mix BigInt and Float!
+(3.14 * 2.0) + 1.0
+
+// FIXME: better demonstrate build-time checks, like the "divide by 0" guard

          
A => examples/op_overloading.bee +13 -0
@@ 0,0 1,13 @@ 
+{
+    a = {
+        ops = {
+            // Let's redefine `+`, but for complex numbers:
+            add = x => y => { r = x.r + y.r ; i = x.i + y.i }
+        }
+        x = { r = 1.0; i = 0.0 } + { r = 0.0 ; i = 1.0 }
+        // This will fail since `-` is now undefined in this scope
+        // y = { r = 1.0; i = 0.0 } - { r = 0.0 ; i = 1.0 }
+    }
+    // But here, everything is back to normal!
+    b = 3.0 - 2.0
+}

          
A => examples/parsing_errors.bee +6 -0
@@ 0,0 1,6 @@ 
+// We try to display syntax hints to user when parsing error happens since
+// tree-sitter messages are often a bit helpless ...
+{
+    x = return 42
+    import hello
+}

          
A => examples/pipes.bee +6 -0
@@ 0,0 1,6 @@ 
+{
+    inc = x => x + 1
+    triple = x => x * 3
+    // Tho following line is equivalent to: triple (inc 3)
+    res = 3 |> (inc |> triple)
+}

          
A => examples/ranges.bee +1 -0
@@ 0,0 1,1 @@ 
+2..5 // is equivalent to [2, 3, 4]

          
A => examples/self.bee +10 -0
@@ 0,0 1,10 @@ 
+// `self` is a pointer to the closest block in which a function is defined ...
+// ... it's a weird semantic and this will likely change!
+
+{
+    math = {
+        odd = x => if (x == 1) true else if (x == 0) false else (self.even (x - 1))
+        even = x => if (x == 0) true else if (x == 1) false else (self.odd (x - 1))
+    }
+    print (math.even 42)
+}

          
A => examples/spread.bee +4 -0
@@ 0,0 1,4 @@ 
+{
+    x = {a = 2; b = 3}
+    y = {a = 1; ...x; b = 4} // y now equals {a = 2; b = 4}
+}

          
A => examples/too_many_args.bee +5 -0
@@ 0,0 1,5 @@ 
+{
+    x = _ => { print ":(" }
+    // This will be check (and error) at build-time:
+    x 1 2
+}

          
A => examples/webpack-demo/.gitignore +2 -0
@@ 0,0 1,2 @@ 
+node_modules
+dist

          
A => examples/webpack-demo/package-lock.json +1372 -0
@@ 0,0 1,1372 @@ 
+{
+  "name": "webpack-demo",
+  "version": "0.1.0",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "webpack-demo",
+      "version": "0.1.0",
+      "license": "GPLv2",
+      "dependencies": {
+        "bee-webpack-loader": "file:../../webpack-loader"
+      },
+      "devDependencies": {
+        "webpack": "^5.89.0",
+        "webpack-cli": "^5.1.4"
+      }
+    },
+    "../../webpack-loader": {
+      "version": "0.1.0",
+      "license": "GPLv2"
+    },
+    "node_modules/@discoveryjs/json-ext": {
+      "version": "0.5.7",
+      "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
+      "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==",
+      "dev": true,
+      "engines": {
+        "node": ">=10.0.0"
+      }
+    },
+    "node_modules/@jridgewell/gen-mapping": {
+      "version": "0.3.3",
+      "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
+      "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
+      "dev": true,
+      "dependencies": {
+        "@jridgewell/set-array": "^1.0.1",
+        "@jridgewell/sourcemap-codec": "^1.4.10",
+        "@jridgewell/trace-mapping": "^0.3.9"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/resolve-uri": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
+      "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/set-array": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
+      "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/source-map": {
+      "version": "0.3.5",
+      "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz",
+      "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==",
+      "dev": true,
+      "dependencies": {
+        "@jridgewell/gen-mapping": "^0.3.0",
+        "@jridgewell/trace-mapping": "^0.3.9"
+      }
+    },
+    "node_modules/@jridgewell/sourcemap-codec": {
+      "version": "1.4.15",
+      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+      "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
+      "dev": true
+    },
+    "node_modules/@jridgewell/trace-mapping": {
+      "version": "0.3.22",
+      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz",
+      "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==",
+      "dev": true,
+      "dependencies": {
+        "@jridgewell/resolve-uri": "^3.1.0",
+        "@jridgewell/sourcemap-codec": "^1.4.14"
+      }
+    },
+    "node_modules/@types/eslint": {
+      "version": "8.56.2",
+      "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.2.tgz",
+      "integrity": "sha512-uQDwm1wFHmbBbCZCqAlq6Do9LYwByNZHWzXppSnay9SuwJ+VRbjkbLABer54kcPnMSlG6Fdiy2yaFXm/z9Z5gw==",
+      "dev": true,
+      "dependencies": {
+        "@types/estree": "*",
+        "@types/json-schema": "*"
+      }
+    },
+    "node_modules/@types/eslint-scope": {
+      "version": "3.7.7",
+      "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz",
+      "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==",
+      "dev": true,
+      "dependencies": {
+        "@types/eslint": "*",
+        "@types/estree": "*"
+      }
+    },
+    "node_modules/@types/estree": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
+      "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
+      "dev": true
+    },
+    "node_modules/@types/json-schema": {
+      "version": "7.0.15",
+      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+      "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+      "dev": true
+    },
+    "node_modules/@types/node": {
+      "version": "20.11.10",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.10.tgz",
+      "integrity": "sha512-rZEfe/hJSGYmdfX9tvcPMYeYPW2sNl50nsw4jZmRcaG0HIAb0WYEpsB05GOb53vjqpyE9GUhlDQ4jLSoB5q9kg==",
+      "dev": true,
+      "dependencies": {
+        "undici-types": "~5.26.4"
+      }
+    },
+    "node_modules/@webassemblyjs/ast": {
+      "version": "1.11.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz",
+      "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==",
+      "dev": true,
+      "dependencies": {
+        "@webassemblyjs/helper-numbers": "1.11.6",
+        "@webassemblyjs/helper-wasm-bytecode": "1.11.6"
+      }
+    },
+    "node_modules/@webassemblyjs/floating-point-hex-parser": {
+      "version": "1.11.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz",
+      "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==",
+      "dev": true
+    },
+    "node_modules/@webassemblyjs/helper-api-error": {
+      "version": "1.11.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz",
+      "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==",
+      "dev": true
+    },
+    "node_modules/@webassemblyjs/helper-buffer": {
+      "version": "1.11.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz",
+      "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==",
+      "dev": true
+    },
+    "node_modules/@webassemblyjs/helper-numbers": {
+      "version": "1.11.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz",
+      "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==",
+      "dev": true,
+      "dependencies": {
+        "@webassemblyjs/floating-point-hex-parser": "1.11.6",
+        "@webassemblyjs/helper-api-error": "1.11.6",
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "node_modules/@webassemblyjs/helper-wasm-bytecode": {
+      "version": "1.11.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz",
+      "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==",
+      "dev": true
+    },
+    "node_modules/@webassemblyjs/helper-wasm-section": {
+      "version": "1.11.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz",
+      "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==",
+      "dev": true,
+      "dependencies": {
+        "@webassemblyjs/ast": "1.11.6",
+        "@webassemblyjs/helper-buffer": "1.11.6",
+        "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
+        "@webassemblyjs/wasm-gen": "1.11.6"
+      }
+    },
+    "node_modules/@webassemblyjs/ieee754": {
+      "version": "1.11.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz",
+      "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==",
+      "dev": true,
+      "dependencies": {
+        "@xtuc/ieee754": "^1.2.0"
+      }
+    },
+    "node_modules/@webassemblyjs/leb128": {
+      "version": "1.11.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz",
+      "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==",
+      "dev": true,
+      "dependencies": {
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "node_modules/@webassemblyjs/utf8": {
+      "version": "1.11.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz",
+      "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==",
+      "dev": true
+    },
+    "node_modules/@webassemblyjs/wasm-edit": {
+      "version": "1.11.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz",
+      "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==",
+      "dev": true,
+      "dependencies": {
+        "@webassemblyjs/ast": "1.11.6",
+        "@webassemblyjs/helper-buffer": "1.11.6",
+        "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
+        "@webassemblyjs/helper-wasm-section": "1.11.6",
+        "@webassemblyjs/wasm-gen": "1.11.6",
+        "@webassemblyjs/wasm-opt": "1.11.6",
+        "@webassemblyjs/wasm-parser": "1.11.6",
+        "@webassemblyjs/wast-printer": "1.11.6"
+      }
+    },
+    "node_modules/@webassemblyjs/wasm-gen": {
+      "version": "1.11.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz",
+      "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==",
+      "dev": true,
+      "dependencies": {
+        "@webassemblyjs/ast": "1.11.6",
+        "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
+        "@webassemblyjs/ieee754": "1.11.6",
+        "@webassemblyjs/leb128": "1.11.6",
+        "@webassemblyjs/utf8": "1.11.6"
+      }
+    },
+    "node_modules/@webassemblyjs/wasm-opt": {
+      "version": "1.11.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz",
+      "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==",
+      "dev": true,
+      "dependencies": {
+        "@webassemblyjs/ast": "1.11.6",
+        "@webassemblyjs/helper-buffer": "1.11.6",
+        "@webassemblyjs/wasm-gen": "1.11.6",
+        "@webassemblyjs/wasm-parser": "1.11.6"
+      }
+    },
+    "node_modules/@webassemblyjs/wasm-parser": {
+      "version": "1.11.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz",
+      "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==",
+      "dev": true,
+      "dependencies": {
+        "@webassemblyjs/ast": "1.11.6",
+        "@webassemblyjs/helper-api-error": "1.11.6",
+        "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
+        "@webassemblyjs/ieee754": "1.11.6",
+        "@webassemblyjs/leb128": "1.11.6",
+        "@webassemblyjs/utf8": "1.11.6"
+      }
+    },
+    "node_modules/@webassemblyjs/wast-printer": {
+      "version": "1.11.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz",
+      "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==",
+      "dev": true,
+      "dependencies": {
+        "@webassemblyjs/ast": "1.11.6",
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "node_modules/@webpack-cli/configtest": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz",
+      "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==",
+      "dev": true,
+      "engines": {
+        "node": ">=14.15.0"
+      },
+      "peerDependencies": {
+        "webpack": "5.x.x",
+        "webpack-cli": "5.x.x"
+      }
+    },
+    "node_modules/@webpack-cli/info": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz",
+      "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==",
+      "dev": true,
+      "engines": {
+        "node": ">=14.15.0"
+      },
+      "peerDependencies": {
+        "webpack": "5.x.x",
+        "webpack-cli": "5.x.x"
+      }
+    },
+    "node_modules/@webpack-cli/serve": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz",
+      "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=14.15.0"
+      },
+      "peerDependencies": {
+        "webpack": "5.x.x",
+        "webpack-cli": "5.x.x"
+      },
+      "peerDependenciesMeta": {
+        "webpack-dev-server": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@xtuc/ieee754": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
+      "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
+      "dev": true
+    },
+    "node_modules/@xtuc/long": {
+      "version": "4.2.2",
+      "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
+      "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
+      "dev": true
+    },
+    "node_modules/acorn": {
+      "version": "8.11.3",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
+      "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
+      "dev": true,
+      "bin": {
+        "acorn": "bin/acorn"
+      },
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/acorn-import-assertions": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz",
+      "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==",
+      "dev": true,
+      "peerDependencies": {
+        "acorn": "^8"
+      }
+    },
+    "node_modules/ajv": {
+      "version": "6.12.6",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+      "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+      "dev": true,
+      "dependencies": {
+        "fast-deep-equal": "^3.1.1",
+        "fast-json-stable-stringify": "^2.0.0",
+        "json-schema-traverse": "^0.4.1",
+        "uri-js": "^4.2.2"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/epoberezkin"
+      }
+    },
+    "node_modules/ajv-keywords": {
+      "version": "3.5.2",
+      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
+      "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
+      "dev": true,
+      "peerDependencies": {
+        "ajv": "^6.9.1"
+      }
+    },
+    "node_modules/bee-webpack-loader": {
+      "resolved": "../../webpack-loader",
+      "link": true
+    },
+    "node_modules/browserslist": {
+      "version": "4.22.3",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz",
+      "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/browserslist"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "dependencies": {
+        "caniuse-lite": "^1.0.30001580",
+        "electron-to-chromium": "^1.4.648",
+        "node-releases": "^2.0.14",
+        "update-browserslist-db": "^1.0.13"
+      },
+      "bin": {
+        "browserslist": "cli.js"
+      },
+      "engines": {
+        "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+      }
+    },
+    "node_modules/buffer-from": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+      "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+      "dev": true
+    },
+    "node_modules/caniuse-lite": {
+      "version": "1.0.30001581",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001581.tgz",
+      "integrity": "sha512-whlTkwhqV2tUmP3oYhtNfaWGYHDdS3JYFQBKXxcUR9qqPWsRhFHhoISO2Xnl/g0xyKzht9mI1LZpiNWfMzHixQ==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ]
+    },
+    "node_modules/chrome-trace-event": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
+      "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.0"
+      }
+    },
+    "node_modules/clone-deep": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
+      "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
+      "dev": true,
+      "dependencies": {
+        "is-plain-object": "^2.0.4",
+        "kind-of": "^6.0.2",
+        "shallow-clone": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/colorette": {
+      "version": "2.0.20",
+      "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
+      "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
+      "dev": true
+    },
+    "node_modules/commander": {
+      "version": "2.20.3",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+      "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+      "dev": true
+    },
+    "node_modules/cross-spawn": {
+      "version": "7.0.3",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+      "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+      "dev": true,
+      "dependencies": {
+        "path-key": "^3.1.0",
+        "shebang-command": "^2.0.0",
+        "which": "^2.0.1"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/electron-to-chromium": {
+      "version": "1.4.650",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.650.tgz",
+      "integrity": "sha512-sYSQhJCJa4aGA1wYol5cMQgekDBlbVfTRavlGZVr3WZpDdOPcp6a6xUnFfrt8TqZhsBYYbDxJZCjGfHuGupCRQ==",
+      "dev": true
+    },
+    "node_modules/enhanced-resolve": {
+      "version": "5.15.0",
+      "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz",
+      "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==",
+      "dev": true,
+      "dependencies": {
+        "graceful-fs": "^4.2.4",
+        "tapable": "^2.2.0"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/envinfo": {
+      "version": "7.11.0",
+      "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.0.tgz",
+      "integrity": "sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==",
+      "dev": true,
+      "bin": {
+        "envinfo": "dist/cli.js"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/es-module-lexer": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz",
+      "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==",
+      "dev": true
+    },
+    "node_modules/escalade": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+      "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/eslint-scope": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+      "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+      "dev": true,
+      "dependencies": {
+        "esrecurse": "^4.3.0",
+        "estraverse": "^4.1.1"
+      },
+      "engines": {
+        "node": ">=8.0.0"
+      }
+    },
+    "node_modules/esrecurse": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+      "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+      "dev": true,
+      "dependencies": {
+        "estraverse": "^5.2.0"
+      },
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/esrecurse/node_modules/estraverse": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+      "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+      "dev": true,
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/estraverse": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+      "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+      "dev": true,
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/events": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+      "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.8.x"
+      }
+    },
+    "node_modules/fast-deep-equal": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+      "dev": true
+    },
+    "node_modules/fast-json-stable-stringify": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+      "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+      "dev": true
+    },
+    "node_modules/fastest-levenshtein": {
+      "version": "1.0.16",
+      "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz",
+      "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 4.9.1"
+      }
+    },
+    "node_modules/find-up": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+      "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+      "dev": true,
+      "dependencies": {
+        "locate-path": "^5.0.0",
+        "path-exists": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/flat": {
+      "version": "5.0.2",
+      "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+      "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
+      "dev": true,
+      "bin": {
+        "flat": "cli.js"
+      }
+    },
+    "node_modules/function-bind": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/glob-to-regexp": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
+      "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
+      "dev": true
+    },
+    "node_modules/graceful-fs": {
+      "version": "4.2.11",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+      "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+      "dev": true
+    },
+    "node_modules/has-flag": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/hasown": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
+      "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==",
+      "dev": true,
+      "dependencies": {
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/import-local": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
+      "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==",
+      "dev": true,
+      "dependencies": {
+        "pkg-dir": "^4.2.0",
+        "resolve-cwd": "^3.0.0"
+      },
+      "bin": {
+        "import-local-fixture": "fixtures/cli.js"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/interpret": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz",
+      "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/is-core-module": {
+      "version": "2.13.1",
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
+      "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
+      "dev": true,
+      "dependencies": {
+        "hasown": "^2.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-plain-object": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+      "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+      "dev": true,
+      "dependencies": {
+        "isobject": "^3.0.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+      "dev": true
+    },
+    "node_modules/isobject": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+      "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/jest-worker": {
+      "version": "27.5.1",
+      "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
+      "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
+      "dev": true,
+      "dependencies": {
+        "@types/node": "*",
+        "merge-stream": "^2.0.0",
+        "supports-color": "^8.0.0"
+      },
+      "engines": {
+        "node": ">= 10.13.0"
+      }
+    },
+    "node_modules/json-parse-even-better-errors": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+      "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+      "dev": true
+    },
+    "node_modules/json-schema-traverse": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+      "dev": true
+    },
+    "node_modules/kind-of": {
+      "version": "6.0.3",
+      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+      "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/loader-runner": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
+      "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.11.5"
+      }
+    },
+    "node_modules/locate-path": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+      "dev": true,
+      "dependencies": {
+        "p-locate": "^4.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/merge-stream": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+      "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+      "dev": true
+    },
+    "node_modules/mime-db": {
+      "version": "1.52.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/mime-types": {
+      "version": "2.1.35",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+      "dev": true,
+      "dependencies": {
+        "mime-db": "1.52.0"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/neo-async": {
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+      "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+      "dev": true
+    },
+    "node_modules/node-releases": {
+      "version": "2.0.14",
+      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
+      "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==",
+      "dev": true
+    },
+    "node_modules/p-limit": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+      "dev": true,
+      "dependencies": {
+        "p-try": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/p-locate": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+      "dev": true,
+      "dependencies": {
+        "p-limit": "^2.2.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/p-try": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/path-exists": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/path-key": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+      "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/path-parse": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+      "dev": true
+    },
+    "node_modules/picocolors": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+      "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+      "dev": true
+    },
+    "node_modules/pkg-dir": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+      "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+      "dev": true,
+      "dependencies": {
+        "find-up": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/punycode": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+      "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/randombytes": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+      "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+      "dev": true,
+      "dependencies": {
+        "safe-buffer": "^5.1.0"
+      }
+    },
+    "node_modules/rechoir": {
+      "version": "0.8.0",
+      "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz",
+      "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==",
+      "dev": true,
+      "dependencies": {
+        "resolve": "^1.20.0"
+      },
+      "engines": {
+        "node": ">= 10.13.0"
+      }
+    },
+    "node_modules/resolve": {
+      "version": "1.22.8",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
+      "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
+      "dev": true,
+      "dependencies": {
+        "is-core-module": "^2.13.0",
+        "path-parse": "^1.0.7",
+        "supports-preserve-symlinks-flag": "^1.0.0"
+      },
+      "bin": {
+        "resolve": "bin/resolve"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/resolve-cwd": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+      "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+      "dev": true,
+      "dependencies": {
+        "resolve-from": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/resolve-from": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+      "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/safe-buffer": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/schema-utils": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
+      "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
+      "dev": true,
+      "dependencies": {
+        "@types/json-schema": "^7.0.8",
+        "ajv": "^6.12.5",
+        "ajv-keywords": "^3.5.2"
+      },
+      "engines": {
+        "node": ">= 10.13.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      }
+    },
+    "node_modules/serialize-javascript": {
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
+      "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
+      "dev": true,
+      "dependencies": {
+        "randombytes": "^2.1.0"
+      }
+    },
+    "node_modules/shallow-clone": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
+      "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
+      "dev": true,
+      "dependencies": {
+        "kind-of": "^6.0.2"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/shebang-command": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+      "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+      "dev": true,
+      "dependencies": {
+        "shebang-regex": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/shebang-regex": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+      "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/source-map-support": {
+      "version": "0.5.21",
+      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+      "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+      "dev": true,
+      "dependencies": {
+        "buffer-from": "^1.0.0",
+        "source-map": "^0.6.0"
+      }
+    },
+    "node_modules/supports-color": {
+      "version": "8.1.1",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+      "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+      "dev": true,
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/supports-color?sponsor=1"
+      }
+    },
+    "node_modules/supports-preserve-symlinks-flag": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+      "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/tapable": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
+      "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/terser": {
+      "version": "5.27.0",
+      "resolved": "https://registry.npmjs.org/terser/-/terser-5.27.0.tgz",
+      "integrity": "sha512-bi1HRwVRskAjheeYl291n3JC4GgO/Ty4z1nVs5AAsmonJulGxpSektecnNedrwK9C7vpvVtcX3cw00VSLt7U2A==",
+      "dev": true,
+      "dependencies": {
+        "@jridgewell/source-map": "^0.3.3",
+        "acorn": "^8.8.2",
+        "commander": "^2.20.0",
+        "source-map-support": "~0.5.20"
+      },
+      "bin": {
+        "terser": "bin/terser"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/terser-webpack-plugin": {
+      "version": "5.3.10",
+      "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz",
+      "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==",
+      "dev": true,
+      "dependencies": {
+        "@jridgewell/trace-mapping": "^0.3.20",
+        "jest-worker": "^27.4.5",
+        "schema-utils": "^3.1.1",
+        "serialize-javascript": "^6.0.1",
+        "terser": "^5.26.0"
+      },
+      "engines": {
+        "node": ">= 10.13.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      },
+      "peerDependencies": {
+        "webpack": "^5.1.0"
+      },
+      "peerDependenciesMeta": {
+        "@swc/core": {
+          "optional": true
+        },
+        "esbuild": {
+          "optional": true
+        },
+        "uglify-js": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/undici-types": {
+      "version": "5.26.5",
+      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
+      "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
+      "dev": true
+    },
+    "node_modules/update-browserslist-db": {
+      "version": "1.0.13",
+      "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz",
+      "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/browserslist"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "dependencies": {
+        "escalade": "^3.1.1",
+        "picocolors": "^1.0.0"
+      },
+      "bin": {
+        "update-browserslist-db": "cli.js"
+      },
+      "peerDependencies": {
+        "browserslist": ">= 4.21.0"
+      }
+    },
+    "node_modules/uri-js": {
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+      "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+      "dev": true,
+      "dependencies": {
+        "punycode": "^2.1.0"
+      }
+    },
+    "node_modules/watchpack": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
+      "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==",
+      "dev": true,
+      "dependencies": {
+        "glob-to-regexp": "^0.4.1",
+        "graceful-fs": "^4.1.2"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/webpack": {
+      "version": "5.90.0",
+      "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.0.tgz",
+      "integrity": "sha512-bdmyXRCXeeNIePv6R6tGPyy20aUobw4Zy8r0LUS2EWO+U+Ke/gYDgsCh7bl5rB6jPpr4r0SZa6dPxBxLooDT3w==",
+      "dev": true,
+      "dependencies": {
+        "@types/eslint-scope": "^3.7.3",
+        "@types/estree": "^1.0.5",
+        "@webassemblyjs/ast": "^1.11.5",
+        "@webassemblyjs/wasm-edit": "^1.11.5",
+        "@webassemblyjs/wasm-parser": "^1.11.5",
+        "acorn": "^8.7.1",
+        "acorn-import-assertions": "^1.9.0",
+        "browserslist": "^4.21.10",
+        "chrome-trace-event": "^1.0.2",
+        "enhanced-resolve": "^5.15.0",
+        "es-module-lexer": "^1.2.1",
+        "eslint-scope": "5.1.1",
+        "events": "^3.2.0",
+        "glob-to-regexp": "^0.4.1",
+        "graceful-fs": "^4.2.9",
+        "json-parse-even-better-errors": "^2.3.1",
+        "loader-runner": "^4.2.0",
+        "mime-types": "^2.1.27",
+        "neo-async": "^2.6.2",
+        "schema-utils": "^3.2.0",
+        "tapable": "^2.1.1",
+        "terser-webpack-plugin": "^5.3.10",
+        "watchpack": "^2.4.0",
+        "webpack-sources": "^3.2.3"
+      },
+      "bin": {
+        "webpack": "bin/webpack.js"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      },
+      "peerDependenciesMeta": {
+        "webpack-cli": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/webpack-cli": {
+      "version": "5.1.4",
+      "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz",
+      "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==",
+      "dev": true,
+      "dependencies": {
+        "@discoveryjs/json-ext": "^0.5.0",
+        "@webpack-cli/configtest": "^2.1.1",
+        "@webpack-cli/info": "^2.0.2",
+        "@webpack-cli/serve": "^2.0.5",
+        "colorette": "^2.0.14",
+        "commander": "^10.0.1",
+        "cross-spawn": "^7.0.3",
+        "envinfo": "^7.7.3",
+        "fastest-levenshtein": "^1.0.12",
+        "import-local": "^3.0.2",
+        "interpret": "^3.1.1",
+        "rechoir": "^0.8.0",
+        "webpack-merge": "^5.7.3"
+      },
+      "bin": {
+        "webpack-cli": "bin/cli.js"
+      },
+      "engines": {
+        "node": ">=14.15.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      },
+      "peerDependencies": {
+        "webpack": "5.x.x"
+      },
+      "peerDependenciesMeta": {
+        "@webpack-cli/generators": {
+          "optional": true
+        },
+        "webpack-bundle-analyzer": {
+          "optional": true
+        },
+        "webpack-dev-server": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/webpack-cli/node_modules/commander": {
+      "version": "10.0.1",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
+      "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
+      "dev": true,
+      "engines": {
+        "node": ">=14"
+      }
+    },
+    "node_modules/webpack-merge": {
+      "version": "5.10.0",
+      "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz",
+      "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==",
+      "dev": true,
+      "dependencies": {
+        "clone-deep": "^4.0.1",
+        "flat": "^5.0.2",
+        "wildcard": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=10.0.0"
+      }
+    },
+    "node_modules/webpack-sources": {
+      "version": "3.2.3",
+      "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
+      "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
+      "dev": true,
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/which": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+      "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+      "dev": true,
+      "dependencies": {
+        "isexe": "^2.0.0"
+      },
+      "bin": {
+        "node-which": "bin/node-which"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/wildcard": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz",
+      "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==",
+      "dev": true
+    }
+  }
+}

          
A => examples/webpack-demo/package.json +21 -0
@@ 0,0 1,21 @@ 
+{
+  "name": "webpack-demo",
+  "version": "0.1.0",
+  "description": "Demo of bee-webpack-loader",
+  "private": true,
+  "source": "src/index.js",
+  "main": "dist/main.js",
+  "scripts": {
+    "build": "webpack",
+    "start": "node dist/main.js"
+  },
+  "author": "Yvan Sraka <yvan@sraka.xyz>",
+  "license": "GPLv2",
+  "devDependencies": {
+    "webpack": "^5.89.0",
+    "webpack-cli": "^5.1.4"
+  },
+  "dependencies": {
+    "bee-webpack-loader": "file:../../webpack-loader"
+  }
+}

          
A => examples/webpack-demo/src/greetings.bee +1 -0
@@ 0,0 1,1 @@ 
+name => print "Hello, ${name}!"

          
A => examples/webpack-demo/src/index.js +3 -0
@@ 0,0 1,3 @@ 
+import greetings from './greetings.bee'
+
+greetings("World")

          
A => examples/webpack-demo/webpack.config.js +11 -0
@@ 0,0 1,11 @@ 
+module.exports = {
+  mode: 'development',
+  module: {
+    rules: [
+      {
+        test: /\.bee$/,
+        use: 'bee-webpack-loader'
+      }
+    ]
+  }
+};

          
A => examples/weird_expr.bee +6 -0
@@ 0,0 1,6 @@ 
+// This expression is evaluated to { a = 42; b = 42 } }
+{ a = 42; b = { return a } }
+// The return keyword replace the value of the Object in which it's called by
+// its argument!
+
+// FIXME: better explain do-block semantics ...

          
A => experimental/bootstrap.js +172 -0
@@ 0,0 1,172 @@ 
+const sexpr = s =>
+  { let i = 0; const rec = () =>
+      { if (/\s/.test(s[i])) { ++i }
+        else if (s[i] === '(') { ++i; elements.push(rec()) }
+        else if (s[i] === ')') { ++i; return elements }
+        else if (s[i]== '"')
+          { let start = ++i; while (i < s.length && s[i] !== '"') { ++i }
+            elements.push(s.slice(start - 1, ++i)) }
+        else
+          { let start = i; while (i < s.length && !/\s|\(|\)/.test(s[i])) { ++i }
+            elements.push(s.slice(start, i)) }
+        return elements }
+    return rec() }
+
+const err = msg => { throw new Error(`\x1b[31m\x1b[1m${msg}\x1b[0m`) }
+const assert = x => { if (!x) { err('Assertion failed') } }
+
+const parse = s =>
+  { const sexpr = s =>
+    { let i = 0
+      const rec = () =>
+        { let elements = []
+          while (i < s.length)
+            { if (/\s/.test(s[i])) ++i
+              else if (s[i] === '(') { ++i; elements.push(rec()) }
+              else if (s[i] === ')') { ++i; return elements }
+              else if (s[i] == '"')
+                { let start = ++i
+                  while (i < s.length && s[i] !== '"') ++i
+                  elements.push(s.slice(start - 1, ++i)) }
+              else
+                { let start = i
+                  while (i < s.length && !/\s|\(|\)/.test(s[i])) ++i
+                  elements.push(s.slice(start, i)) } }
+          return elements }
+      return rec() }
+  // This parser always return an Array, which can be seen as like the whole
+  // expression is always implicitly wraped into parenthesis:
+  //    assert(sexpr(``), []);
+  // This is an S-Expression parser, spaces are ignored:
+  //    assert(sexpr(`  (A (  B C  )  D  `), [ [ 'A', [ 'B', 'C' ] ], 'D' ]);
+  // Strings are written within " and could contains parenthesis:
+  //    assert(sexpr(`(print "Hello :-)")`), [ [ 'print', '"Hello :-)"' ] ]);
+  // The parser will implicitly add missing closing parenthesis at the end of
+  // the input, and will ignore every extra closing parenthesis:
+  //    assert(sexpr(`(((X`), [ [ [ [ 'X' ] ] ] ]);
+  //    assert(sexpr(`X)))`), [ 'X' ]);
+  // The core design goal of this parser is to never fail, but here (for debug
+  // purposes) we provide a stricter version of it that only accept a subset of
+  // "valid" programs:
+  const x = sexpr(s)
+  return x.length == 1 ? x[0] : err("Malformed program") }
+
+const get = (obj, path) =>
+  { const keys = path.split('.')
+    let current = obj
+    for (const key of keys)
+      { if (current[key] === undefined) return undefined
+        current = current[key] }
+    return current }
+
+const arrity = (e, n) =>
+  { if (e.length !== n) err(`Expected ${n} arguments, got ${e.length}`) }
+
+const NATIVE =
+  { 'randInt': min => max => min + Math.floor(Math.random() * (max - min + 1)),
+    '+': a => b => a + b,
+    '==': a => b => a === b,
+    '|': a => b => a || b,
+    '!': a => !a,
+    // FIXME: function are eager, `if` need to be a keyword
+    // '?': a => b => c => a ? b : c,
+    'print': s => console.log(s),
+    'panic': e => console.log("Runtime Type Error:", e) }
+
+// KEYWORDS: let, do, fn, quote, case, return
+const eval = (e, ENV = {}) =>
+  { if (Array.isArray(e))
+      { if (e[0] === 'quote') { return e.slice(1) }
+        else if (e[0] === 'do')
+          { ENV = { ...ENV }
+            for (let i = 1; i < e.length; ++i) eval(e[i], ENV)
+            return ENV }
+        else if (e[0] === 'let')
+          { arrity(e, 3); const x = eval(e[2], ENV); ENV[e[1]] = x; return x }
+        else if (e[0] === 'fn')
+          { if (e.length > 3)
+            { const sugar = x =>
+              { if (x.length <= 3) return x
+                return ["fn", x[1], sugar(["fn", ...x.slice(2)])] }
+              return eval(sugar(e), ENV) }
+            arrity(e, 3)
+            return arg => eval(e[2], { ...ENV, [e[1]]: arg }) }
+        else if (e[0] === 'if')
+          { arrity(e, 4)
+            return eval(e[1], ENV) === true
+                 ? eval(e[2], ENV)
+                 : eval(e[3], ENV) }
+        else
+          { if (e.length > 2)
+              { const sugar = x =>
+                { if (x.length <= 2) return x
+                  return [sugar(x.slice(0, x.length - 1)), x[x.length - 1]] }
+                return eval(sugar(e), ENV) }
+            arrity(e, 2)
+            let fn = e[0]
+            if (Array.isArray(fn)) fn = eval(fn, ENV)
+            if (typeof fn !== 'function')
+              { const x = get(ENV, fn)
+                if (x !== undefined) fn = x
+                else
+                  { if (NATIVE[fn]) fn = NATIVE[fn]
+                    else err(`Function ${fn} not found`) }
+                if (typeof fn !== 'function') err(`${fn} is not a function`) }
+            return fn(eval(e[1], ENV, true)) } }
+      else
+        { if (e === true || e === "true") return true
+          if (e === false || e === "false") return false
+          if (/^-?\d+$/.test(e)) return parseInt(e)
+          if (/^".*"$/.test(e)) return e.slice(1, -1)
+          else
+            { const x = get(ENV, e)
+              if (x !== undefined) return x
+              else err(`Variable ${e} not found`) } } }
+// `let` implicitly return the value assigned:
+assert(eval(parse(`(let x 42)`)) == 42)
+// ... but used within `do` block, it serve as field identifier:
+assert(eval(parse(`(do (let x (do (let y 42))))`)).x.y == 42)
+// `let` fields of a `do` struct could be accessed with `.` operator:
+assert(eval(parse(`(do (let x (do (let y 42))) (let z x.y))`)).z == 42)
+// instructions of a `do` block are evaluated in order:
+assert(eval(parse(`(do (let x 42) (let y x) (let z y))`)).z == 42)
+// and let definitions could be shadowed:
+assert(eval(parse(`(do (let x 40) (let x 41) (let x 42))`)).x == 42)
+// `do` blocks work as lexical scopes:
+assert(eval(parse(`(do (let x 42) (do (let x 0)))`)).x == 42)
+// `do` blocks could contains any instruction:
+assert(eval(parse(`(do (+ 2 2) (let x 42))`)).x == 42)
+// `fn` (function) support partial application:
+assert(eval(parse(`(do (let x (fn x (+ x)))` + // x is (fn x (+ x))
+  `(let x (x 2))` + // x is (+ 2)
+  `(let x (x 40))`)        // x is ((+ 2) 40)
+).x == 42)
+// `fn` also capture their environment (here `y`):
+assert(eval(parse(`(do (let x 0)
+                       (let y 1)
+                       (let x ((fn x (+ y x)) 41)))`)).x == 42)
+// values:                  42     41   1 41
+// `fn` have some nice syntaxic sugar, these 2 expressions are equivalents:
+assert(eval(parse(`((fn x (fn y ((+ x) y))) 2 40)`)) == 42)
+assert(eval(parse(`((fn x     y ( + x  y) ) 2 40)`)) == 42)
+// ... this is call curryfication!
+// Within a `do` block you can break the flow of computation by replacing the
+// struct by a specific value:
+// FIXME: assert(eval(parse(`(do (let x 42) (return x) (let x 0))`)) == 42)
+// n.b. Haskell/Nix/OCaml/Scheme let X (in) Y keywords could be emulate by:
+// (do (let X) (return Y))
+// FIXME: console.log(eval(parse(`(do (return (list A B C)))`)))
+// TODO: explain and test `quote` ...
+// eval(parse(`
+// (do
+//   (let x (randInt 0 1))
+//   (let y (if (== x 1)
+//             "foo"
+//             "bar"))
+//   (print y)
+//   (if (! (| "bar" "foo"))
+//      (panic "Err")
+//      (print "Ok")))
+// `)) // Print "foo\nOk"
+//
+// To be continued ...

          
A => experimental/gc.h +405 -0
@@ 0,0 1,405 @@ 
+/*
+ * This file should build without warning with clang version 14.0.0:
+ * > clang gc.h -std=c89
+ * I tested it also with gcc version 11.3.0:
+ * > gcc   gc.h -std=c89
+ */
+
+#include <errno.h>     /* Needed by strerror_r(errno, ...) */
+#include <stdio.h>     /* Needed by fprintf(stderr, ...) */
+#include <stdlib.h>    /* Needed by exit(EXIT_FAILURE) */
+#include <string.h>    /* Needed by memset, memmove */
+#include <sys/mman.h>  /* Needed by mmap, munmap, mremap */
+#include <unistd.h>    /* Needed by sysconf(_SC_PAGE_SIZE) */
+/* #include <Windows.h> *//* Needed by VirtualAlloc, VirtualFree */
+
+/* TODO ... */
+/* #define NDEBUG */
+/* #include <assert.h> */
+
+/* Handy panic handlers defined later in this file ... */
+void gc_panic(const char* file, int line);
+void* gc_unwrap(void* value, const char* file, int line);
+#define panic() gc_panic(__FILE__, __LINE__)
+#define unwrap(value) gc_unwrap(value, __FILE__, __LINE__)
+
+/*
+ * Memory management primitives
+ * ----------------------------
+ *
+ * The purpose of this part is to define a gc_sbrk that allow memory allocation
+ * / liberation in roughly O(1) using internally mmap / munmap when such
+ * syscalls are OS defined.
+ *
+ * The memory is a continuous space of allocated adresse growing such as a heap
+ * segment would, we have few markers around our pages:
+ *
+ *  ------ allocated memory adresses ---->
+ *  |zzzzzzzz|yyyyy|xxxxxxxxxx|----------|~~
+ * start          last       used       stop
+ *
+ * n.b. an alternative noncontinuous (hardened for security concern) version of
+ * this allocator is just a stack of pointer (and so would require one more
+ * indirection) ...
+ *
+ */
+
+static void* start = NULL;
+static void* last = NULL;
+static void* used = NULL;
+static void* stop = NULL;
+static size_t page_size = 0;
+
+/* TODO: This should better be a #define ... */
+void assert_gc_init(void) {
+  if (page_size == 0) {
+#ifdef _WIN32  /* Windows */
+    fprintf_s(stderr, "gc_init haven't be call before memory allocation\n");
+    ExitProcess(EXIT_FAILURE);
+#else  /* Unix */
+    fprintf(stderr, "gc_init haven't be call before memory allocation\n");
+    exit(EXIT_FAILURE);
+#endif
+  }
+}
+
+#ifdef HARD_MODE
+
+/*
+ * HARD_MODE means "bring your memory" by giving to init function a start
+ * address and a size.
+ *
+ * TODO: should provide a callback mechanism to let user handle out-of-memory
+ * scenario gracefully.
+ */
+
+void gc_init_hard_mode(void* ptr, size_t size) {
+    start = last = used = ptr;
+    stop = ptr + size;
+}
+
+void* gc_sbrk(int increment) { /* TODO */ }
+
+/* if mmap() or VirtualAlloc() syscalls are available, then ... */
+#elif defined(_POSIX_MAPPED_FILES) || defined(_WIN32)
+
+/* gc_init should be call at the top of your main function */
+void gc_init(void) {
+#ifdef _WIN32  /* Windows */
+  SYSTEM_INFO sysInfo;
+  GetSystemInfo(&sysInfo);
+  page_size = sysInfo.dwPageSize;
+  start = last = used =
+      VirtualAlloc(NULL, page_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+  if (start == NULL) {
+    fprintf_s(stderr, "Fail to initialize memory\n");
+    ExitProcess(EXIT_FAILURE);
+  }
+#else  /* Unix */
+  page_size = sysconf(_SC_PAGE_SIZE);
+  start = last = used = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
+                             MAP_PRIVATE, -1, 0);
+  if (start == MAP_FAILED) {
+    fprintf(stderr, "Fail to initialize memory\n");
+    exit(EXIT_FAILURE);
+  }
+#endif
+  stop = start + page_size;
+}
+
+/*
+ * gc_sbrk - Custom implementation of the sbrk function using mmap and munmap
+ *
+ * @increment: the number of bytes to increment the break value by. If increment
+ * is negative, the equivalent amount of memory is deallocated. If increment is
+ * zero, the current break value is returned.
+ *
+ * Returns a pointer to the start of the newly allocated memory block, or NULL
+ * if the allocation failed.
+ */
+void* gc_sbrk(int increment) {
+  assert_gc_init();
+  void* current = stop;
+  if (increment > 0) {
+    int asked = ((increment / page_size) + 1) * page_size;
+#ifdef _WIN32  /* Windows */
+    void* ptr =
+        VirtualAlloc(stop, asked, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+    if (ptr == NULL)
+      return NULL;
+#else  /* Unix */
+    void* ptr = mmap(stop, asked, PROT_READ | PROT_WRITE,
+                     MAP_PRIVATE | MAP_FIXED, -1, 0);
+    if (ptr == MAP_FAILED)
+      return NULL;
+#endif
+    stop = ptr + asked;
+  }
+  if (increment < 0) {
+    int asked = ((-increment) / page_size) * page_size;
+#ifdef _WIN32  /* Windows */
+    if (asked > 0 && !VirtualFree(stop - asked, 0, MEM_RELEASE))
+      panic();
+#else  /* Unix */
+    if (asked > 0 && munmap(stop - asked, asked) != 0)
+      panic();
+#endif
+    stop -= asked;
+  }
+  return current;
+}
+
+#else  /* ... else, we rely on brk() ... */
+
+/* Warning: brk and sbrk are deprecated on macOS ... */
+void* gc_sbrk(int increment) {
+  assert_gc_init();
+  void* current = stop;
+  stop += increment;
+  if (brk(stop) != 0) {
+    return NULL;
+  }
+  return current;
+}
+
+void gc_init(void) {
+  page_size = sysconf(_SC_PAGE_SIZE);
+  stop = (void*) (long int) brk(NULL);
+  start = last = used = gc_sbrk(page_size);
+  if (start == NULL) {
+    fprintf(stderr, "Fail to initialize memory\n");
+    exit(EXIT_FAILURE);
+  }
+}
+
+#endif
+
+/*
+ * Memory management utilities
+ * ---------------------------
+ *
+ * Memory allocation utilities that behave like you would expect, EXCEPT for the
+ * gc_free function! The gc_free free all memory allocated since the allocation
+ * of the pointer given to it (n.b. gc_realloc count as a new allocation). You
+ * can see pointers as timestamp, in this model if you gc_malloc A, then B, then
+ * C, and then gc_free B, implicitly it means that you freed C. Another mental
+ * model around this mechanism is the stack: memory allocated is free in the
+ * reverse order of allocations.
+ */
+
+/*
+ * gc_malloc - Allocate memory block of given size
+ *
+ * @size: size of the memory block in bytes
+ *
+ * Returns a pointer to the allocated memory block
+ */
+void* gc_malloc(size_t size) {
+  int needed = used + size - stop;
+  if (needed > 0) {
+    if (gc_sbrk(needed) == NULL) {
+      errno = ENOMEM;
+      panic();
+    }
+    stop += needed;
+  }
+  void* ptr = used;
+  used += size;
+  last = ptr;
+  return ptr;
+}
+
+/*
+ * gc_calloc - Allocate and initialize memory block of given size
+ *
+ * @n: number of elements in the array
+ * @size: size of each element in bytes
+ *
+ * Returns a pointer to the allocated and initialized memory block
+ */
+void* gc_calloc(size_t n, size_t size) {
+  size *= n;
+  return memset(gc_malloc(size), 0, size);
+}
+
+/*
+ * gc_realloc - Reallocate memory block to a new size
+ *
+ * @ptr: pointer to the original memory block
+ * @size: new size of the memory block in bytes
+ *
+ * Returns a pointer to the reallocated memory block
+ */
+void* gc_realloc(void* ptr, size_t size) {
+  if (ptr == last)
+    used = last;
+  void* new_ptr = gc_malloc(size);
+  if (ptr != last && ptr != NULL)
+    memmove(new_ptr, ptr, size);
+  return new_ptr;
+}
+
+/*
+ * gc_free - Free allocated memory block
+ *
+ * @ptr: pointer to the memory block to be freed
+ */
+void gc_free(void* ptr) {
+  if (ptr == NULL || start > ptr || ptr > used)
+    return;
+  used = ptr;
+  int unused = stop - used;
+  if (gc_sbrk(-unused) != NULL)
+    stop -= unused;
+}
+
+/*
+ * Boxed utilities
+ * ---------------
+ *
+ * Keep track of the size of items allocated on the heap could be tiresome, here
+ * is a simple type and utilities to keep track of the size of memory allocated
+ * to a pointer in "boxed" fashion.
+ */
+
+typedef struct Box {
+  void* data;
+  size_t size;
+} Box;
+
+/* Boxed version of: void* gc_malloc(size_t size) */
+Box boxed_malloc(size_t size) {
+  Box ret = {gc_malloc(size), size};
+  return ret;
+}
+
+/* Boxed version of: void* gc_calloc(size_t n, size_t size) */
+Box boxed_calloc(size_t n, size_t size) {
+  Box ret = {gc_calloc(n, size), n * size};
+  return ret;
+}
+
+/* Boxed version of: void* gc_realloc(void* ptr, size_t size) */
+Box boxed_realloc(Box x, size_t size) {
+  Box ret = {gc_realloc(x.data, size), size};
+  return ret;
+}
+
+/* Boxed version of: void gc_free(void* ptr) */
+void boxed_free(Box x) {
+  gc_free(x.data);
+}
+
+/*
+ * Collector
+ * ---------
+ *
+ * TODO: This would be the core logic of the "destructor" mechanism, it should
+ * work recursively but for now only accept a dumb Box. Thanks to Nao, I will
+ * reimplement it using an OCaml like Object abstraction
+ * https://git.naomini.tel/nao/lysp/src/c-interp/object.c
+ *
+ * gc_collect take an object (or later a list of objects), and, in increasing
+ * pointer order, move objects (and compact memory) starting at target pointer
+ * address: target should be the value of the beginning of the heap region
+ * associated to your stack frame, you can obtain it using gc_malloc(0) at the
+ * start of your function definition.
+ *
+ * Then gc_collect will gc_free the memory after the last moved value. Collect
+ * has a heuristic criterion to save on moving values (e.g., the implementation
+ * doesn’t move overlapping memory). Here is a little schema:
+ *
+ *         target
+ * |---------|---A---B----C---|
+ *  *** collect(target, C) ***
+ * |---------|ABC|
+ */
+
+/*
+ * Increasing this value could speed up programs while being more greedy on
+ * memory usage ...
+ */
+#define HEURISTIC_VALUE 0
+
+void gc_collect(void* target, Box x) {
+  /* TODO: if ptr == NULL ... panic? */
+  if (target >= x.data || (x.data - target) < x.size + HEURISTIC_VALUE)
+    return;
+  /*
+   * #ifdef MREMAP_MAYMOVE
+   * TODO: There is likely a efficient memmove implementation using ...
+   * mremap(x.data, x.size, x.size, MREMAP_MAYMOVE | MREMAP_FIXED, target)
+   * ... and the right munmap combination on modern Linux!
+   */
+  memmove(target, x.data, x.size);
+  gc_free(target + x.size);
+}
+
+/*
+ * Panic handler
+ * -------------
+ *
+ * Just as a bonus, panic handler that magical unwind all allocated objects :)
+ */
+
+/*
+ * panic - Print error message and exit with failure status
+ *
+ * @file: file name where the error occurred
+ * @line: line number where the error occurred
+ */
+#ifdef _WIN32  /* Windows */
+
+void gc_panic(const char* file, int line) {
+  DWORD errorCode = GetLastError();
+  /*
+   * TODO: Windows syscalls doesn't use errno ... how boring to trigger
+   * cross-platform errors in my code ...
+   */
+  LPVOID lpMsgBuf;
+  FormatMessage(
+    FORMAT_MESSAGE_ALLOCATE_BUFFER |
+    FORMAT_MESSAGE_FROM_SYSTEM |
+    FORMAT_MESSAGE_IGNORE_INSERTS,
+    NULL,
+    errorCode,
+    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+    (LPTSTR)&lpMsgBuf,
+    0, NULL);
+  fprintf(stderr, "Error: %s\n", (char *)lpMsgBuf);
+  LocalFree(lpMsgBuf);
+  gc_free(start);
+  ExitProcess(EXIT_FAILURE);
+}
+
+#else  /* Unix */
+
+void gc_panic(const char* file, int line) {
+  char buffer[256];
+  int result = strerror_r(errno, buffer, sizeof buffer);
+  if (result == 0) {
+    fprintf(stderr, "Error (%s:%d): %s\n", file, line, buffer);
+  } else {
+    fprintf(stderr, "Error (%s:%d): strerror_r() failed with error code %d\n",
+            file, line, result);
+  }
+  gc_free(start);
+  exit(EXIT_FAILURE);
+}
+
+#endif
+
+/*
+ * unwrap - Check if a value is NULL and call panic if it is
+ *
+ * @value: value to check
+ * @file: file name where the error occurred
+ * @line: line number where the error occurred
+ *
+ * Returns the value if it is not NULL
+ */
+void* gc_unwrap(void* value, const char* file, int line) {
+  if (value == NULL)
+    gc_panic(file, line);
+  return value;
+}
  No newline at end of file

          
A => experimental/playground.html +13 -0
@@ 0,0 1,13 @@ 
+<script src="./tree-sitter.js"></script>
+<script>
+  const Parser = window.TreeSitter;
+  Parser.init().then(() =>
+    { const parser = new Parser();
+      parser.Language.load('../tree-sitter-bee-lang/tree-sitter-bee.wasm').then((BeeLang) =>
+        { parser.setLanguage(BeeLang);
+          const sourceCode = `{ x = x -> y -> add x y; y = x 2 3; }`;
+          const tree = parser.parse(sourceCode);
+          console.log(tree.rootNode.toString()); }); });
+  // To be continued ...
+  // https://github.com/tree-sitter/tree-sitter/tree/master/lib/binding_web
+</script>

          
A => flake.lock +130 -0
@@ 0,0 1,130 @@ 
+{
+  "nodes": {
+    "flake-utils": {
+      "inputs": {
+        "systems": "systems"
+      },
+      "locked": {
+        "lastModified": 1705309234,
+        "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "type": "github"
+      }
+    },
+    "flake-utils_2": {
+      "inputs": {
+        "systems": "systems_2"
+      },
+      "locked": {
+        "lastModified": 1705309234,
+        "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "type": "github"
+      }
+    },
+    "nixpkgs": {
+      "locked": {
+        "lastModified": 1706683685,
+        "narHash": "sha256-FtPPshEpxH/ewBOsdKBNhlsL2MLEFv1hEnQ19f/bFsQ=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "5ad9903c16126a7d949101687af0aa589b1d7d3d",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "ref": "nixpkgs-unstable",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
+    "nixpkgs_2": {
+      "locked": {
+        "lastModified": 1706487304,
+        "narHash": "sha256-LE8lVX28MV2jWJsidW13D2qrHU/RUUONendL2Q/WlJg=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "90f456026d284c22b3e3497be980b2e47d0b28ac",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "ref": "nixpkgs-unstable",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
+    "root": {
+      "inputs": {
+        "flake-utils": "flake-utils",
+        "nixpkgs": "nixpkgs",
+        "rust-overlay": "rust-overlay"
+      }
+    },
+    "rust-overlay": {
+      "inputs": {
+        "flake-utils": "flake-utils_2",
+        "nixpkgs": "nixpkgs_2"
+      },
+      "locked": {
+        "lastModified": 1706753617,
+        "narHash": "sha256-ZKqTFzhFwSWFEpQTJ0uXnfJBs5Y/po9/8TK4bzssdbs=",
+        "owner": "oxalica",
+        "repo": "rust-overlay",
+        "rev": "58be43ae223034217ea1bd58c73210644031b687",
+        "type": "github"
+      },
+      "original": {
+        "owner": "oxalica",
+        "repo": "rust-overlay",
+        "type": "github"
+      }
+    },
+    "systems": {
+      "locked": {
+        "lastModified": 1681028828,
+        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+        "owner": "nix-systems",
+        "repo": "default",
+        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-systems",
+        "repo": "default",
+        "type": "github"
+      }
+    },
+    "systems_2": {
+      "locked": {
+        "lastModified": 1681028828,
+        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+        "owner": "nix-systems",
+        "repo": "default",
+        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-systems",
+        "repo": "default",
+        "type": "github"
+      }
+    }
+  },
+  "root": "root",
+  "version": 7
+}

          
A => flake.nix +16 -0
@@ 0,0 1,16 @@ 
+{
+  inputs = {
+    flake-utils.url = "github:numtide/flake-utils";
+    nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
+    rust-overlay.url = "github:oxalica/rust-overlay";
+  };
+  outputs = { flake-utils, nixpkgs, rust-overlay, ... }:
+    flake-utils.lib.eachDefaultSystem (system:
+      let
+        overlays = [ (import rust-overlay) ];
+        pkgs = import nixpkgs { inherit system overlays; };
+      in {
+        defaultPackage = import ./default.nix { inherit pkgs system; };
+        devShell = import ./shell.nix { inherit pkgs system; };
+      });
+}

          
A => index.js +14 -0
@@ 0,0 1,14 @@ 
+// FIXME: implement a LSP and a DAP ...
+// https://code.visualstudio.com/api/language-extensions/language-server-extension-guide
+// https://microsoft.github.io/debug-adapter-protocol/
+
+const Parser = require('tree-sitter');
+const BeeLang = require('./tree-sitter-bee-lang');
+
+const parser = new Parser();
+parser.setLanguage(BeeLang);
+
+// const sourceCode = `{ x = x => y => add x y; y = x 2 3; }`;
+// const tree = parser.parse(sourceCode);
+
+// console.log(tree.rootNode.toString());

          
A => package-lock.json +475 -0
@@ 0,0 1,475 @@ 
+{
+  "name": "bee-lang",
+  "version": "0.1.0",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "bee-lang",
+      "version": "0.1.0",
+      "license": "GPLv2",
+      "dependencies": {
+        "tree-sitter": "^0.20.6",
+        "tree-sitter-bee-lang": "file:tree-sitter"
+      }
+    },
+    "node_modules/base64-js": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/bl": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+      "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+      "dependencies": {
+        "buffer": "^5.5.0",
+        "inherits": "^2.0.4",
+        "readable-stream": "^3.4.0"
+      }
+    },
+    "node_modules/buffer": {
+      "version": "5.7.1",
+      "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+      "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "dependencies": {
+        "base64-js": "^1.3.1",
+        "ieee754": "^1.1.13"
+      }
+    },
+    "node_modules/chownr": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+      "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
+    },
+    "node_modules/decompress-response": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
+      "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
+      "dependencies": {
+        "mimic-response": "^3.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/deep-extend": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+      "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+      "engines": {
+        "node": ">=4.0.0"
+      }
+    },
+    "node_modules/detect-libc": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz",
+      "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/end-of-stream": {
+      "version": "1.4.4",
+      "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+      "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+      "dependencies": {
+        "once": "^1.4.0"
+      }
+    },
+    "node_modules/expand-template": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
+      "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/fs-constants": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+      "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
+    },
+    "node_modules/github-from-package": {
+      "version": "0.0.0",
+      "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
+      "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="
+    },
+    "node_modules/ieee754": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+      "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+    },
+    "node_modules/ini": {
+      "version": "1.3.8",
+      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+      "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
+    },
+    "node_modules/lru-cache": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/mimic-response": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
+      "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/minimist": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+      "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/mkdirp-classic": {
+      "version": "0.5.3",
+      "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
+      "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
+    },
+    "node_modules/nan": {
+      "version": "2.18.0",
+      "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz",
+      "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w=="
+    },
+    "node_modules/napi-build-utils": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
+      "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg=="
+    },
+    "node_modules/node-abi": {
+      "version": "3.52.0",
+      "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.52.0.tgz",
+      "integrity": "sha512-JJ98b02z16ILv7859irtXn4oUaFWADtvkzy2c0IAatNVX2Mc9Yoh8z6hZInn3QwvMEYhHuQloYi+TTQy67SIdQ==",
+      "dependencies": {
+        "semver": "^7.3.5"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+      "dependencies": {
+        "wrappy": "1"
+      }
+    },
+    "node_modules/prebuild-install": {
+      "version": "7.1.1",
+      "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz",
+      "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==",
+      "dependencies": {
+        "detect-libc": "^2.0.0",
+        "expand-template": "^2.0.3",
+        "github-from-package": "0.0.0",
+        "minimist": "^1.2.3",
+        "mkdirp-classic": "^0.5.3",
+        "napi-build-utils": "^1.0.1",
+        "node-abi": "^3.3.0",
+        "pump": "^3.0.0",
+        "rc": "^1.2.7",
+        "simple-get": "^4.0.0",
+        "tar-fs": "^2.0.0",
+        "tunnel-agent": "^0.6.0"
+      },
+      "bin": {
+        "prebuild-install": "bin.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/pump": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+      "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+      "dependencies": {
+        "end-of-stream": "^1.1.0",
+        "once": "^1.3.1"
+      }
+    },
+    "node_modules/rc": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+      "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+      "dependencies": {
+        "deep-extend": "^0.6.0",
+        "ini": "~1.3.0",
+        "minimist": "^1.2.0",
+        "strip-json-comments": "~2.0.1"
+      },
+      "bin": {
+        "rc": "cli.js"
+      }
+    },
+    "node_modules/readable-stream": {
+      "version": "3.6.2",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+      "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+      "dependencies": {
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/safe-buffer": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/semver": {
+      "version": "7.5.4",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+      "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+      "dependencies": {
+        "lru-cache": "^6.0.0"
+      },
+      "bin": {
+        "semver": "bin/semver.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/simple-concat": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
+      "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/simple-get": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
+      "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "dependencies": {
+        "decompress-response": "^6.0.0",
+        "once": "^1.3.1",
+        "simple-concat": "^1.0.0"
+      }
+    },
+    "node_modules/string_decoder": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+      "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+      "dependencies": {
+        "safe-buffer": "~5.2.0"
+      }
+    },
+    "node_modules/strip-json-comments": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+      "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/tar-fs": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
+      "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
+      "dependencies": {
+        "chownr": "^1.1.1",
+        "mkdirp-classic": "^0.5.2",
+        "pump": "^3.0.0",
+        "tar-stream": "^2.1.4"
+      }
+    },
+    "node_modules/tar-stream": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
+      "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
+      "dependencies": {
+        "bl": "^4.0.3",
+        "end-of-stream": "^1.4.1",
+        "fs-constants": "^1.0.0",
+        "inherits": "^2.0.3",
+        "readable-stream": "^3.1.1"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/tree-sitter": {
+      "version": "0.20.6",
+      "resolved": "https://registry.npmjs.org/tree-sitter/-/tree-sitter-0.20.6.tgz",
+      "integrity": "sha512-GxJodajVpfgb3UREzzIbtA1hyRnTxVbWVXrbC6sk4xTMH5ERMBJk9HJNq4c8jOJeUaIOmLcwg+t6mez/PDvGqg==",
+      "hasInstallScript": true,
+      "dependencies": {
+        "nan": "^2.18.0",
+        "prebuild-install": "^7.1.1"
+      }
+    },
+    "node_modules/tree-sitter-bee-lang": {
+      "resolved": "tree-sitter",
+      "link": true
+    },
+    "node_modules/tree-sitter-cli": {
+      "version": "0.20.8",
+      "resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.20.8.tgz",
+      "integrity": "sha512-XjTcS3wdTy/2cc/ptMLc/WRyOLECRYcMTrSWyhZnj1oGSOWbHLTklgsgRICU3cPfb0vy+oZCC33M43u6R1HSCA==",
+      "dev": true,
+      "hasInstallScript": true,
+      "bin": {
+        "tree-sitter": "cli.js"
+      }
+    },
+    "node_modules/tunnel-agent": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+      "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
+      "dependencies": {
+        "safe-buffer": "^5.0.1"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+    },
+    "node_modules/wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+    },
+    "node_modules/yallist": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+    },
+    "tree-sitter": {
+      "version": "0.1.0",
+      "hasInstallScript": true,
+      "license": "ISC",
+      "dependencies": {
+        "nan": "^2.18.0"
+      },
+      "devDependencies": {
+        "tree-sitter-cli": "^0.20.8"
+      }
+    },
+    "tree-sitter-bee-lang": {
+      "version": "0.0.1",
+      "extraneous": true,
+      "hasInstallScript": true,
+      "license": "ISC",
+      "dependencies": {
+        "nan": "^2.18.0"
+      },
+      "devDependencies": {
+        "tree-sitter-cli": "^0.20.8"
+      }
+    }
+  }
+}

          
A => package.json +12 -0
@@ 0,0 1,12 @@ 
+{
+  "name": "bee-lang",
+  "version": "0.1.0",
+  "description": "",
+  "main": "index.js",
+  "author": "Yvan Sraka <yvan@sraka.xyz>",
+  "license": "GPLv2",
+  "dependencies": {
+    "tree-sitter": "^0.20.6",
+    "tree-sitter-bee-lang": "file:tree-sitter"
+  }
+}

          
A => rust-toolchain +1 -0
@@ 0,0 1,1 @@ 
+stable

          
A => shell.nix +24 -0
@@ 0,0 1,24 @@ 
+# If you plan to use `nix-shell` you have first to:
+#
+# $ nix-channel --add https://github.com/oxalica/rust-overlay/archive/master.tar.gz rust-overlay
+# $ nix-channel --update
+{ pkgs ? import <nixpkgs> { overlays = [ (import <rust-overlay>) ]; }
+, system ? builtins.currentSystem }:
+with pkgs;
+let
+  toolchain = (rust-bin.fromRustupToolchainFile ./rust-toolchain).override {
+    extensions = [ "rust-src" "rust-analyzer" "clippy" ];
+  };
+in mkShell {
+  buildInputs = [ nodejs toolchain tree-sitter ]
+    ++ (if system == "x86_64-linux" then [ mold ] else [ ]);
+  RUST_BACKTRACE = "full";
+  shellHook = ''
+    if [ ! -f "tree-sitter-bee-lang/src/parser.c" ]; then
+        pushd tree-sitter-bee-lang
+        tree-sitter generate
+        popd
+    fi
+  '';
+
+}

          
A => src/bin/bee/build.rs +175 -0
@@ 0,0 1,175 @@ 
+use bee::build::{build, Error, PRELUDE};
+use bee::cache::{cached, relative};
+use bee::cli::BuildArgs;
+use bee::codegen::{is_valid_extension, is_valid_filename};
+use bee::parser::Span;
+use log::{error, info, warn};
+use miette::miette;
+use owo_colors::{OwoColorize, Stream::Stdout, Style};
+use regex::Regex;
+use std::cmp::min;
+use std::collections::{BTreeSet, HashMap};
+use std::fs::{self, File};
+use std::io::{self, IsTerminal, Read, Write};
+
+/// TODO: write documentation...
+pub(crate) fn handle(args: &BuildArgs) -> exitcode::ExitCode {
+    let input_piped = !io::stdin().is_terminal();
+    let output_piped = !io::stdout().is_terminal();
+
+    if args.output.is_none() && !output_piped {
+        error!("output was not specified with `-o`/`--output` or stdout piped");
+        return exitcode::USAGE;
+    }
+    if args.input.is_some() && input_piped {
+        error!("I'm confuse, you specified both an input file and piped stdin");
+        return exitcode::USAGE;
+    }
+    if args.output.is_some() && output_piped {
+        error!(
+            "I'm confuse, you specified both an output file with `-o`/`--output` and piped stdout"
+        );
+        return exitcode::USAGE;
+    }
+
+    let src = if input_piped {
+        let mut src = String::new();
+        io::stdin().read_to_string(&mut src).unwrap();
+        src
+    } else {
+        let mut input = match &args.input {
+            Some(x) => x.clone(),
+            None => "./main.bee".into(),
+        };
+        if let Ok(metadata) = fs::metadata(&input) {
+            if metadata.is_dir() {
+                input = input.join("main.bee");
+            }
+        };
+        match fs::read_to_string(&input) {
+            Ok(src) => src,
+            Err(err) => {
+                error!("while reading file `{}`: {err}", input.display());
+                return exitcode::NOINPUT;
+            }
+        }
+    };
+    // FIXME: This error isn't really meaningful and isn't triggered if an empty
+    // file is imported ...
+    // if src.trim() == "" {
+    //     error!("the given input file is empty");
+    //     return exitcode::NOINPUT;
+    // }
+
+    let filename = if input_piped {
+        "/dev/stdin".into()
+    } else {
+        let path = match &args.input {
+            Some(x) => x.clone(),
+            None => "./main.bee".into(),
+        };
+        if let Ok(metadata) = fs::metadata(&path) {
+            if metadata.len() > 50000 {
+                warn!("file `{}` seems big, consider spliting it into modules to better use build cache", path.display());
+            }
+        }
+        if !is_valid_extension(&path) {
+            error!("file `{}` extension should be `.bee`", path.display());
+            return exitcode::USAGE;
+        }
+        if !is_valid_filename(&path) {
+            error!(
+                "file path `{}` contains illegal characters: `:`, `.`, `[` or `]`",
+                path.display()
+            );
+            return exitcode::USAGE;
+        }
+        fs::canonicalize(&path).unwrap()
+    };
+
+    let mut targets = match &args.targets {
+        Some(x) => Regex::new(r"[, ]").unwrap().split(x).collect(),
+        None => BTreeSet::new(),
+    };
+    if targets.contains("debug") && targets.contains("release") {
+        error!("both @debug and @release mutually exclusive targets are given as arguments");
+        return exitcode::USAGE;
+    }
+    if !targets.contains("release") {
+        targets.insert("debug");
+    }
+
+    match if input_piped {
+        warn!("build cache doesn't store piped input");
+        build(src.as_bytes(), &filename, &targets)
+    } else {
+        cached(src.as_bytes(), &filename, &targets, build)
+    } {
+        Ok(output) => {
+            // FIXME: print the `lazy_static` stack of WARNINGS on stderr
+            if output_piped {
+                println!("{}", output);
+            } else {
+                let mut file = File::create(args.output.clone().unwrap()).unwrap();
+                file.write_all(output.as_bytes()).unwrap();
+            }
+            exitcode::OK
+        }
+        Err(err) => {
+            error(err);
+            exitcode::DATAERR // FIXME: rather use a custom error > 78
+        }
+    }
+}
+
+fn error(err: Error) {
+    let Error {
+        msg,
+        code,
+        help,
+        stacktrace,
+    } = err;
+    println!();
+    error!(
+        "{} {}",
+        code.if_supports_color(Stdout, |text| text.style(Style::new().bold().red())),
+        msg, // FIXME: color every verbatim content between ``
+    );
+    if let Some(stacktrace) = stacktrace {
+        let total = min(5, stacktrace.len());
+        let stacktrace = &stacktrace[..total];
+        let mut map = HashMap::new();
+        for (index, span) in stacktrace.iter().enumerate() {
+            map.entry(span.filename.clone())
+                .or_insert_with(Vec::new)
+                .push((span, index));
+        }
+        let grouped_span_by_filename: Vec<Vec<(&Span, usize)>> = map.into_values().collect();
+        for spans in grouped_span_by_filename {
+            let filename = &spans[0].0.filename;
+            let src = if filename.display().to_string() == "prelude" {
+                PRELUDE.to_owned()
+            } else {
+                fs::read_to_string(filename).unwrap()
+            };
+            let named_src = miette::NamedSource::new(relative(filename).display().to_string(), src);
+            let labels: Vec<_> = spans
+                .iter()
+                .map(|span| {
+                    miette::LabeledSpan::at(
+                        span.0.clone().byte_range,
+                        format!("{}/{total}", span.1 + 1),
+                    )
+                })
+                .collect();
+            let report = match help {
+                Some(ref help) => miette!(help = help, labels = labels, ""),
+                None => miette!(labels = labels, ""),
+            };
+            eprint!("{:?}", report.with_source_code(named_src));
+        }
+    } else if let Some(help) = help {
+        info!("help: {help}");
+    }
+    // FIXME: println!("\n... to display a more verbose message use: {}", format!("bee explain {code}"));
+}

          
A => src/bin/bee/cache.rs +78 -0
@@ 0,0 1,78 @@ 
+use bee::cache::CACHE_ROOT;
+use bee::cli::CacheArgs;
+use log::{error, info};
+use std::fs;
+use std::path::Path;
+use walkdir::WalkDir;
+
+/// TODO: write documentation...
+pub(crate) fn handle(args: &CacheArgs) -> exitcode::ExitCode {
+    match args {
+        CacheArgs::Clear(args) => {
+            if args.all && args.input.is_some() {
+                error!("I'm confused ... you give to `bee cache` command an input and the `--all` arg, there are mutually exclusive");
+                return exitcode::USAGE;
+            }
+            if !args.all && args.input.is_none() {
+                error!("`bee cache` command take either an input or the `--all` arg (that remove all of the global build cache)");
+                return exitcode::USAGE;
+            }
+            if args.all {
+                if CACHE_ROOT.exists() {
+                    fs::remove_dir_all(CACHE_ROOT.clone()).unwrap();
+                }
+                info!("The build cache have been globally cleared.");
+            }
+            if let Some(input) = &args.input {
+                // FIXME: be able to remove a file or folder in cache that does not exist on filesystem
+                if !input.exists() {
+                    error!("file or folder {} does not exist", input.display());
+                    return exitcode::NOINPUT;
+                }
+                let cache_path = &CACHE_ROOT.join(fs::canonicalize(input).unwrap());
+                if cache_path.is_dir() {
+                    fs::remove_dir_all(cache_path).unwrap();
+                }
+                if cache_path.is_file() {
+                    fs::remove_file(cache_path).unwrap();
+                    fs::remove_file(cache_path.with_extension("deps")).unwrap();
+                }
+            }
+            exitcode::OK
+        }
+        CacheArgs::Gc => {
+            for entry in WalkDir::new(CACHE_ROOT.clone()) {
+                let entry = entry.unwrap();
+                if entry.file_type().is_file() {
+                    let cache_path = entry.path();
+                    if cache_path.extension().unwrap() == "js" {
+                        let path = cache_path.display().to_string();
+                        let path = path
+                            .strip_prefix(&CACHE_ROOT.display().to_string())
+                            .unwrap();
+                        // FIXME: this will not play well with filename
+                        // containing `.` (other than the `.bee` extension) ...
+                        let path = format!("{}.bee", path.split('.').collect::<Vec<&str>>()[0]);
+                        let path = Path::new(&path);
+                        // FIXME: understand why it's /.prelude... and not /prelude...
+                        if !path.exists() && !path.display().to_string().starts_with("/.") {
+                            fs::remove_file(cache_path).unwrap();
+                            fs::remove_file(cache_path.with_extension("deps")).unwrap();
+                            info!("Cleared `{}` from build cache ...", path.display())
+                        }
+                    }
+                }
+            }
+            info!("The build cache garbage-collection (GC) is completed.");
+            exitcode::OK
+        }
+        CacheArgs::Prune(_) => {
+            error!("`bee cache prune` command is not yet implemented");
+            info!(
+                "To keep up-to-date with the project, subscribe to \"announce\" mailing-list:
+https://lists.sr.ht/~yvan-sraka/bee-lang-announce"
+            );
+            exitcode::UNAVAILABLE
+        }
+    }
+}

          
A => src/bin/bee/explain.rs +12 -0
@@ 0,0 1,12 @@ 
+use bee::cli::ExplainArgs;
+use log::{error, info};
+
+/// TODO: write documentation...
+pub(crate) fn handle(_args: &ExplainArgs) -> exitcode::ExitCode {
+    error!("`bee explain` command is not yet implemented");
+    info!(
+        "To keep up-to-date with the project, subscribe to \"announce\" mailing-list:
+https://lists.sr.ht/~yvan-sraka/bee-lang-announce"
+    );
+    exitcode::UNAVAILABLE
+}

          
A => src/bin/bee/main.rs +84 -0
@@ 0,0 1,84 @@ 
+mod build;
+mod cache;
+mod explain;
+mod run;
+
+use bee::cli::{Cli, Commands};
+use clap::{CommandFactory, Parser};
+#[cfg(debug_assertions)]
+use log::warn;
+use owo_colors::{OwoColorize, Stream::Stdout, Style};
+use std::io::Write;
+
+fn main() {
+    let env = env_logger::Env::default()
+        .filter_or("BEE_LOG", "info")
+        .write_style_or("BEE_LOG_STYLE", "auto");
+    env_logger::Builder::from_env(env)
+        .format(|buf, record| {
+            writeln!(
+                buf,
+                "{}{}",
+                match record.level() {
+                    log::Level::Error => "error: "
+                        .if_supports_color(Stdout, |text| text.style(Style::new().red().bold()))
+                        .to_string(),
+                    log::Level::Warn => "warning: "
+                        .if_supports_color(Stdout, |text| text.style(Style::new().yellow().bold()))
+                        .to_string(),
+                    log::Level::Info => "".to_owned(),
+                    log::Level::Debug => "debug: ".to_owned(),
+                    log::Level::Trace => "trace: ".to_owned(),
+                },
+                record.args()
+            )
+        })
+        .init();
+    #[cfg(debug_assertions)]
+    warn!("you use a debug build of bee, the build cache is disabled");
+    #[cfg(not(debug_assertions))]
+    human_panic::setup_panic!();
+    // FIXME: I forked `human_panic` to customize the message:
+    // let prev = std::panic::take_hook();
+    // std::panic::set_hook(Box::new(move |info| {
+    //     prev(info);
+    // }));
+
+    // FIXME: This break NO_COLOR support, so I forked `miette` ...
+    // miette::set_hook(Box::new(|_| {
+    //     Box::new(
+    //         miette::MietteHandlerOpts::new()
+    //             .graphical_theme(miette::GraphicalTheme {
+    //                 characters: miette::ThemeCharacters {
+    //                     warning: "".into(),
+    //                     error: "".into(),
+    //                     advice: "".into(),
+    //                     ..miette::ThemeCharacters::unicode()
+    //                 },
+    //                 ..Default::default()
+    //             })
+    //             .build(),
+    //     )
+    // }))
+    // .unwrap();
+
+    let args = std::env::args().collect::<Vec<String>>();
+    if args.contains(&"--help".to_string()) || args.contains(&"-h".to_string()) {
+        Cli::command().print_help().unwrap();
+        println!(
+            "
+To keep up-to-date with the project, subscribe to \"announce\" mailing-list:
+https://lists.sr.ht/~yvan-sraka/bee-lang-announce bzz bzz bzz"
+        );
+        std::process::exit(0);
+    }
+
+    let cli = Cli::parse();
+
+    std::process::exit(match &cli.command {
+        Commands::Build(args) => build::handle(args),
+        Commands::Cache(args) => cache::handle(args),
+        Commands::Run(args) => run::handle(args),
+        Commands::Explain(args) => explain::handle(args),
+    });
+}

          
A => src/bin/bee/run.rs +12 -0
@@ 0,0 1,12 @@ 
+use bee::cli::RunArgs;
+use log::{error, info};
+
+/// TODO: write documentation...
+pub(crate) fn handle(_args: &RunArgs) -> exitcode::ExitCode {
+    error!("`bee run` command is not yet implemented");
+    info!(
+        "To keep up-to-date with the project, subscribe to \"announce\" mailing-list:
+https://lists.sr.ht/~yvan-sraka/bee-lang-announce"
+    );
+    exitcode::UNAVAILABLE
+}

          
A => src/build.rs +58 -0
@@ 0,0 1,58 @@ 
+use crate::codegen::{codegen, targets_codegen};
+use crate::eval::eval;
+use crate::parser::{parse, Span};
+use log::{trace, warn};
+use std::collections::BTreeSet;
+use std::path::Path;
+use std::sync::{Arc, Mutex};
+
+/// TODO: write documentation...
+pub const PRELUDE: &str = include_str!("./prelude.bee");
+
+lazy_static! {
+    /// TODO: write documentation...
+    static ref WARNINGS: Arc<Mutex<Vec<Error>>> =
+        Arc::new(Mutex::new(vec![]));
+}
+
+/// Custom error type that is use to produce a compiler error
+#[derive(Debug)]
+pub struct Error {
+    /// TODO: write documentation...
+    pub code: String, // FIXME: error code should be an enum!
+    /// TODO: write documentation...
+    pub msg: String,
+    /// TODO: write documentation...
+    pub stacktrace: Option<Vec<Span>>,
+    /// TODO: write documentation...
+    pub help: Option<String>,
+}
+
+/// TODO: write documentation...
+pub fn build(src: &[u8], filename: &Path, targets: &BTreeSet<&str>) -> Result<String, Error> {
+    // FIXME: give a try to `imbl` crate rather than cloning a BTreeSet ...
+    let mut targets = targets.clone();
+    if targets.contains("abstract") {
+        warn!("@abstract target is reserved to compiler internals and is ignored when passed as CLI argument")
+    }
+    let tree = parse(src);
+    trace!("Parsing ... done");
+    // FIXME: typing (abstract interpretation of program) should not be ran if
+    // a .bee.t file already exist and is more recent than the .bee file built
+    targets.insert("abstract");
+    let js = codegen(&tree, src, filename, &targets)?;
+    // ... yes yes ... we run codegen BEFORE typing ...
+    trace!("Codegen ... done");
+    // FIXME: had a --disable-checks CLI arg that remove this step?
+    eval(format!("{}{js}", targets_codegen(&targets)))?;
+    targets.remove("abstract");
+    trace!("Typing  ... done");
+    let js = codegen(&tree, src, filename, &targets)?;
+    // FIXME: have a @release target that minify the output ...
+    // ... e.g. with https://github.com/wilsonzlin/minify-js
+    Ok(format!(
+        "{}{js}
+module.exports = __bee_export;",
+        targets_codegen(&targets)
+    ))
+}

          
A => src/cache.rs +139 -0
@@ 0,0 1,139 @@ 
+use crate::build::Error;
+use crate::VERSION;
+use directories::ProjectDirs;
+use log::info;
+use owo_colors::{OwoColorize, Stream::Stdout, Style};
+use std::collections::{BTreeSet, HashMap};
+use std::env;
+#[cfg(not(debug_assertions))]
+use std::fs;
+use std::path::{Path, PathBuf};
+use std::sync::{Arc, Mutex};
+
+lazy_static! {
+    /// TODO: write documentation...
+    static ref DEPENDENCIES: Arc<Mutex<HashMap<PathBuf, Vec<PathBuf>>>> =
+        Arc::new(Mutex::new(HashMap::new()));
+    /// TODO: write documentation...
+    pub static ref CACHE_ROOT: PathBuf = ProjectDirs::from("org", "yvan-sraka", "bee-lang")
+        .unwrap()
+        .cache_dir()
+        .join(VERSION);
+    /// TODO: write documentation...
+    static ref CURRENT_DIR: PathBuf = env::current_dir().unwrap();
+}
+
+/// TODO: write documentation...
+#[inline(always)]
+pub(crate) fn register_dependency(filename: &Path, dependency: &Path) {
+    DEPENDENCIES
+        .lock()
+        .unwrap()
+        .entry(filename.into())
+        .or_default()
+        .push(dependency.into());
+}
+
+#[cfg(not(debug_assertions))]
+fn dependencies_changed(cache_file: &Path, targets: &BTreeSet<&str>) -> bool {
+    let mut deps_file = cache_file.to_path_buf();
+    deps_file.set_extension("deps");
+    for dep in fs::read_to_string(&deps_file).unwrap().lines() {
+        let dep = Path::new(dep);
+        match use_cached_version(dep, targets) {
+            Ok(_) => {}
+            Err(_) => return true,
+        }
+    }
+    false
+}
+
+#[cfg(not(debug_assertions))]
+fn use_cached_version(filename: &Path, targets: &BTreeSet<&str>) -> Result<PathBuf, PathBuf> {
+    let mut cached_file = CACHE_ROOT.join(format!(".{}", filename.display()));
+    cached_file.set_extension(format!(
+        "{}.js",
+        targets
+            .iter()
+            .map(|x| x.to_owned())
+            .collect::<Vec<&str>>()
+            .join(".")
+    ));
+    if cached_file.exists()
+        && (filename.display().to_string() == "prelude"
+            || (cached_file.metadata().unwrap().modified().unwrap()
+                > filename.metadata().unwrap().modified().unwrap()
+                && !dependencies_changed(&cached_file, targets)))
+    {
+        Ok(cached_file)
+    } else {
+        Err(cached_file)
+    }
+}
+
+type Builder = fn(&[u8], &Path, &BTreeSet<&str>) -> Result<String, Error>;
+
+/// TODO: write documentation...
+pub fn cached(
+    src: &[u8],
+    filename: &Path,
+    targets: &BTreeSet<&str>,
+    callback: Builder,
+) -> Result<String, Error> {
+    #[cfg(debug_assertions)]
+    {
+        build_log(filename, targets, false);
+        callback(src, filename, targets)
+    }
+    // Disabling caching in debug mode save hours as you may not want to return
+    // artifacts that doesn't reflect your changes as you're hacking on the
+    // compiler ;)
+    #[cfg(not(debug_assertions))]
+    Ok(match use_cached_version(filename, targets) {
+        Ok(cached_file) => {
+            build_log(filename, targets, true);
+            fs::read_to_string(cached_file).unwrap()
+        }
+        Err(cached_file) => {
+            build_log(filename, targets, false);
+            let result = callback(src, filename, targets)?;
+
+            fs::create_dir_all(cached_file.parent().unwrap()).unwrap();
+            fs::write(&cached_file, &result).unwrap();
+
+            let mut deps_file = cached_file.to_path_buf();
+            deps_file.set_extension("deps");
+            let deps = match DEPENDENCIES.lock().unwrap().get(filename) {
+                Some(x) => x
+                    .iter()
+                    .map(|x| x.display().to_string())
+                    .collect::<Vec<_>>()
+                    .join("\n"),
+                None => "".to_owned(),
+            };
+            fs::write(&deps_file, deps).unwrap();
+
+            result
+        }
+    })
+}
+
+/// TODO: write documentation...
+#[inline(always)]
+fn build_log(filename: &Path, targets: &BTreeSet<&str>, cached: bool) {
+    if !targets.contains("abstract") {
+        info!(
+            "Building {} {}...",
+            relative(filename)
+                .display()
+                .if_supports_color(Stdout, |text| text.style(Style::new().bold().bright_cyan())),
+            if cached { "(cached) " } else { "" }
+        );
+    }
+}
+
+/// TODO: write documentation...
+#[inline(always)]
+pub fn relative(path: &Path) -> PathBuf {
+    pathdiff::diff_paths(path, CURRENT_DIR.to_owned()).unwrap_or(path.to_owned())
+}

          
A => src/cli.rs +87 -0
@@ 0,0 1,87 @@ 
+use std::path::PathBuf;
+
+/// 🌸 🌼 🐝 The Bee programming language compiler 🌺 🌼 🌸
+#[derive(clap::Parser, Debug)]
+#[clap(author, version, about, long_about = None)]
+pub struct Cli {
+    #[clap(subcommand)]
+    pub command: Commands,
+}
+
+/// Main list of commands that can take `bee` CLI as argument
+#[derive(clap::Subcommand, Debug)]
+pub enum Commands {
+    /// Builds a given file or the `main.bee` within a given folder (by default the current folder)
+    Build(BuildArgs),
+    /// Manage build cache used by Bee compiler
+    #[clap(subcommand)]
+    Cache(CacheArgs),
+    /// Print a more verbose explaination for a given compiler error code
+    Explain(ExplainArgs),
+    /// Run a given script without compiling it to ECMAScript
+    Run(RunArgs),
+    // FIXME: add REPL command ... with cool message explaining the feature is missing :'(
+}
+
+/// Arguments for the `build` command
+#[derive(clap::Parser, Debug)]
+pub struct BuildArgs {
+    /// Input file name (.bee), that can also be piped in
+    pub input: Option<PathBuf>,
+
+    /// Output file name (.js), that can also be piped out
+    #[clap(short, long)]
+    pub output: Option<PathBuf>,
+
+    /// List of (comma or space separated) compiler targets
+    #[clap(short, long)]
+    pub targets: Option<String>,
+}
+
+/// Subcommands of the `cache` command
+#[derive(clap::Subcommand, Debug)]
+pub enum CacheArgs {
+    /// Clears the cache based on various criteria
+    Clear(CacheClearArgs),
+    /// Performs garbage collection on the cache, removing entries for files that no longer exist in the user’s file system
+    Gc,
+    /// Removes items from the cache based on age
+    Prune(CachePruneArgs),
+}
+
+/// TODO: write documentation...
+#[derive(clap::Parser, Debug)]
+pub struct CacheClearArgs {
+    /// Clears the cache for a specific path (file or folder)
+    pub input: Option<PathBuf>,
+
+    /// Clears the cache for a specific file and its dependencies
+    #[clap(short, long)]
+    pub deps: Option<String>,
+
+    /// Clears the entire build cache
+    #[clap(short, long)]
+    pub all: bool,
+    // FIXME: let user pass a --targets argument to allow more fine grained
+    // control over cache management?
+}
+
+/// TODO: write documentation...
+#[derive(clap::Parser, Debug)]
+pub struct CachePruneArgs {
+    /// Removes cache items that were created before a specific date
+    #[clap(short, long)]
+    before: Option<String>,
+
+    /// Removes cache items that are older than a specified duration (e.g., β€œ30d” for 30 days)
+    #[clap(short, long)]
+    older_than: Option<String>,
+}
+
+/// TODO: write documentation...
+#[derive(clap::Parser, Debug)]
+pub struct ExplainArgs;
+
+/// TODO: write documentation...
+#[derive(clap::Parser, Debug)]
+pub struct RunArgs;

          
A => src/codegen.rs +641 -0
@@ 0,0 1,641 @@ 
+use crate::build::{Error, PRELUDE};
+use crate::cache::{cached, register_dependency};
+#[cfg(feature = "rayon")]
+use crate::parser::Nodes;
+use crate::parser::{parse, Span};
+#[cfg(feature = "rayon")]
+use rayon::prelude::*;
+use regex::{Captures, Regex};
+use std::collections::BTreeSet;
+use std::fs;
+use std::path::{Path, PathBuf};
+
+/// This is a naive approach to code generation intended for experimenting with
+/// the semantics of a Bee program.
+///
+/// The main idea is to generate JS values that can be embedded in a JS script.
+/// For example, the Bee expression `[1 2 3]` should produce JS code that, once
+/// evaluated, equals `[1, 2, 3]`.
+///
+/// The code generation should be capable of taking as input both the AST built
+/// by parsing (as it currently does) and an AST augmented with type
+/// annotations (and other invariants) inferred from static analysis. These
+/// annotations will be cached in a `.bee.t` file, which users are advised to
+/// distribute with their script.
+///
+/// This setup will enable a fast build mode (without typing if `.bee.t` is
+/// missing) and a slow one (typing is required if `.bee.ts` is missing or
+/// outdated). The fast compilation mode could be dropped if a Bee VM is
+/// implemented, as users who want to quickly evaluate their programs might
+/// prefer an interpreter over a compiler.
+///
+/// Currently, there is a WIP JavaScript implementation of a VM. One strategy
+/// could then be to perform codegen by simply serializing the AST to JSON and
+/// appending the JS runtime next to it. The generated JS will likely not be
+/// handled efficiently by JavaScript's JIT and tooling, but this approach
+/// allows more room for implementing reflexivity features without relying on
+/// JS's `eval`.
+///
+/// Currently, the codegen always adds debug symbols to the JS output, but this
+/// should be made optional. For example, a `--release` mode could omit the
+/// symbols and run a JS minification pass.
+pub fn codegen(
+    tree: &tree_sitter::Tree,
+    src: &[u8],
+    filename: &Path,
+    targets: &BTreeSet<&str>,
+) -> Result<String, Error> {
+    let prelude = PRELUDE.as_bytes();
+    Ok(format!(
+        "// RUNTIME
+{}
+// PRELUDE
+__bee_env = {};
+// USER CODE
+const __bee_export = {};
+",
+        include_str!("./runtime.js"),
+        cached(prelude, Path::new("prelude"), targets, codegen_module)?,
+        rec_codegen(&tree.root_node(), src, filename, targets)?
+    ))
+}
+
+/// TODO: write documentation...
+#[inline(always)]
+pub fn codegen_module(
+    src: &[u8],
+    filename: &Path,
+    targets: &BTreeSet<&str>,
+) -> Result<String, Error> {
+    rec_codegen(&parse(src).root_node(), src, filename, targets)
+}
+
+fn rec_codegen(
+    node: &tree_sitter::Node,
+    src: &[u8],
+    filename: &Path,
+    targets: &BTreeSet<&str>,
+) -> Result<String, Error> {
+    let kind = node.kind();
+
+    let span = Span {
+        byte_range: node.byte_range(),
+        filename: filename.to_owned(),
+    };
+
+    if node.is_error() || node.is_missing() {
+        // FIXME: have a codegen::Error type
+        Err(Error {
+            msg: format!(
+                "parsing error{}",
+                if node.is_missing() {
+                    format!(": `{}` is missing", kind)
+                } else {
+                    "".to_owned()
+                }
+            ),
+            help: hint(node.utf8_text(src).unwrap()),
+            stacktrace: Some(vec![span.clone()]),
+            code: "PA001".to_owned(),
+        })?;
+    }
+
+    let children = (0..node.child_count())
+        .map(|i| node.child(i).unwrap())
+        .filter(|x| {
+            !matches!(
+                x.kind(),
+                "," | ";"
+                    | "."
+                    | "..."
+                    | "("
+                    | ")"
+                    | "["
+                    | "]"
+                    | "{"
+                    | "}"
+                    | "\n"
+                    | "="
+                    | "=>"
+                    | "$"
+                    | "block_comment"
+                    | "inline_comment"
+                    | "else"
+                    | "if"
+                    | "import"
+                    | "native"
+                    | "panic"
+                    | "return"
+                    | "then"
+            )
+        })
+        .collect::<Vec<tree_sitter::Node>>();
+
+    Ok(match kind {
+        "apply" => {
+            let xs = children_codegen(children, src, filename, targets)?;
+            let id = &xs[0];
+            let args = xs[1..].join(", ");
+            format!("__bee_fn_apply({id}, [{args}], \"{span}\")")
+        }
+
+        "arg" | "bool" | "delimiter" | "expr" | "field" | "source_file" | "statement" | "value" => {
+            children_codegen(children, src, filename, targets)?.join("")
+        }
+
+        "id" => {
+            // FIXME: warning if `_` is used as an `id` unless it's an lambda `arg`
+            let id = children_codegen(children, src, filename, targets)?.join(", ");
+            format!("__bee_get_id(__bee_env, [{id}], \"{span}\")")
+        }
+
+        "name" => {
+            let name = node.utf8_text(src).unwrap();
+            let help = if name == "return" {
+                Some("`return` could be use only directly inside a block. e.g. `{ a = 1; b = 2; return {a} }`".to_owned())
+            } else {
+                None
+            };
+            if is_reserved_keywords(name) {
+                Err(Error {
+                    msg: format!(
+                        "use of the reserved keyword `{name}` as an identifier is forbidden"
+                    ),
+                    help,
+                    stacktrace: Some(vec![span]),
+                    code: "PA002".to_owned(),
+                })?
+            }
+            format!("\"{name}\"")
+        }
+
+        "nth" => node.utf8_text(src).unwrap().to_owned(),
+
+        "placeholder" => {
+            debug_assert!(children.len() == 1);
+            rec_codegen(&children[0], src, filename, targets)?
+        }
+
+        "true" => "true".to_owned(),
+        "false" => "false".to_owned(),
+
+        "target" => {
+            let x = &node.utf8_text(src).unwrap()[1..];
+            format!("__bee_targets.{x}")
+        }
+
+        "bigint" => {
+            let x = node.utf8_text(src).unwrap();
+            format!("{x}n")
+        }
+
+        "f64" => {
+            let x: f64 = node.utf8_text(src).unwrap().parse().unwrap();
+            x.to_string()
+        }
+
+        "string" => {
+            // FIXME: Rust strings are UTF-8, but JavaScript ones are UTF-16 ...
+            let haystack = node.utf8_text(src).unwrap();
+            let pattern = Regex::new(r"\$\{([^}]+)\}").unwrap();
+            for caps in pattern.captures_iter(haystack) {
+                let name = &caps[1];
+                let re = Regex::new(r"^[a-zA-Z_][a-zA-Z0-9_]*$").unwrap();
+                if !re.is_match(name) {
+                    return Err(Error { code: "PA008".to_owned(), msg: format!("`{name}` is invalid, only simple identifiers can be interpolated in string."), stacktrace: Some(vec![span]), help: None });
+                }
+            }
+            pattern
+                .replace_all(haystack, |caps: &Captures| {
+                    let name = &caps[1];
+                    format!("\" + __bee_get_id(__bee_env, [\"{name}\"], \"{span}\") + \"")
+                })
+                .to_string()
+        }
+
+        "do" => {
+            let block = children_codegen(children, src, filename, targets)?.join(";\n");
+            format!(
+                "(__bee_env => {{
+    __bee_env.self = __bee_env;
+    {block}
+    return  __bee_env_untag(__bee_env);
+}})(__bee_env_tag(__bee_env))"
+            )
+        }
+
+        // FIXME: pattern match on arguments!
+        "fn" => {
+            debug_assert!(children.len() == 2);
+            let arg = children[0].utf8_text(src).unwrap();
+            let value = rec_codegen(&children[1], src, filename, targets)?;
+            format!(
+                "(__bee_env_captured => {{
+    __bee_env_captured.self = __bee_env.self;
+    return __bee_arg => {{
+        const __bee_env = __bee_env_captured;
+        __bee_env.{arg} = __bee_arg;
+        return {value};
+    }};
+}})(__bee_env_copy(__bee_env))",
+            )
+        }
+
+        "if_then_else" => {
+            debug_assert!(children.len() == 3);
+            let xs = &children_codegen(children, src, filename, targets)?;
+            // FIXME: this is a hack ... add @concrete target? do this for any target ...
+            if targets.contains("abstract") {
+                return Ok(if xs[0] == "__bee_targets.abstract" {
+                    &xs[1]
+                } else {
+                    &xs[2]
+                }
+                .to_owned());
+            }
+            // FIXME: on @abstract a different codegen should be used!
+            format!("({} ? {} : {})", xs[0], xs[1], xs[2])
+        }
+
+        "let" => {
+            debug_assert!(children.len() == 2);
+            let lvalue = children[0].utf8_text(src).unwrap();
+            let rvalue = rec_codegen(&children[1], src, filename, targets)?;
+            let lvalue_span = Span {
+                byte_range: children[0].byte_range(),
+                ..span.clone()
+            };
+            if is_reserved_keywords(lvalue) {
+                Err(Error {
+                    msg: format!("use of the reserved keyword `{lvalue}` as l-value is forbidden"),
+                    help: None,
+                    stacktrace: Some(vec![lvalue_span]),
+                    code: "PA003".to_owned(),
+                })?
+            } else if lvalue == "_" || lvalue == "self" {
+                Err(Error {
+                    msg: format!("`${lvalue}` should not be used as an l-value"),
+                    help: None,
+                    stacktrace: Some(vec![lvalue_span]),
+                    code: "PA004".to_owned(),
+                })?
+            } else {
+                format!("__bee_env.{lvalue} = {rvalue}")
+            }
+        }
+
+        // FIXME: code is duplicated form `let` codegen ...
+        "name_alias" => {
+            debug_assert!(children.len() == 1);
+            let lvalue = children[0].utf8_text(src).unwrap();
+            let rvalue = format!("__bee_get_id(__bee_env, [\"{lvalue}\"], \"{span}\")");
+            if is_reserved_keywords(lvalue) {
+                Err(Error {
+                    msg: format!("use of the reserved keyword `{lvalue}` as l-value is forbidden"),
+                    help: None,
+                    stacktrace: Some(vec![span]),
+                    code: "PA003".to_owned(),
+                })?
+            } else if lvalue == "_" || lvalue == "self" {
+                Err(Error {
+                    msg: format!("`${lvalue}` should not be used as an l-value"),
+                    help: None,
+                    stacktrace: Some(vec![span]),
+                    code: "PA004".to_owned(),
+                })?
+            } else {
+                format!("__bee_env.{lvalue} = {rvalue}")
+            }
+        }
+
+        "spread" => {
+            debug_assert!(children.len() == 1);
+            let id = children[0].utf8_text(src).unwrap();
+            let rvalue = format!("__bee_get_id(__bee_env, [\"{id}\"], \"{span}\")");
+            format!("__bee_env = {{...__bee_env, ...{rvalue}}}")
+        }
+
+        "array" => {
+            let array = children_codegen(children, src, filename, targets)?.join(", ");
+            format!("[{array}]")
+        }
+
+        "panic_" => {
+            debug_assert!(children.len() == 1);
+            let rvalue = rec_codegen(&children[0], src, filename, targets)?;
+            format!("__bee_error(\"RT001\", {rvalue}, \"{span}\")")
+        }
+
+        "return_" => {
+            debug_assert!(children.len() == 1);
+            let rvalue = rec_codegen(&children[0], src, filename, targets)?;
+            format!("return {rvalue}")
+        }
+
+        // FIXME: a warning should be displayed to user when `native` keyword
+        // is used outside of prelude
+        "native_" => {
+            debug_assert!(children.len() == 1);
+            // FIXME: forbid the use of `native` in @abstract mode, this will
+            // force a better separation of concerns ...
+            // if targets.contains("abstract") {
+            //     "{}".to_owned()
+            // } else ...
+            let haystack = children[0].utf8_text(src).unwrap().replace("\\\"", "\"");
+            let pattern = Regex::new(r"\$\{([^}]+)\}").unwrap();
+            for caps in pattern.captures_iter(&haystack) {
+                let name = &caps[1];
+                let re = Regex::new(r"^[a-zA-Z_][a-zA-Z0-9_]*$").unwrap();
+                if !re.is_match(name) {
+                    return Err(Error { code: "PA008".to_owned(), msg: format!("`{name}` is invalid, only simple identifiers can be interpolated in string."), stacktrace: Some(vec![span]), help: None });
+                }
+            }
+            let interpolated = pattern.replace_all(&haystack, |caps: &Captures| {
+                let name = &caps[1];
+                format!("__bee_get_id(__bee_env, [\"{name}\"], \"{span}\")")
+            });
+            strip_quotes(&interpolated)
+        }
+
+        "import_" => {
+            // FIXME: support URLs (pointing e.g. to a git repository or a code
+            // archive). This is not trivial to implement as it should require
+            // e.g. some TOFU mechanism that store a checksum of the remote
+            // ressource in a .lock file that could be distributed with user
+            // sources.
+            debug_assert!(children.len() == 1);
+            let mut import = PathBuf::from(filename)
+                .parent()
+                .unwrap()
+                .join(strip_quotes(children[0].utf8_text(src).unwrap()));
+            if let Ok(metadata) = fs::metadata(&import) {
+                if metadata.is_dir() {
+                    import = import.join("main.bee");
+                }
+            };
+            if !is_valid_extension(&import) {
+                Err(Error {
+                    msg: format!("File `{}` extension should be `.bee`", import.display()),
+                    help: None,
+                    stacktrace: Some(vec![Span {
+                        byte_range: children[0].byte_range(),
+                        ..span.clone()
+                    }]),
+                    code: "PA006".to_owned(),
+                })?
+            }
+            if !is_valid_filename(&import) {
+                Err(Error {
+                    msg: format!(
+                        "File path `{}` contains illegal characters: `:`, `.`, `[` or `]`",
+                        import.display()
+                    ),
+                    help: None,
+                    stacktrace: Some(vec![Span {
+                        byte_range: children[0].byte_range(),
+                        ..span.clone()
+                    }]),
+                    code: "PA007".to_owned(),
+                })?
+            }
+            match std::fs::read_to_string(&import) {
+                Ok(src) => {
+                    let src = src.as_bytes();
+                    let import = fs::canonicalize(import).unwrap();
+                    register_dependency(filename, &import);
+                    cached(src, &import, targets, codegen_module)?
+                }
+                Err(err) => Err(Error {
+                    msg: format!("error while reading file {}: {err}", &import.display()),
+                    help: None,
+                    stacktrace: Some(vec![Span {
+                        byte_range: children[0].byte_range(),
+                        ..span.clone()
+                    }]),
+                    code: "PA005".to_owned(),
+                })?,
+            }
+        }
+
+        "prefix" => {
+            debug_assert!(children.len() == 2);
+            let op = children[0].utf8_text(src).unwrap();
+            let op_span = Span {
+                byte_range: children[0].byte_range(),
+                ..span.clone()
+            };
+            let right = rec_codegen(&children[1], src, filename, targets)?;
+            format!("__bee_fn_apply(__bee_get_id(__bee_env, [\"ops\", \"{}\"], \"{op_span}\"), [{right}], \"{span}\")",
+            match op {
+                "!" => "not",
+                "-" => "unary_minus",
+                _ => unimplemented!(
+                    "`{}' prefix operator handling is missing in `codegen.rs` implentation",
+                    op
+                ),
+            })
+        }
+
+        "infix" => {
+            debug_assert!(children.len() == 3);
+            let left = rec_codegen(&children[0], src, filename, targets)?;
+            let op = children[1].utf8_text(src).unwrap();
+            let op_span = Span {
+                byte_range: children[1].byte_range(),
+                ..span.clone()
+            };
+            let right = rec_codegen(&children[2], src, filename, targets)?;
+            format!("__bee_fn_apply(__bee_get_id(__bee_env, [\"ops\", \"{}\"], \"{op_span}\"), [{left}, {right}], \"{span}\")",
+            match op {
+                "==" => "eq",
+                "!=" => "neq",
+                "/" => "div",
+                "*" => "mul",
+                "%" => "mod",
+                "+" => "add",
+                "-" => "sub",
+                "<" => "lt",
+                ">" => "gt",
+                "<=" => "lte",
+                ">=" => "gte",
+                "|" => "or",
+                "&" => "and",
+                "|>" => "pipe",
+                "<|" => "reverse_pipe",
+                ".." => "range",
+                _ => unimplemented!(
+                    "`{}' infix operator handling is missing in `codegen.rs` implentation",
+                    op
+                ),
+            })
+        }
+
+        _ => unimplemented!(
+            "`{}' token kind handling is missing in `codegen.rs` implentation",
+            kind
+        ),
+    })
+}
+
+/// TODO: write documentation...
+#[inline(always)]
+pub fn is_valid_extension(path: &Path) -> bool {
+    if let Some(ext) = path.extension() {
+        ext == "bee"
+    } else {
+        false
+    }
+}
+
+/// TODO: write documentation...
+#[inline(always)]
+pub fn is_valid_filename(path: &Path) -> bool {
+    !path.file_stem().unwrap().to_string_lossy().contains('.')
+        && !path.to_string_lossy().contains(':')
+        && !path.to_string_lossy().contains('[')
+        && !path.to_string_lossy().contains(']')
+}
+
+/// TODO: write documentation...
+#[inline(always)]
+pub fn hint(keyword: &str) -> Option<String> {
+    match keyword {
+        "import" => Some(
+            "`import` take one string argument which is a path, e.g. `import \"my_module.bee\"`"
+                .to_owned(),
+        ),
+        _ => None,
+    }
+}
+
+/// TODO: write documentation...
+#[inline(always)]
+pub fn strip_quotes(x: &str) -> String {
+    debug_assert!(x.starts_with('\"') && x.chars().nth(x.len() - 1).unwrap() == '"');
+    x[1..x.len() - 1].to_owned()
+}
+
+#[inline(always)]
+fn children_codegen(
+    children: Vec<tree_sitter::Node>,
+    src: &[u8],
+    filename: &Path,
+    targets: &BTreeSet<&str>,
+) -> Result<Vec<String>, Error> {
+    #[cfg(feature = "rayon")]
+    {
+        let nodes: Nodes = children.into();
+        return nodes
+            .par_iter()
+            .map(|x| rec_codegen(x.into(), src, filename, targets))
+            .collect::<Result<Vec<_>, _>>();
+    }
+    #[cfg(not(feature = "rayon"))]
+    return children
+        .iter()
+        .map(|x| rec_codegen(x, src, filename, targets))
+        .collect::<Result<Vec<_>, _>>();
+}
+
+/// TODO: write documentation...
+pub(crate) fn targets_codegen(targets: &BTreeSet<&str>) -> String {
+    let targets = targets
+        .iter()
+        .map(|x| format!("__bee_targets.{x} = true;"))
+        .collect::<Vec<String>>()
+        .join("\n");
+    format!(
+        "// TARGETS
+const __bee_targets = {{}};
+{targets}
+"
+    )
+}
+
+/// TODO: write documentation...
+#[inline(always)]
+pub fn is_reserved_keywords(x: &str) -> bool {
+    matches!(
+        x,
+        "abstract"
+            | "__proto__"
+            | "arguments"
+            | "as"
+            | "async"
+            | "await"
+            | "boolean"
+            | "break"
+            | "byte"
+            | "case"
+            | "catch"
+            | "char"
+            | "class"
+            | "concrete"
+            | "const"
+            | "constructor"
+            | "continue"
+            | "debugger"
+            | "default"
+            | "delete"
+            | "do"
+            | "double"
+            | "else"
+            | "enum"
+            | "eval"
+            | "export"
+            | "extends"
+            | "false"
+            | "final"
+            | "finally"
+            | "float"
+            | "for"
+            | "from"
+            | "function"
+            | "get"
+            | "goto"
+            | "hasOwnProperty"
+            | "if"
+            | "implements"
+            | "import"
+            | "in"
+            | "instanceof"
+            | "int"
+            | "interface"
+            | "isPrototypeOf"
+            | "let"
+            | "long"
+            | "native"
+            | "new"
+            | "null"
+            | "of"
+            | "package"
+            | "private"
+            | "propertyIsEnumerable"
+            | "protected"
+            | "public"
+            | "return"
+            | "set"
+            | "short"
+            | "static"
+            | "super"
+            | "switch"
+            | "synchronized"
+            | "then"
+            | "this"
+            | "throw"
+            | "throws"
+            | "toLocaleString"
+            | "toString"
+            | "transient"
+            | "true"
+            | "try"
+            | "typeof"
+            | "valueOf"
+            | "var"
+            | "void"
+            | "volatile"
+            | "while"
+            | "with"
+            | "yield"
+    ) || (x.len() >= 5 && &x[..5] == "__bee")
+}

          
A => src/eval.rs +107 -0
@@ 0,0 1,107 @@ 
+use crate::build::Error;
+use crate::parser::Span;
+use log::debug;
+use regex::Regex;
+
+/// Wow, what the !@#$ is this?
+///
+/// You've guessed it right – this evaluates a variant of the codegen at
+/// compile-time, one that uses a different prelude. When `prelude.bee` is
+/// compiled with the `@abstract` target, it provides users with a function
+/// that doesn't produce any side effects. Instead, it offers the abstract,
+/// type-as-values, equivalent of the expected result.
+///
+/// E.g., the `randint` function returns the `Range` of possible values when
+/// the program is built with the `@abstract` target, rather than generating
+/// native code:
+/// ```ignore
+/// randint = min => max =>
+///      if @abstract Range min max
+///      else native "${min} + Math.floor(Math.random() * ${max})"
+/// ```
+/// This approach means that the _soundness_ of a program's typing is linked to
+/// the _soundness_ of the Bee standard library constructs. You can find more
+/// details about how this is implemented in the Prelude documentation.
+///
+/// However, there is a downside. By embedding `deno_core`, a large crate, as a
+/// dependency of our compiler, `bee` has become a self-contained binary of
+/// ~60Mb. So, what's the alternative? The solution could be to implement our
+/// own VM that directly interprets the AST: `eval(s: &S) -> Result<(), Error>`
+///
+/// Such a VM implementation could also be repurposed to build, for example, a
+/// REPL!
+pub fn eval(src: String) -> Result<(), Error> {
+    #[cfg(all(feature = "quickjs", feature = "deno"))]
+    return Err(compile_error!(
+        "cargo features `deno` and `quickjs` are mutually exclusive"
+    ));
+    #[cfg(all(not(feature = "quickjs"), not(feature = "deno")))]
+    todo!(); // FIXME: use an external program (set in BEE_RUNTIME env
+             // variable) to perform the evaluation?
+    #[cfg(all(not(feature = "quickjs"), feature = "deno"))]
+    {
+        let mut rt = deno_core::JsRuntime::new(deno_core::RuntimeOptions::default());
+        Ok(if let Err(err) = rt.execute_script("<usage>", src.into()) {
+            debug!("Deno error: {err}");
+            read_debug_symbols(&err.to_string())?
+        })
+    }
+    #[cfg(all(feature = "quickjs", not(feature = "deno")))]
+    {
+        let rt = rquickjs::Runtime::new().unwrap();
+        rt.set_max_stack_size(1024 * 1024);
+        let ctx = rquickjs::Context::full(&rt).unwrap();
+        ctx.with(|ctx| {
+            if let Err(rquickjs::Error::Exception) = ctx.eval::<(), _>(src) {
+                let err = ctx.catch().as_exception().unwrap().message().unwrap();
+                debug!("QuickJS error: {err}");
+                read_debug_symbols(&err)?
+            }
+            Ok(())
+        })
+    }
+}
+
+/// TODO: write documentation...
+#[inline(always)]
+pub fn read_debug_symbols(trace: &str) -> Result<(), Error> {
+    if trace == "stack overflow" {
+        // FIXME: use `__bee_stacktrace` to give user a more semantic error!
+        // ctx.globals().get::<_, rquickjs::Array>("__bee_stacktrace").unwrap();
+        return Err(Error {
+            help: None,
+            msg: "a stack overflow was encountered, it's likely caused by an infinite recursion"
+                .to_owned(),
+            code: "TY007".to_owned(),
+            stacktrace: None,
+        });
+    }
+    let pattern = Regex::new(r"(\[.+:\d+:\d+\])* ([A-Z]{2}\d{3}) (.+)").unwrap();
+    let cap = pattern.captures_iter(trace).next().unwrap();
+    debug_assert!(cap.len() == 4);
+    let mut spans = cap[1].split("][").collect::<Vec<&str>>();
+    let last = spans.len() - 1;
+    spans[0] = spans[0].strip_prefix('[').unwrap();
+    spans[last] = spans[last].strip_suffix(']').unwrap();
+    let stacktrace: Option<Vec<Span>> = Some(
+        (0..=last)
+            .map(|i| {
+                let pattern = Regex::new(r"(.+):(\d+):(\d+)").unwrap();
+                let cap = pattern.captures_iter(spans[i]).next().unwrap();
+                debug_assert!(cap.len() == 4);
+                Span {
+                    byte_range: cap[2].parse().unwrap()..cap[3].parse().unwrap(),
+                    filename: cap[1].into(),
+                }
+            })
+            .collect(),
+    );
+    let code = cap[2].to_owned();
+    let msg = cap[3].to_owned();
+    Err(Error {
+        help: None,
+        msg,
+        code,
+        stacktrace,
+    })
+}

          
A => src/lib.rs +25 -0
@@ 0,0 1,25 @@ 
+//! TODO: write documentation...
+//!
+//! FIXME: use `cargo-sync-readme` to turn "to-be-written" crate top doc comment
+//! into a proper `README.md`!
+//!
+//! MSRV 1.70.0
+
+#[macro_use]
+extern crate lazy_static;
+
+/// TODO: write documentation...
+pub mod build;
+/// TODO: write documentation...
+pub mod cache;
+/// TODO: write documentation...
+pub mod cli;
+/// TODO: write documentation...
+pub mod codegen;
+/// TODO: write documentation...
+pub mod eval;
+/// TODO: write documentation...
+pub mod parser;
+
+/// TODO: write documentation...
+pub const VERSION: &str = "0.0.1";

          
A => src/parser.rs +79 -0
@@ 0,0 1,79 @@ 
+use std::fmt::Display;
+use std::ops::Range;
+use std::path::PathBuf;
+
+// FIXME: use https://codeberg.org/xlambein/ts-typed-ast
+// include!(concat!(env!("OUT_DIR"), "/ast.rs"));
+
+/// TODO: write documentation...
+pub fn parse(src: &[u8]) -> tree_sitter::Tree {
+    let mut parser = tree_sitter::Parser::new();
+    parser
+        .set_language(tree_sitter_bee_lang::language())
+        .unwrap();
+    parser.parse(src, None).unwrap()
+}
+
+/// TODO: write documentation...
+#[derive(Debug, Clone)]
+pub struct Span {
+    /// TODO: write documentation...
+    pub byte_range: Range<usize>,
+    /// TODO: write documentation...
+    pub filename: PathBuf,
+}
+
+impl Display for Span {
+    #[inline(always)]
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        // FIXME: this Display could cause confusion, since we output the
+        // `byte_range` and not the `line:column` ...
+        write!(
+            f,
+            "[{}:{}:{}]",
+            self.filename.display(),
+            self.byte_range.start,
+            self.byte_range.end
+        )?;
+        Ok(())
+    }
+}
+
+// FIXME: this was fixed in the `master` branch of TreeSitter, so this will
+// soon no longer be needed :)
+
+#[cfg(feature = "rayon")]
+pub(crate) struct NodeWrapper<'a>(tree_sitter::Node<'a>);
+
+#[cfg(feature = "rayon")]
+unsafe impl<'a> Sync for NodeWrapper<'a> {}
+
+#[cfg(feature = "rayon")]
+pub(crate) struct Nodes<'a>(Vec<NodeWrapper<'a>>);
+
+#[cfg(feature = "rayon")]
+impl<'a> From<Vec<tree_sitter::Node<'a>>> for Nodes<'a> {
+    #[inline(always)]
+    fn from(nodes: Vec<tree_sitter::Node<'a>>) -> Self {
+        Self(nodes.into_iter().map(NodeWrapper).collect())
+    }
+}
+
+#[cfg(feature = "rayon")]
+impl<'a, 'b> From<&'b NodeWrapper<'a>> for &'b tree_sitter::Node<'a> {
+    #[inline(always)]
+    fn from(safe_node: &'b NodeWrapper<'a>) -> Self {
+        &safe_node.0
+    }
+}
+
+#[cfg(feature = "rayon")]
+impl<'a> rayon::iter::IntoParallelRefIterator<'a> for Nodes<'a> {
+    type Iter = rayon::slice::Iter<'a, NodeWrapper<'a>>;
+    type Item = &'a NodeWrapper<'a>;
+
+    #[inline(always)]
+    fn par_iter(&'a self) -> Self::Iter {
+        self.0.par_iter()
+    }
+}

          
A => src/prelude.bee +208 -0
@@ 0,0 1,208 @@ 
+{
+    // assert :: Bool -> ()
+    assert = x => if x {} else panic "assertion failed"
+    // FIXME: add an "assert?" runtime primitive
+
+    // FIXME: add an UNSAFE "require"?
+
+    // show :: Any -> String
+    show = x => native "__bee_debug_display(${x})" // FIXME: use in print ...
+
+    // print :: Any -> ()
+    print = x => if @abstract {} else { x = show x; native "console.log(${x})"; return {} }
+
+    console = { log = print }
+
+    // parse :: String -> Any
+    parse = str => native "JSON.parse(${str})"
+
+    // length :: Object -> Number
+    length = obj => native "${obj}.length"
+
+    // reverse :: Object -> Object
+    reverse = obj => native "Array.isArray(${obj}) ? ${obj}.reverse() : Array.from(${obj}).reverse().join('')"
+
+    maths = {
+        // pow :: Number -> Number -> Number
+        pow = base => exponent => native "Math.pow(${base}, ${exponent})"
+
+        // sqrt :: Number -> Number
+        sqrt = x => native "Math.sqrt(${x})"
+
+        // abs :: Number -> Number
+        abs = x => native "Math.abs(${x})"
+
+        // round :: Number -> Number
+        round = x => native "Math.round(${x})"
+
+        // floor :: Number -> Number
+        floor = x => native "Math.floor(${x})"
+
+        // ceil :: Number -> Number
+        ceil = x => native "Math.ceil(${x})"
+    }
+
+    array = {
+        // all :: Array a -> (a -> Bool) -> Bool
+        all = arr => predicate => native "Array.isArray(${arr}) && ${arr}.every(${predicate})"
+
+        // any :: Array a -> (a -> Bool) -> Bool
+        any = arr => predicate => native "Array.isArray(${arr}) && ${arr}.some(${predicate})"
+
+        // push :: Array a -> a -> Array a
+        push = arr => item => native "(() => { ${arr}.push(${item}); return ${arr}; })()"
+
+        // pop :: Array a -> a
+        pop = arr => native "(() => { return ${arr}.pop(); })()"
+
+        // sort :: Array a -> (a -> a -> Number) -> Array a
+        sort = arr => compareFunction => native "(() => { ${arr}.sort(${compareFunction}); return ${arr}; })()"
+
+        // filter :: Array a -> (a -> Bool) -> Array a
+        filter = arr => predicate => native "${arr}.filter(${predicate})"
+
+        // map :: Array a -> (a -> b) -> Array b
+        map = arr => mapper => native "${arr}.map(${mapper})"
+
+        // reduce :: Array a -> (b -> a -> b) -> b -> b
+        reduce = arr => reducer => initialValue => native "${arr}.reduce(${reducer}, ${initialValue})"
+
+        // forEach :: Array a -> (a -> ()) -> Array a
+        forEach = arr => action => native "(() => { ${arr}.forEach(${action}); return ${arr}; })()"
+
+        // find :: Array a -> (a -> Bool) -> a
+        find = arr => predicate => native "(${arr}.find(${predicate}) || null)"
+
+        // indexOf :: Array a -> a -> Number
+        indexOf = arr => item => native "${arr}.indexOf(${item})"
+
+        // slice :: Array a -> Number -> Number -> Array a
+        slice = arr => begin => end => native "${arr}.slice(${begin}, ${end})"
+
+        // reduceRight :: Array a -> (b -> a -> b) -> b -> b
+        reduceRight = arr => reducer => initialValue => native "${arr}.reduceRight(${reducer}, ${initialValue})"
+    }
+
+    string = {
+        // match :: String -> String -> Bool
+        match = str => pattern => native "${str}.match(${pattern})"
+
+        // chars :: String -> Array String
+        chars = str => native "Array.from(${str})"
+
+        // concat :: String -> String -> String
+        concat = str1 => str2 => native "${str1}.concat(${str2})"
+
+        // substring :: String -> Number -> Number -> String
+        substring = str => start => end => native "${str}.substring(${start}, ${end})"
+
+        // split :: String -> String -> Array String
+        split = str => delimiter => native "${str}.split(${delimiter})"
+
+        // trim :: String -> String
+        trim = str => native "${str}.trim()"
+
+        // toUpper :: String -> String
+        toUpper = str => native "${str}.toUpperCase()"
+
+        // toLower :: String -> String
+        toLower = str => native "${str}.toLowerCase()"
+
+        // indexOf :: String -> String -> Number
+        indexOf = str => searchStr => native "${str}.indexOf(${searchStr})"
+
+        // endsWith :: String -> String -> Bool
+        endsWith = str => searchStr => native "${str}.endsWith(${searchStr})"
+
+        // startsWith :: String -> String -> Bool
+        startsWith = str => searchStr => native "${str}.startsWith(${searchStr})"
+
+        // replace :: String -> String -> String -> String
+        replace = str => search => replacement => native "${str}.replace(${search}, ${replacement})"
+
+        // regexMatch :: String -> RegExp -> Array String
+        regexMatch = str => pattern => native "${str}.match(${pattern})"
+
+        // regexTest :: String -> RegExp -> Bool
+        regexTest = str => pattern => native "${pattern}.test(${str})"
+    }
+
+    object = {
+        // values :: Object -> Array Any
+        values = obj => native "Object.values(${obj})"
+
+        // keys :: Object -> Array String
+        keys = obj => native "Object.keys(${obj})"
+
+        // drop :: Object -> String -> Object
+        drop = obj => key => native "(() => { delete ${obj}[${key}]; return ${obj}; })()"
+
+        // merge :: Object -> Object -> Object
+        merge = obj1 => obj2 => native "Object.assign({}, ${obj1}, ${obj2})"
+    }
+
+    os = {
+        // UNSAFE readFile :: String -> String
+        readFile = path => encoding => native "require('fs').readFileSync(${path}, ${encoding})"
+
+        // UNSAFE writeFile :: String -> String -> ()
+        writeFile = path => data => native "require('fs').writeFileSync(${path}, ${data})"
+
+        // UNSAFE getenv :: String -> String
+        getenv = variable => native "process.env[${variable}]"
+
+        // UNSAFE setenv :: String -> String -> ()
+        setenv = variable => value => { native "(() => { process.env[${variable}] = ${value}; })()" }
+    }
+
+    // UNSAFE random :: () -> Number
+    random = _ => native "Math.random()"
+    // FIXME: add a randInt :: () -> BigInt
+
+    // UNSAFE getCurrentDate :: () -> String
+    getCurrentDate = _ => native "new Date().toISOString()"
+
+    // Explicit type-casting utils between Number (double / f64) and BigInt
+    toNumber = x => native "__bee_cast_to_number(${x})"
+    toBigInt = x => native "__bee_cast_to_bigint(${x})"
+
+    // Operators (infix and prefix) that can be overloaded by user :)
+    ops = {
+        // !x
+        not = x => native "__bee_op_not(${x})"
+        // -x
+        unary_minus = x => native "__bee_op_unary_minus(${x})"
+        // x == y
+        eq = x => y => native "__bee_op_eq(${x}, ${y})"
+        // x != y
+        neq = x => y => native "__bee_op_neq(${x}, ${y})"
+        // x / y
+        div = x => y => native "__bee_op_div(${x}, ${y})"
+        // x * y
+        mul = x => y => native "__bee_op_mul(${x}, ${y})"
+        // x % y
+        mod = x => y => native "__bee_op_mod(${x}, ${y})"
+        // x + y
+        add = x => y => native "__bee_op_add(${x}, ${y})"
+        // x - y
+        sub = x => y => native "__bee_op_sub(${x}, ${y})"
+        // x < y
+        lt = x => y => native "__bee_op_lt(${x}, ${y})"
+        // x > y
+        gt = x => y => native "__bee_op_gt(${x}, ${y})"
+        // x <= y
+        lte = x => y => native "__bee_op_lte(${x}, ${y})"
+        // x >= y
+        gte = x => y => native "__bee_op_gte(${x}, ${y})"
+        // x | y
+        or = x => y => native "__bee_op_or(${x}, ${y})"
+        // x & y
+        and = x => y => native "__bee_op_and(${x}, ${y})"
+        // x |> y
+        pipe = x => y => native "__bee_op_pipe(${x}, ${y})"
+        // x <| y
+        reverse_pipe = x => y => native "__bee_op_reverse_pipe(${x}, ${y})"
+        // x..y
+        range = start => end => native "__bee_op_range(${start}, ${end})"
+    }
+}

          
A => src/runtime.js +165 -0
@@ 0,0 1,165 @@ 
+const __bee_error = (__bee_error_code, __bee_msg, __bee_debug_symbol) => {
+    throw new Error(`${__bee_debug_symbol}${__bee_stacktrace.slice(0, 4).join("")} ${__bee_error_code} ${__bee_msg}`);
+};
+
+let __bee_env = {}; // FIXME: use a `Map()` instead?
+
+const __bee_env_tag = __bee_env => { return { __bee_env_cow: __bee_env }; };
+
+const __bee_env_untag = __bee_env => {
+    delete __bee_env.self;
+    delete __bee_env.__bee_env_cow;
+    return __bee_env;
+};
+
+// FIXME: add a an `unsafe` wrapper that check for undefined values!
+// __bee_env = (typeof __bee_env === 'undefined' ? {} : __bee_env);
+
+const __bee_env_error = (__bee_env, __bee_id, __bee_debug_symbol) =>
+    (typeof __bee_id === "string" && Array.isArray(__bee_env)
+        ? __bee_error("TY001", `you can't access the property \`${__bee_id}\` of the Array \`${__bee_debug_display(__bee_env)}\``, __bee_debug_symbol)
+        : (typeof __bee_id === "number" ? (Array.isArray(__bee_env)
+            // FIXME: add support for inverse index: [1 2 3].(-1) == 3 ?
+            ? (__bee_id >= __bee_env.length ? __bee_error("TY005", `out of bound access: try to access position \`${__bee_id}\` while \`${__bee_debug_display(__bee_env)}\` have a lenght of \`${__bee_env.length}\``, __bee_debug_symbol) : {})
+            : __bee_error("TY002", `you can't access the \`${__bee_id}\` element of the Object \`${__bee_debug_display(__bee_env)}\``, __bee_debug_symbol))
+            : __bee_error("TY003", `identifier \`${__bee_id}\` is not defined`, __bee_debug_symbol)));
+
+const __bee_get_id = (__bee_env, __bee_id, __bee_debug_symbol, __bee_in_self = false) => {
+    const __bee_get_name = (__bee_env, __bee_id, __bee_debug_symbol) =>
+        typeof __bee_env === "object" ? (__bee_id in __bee_env ? __bee_env[__bee_id]
+            : (/* !__bee_in_self && */ "__bee_env_cow" in __bee_env ? __bee_get_name(__bee_env.__bee_env_cow, __bee_id, __bee_debug_symbol)
+                : __bee_env_error(__bee_env, __bee_id, __bee_debug_symbol)))
+            : __bee_error("TY004", `\`${__bee_debug_display(__bee_env)}\` is neither an Array or Object, you can't use \`.\` operator on it`, __bee_debug_symbol);
+    const id = __bee_id.shift();
+    const value = __bee_get_name(__bee_env, id, __bee_debug_symbol);
+    return __bee_id.length ? __bee_get_id(value, __bee_id, __bee_debug_symbol, __bee_in_self || id == "self") : __bee_env_untag(value);
+};
+
+const __bee_env_copy = __bee_env => {
+    if (typeof __bee_env !== "object") { return __bee_env; }
+    if (Array.isArray(__bee_env)) { return __bee_env.map(x => __bee_env_copy(x)); }
+    const { self, __bee_env_cow, ...xs } = __bee_env;
+    const x = typeof __bee_env_cow === 'undefined' ? {} : __bee_env_copy(__bee_env_cow)
+    return {
+        ...x, ...Object.keys(xs).reduce((acc, key) => {
+            acc[key] = __bee_env_copy(xs[key]);
+            return acc;
+        }, {})
+    };
+};
+
+const __bee_stacktrace = [];
+
+const __bee_fn_apply = (__bee_ret, __bee_args, __bee_debug_symbol) => {
+    __bee_stacktrace.unshift(__bee_debug_symbol);
+    for (let i = 0; i < __bee_args.length; ++i) {
+        const __bee_arg = __bee_args[i]
+        __bee_ret = (typeof __bee_ret === "function" ? __bee_ret(__bee_arg)
+            : __bee_error("TY006", "function is called with too many arguments...", __bee_debug_symbol));
+    }
+    __bee_stacktrace.shift();
+    return __bee_ret;
+};
+
+const __bee_op_not = x => !x;
+
+const __bee_op_unary_minus = x => -x;
+
+const __bee_op_eq = (x, y) => x === y;
+
+const __bee_op_neq = (x, y) => x !== y;
+
+const __bee_op_add = (x, y) => {
+    __bee_check_types(x, y);
+    return x + y;
+};
+
+const __bee_op_sub = (x, y,) => {
+    __bee_check_types(x, y);
+    return x - y;
+};
+
+const __bee_op_mul = (x, y) => {
+    __bee_check_types(x, y);
+    return x * y;
+};
+
+const __bee_op_div = (x, y) => {
+    y == 0 ? __bee_error("TY009", `division by 0 is forbidden`, "") : {};
+    __bee_check_types(x, y);
+    return x / y;
+};
+
+const __bee_op_mod = (x, y) => {
+    __bee_check_types(x, y);
+    return x % y;
+};
+
+const __bee_check_types = (x, y) => {
+    // FIXME: check !isNan() and isFinite() ?
+    (typeof x == typeof y) ? {} : __bee_error("TY009", `can't mix ${typeof x} (${x}) and  ${typeof y} (${y})`, "");
+    // FIXME: advice to use explicit type casting!
+};
+
+const __bee_op_lt = (x, y) => x < y;
+
+const __bee_op_gt = (x, y) => x > y;
+
+const __bee_op_lte = (x, y) => x <= y;
+
+const __bee_op_gte = (x, y) => x >= y;
+
+const __bee_op_and = (x, y) => x && y;
+
+const __bee_op_or = (x, y) => x || y;
+
+const __bee_op_pipe = (f, g) => typeof f == "function" ? x => g(f(x)) : g(f);
+
+const __bee_op_reverse_pipe = (f, g) => typeof f == "function" ? x => f(g(x)) : f(g);
+
+const __bee_op_range = (x, y) => {
+    // FIXME: should check that the conversion is safe ...
+    const start = __bee_cast_to_number(x);
+    const end = __bee_cast_to_number(y);
+    return Array.from({ length: end - start }, (_, i) => start + i);
+}
+
+const __bee_cast_to_number = x => Number.isSafeInteger(x) ? Number(x) : __bee_error("TY010", `${x} can't be safely convert to Number`, "");
+
+const __bee_cast_to_bigint = x => Number.isSafeInteger(x) ? BigInt(x) : __bee_error("TY011", `${x} can't be safely convert to BigInt`, "");
+
+const __bee_debug_display = (x, truncateLargeCollections = true) => {
+    const __bee_truncate_if_needed = (collection, truncate) => {
+        if (truncate && collection.length > 8) {
+            return [...collection.slice(0, 6), '...', collection[collection.length - 1]];
+        }
+        return collection;
+    };
+    if (typeof x === 'number') {
+        if (Number.isInteger(x)) {
+            return x + '.0';
+        } else {
+            return x.toString();
+        }
+    } else if (typeof x === 'bigint') {
+        return x.toString();
+    } else if (typeof x === 'string') {
+        return '"' + x + '"';
+    } else if (Array.isArray(x)) {
+        const arrayString = x.map(item => __bee_debug_display(item, truncateLargeCollections));
+        return '[' + __bee_truncate_if_needed(arrayString, truncateLargeCollections).join(', ') + ']';
+    } else if (typeof x === 'object' && x !== null) {
+        const objectString = Object.entries(x).map(([key, value]) => `${key} = ${__bee_debug_display(value, truncateLargeCollections)}`);
+        return '{' + __bee_truncate_if_needed(objectString, truncateLargeCollections).join('; ') + '}';
+    } else {
+        return x.toString();
+    }
+};
+
+// FIXME: write an alternative JS `.toString()` that turn any JS value into the
+// code that would be interpreted such as this value!
+
+// FIXME: __functor and __toString special attributes, e.g.:
+// let add = { __functor = self: x: x + self.x; };
+//     inc = add // { x = 1; };
+// in inc 1

          
A => tree-sitter-bee-lang/.gitattributes +2 -0
@@ 0,0 1,2 @@ 
+# Auto detect text files and perform LF normalization
+* text=auto

          
A => tree-sitter-bee-lang/.gitignore +15 -0
@@ 0,0 1,15 @@ 
+# Build artifacts
+build/
+src/parser.c
+src/scanner.c
+
+# Dependency directories
+node_modules/
+
+# IDE/Editor specific files
+.vscode/
+.idea/
+
+# Operating System specific files
+.DS_Store
+Thumbs.db

          
A => tree-sitter-bee-lang/Cargo.toml +26 -0
@@ 0,0 1,26 @@ 
+[package]
+name = "tree-sitter-bee-lang"
+description = "Bee grammar for the tree-sitter parsing library"
+version = "0.1.0"
+keywords = ["incremental", "parsing", "bee"]
+categories = ["parsing", "text-editors"]
+edition = "2018"
+authors = ["Yvan Sraka <yvan@sraka.xyz>"]
+license = "GPLv2"
+
+build = "bindings/rust/build.rs"
+include = [
+  "bindings/rust/*",
+  "grammar.js",
+  "queries/*",
+  "src/*",
+]
+
+[lib]
+path = "bindings/rust/lib.rs"
+
+[dependencies]
+tree-sitter = "0.20"
+
+[build-dependencies]
+cc = "1.0"

          
A => tree-sitter-bee-lang/README.md +73 -0
@@ 0,0 1,73 @@ 
+## How to Set Up Bee Syntax Highlighting?
+
+This tutorial assumes that you have cloned this repository and that you are in the `tree-sitter` subfolder where this `README.md` resides.
+
+### VSCode
+
+Press `Ctrl` (`Cmd` on macOS) + `Shift` + `P`, then type "Developer: Install Extension from Location...", and select the `vscode-syntax-highlighting` folder.
+
+### Vim
+
+Copy the `bee.vim` file from this folder to `~/.vim/syntax/` (if you're using Neovim, the path is `~/.config/nvim/syntax/`).
+
+Edit (or create) the `filetype.vim` script, which should be in `~/.vim/` (or `~/.config/nvim/` for Neovim). It should contain the following lines:
+
+```vim
+if exists("did_load_filetypes")
+    finish
+endif
+
+augroup filetypedetect
+    au! BufRead,BufNewFile *.bee setfiletype bee
+augroup END
+```
+
+Ensure that your Vim is configured to allow custom syntax files and filetype detection. In your `~/.vimrc` (or `~/.config/nvim/init.vim` for Neovim), you should have syntax highlighting enabled with `syntax on` or `syntax enable`.
+
+### Emacs
+
+Copy the `bee-mode.el` file from this folder in a subdirectory of your Emacs configuration directory, e.g. `~/.emacs.d/bee/`.
+
+To automatically load this mode when opening `.bee` files, add the following lines to your Emacs configuration file (usually `~/.emacs` or `~/.emacs.d/init.el`):
+
+```elisp
+(add-to-list 'load-path "~/.emacs.d/bee/")
+(require 'bee-mode)
+```
+
+### Helix
+
+First, add the following to your `~/.config/helix/languages.toml` configuration file:
+
+```toml
+[[grammar]]
+name = "bee"
+
+[grammar.source]
+path = "/Users/yvan/bee-lang/tree-sitter" # Don't forget to change this line ;)
+
+[[language]]
+comment-token = "//"
+file-types = ["bee"]
+injection-regex = "bee"
+name = "bee"
+roots = ["main.bee"]
+scope = "source.bee"
+
+[language.indent]
+tab-width = 4
+unit = "    "
+```
+
+Then run the following commands (from the folder containing the `grammar.js` file):
+
+```bash
+mkdir -p ~/.config/helix/runtime/{queries,grammars}
+ln -s "$(pwd)/queries" ~/.config/helix/runtime/queries/bee
+# /!\ Warning: re-run the next line after each change to grammar.js
+cc -shared src/parser.c -o ~/.config/helix/runtime/grammars/bee.so # (yes, .so and not .dylib, even on macOS...)
+```
+
+---
+
+If you still can't get syntax highlighting to work on your machine after following these instructions, please ask for help at discuss@bee-lang.org.

          
A => tree-sitter-bee-lang/bee-mode.el +51 -0
@@ 0,0 1,51 @@ 
+;;; bee-mode.el --- Syntax highlighting for Bee language
+
+; If you discover a way to improve Emacs syntax highlighting support by editing this file,
+; please share it with us at devel@bee-lang.org :)
+
+(defvar bee-font-lock-keywords
+  (let* (
+         ;; Define patterns for basic syntax categories.
+         (x-constants '("true" "false"))
+         (x-keywords '("if" "else" "import" "native" "return" "panic"))
+         (x-operators '("=" "=>" "==" "!=" "/" "*" "%" "+" "-" "<" ">" "<=" ">=" "|" "&" "|>" "<|" ".."))
+         (x-unary-operators '("!" "-"))
+         (x-spread-operator '("\\.\\.\\."))
+         (x-constants-regexp (regexp-opt x-constants 'words))
+         (x-keywords-regexp (regexp-opt x-keywords 'words))
+         (x-operators-regexp (regexp-opt x-operators))
+         (x-unary-operators-regexp (regexp-opt x-unary-operators))
+         (x-spread-operator-regexp (regexp-opt x-spread-operator))
+         (single-line-comment "//.*")
+         (multi-line-comment-start "/\\*")
+         (multi-line-comment-end "\\*/")
+        )
+    `(
+      (,x-constants-regexp . font-lock-constant-face)
+      (,x-keywords-regexp . font-lock-keyword-face)
+      (,x-operators-regexp . font-lock-operator-face)
+      (,x-unary-operators-regexp . font-lock-operator-face)
+      (,x-spread-operator-regexp . font-lock-operator-face)
+      ("@[a-zA-Z_][a-zA-Z0-9_]*" . font-lock-variable-name-face)
+      ("\\b[0-9]+\\b" . font-lock-number-face)
+      ("\".*?\"" . font-lock-string-face)
+      ("//.*" . font-lock-comment-face)
+      ("/\\*\\(.\\|\n\\)*?\\*/" . font-lock-comment-face)
+            (,single-line-comment . font-lock-comment-face)
+      (,multi-line-comment-start . font-lock-comment-face)
+      (,multi-line-comment-end . font-lock-comment-face)
+    ))
+  "Highlighting expressions for Bee mode")
+
+(define-derived-mode bee-mode prog-mode "Bee"
+  "Major mode for editing Bee language files."
+  (setq font-lock-defaults '((bee-font-lock-keywords)))
+  (modify-syntax-entry ?/ ". 124b" bee-mode-syntax-table)
+  (modify-syntax-entry ?* ". 23" bee-mode-syntax-table)
+  (modify-syntax-entry ?\n "> b" bee-mode-syntax-table))
+
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.bee\\'" . bee-mode))
+
+(provide 'bee-mode)
+;;; bee-mode.el ends here

          
A => tree-sitter-bee-lang/bee.vim +50 -0
@@ 0,0 1,50 @@ 
+" Vim syntax file
+" Language: bee
+" File: bee.vim
+
+" If you discover a way to improve Vim syntax highlighting support by editing this file,
+" please share it with us at devel@bee-lang.org :)
+
+if exists("b:current_syntax")
+  finish
+endif
+
+syntax clear
+
+syntax keyword beeBoolean true false
+syntax keyword beeDirective @target
+syntax keyword beeControl panic if else
+syntax keyword beeConditional if else
+syntax keyword beeImport import
+syntax keyword beeSpecialFunction native
+syntax keyword beeReturn return
+
+syntax match beeOperator "\v[=!/\*\%+\-<>|&]+"
+syntax match beeUnaryOperator "\v[!\-]"
+syntax match beeSpreadOperator "\.\.\."
+syntax match beeDelimiter "[{}();\[\]]"
+syntax match beeNumber "\v\-?\d+(\.\d+)?([eE][\-+]?\d+)?"
+syntax match beeString /"[^"\\]*"/
+syntax match beeComment "//.*" contains=beeTodo
+syntax region beeComment start="/\*" end="\*/" contains=beeTodo
+" FIXME: recursive comments are not highlighted correctly ...
+
+syntax keyword beeTodo contained TODO FIXME XXX
+
+hi def link beeBoolean Boolean
+hi def link beeDirective Identifier
+hi def link beeControl Statement
+hi def link beeConditional Conditional
+hi def link beeImport Include
+hi def link beeSpecialFunction PreProc
+hi def link beeReturn Keyword
+hi def link beeOperator Operator
+hi def link beeUnaryOperator Operator
+hi def link beeSpreadOperator Operator
+hi def link beeDelimiter Delimiter
+hi def link beeNumber Number
+hi def link beeString String
+hi def link beeComment Comment
+hi def link beeTodo Todo
+
+let b:current_syntax = "bee"

          
A => tree-sitter-bee-lang/binding.gyp +19 -0
@@ 0,0 1,19 @@ 
+{
+  "targets": [
+    {
+      "target_name": "tree_sitter_bee_binding",
+      "include_dirs": [
+        "<!(node -e \"require('nan')\")",
+        "src"
+      ],
+      "sources": [
+        "bindings/node/binding.cc",
+        "src/parser.c",
+        # If your language uses an external scanner, add it here.
+      ],
+      "cflags_c": [
+        "-std=c99",
+      ]
+    }
+  ]
+}

          
A => tree-sitter-bee-lang/bindings/node/binding.cc +28 -0
@@ 0,0 1,28 @@ 
+#include "tree_sitter/parser.h"
+#include <node.h>
+#include "nan.h"
+
+using namespace v8;
+
+extern "C" TSLanguage * tree_sitter_bee();
+
+namespace {
+
+NAN_METHOD(New) {}
+
+void Init(Local<Object> exports, Local<Object> module) {
+  Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
+  tpl->SetClassName(Nan::New("Language").ToLocalChecked());
+  tpl->InstanceTemplate()->SetInternalFieldCount(1);
+
+  Local<Function> constructor = Nan::GetFunction(tpl).ToLocalChecked();
+  Local<Object> instance = constructor->NewInstance(Nan::GetCurrentContext()).ToLocalChecked();
+  Nan::SetInternalFieldPointer(instance, 0, tree_sitter_bee());
+
+  Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("bee").ToLocalChecked());
+  Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance);
+}
+
+NODE_MODULE(tree_sitter_bee_binding, Init)
+
+}  // namespace

          
A => tree-sitter-bee-lang/bindings/node/index.js +19 -0
@@ 0,0 1,19 @@ 
+try {
+  module.exports = require("../../build/Release/tree_sitter_bee_binding");
+} catch (error1) {
+  if (error1.code !== 'MODULE_NOT_FOUND') {
+    throw error1;
+  }
+  try {
+    module.exports = require("../../build/Debug/tree_sitter_bee_binding");
+  } catch (error2) {
+    if (error2.code !== 'MODULE_NOT_FOUND') {
+      throw error2;
+    }
+    throw error1
+  }
+}
+
+try {
+  module.exports.nodeTypeInfo = require("../../src/node-types.json");
+} catch (_) {}

          
A => tree-sitter-bee-lang/bindings/rust/build.rs +40 -0
@@ 0,0 1,40 @@ 
+fn main() {
+    let src_dir = std::path::Path::new("src");
+
+    let mut c_config = cc::Build::new();
+    c_config.include(&src_dir);
+    c_config
+        .flag_if_supported("-Wno-unused-parameter")
+        .flag_if_supported("-Wno-unused-but-set-variable")
+        .flag_if_supported("-Wno-trigraphs");
+    let parser_path = src_dir.join("parser.c");
+    c_config.file(&parser_path);
+
+    // If your language uses an external scanner written in C,
+    // then include this block of code:
+
+    /*
+    let scanner_path = src_dir.join("scanner.c");
+    c_config.file(&scanner_path);
+    println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
+    */
+
+    c_config.compile("parser");
+    println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap());
+
+    // If your language uses an external scanner written in C++,
+    // then include this block of code:
+
+    /*
+    let mut cpp_config = cc::Build::new();
+    cpp_config.cpp(true);
+    cpp_config.include(&src_dir);
+    cpp_config
+        .flag_if_supported("-Wno-unused-parameter")
+        .flag_if_supported("-Wno-unused-but-set-variable");
+    let scanner_path = src_dir.join("scanner.cc");
+    cpp_config.file(&scanner_path);
+    cpp_config.compile("scanner");
+    println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
+    */
+}

          
A => tree-sitter-bee-lang/bindings/rust/lib.rs +52 -0
@@ 0,0 1,52 @@ 
+//! This crate provides bee language support for the [tree-sitter][] parsing library.
+//!
+//! Typically, you will use the [language][language func] function to add this language to a
+//! tree-sitter [Parser][], and then use the parser to parse some code:
+//!
+//! ```
+//! let code = "";
+//! let mut parser = tree_sitter::Parser::new();
+//! parser.set_language(tree_sitter_bee::language()).expect("Error loading bee grammar");
+//! let tree = parser.parse(code, None).unwrap();
+//! ```
+//!
+//! [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
+//! [language func]: fn.language.html
+//! [Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html
+//! [tree-sitter]: https://tree-sitter.github.io/
+
+use tree_sitter::Language;
+
+extern "C" {
+    fn tree_sitter_bee() -> Language;
+}
+
+/// Get the tree-sitter [Language][] for this grammar.
+///
+/// [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
+pub fn language() -> Language {
+    unsafe { tree_sitter_bee() }
+}
+
+/// The content of the [`node-types.json`][] file for this grammar.
+///
+/// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types
+pub const NODE_TYPES: &'static str = include_str!("../../src/node-types.json");
+
+// Uncomment these to include any queries that this grammar contains
+
+// pub const HIGHLIGHTS_QUERY: &'static str = include_str!("../../queries/highlights.scm");
+// pub const INJECTIONS_QUERY: &'static str = include_str!("../../queries/injections.scm");
+// pub const LOCALS_QUERY: &'static str = include_str!("../../queries/locals.scm");
+// pub const TAGS_QUERY: &'static str = include_str!("../../queries/tags.scm");
+
+#[cfg(test)]
+mod tests {
+    #[test]
+    fn test_can_load_grammar() {
+        let mut parser = tree_sitter::Parser::new();
+        parser
+            .set_language(super::language())
+            .expect("Error loading bee language");
+    }
+}

          
A => tree-sitter-bee-lang/grammar.js +71 -0
@@ 0,0 1,71 @@ 
+// This grammar have by design, no conflicts between rules and no need for
+// precedence rules, instead it force the use of parenthesis on any ambiguity
+// this is a feature!
+
+const list = (value, delimiter) => optional(seq(value, repeat(seq(delimiter, value)), optional(delimiter)));
+
+module.exports = grammar({
+    name: 'bee',
+    extras: $ => [/\s/, $.inline_comment, $.block_comment],
+    // FIXME: https://github.com/tree-sitter/tree-sitter/pull/1635
+    // reserved: _ => ['true', 'false', 'if', 'else', 'return', 'native', 'import'],
+    word: $ => $.name,
+    rules: {
+        source_file: $ => $.expr,
+        expr: $ => choice($.fn, $.statement, $.value, $.prefix, $.infix, seq('(', $.expr, ')')),
+        value: $ => choice($.array, $.bigint, $.bool, $.id, $.f64, $.string, $.target),
+        statement: $ => choice($.do, $.if_then_else, $.import_, $.native_, $.panic_, $.let, $.apply),
+        apply: $ => seq($.arg, repeat1($.arg)),
+        arg: $ => choice($.value, $.do, seq('(', $.expr, ')')),
+        array: $ => seq('[', list($.expr, ','), ']'),
+        delimiter: $ => choice(';', '\n'),
+        field: $ => choice($.return_, $.statement, $.name_alias, $.spread),
+        do: $ => seq('{', list($.field, $.delimiter), '}'),
+        if_then_else: $ => seq('if', $.arg, $.expr, seq('else', $.expr)),
+        let: $ => seq($.name, '=', $.expr), // FIXME: let use $.id instead of $.name?
+        fn: $ => seq($.name, '=>', $.expr),
+        spread: $ => seq("...", $.id), // FIXME: spread arbitrary $.expr? spread in $.array?
+        return_: $ => seq('return', $.expr),
+        panic_: $ => seq('panic', $.string),
+        native_: $ => seq('native', $.string),
+        import_: $ => seq('import', $.string),
+        id: $ => seq(choice($.name, $.placeholder), repeat(seq('.', choice($.name, $.nth, $.placeholder)))),
+        nth: _ => /-?\d+/,
+        placeholder: $ => seq('$', '{', $.expr, '}'),
+        bool: _ => choice('true', 'false'),
+        target: _ => /@[a-zA-Z_][a-zA-Z0-9_]*/,
+        name_alias: $ => $.name,
+        name: _ => /[a-zA-Z_][a-zA-Z0-9_]*/,
+        bigint: _ => /-?\d+([eE]+?\d+)?/,
+        f64: _ => /-?\d+(\.\d+)?([eE][-+]?\d+)?/,
+        string: _ => /"([^"\\]|\\.)*"/,
+        inline_comment: _ => seq('//', /.*/),
+        block_comment: $ => seq('/*', repeat(choice(/[^*]/, /\*[^/]/, $.block_comment)), '*/'),
+        prefix: $ => choice(
+            ...[
+                '!', '-'
+            ].map(operator =>
+                seq(
+                    operator,
+                    $.arg
+                )
+            )
+        ),
+        infix: $ => choice(
+            ...[
+                '==', '!=', '/', '*', '%', '+', '-', '<', '>', '<=', '>=', '|', '&', '|>', '<|', '..'
+            ].map(operator =>
+                seq(
+                    $.arg,
+                    operator,
+                    $.arg
+                )
+            )
+        ),
+        // FIXME: `.` operator should be callable directly on array or object inline declaration ...
+        // FIXME: add `async` and `await` support ... in grammar? in prelude?
+    }
+});
+
+// FIXME: open a PR to add syntax highlighting support to Zed editor ...
+// https://github.com/zed-industries/zed/tree/main/crates/zed/src/languages

          
A => tree-sitter-bee-lang/package-lock.json +32 -0
@@ 0,0 1,32 @@ 
+{
+  "name": "tree-sitter-bee-lang",
+  "version": "0.1.0",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "tree-sitter-bee-lang",
+      "version": "0.1.0",
+      "license": "ISC",
+      "dependencies": {
+        "nan": "^2.18.0"
+      },
+      "devDependencies": {
+        "tree-sitter-cli": "^0.20.8"
+      }
+    },
+    "node_modules/nan": {
+      "version": "2.18.0",
+      "license": "MIT"
+    },
+    "node_modules/tree-sitter-cli": {
+      "version": "0.20.8",
+      "dev": true,
+      "hasInstallScript": true,
+      "license": "MIT",
+      "bin": {
+        "tree-sitter": "cli.js"
+      }
+    }
+  }
+}

          
A => tree-sitter-bee-lang/package.json +22 -0
@@ 0,0 1,22 @@ 
+{
+  "name": "tree-sitter-bee-lang",
+  "version": "0.1.0",
+  "description": "Bee grammar for the tree-sitter parsing library",
+  "main": "bindings/node",
+  "author": "Yvan Sraka <yvan@sraka.xyz>",
+  "license": "ISC",
+  "dependencies": {
+    "nan": "^2.18.0"
+  },
+  "devDependencies": {
+    "tree-sitter-cli": "^0.20.8"
+  },
+  "tree-sitter": [
+    {
+      "scope": "source.bee",
+      "file-types": [
+        "bee"
+      ]
+    }
+  ]
+}

          
A => tree-sitter-bee-lang/queries/highlights.scm +16 -0
@@ 0,0 1,16 @@ 
+(bool) @constant.builtin.boolean
+(id) @variable.other
+(string) @string
+(target) @keyword.directive
+[";"] @punctuation.delimiter
+["!" "-"] @operator.unary
+["..."] @operator.spread
+["{" "(" "[" "]" ")" "}"] @punctuation.bracket
+["=" "=>" "==" "!=" "/" "*" "%" "+" "-" "<" ">" "<=" ">=" "|" "&" "|>" "<|" ".."] @operator
+["panic"] @keyword.control
+["if" "else"] @keyword.control.conditional
+["import"] @keyword.control.import
+["native"] @function.special
+["return"] @keyword.control.return
+[(bigint) (f64)] @number
+[(inline_comment) (block_comment)] @comment

          
A => tree-sitter-bee-lang/queries/injections.scm +4 -0
@@ 0,0 1,4 @@ 
+([(inline_comment)] @injection.content
+ (#set! injection.language "inline_comment"))
+([(block_comment)] @injection.content
+ (#set! injection.language "block_comment"))

          
A => tree-sitter-bee-lang/queries/locals.scm +5 -0
@@ 0,0 1,5 @@ 
+(do (field) @scope)
+(let (name) @variable)
+(fn (name) @parameter)
+(block_comment) @comment
+(inline_comment) @comment

          
A => tree-sitter-bee-lang/queries/tags.scm +5 -0
@@ 0,0 1,5 @@ 
+(do) @foldable
+(block_comment) @foldable
+(array) @foldable
+(if_then_else) @foldable
+(fn) @foldable

          
A => tree-sitter-bee-lang/src/grammar.json +926 -0
@@ 0,0 1,926 @@ 
+{
+  "name": "bee",
+  "word": "name",
+  "rules": {
+    "source_file": {
+      "type": "SYMBOL",
+      "name": "expr"
+    },
+    "expr": {
+      "type": "CHOICE",
+      "members": [
+        {
+          "type": "SYMBOL",
+          "name": "fn"
+        },
+        {
+          "type": "SYMBOL",
+          "name": "statement"
+        },
+        {
+          "type": "SYMBOL",
+          "name": "value"
+        },
+        {
+          "type": "SYMBOL",
+          "name": "prefix"
+        },
+        {
+          "type": "SYMBOL",
+          "name": "infix"
+        },
+        {
+          "type": "SEQ",
+          "members": [
+            {
+              "type": "STRING",
+              "value": "("
+            },
+            {
+              "type": "SYMBOL",
+              "name": "expr"
+            },
+            {
+              "type": "STRING",
+              "value": ")"
+            }
+          ]
+        }
+      ]
+    },
+    "value": {
+      "type": "CHOICE",
+      "members": [
+        {