diff --git a/.cargo/config b/.cargo/config.toml similarity index 73% rename from .cargo/config rename to .cargo/config.toml index 544ab69523..4aa93e2080 100644 --- a/.cargo/config +++ b/.cargo/config.toml @@ -6,14 +6,21 @@ test-gen-llvm-wasm = "test -p roc_gen_wasm -p test_gen --no-default-features --f [target.wasm32-unknown-unknown] # Rust compiler flags for minimum-sized .wasm binary in the web REPL -# opt-level=s Optimizations should focus more on size than speed -# lto=fat Spend extra effort on link-time optimization across crates -rustflags = ["-Copt-level=s", "-Clto=fat"] +# opt-level=s Optimizations should focus more on size than speed +# lto=fat Spend extra effort on link-time optimization across crates +# embed-bitcode=yes Turn back on lto since it is no longer default +rustflags = ["-Copt-level=s", "-Clto=fat", "-Cembed-bitcode=yes"] [target.'cfg(not(target = "wasm32-unknown-unknown"))'] # Sets the avx, avx2, sse2 and sse4.2 target-features correctly based on your CPU. rustflags = ["-Ctarget-cpu=native"] +# TODO: there is probably a more proper solution to this. +# We are pulling in roc_alloc and friends due to using roc_std. +# They ared defined in roc_glue, but windows linking breaks before we get there. +[target.'cfg(target_os = "windows")'] +rustflags = ["-Clink-args=/FORCE:UNRESOLVED"] + [env] # Gives us the path of the workspace root for use in cargo tests without having # to compute it per-package. diff --git a/.github/workflows/nightly_linux_x86_64.yml b/.github/workflows/nightly_linux_x86_64.yml index cf464875ad..e44e174a6d 100644 --- a/.github/workflows/nightly_linux_x86_64.yml +++ b/.github/workflows/nightly_linux_x86_64.yml @@ -16,8 +16,8 @@ jobs: - name: create version.txt run: ./ci/write_version.sh - - name: build release - run: RUSTFLAGS="-C target-cpu=x86-64" cargo build --features with_sound --release --locked + - name: build release with lto + run: RUSTFLAGS="-C target-cpu=x86-64" cargo build --profile=release-with-lto --locked # target-cpu=x86-64 -> For maximal compatibility for all CPU's. Note that this setting will likely make the compiler slower. - name: get commit SHA @@ -41,6 +41,10 @@ jobs: DATE: ${{ env.DATE }} SHA: ${{ env.SHA }} run: echo "RELEASE_FOLDER_NAME=roc_nightly-linux_x86_64-$DATE-$SHA" >> $GITHUB_ENV + + # this makes the roc binary a lot smaller + - name: strip debug info + run: strip ./target/release-with-lto/roc - name: Make nightly release tar archive run: ./ci/package_release.sh ${{ env.RELEASE_FOLDER_NAME }} diff --git a/.github/workflows/nightly_macos_apple_silicon.yml b/.github/workflows/nightly_macos_apple_silicon.yml index 7bc89abef5..96833a80dd 100644 --- a/.github/workflows/nightly_macos_apple_silicon.yml +++ b/.github/workflows/nightly_macos_apple_silicon.yml @@ -36,7 +36,11 @@ jobs: run: ./ci/write_version.sh - name: build nightly release - run: cargo build --locked --release + run: cargo build --locked --profile=release-with-lto + + # this makes the roc binary a lot smaller + - name: strip debug info + run: strip ./target/release-with-lto/roc - name: package release run: ./ci/package_release.sh ${{ env.RELEASE_FOLDER_NAME }} diff --git a/.github/workflows/nightly_macos_x86_64.yml b/.github/workflows/nightly_macos_x86_64.yml index 7b4f0e2eb0..4627c97b9f 100644 --- a/.github/workflows/nightly_macos_x86_64.yml +++ b/.github/workflows/nightly_macos_x86_64.yml @@ -22,7 +22,7 @@ jobs: # this issue may be caused by using older versions of XCode - name: build release - run: RUSTFLAGS="-C target-cpu=x86-64" cargo build --features with_sound --release --locked + run: RUSTFLAGS="-C target-cpu=x86-64" cargo build --profile=release-with-lto --locked # target-cpu=x86-64 -> For maximal compatibility for all CPU's. Note that this setting will likely make the compiler slower. - name: get commit SHA @@ -36,6 +36,10 @@ jobs: DATE: ${{ env.DATE }} SHA: ${{ env.SHA }} run: echo "RELEASE_FOLDER_NAME=roc_nightly-macos_x86_64-$DATE-$SHA" >> $GITHUB_ENV + + # this makes the roc binary a lot smaller + - name: strip debug info + run: strip ./target/release-with-lto/roc - name: package release run: ./ci/package_release.sh ${{ env.RELEASE_FOLDER_NAME }} diff --git a/.github/workflows/nix_macos_x86_64.yml b/.github/workflows/nix_macos_x86_64.yml index 755ebb608c..03fb59e743 100644 --- a/.github/workflows/nix_macos_x86_64.yml +++ b/.github/workflows/nix_macos_x86_64.yml @@ -19,13 +19,7 @@ jobs: with: clean: "true" - - uses: cachix/install-nix-action@v15 - - # to cache nix packages - - uses: cachix/cachix-action@v10 - with: - name: enigmaticsunrise - authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' + - uses: cachix/install-nix-action@v20 - name: execute cli_run tests only, the full tests take too long but are run nightly run: nix develop -c cargo test --locked --release -p roc_cli diff --git a/.gitignore b/.gitignore index 762394cc30..dffbb9c5dc 100644 --- a/.gitignore +++ b/.gitignore @@ -72,4 +72,11 @@ roc_linux_x86_64.tar.gz result # tutorial -www/src/roc-tutorial \ No newline at end of file +www/src/roc-tutorial + +# Only keep Cargo.lock dependencies for the main compiler. +# Examples and test only crates should be fine to be unlocked. +# This remove unneccessary lock file versioning. +# It also ensures the compiler can always pull in 1 version of things and doesn't get restricted by sub lockfiles. +/**/Cargo.lock +!/Cargo.lock \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index ec06ea7ab1..4f47333068 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "ab_glyph" -version = "0.2.15" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24606928a235e73cdef55a0c909719cadd72fce573e5713d58cb2952d8f5794c" +checksum = "fe21446ad43aa56417a767f3e2f3d7c4ca522904de1dd640529a76e9c5c3b33c" dependencies = [ "ab_glyph_rasterizer", "owned_ttf_parser", @@ -14,15 +14,15 @@ dependencies = [ [[package]] name = "ab_glyph_rasterizer" -version = "0.1.5" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a13739d7177fbd22bb0ed28badfff9f372f8bef46c863db4e1c6248f6b223b6e" +checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" [[package]] name = "addr2line" -version = "0.17.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" dependencies = [ "gimli", ] @@ -45,14 +45,34 @@ dependencies = [ ] [[package]] -name = "aho-corasick" -version = "0.7.18" +name = "ahash" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if 1.0.0", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] +[[package]] +name = "aligned" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80a21b9440a626c7fc8573a9e3d3a06b75c7c97754c2949bc7857b90353ca655" +dependencies = [ + "as-slice", +] + [[package]] name = "alloc-no-stdlib" version = "2.0.4" @@ -68,28 +88,6 @@ dependencies = [ "alloc-no-stdlib", ] -[[package]] -name = "alsa" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5915f52fe2cf65e83924d037b6c5290b7cee097c6b5c8700746e6168a343fd6b" -dependencies = [ - "alsa-sys", - "bitflags", - "libc", - "nix 0.23.1", -] - -[[package]] -name = "alsa-sys" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" -dependencies = [ - "libc", - "pkg-config", -] - [[package]] name = "approx" version = "0.4.0" @@ -133,6 +131,15 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + [[package]] name = "ash" version = "0.34.0+1.2.203" @@ -148,7 +155,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] @@ -161,9 +168,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.66" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" dependencies = [ "addr2line", "cc", @@ -180,13 +187,19 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[package]] +name = "base64" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" + [[package]] name = "base64-url" version = "1.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67a99c239d0c7e77c85dddfa9cebce48704b3c49550fcd3b84dd637e4484899f" dependencies = [ - "base64", + "base64 0.13.1", ] [[package]] @@ -198,30 +211,11 @@ dependencies = [ "serde", ] -[[package]] -name = "bindgen" -version = "0.59.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8" -dependencies = [ - "bitflags", - "cexpr", - "clang-sys", - "lazy_static", - "lazycell", - "peeking_take_while", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", -] - [[package]] name = "bit-set" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" dependencies = [ "bit-vec", ] @@ -247,28 +241,16 @@ dependencies = [ "typenum", ] -[[package]] -name = "bitvec" -version = "0.22.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5237f00a8c86130a0cc317830e558b966dd7850d48a953d998c813f01a41b527" -dependencies = [ - "funty 1.2.0", - "radium 0.6.2", - "tap", - "wyz 0.4.0", -] - [[package]] name = "bitvec" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ - "funty 2.0.0", - "radium 0.7.0", + "funty", + "radium", "tap", - "wyz 0.5.0", + "wyz", ] [[package]] @@ -293,9 +275,9 @@ checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" [[package]] name = "block-buffer" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" dependencies = [ "generic-array", ] @@ -313,46 +295,34 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "2.3.2" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ad2d4653bf5ca36ae797b1f4bb4dbddb60ce49ca4aed8a2ce4829f60425b80" +checksum = "4b6561fd3f895a11e8f72af2cb7d22e08366bebc2b6b57f7744c4bda27034744" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", ] -[[package]] -name = "bstr" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" -dependencies = [ - "lazy_static", - "memchr", - "regex-automata", - "serde", -] - [[package]] name = "bumpalo" -version = "3.11.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" [[package]] name = "bytemuck" -version = "1.12.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f5715e491b5a1598fc2bef5a606847b5dc1d48ea625bd3c02c00de8285591da" +checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.2.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9e1f5fa78f69496407a27ae9ed989e3c3b072310286f5ef385525e4cbc24a9" +checksum = "1aca418a974d83d40a0c1f0c5cba6ff4bc28d8df099109ca459a2118d40b6322" dependencies = [ "proc-macro2", "quote", @@ -367,9 +337,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "calloop" @@ -412,27 +382,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.73" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" -dependencies = [ - "jobserver", -] - -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" [[package]] name = "cfg-if" @@ -462,17 +414,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "clang-sys" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a050e2153c5be08febd6734e29298e844fdb0fa21aeddd63b4eb7baa106c69b" -dependencies = [ - "glob", - "libc", - "libloading", -] - [[package]] name = "clap" version = "2.34.0" @@ -486,32 +427,17 @@ dependencies = [ [[package]] name = "clap" -version = "3.2.20" +version = "3.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b71c3ce99b7611011217b366d923f1d0a7e07a92bb2dbf1e84508c673ca3bd" +checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" dependencies = [ "atty", "bitflags", - "clap_derive", "clap_lex", "indexmap", - "once_cell", "strsim", "termcolor", - "textwrap 0.15.0", -] - -[[package]] -name = "clap_derive" -version = "3.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2", - "quote", - "syn", + "textwrap 0.16.0", ] [[package]] @@ -523,12 +449,6 @@ dependencies = [ "os_str_bytes", ] -[[package]] -name = "claxon" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688" - [[package]] name = "cli_utils" version = "0.0.1" @@ -537,13 +457,12 @@ dependencies = [ "criterion", "rlimit", "roc_collections", + "roc_command_utils", "roc_load", "roc_module", "roc_reporting", - "roc_utils", "serde", "serde-xml-rs", - "strip-ansi-escapes", "tempfile", ] @@ -559,9 +478,9 @@ dependencies = [ [[package]] name = "clipboard-win" -version = "4.4.1" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f3e1238132dc01f081e1cbb9dace14e5ef4c3a51ee244bd982275fb514605db" +checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362" dependencies = [ "error-code", "str-buf", @@ -570,9 +489,9 @@ dependencies = [ [[package]] name = "cocoa" -version = "0.24.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63902e9223530efb4e26ccd0cf55ec30d592d3b42e21a28defc42a9586e832" +checksum = "f425db7937052c684daec3bd6375c8abe2d146dca4b8b143d6db777c39138f3a" dependencies = [ "bitflags", "block", @@ -620,20 +539,10 @@ dependencies = [ "winapi", ] -[[package]] -name = "combine" -version = "4.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a604e93b79d1808327a6fca85a6f2d69de66461e7620f5a4cbf5fb4d1d7c948" -dependencies = [ - "bytes", - "memchr", -] - [[package]] name = "confy" -version = "0.5.0" -source = "git+https://github.com/rust-cli/confy#fd069f062aa3373c846f0d8c6e3b5e2a5cd0096b" +version = "0.5.1" +source = "git+https://github.com/rust-cli/confy#700337e5a3fbc12f4f49fc9b7ce449b1b71040ee" dependencies = [ "directories", "serde", @@ -643,15 +552,14 @@ dependencies = [ [[package]] name = "console" -version = "0.15.1" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89eab4d20ce20cea182308bca13088fecea9c05f6776cf287205d41a0ed3c847" +checksum = "c3d79fbe8970a77e3e34151cc13d3b3e248aa0faaecb9f6091fa07ebefe5ad60" dependencies = [ "encode_unicode 0.3.6", + "lazy_static", "libc", - "once_cell", - "terminal_size", - "winapi", + "windows-sys 0.42.0", ] [[package]] @@ -666,18 +574,18 @@ dependencies = [ [[package]] name = "const_format" -version = "0.2.26" +version = "0.2.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "939dc9e2eb9077e0679d2ce32de1ded8531779360b003b4a972a7a39ec263495" +checksum = "7309d9b4d3d2c0641e018d449232f2e28f1b22933c137f157d3dbc14228b8c0e" dependencies = [ "const_format_proc_macros", ] [[package]] name = "const_format_proc_macros" -version = "0.2.22" +version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef196d5d972878a48da7decb7686eded338b4858fbabeed513d63a7c98b2b82d" +checksum = "d897f47bf7270cf70d370f8f98c1abb6d2d4cf60a6845d30e05bfb90c6568650" dependencies = [ "proc-macro2", "quote", @@ -698,9 +606,9 @@ checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536" [[package]] name = "copypasta" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7216b5c1e9ad3867252505995b02d01c6fa7e6db0d8abd42634352ef377777e" +checksum = "133fc8675ee3a4ec9aa513584deda9aa0faeda3586b87f7f0f2ba082c66fb172" dependencies = [ "clipboard-win 3.1.1", "objc", @@ -792,55 +700,11 @@ dependencies = [ "objc", ] -[[package]] -name = "coreaudio-rs" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11894b20ebfe1ff903cbdc52259693389eea03b94918a2def2c30c3bf227ad88" -dependencies = [ - "bitflags", - "coreaudio-sys", -] - -[[package]] -name = "coreaudio-sys" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dff444d80630d7073077d38d40b4501fd518bd2b922c2a55edcc8b0f7be57e6" -dependencies = [ - "bindgen", -] - -[[package]] -name = "cpal" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74117836a5124f3629e4b474eed03e479abaf98988b4bb317e29f08cfe0e4116" -dependencies = [ - "alsa", - "core-foundation-sys 0.8.3", - "coreaudio-rs", - "jni", - "js-sys", - "lazy_static", - "libc", - "mach", - "ndk 0.6.0", - "ndk-glue 0.6.2", - "nix 0.23.1", - "oboe", - "parking_lot 0.11.2", - "stdweb", - "thiserror", - "web-sys", - "winapi", -] - [[package]] name = "cpufeatures" -version = "0.2.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" dependencies = [ "libc", ] @@ -904,9 +768,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c02a4d71819009c192cf4872265391563fd6a84c81ff2c0f2a7026ca4c1d85c" +checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -914,9 +778,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" dependencies = [ "cfg-if 1.0.0", "crossbeam-epoch", @@ -925,23 +789,22 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.9" +version = "0.9.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07db9d94cbd326813772c968ccd25999e5f8ae22f4f8d1b11effa37ef6ce281d" +checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" dependencies = [ "autocfg", "cfg-if 1.0.0", "crossbeam-utils", - "memoffset", - "once_cell", + "memoffset 0.8.0", "scopeguard", ] [[package]] name = "crossbeam-queue" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f25d8400f4a7a5778f0e4e52384a48cbd9b5c495d110786187fc750075277a2" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -949,19 +812,18 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.10" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d82ee10ce34d7bc12c2122495e7593a9c41347ecdd64185af4ecf72cb1a7f83" +checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" dependencies = [ "cfg-if 1.0.0", - "once_cell", ] [[package]] name = "crypto-common" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ccfd8c0ee4cce11e45b3fd6f9d5e69e0cc62912aa6a0cb1bf4617b0eba5a12f" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", "typenum", @@ -969,13 +831,12 @@ dependencies = [ [[package]] name = "csv" -version = "1.1.6" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" +checksum = "0b015497079b9a9d69c02ad25de6c0a6edef051ea6360a327d0bd05802ef64ad" dependencies = [ - "bstr", "csv-core", - "itoa 0.4.8", + "itoa", "ryu", "serde", ] @@ -991,9 +852,9 @@ dependencies = [ [[package]] name = "ctor" -version = "0.1.22" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c" +checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" dependencies = [ "quote", "syn", @@ -1005,6 +866,15 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" +[[package]] +name = "cvt" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ac344c7efccb80cd25bc61b2170aec26f2f693fd40e765a539a1243db48c71" +dependencies = [ + "cfg-if 0.1.10", +] + [[package]] name = "d3d12" version = "0.4.1" @@ -1053,14 +923,15 @@ dependencies = [ [[package]] name = "dashmap" -version = "5.3.4" +version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3495912c9c1ccf2e18976439f4443f3fee0fd61f424ff99fde6a66b15ecb448f" +checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" dependencies = [ "cfg-if 1.0.0", "hashbrown 0.12.3", "lock_api", - "parking_lot_core 0.9.3", + "once_cell", + "parking_lot_core 0.9.7", ] [[package]] @@ -1071,9 +942,9 @@ checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] name = "digest" -version = "0.10.3" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ "block-buffer", "crypto-common", @@ -1082,9 +953,9 @@ dependencies = [ [[package]] name = "dircpy" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73ff6269b47c0c5220a0ff5eb140424340276ec89a10e58cbd4cf366de52dfa9" +checksum = "10b6622b9d0dc20c70e74ff24c56493278d7d9299ac8729deb923703616e5a7e" dependencies = [ "jwalk", "log", @@ -1093,11 +964,10 @@ dependencies = [ [[package]] name = "directories" -version = "2.0.2" +version = "4.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "551a778172a450d7fc12e629ca3b0428d00f6afa9a43da1b630d54604e97371c" +checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210" dependencies = [ - "cfg-if 0.1.10", "dirs-sys", ] @@ -1174,9 +1044,9 @@ checksum = "0bd4b30a6560bbd9b4620f4de34c3f14f60848e58a9b7216801afcb4c7b31c3c" [[package]] name = "either" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "encode_unicode" @@ -1192,9 +1062,9 @@ checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[package]] name = "encoding_rs" -version = "0.8.31" +version = "0.8.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" dependencies = [ "cfg-if 1.0.0", ] @@ -1226,6 +1096,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "errno" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys 0.45.0", +] + [[package]] name = "errno-dragonfly" version = "0.1.2" @@ -1246,36 +1127,27 @@ dependencies = [ "str-buf", ] -[[package]] -name = "fastrand" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" -dependencies = [ - "instant", -] - [[package]] name = "fd-lock" -version = "3.0.6" +version = "3.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e11dcc7e4d79a8c89b9ab4c6f5c30b1fc4a83c420792da3542fd31179ed5f517" +checksum = "8ef1a30ae415c3a691a4f41afddc2dbcd6d70baf338368d85ebc1e8ed92cedb9" dependencies = [ "cfg-if 1.0.0", "rustix", - "windows-sys 0.36.1", + "windows-sys 0.45.0", ] [[package]] name = "filetime" -version = "0.2.18" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b9663d381d07ae25dc88dbdf27df458faa83a9b25336bcac83d5e452b5fc9d3" +checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] @@ -1289,9 +1161,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" dependencies = [ "crc32fast", "miniz_oxide", @@ -1320,25 +1192,33 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ - "matches", "percent-encoding", ] [[package]] -name = "fs_extra" -version = "1.2.0" +name = "fs_at" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" +checksum = "ab60b097d8208fe02d24ae954c3248a9436f96edefa8f4b9fcb0f26d60d003a9" +dependencies = [ + "aligned", + "cfg-if 1.0.0", + "cvt", + "libc", + "nix 0.26.2", + "smart-default", + "windows-sys 0.45.0", +] [[package]] -name = "funty" -version = "1.2.0" +name = "fs_extra" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1847abb9cb65d566acd5942e94aea9c8f547ad02c98e1649326fc0e8910b8b1e" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" [[package]] name = "funty" @@ -1348,9 +1228,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.24" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f21eda599937fba36daeb58a22e8f5cee2d14c4a17b5b7739c7c8e5e3b8230c" +checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84" dependencies = [ "futures-channel", "futures-core", @@ -1363,9 +1243,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.24" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050" +checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" dependencies = [ "futures-core", "futures-sink", @@ -1373,15 +1253,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.24" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf" +checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" [[package]] name = "futures-executor" -version = "0.3.24" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ff63c23854bee61b6e9cd331d523909f238fc7636290b96826e9cfa5faa00ab" +checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" dependencies = [ "futures-core", "futures-task", @@ -1390,15 +1270,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.24" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68" +checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" [[package]] name = "futures-macro" -version = "0.3.24" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17" +checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" dependencies = [ "proc-macro2", "quote", @@ -1407,21 +1287,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.24" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56" +checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" [[package]] name = "futures-task" -version = "0.3.24" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1" +checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" [[package]] name = "futures-util" -version = "0.3.24" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90" +checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" dependencies = [ "futures-channel", "futures-core", @@ -1446,36 +1326,42 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ "typenum", "version_check", ] [[package]] -name = "getrandom" -version = "0.2.7" +name = "gethostname" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "getrandom" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if 1.0.0", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] name = "gimli" -version = "0.26.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" - -[[package]] -name = "glob" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" [[package]] name = "glow" @@ -1491,13 +1377,12 @@ dependencies = [ [[package]] name = "glyph_brush" -version = "0.7.5" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac02497410cdb5062cc056a33f2e1e19ff69fbf26a4be9a02bf29d6e17ea105b" +checksum = "4edefd123f28a0b1d41ec4a489c2b43020b369180800977801611084f342978d" dependencies = [ "glyph_brush_draw_cache", "glyph_brush_layout", - "log", "ordered-float", "rustc-hash", "twox-hash", @@ -1549,13 +1434,13 @@ dependencies = [ [[package]] name = "gpu-descriptor" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a538f217be4d405ff4719a283ca68323cc2384003eca5baaa87501e821c81dda" +checksum = "0b0c02e1ba0bdb14e965058ca34e09c020f8e507a760df1121728e0aef68d57a" dependencies = [ "bitflags", "gpu-descriptor-types", - "hashbrown 0.11.2", + "hashbrown 0.12.3", ] [[package]] @@ -1569,9 +1454,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" +checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d" dependencies = [ "bytes", "fnv", @@ -1592,30 +1477,30 @@ version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash", -] - [[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "ahash", + "ahash 0.7.6", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash 0.8.3", "bumpalo", ] [[package]] name = "heck" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" @@ -1626,6 +1511,15 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + [[package]] name = "hexf-parse" version = "0.2.1" @@ -1633,20 +1527,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" [[package]] -name = "hound" -version = "3.4.0" +name = "html-escape" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a164bb2ceaeff4f42542bdb847c41517c78a60f5649671b2a07312b6e117549" +checksum = "6d1ad449764d627e22bfd7cd5e8868264fc9236e07c752972b4080cd351cb476" +dependencies = [ + "utf8-width", +] [[package]] name = "http" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" dependencies = [ "bytes", "fnv", - "itoa 1.0.2", + "itoa", ] [[package]] @@ -1674,9 +1571,9 @@ checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "hyper" -version = "0.14.23" +version = "0.14.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" +checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c" dependencies = [ "bytes", "futures-channel", @@ -1687,7 +1584,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 1.0.2", + "itoa", "pin-project-lite", "socket2", "tokio", @@ -1698,9 +1595,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.23.1" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59df7c4e19c950e6e0e868dcc0a300b09a9b88e9ec55bd879ca819087a77355d" +checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" dependencies = [ "http", "hyper", @@ -1711,12 +1608,11 @@ dependencies = [ [[package]] name = "iced-x86" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "158f5204401d08f91d19176112146d75e99b3cf745092e268fa7be33e09adcec" +checksum = "1dd04b950d75b3498320253b17fb92745b2cc79ead8814aede2f7c1bab858bec" dependencies = [ "lazy_static", - "static_assertions", ] [[package]] @@ -1727,11 +1623,10 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" dependencies = [ - "matches", "unicode-bidi", "unicode-normalization", ] @@ -1766,9 +1661,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.1" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", "hashbrown 0.12.3", @@ -1776,9 +1671,9 @@ dependencies = [ [[package]] name = "indoc" -version = "1.0.7" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adab1eaa3408fb7f0c777a73e7465fd5656136fc93b670eb6df3c88c2c1344e3" +checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306" [[package]] name = "inkwell" @@ -1805,19 +1700,19 @@ dependencies = [ [[package]] name = "inplace_it" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90953f308a79fe6d62a4643e51f848fbfddcd05975a38e69fdf4ab86a7baf7ca" +checksum = "e567468c50f3d4bc7397702e09b380139f9b9288b4e909b070571007f8b5bf78" [[package]] name = "insta" -version = "1.20.0" +version = "1.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58a931b01c76064c5be919faa2ef0dc570e9a889dcd1e5fef08a8ca6eb4d6c0b" +checksum = "fea5b3894afe466b4bcf0388630fc15e11938a6074af0cd637c825ba2ec8a099" dependencies = [ "console", + "lazy_static", "linked-hash-map", - "once_cell", "similar", "yaml-rust", ] @@ -1836,15 +1731,19 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "0.7.2" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24c3f4eff5495aee4c0399d7b6a0dc2b6e81be84242ffbfcf253ebacccc1d0cb" +checksum = "cfa919a82ea574332e2de6e74b4c36e74d41982b335080fa59d4ef31be20fdf3" +dependencies = [ + "libc", + "windows-sys 0.45.0", +] [[package]] name = "ipnet" -version = "2.5.1" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f88c5561171189e69df9d98bcf18fd5f9558300f7ea7b801eb8a0fd748bd8745" +checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" [[package]] name = "itertools" @@ -1866,29 +1765,9 @@ dependencies = [ [[package]] name = "itoa" -version = "0.4.8" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - -[[package]] -name = "itoa" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" - -[[package]] -name = "jni" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" -dependencies = [ - "cesu8", - "combine", - "jni-sys", - "log", - "thiserror", - "walkdir", -] +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "jni-sys" @@ -1896,29 +1775,20 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" -[[package]] -name = "jobserver" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" -dependencies = [ - "libc", -] - [[package]] name = "js-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" dependencies = [ "wasm-bindgen", ] [[package]] name = "jwalk" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "172752e853a067cbce46427de8470ddf308af7fd8ceaf9b682ef31a5021b6bb9" +checksum = "5dbcda57db8b6dc067e589628b7348639014e793d9e8137d8cf215e8b133a0bd" dependencies = [ "crossbeam", "rayon", @@ -1946,46 +1816,36 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[package]] -name = "lewton" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030" -dependencies = [ - "byteorder", - "ogg", - "tinyvec", -] - [[package]] name = "libc" -version = "0.2.135" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "libloading" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" dependencies = [ "cfg-if 1.0.0", "winapi", ] [[package]] -name = "libmimalloc-sys" -version = "0.1.25" +name = "libm" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11ca136052550448f55df7898c6dbe651c6b574fe38a0d9ea687a9f8088a2e2c" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" + +[[package]] +name = "libmimalloc-sys" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8c7cbf8b89019683667e347572e6d55a7df7ea36b0c4ce69961b0cde67b174" dependencies = [ "cc", + "libc", ] [[package]] @@ -1996,15 +1856,15 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.0.46" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4d2456c373231a208ad294c33dc5bff30051eafd954cd4caae83a712b12854d" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" [[package]] name = "llvm-sys" -version = "130.0.4" +version = "130.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdb6ea20e8a348f6db0b43a7f009fa7d981d22edf4cbe2e0c7b2247dbb25be61" +checksum = "b54ec4a457c4b55ffb2bd56ed44841161ae933fd4fe3dc379748fcd4193661d4" dependencies = [ "cc", "lazy_static", @@ -2015,9 +1875,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ "autocfg", "scopeguard", @@ -2032,15 +1892,6 @@ dependencies = [ "cfg-if 1.0.0", ] -[[package]] -name = "mach" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" -dependencies = [ - "libc", -] - [[package]] name = "mach_object" version = "0.1.17" @@ -2081,12 +1932,6 @@ dependencies = [ "regex-automata", ] -[[package]] -name = "matches" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" - [[package]] name = "memchr" version = "2.5.0" @@ -2104,9 +1949,9 @@ dependencies = [ [[package]] name = "memmap2" -version = "0.5.7" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95af15f345b17af2efc8ead6080fb8bc376f8cec1b35277b935637595fe77498" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" dependencies = [ "libc", ] @@ -2120,6 +1965,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memoffset" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +dependencies = [ + "autocfg", +] + [[package]] name = "metal" version = "0.23.1" @@ -2136,9 +1990,9 @@ dependencies = [ [[package]] name = "mimalloc" -version = "0.1.29" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f64ad83c969af2e732e907564deb0d0ed393cec4af80776f77dd77a1a427698" +checksum = "9dcb174b18635f7561a0c6c9fc2ce57218ac7523cf72c50af80e2d79ab8f3ba1" dependencies = [ "libmimalloc-sys", ] @@ -2155,45 +2009,25 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "minimp3" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "985438f75febf74c392071a975a29641b420dd84431135a6e6db721de4b74372" -dependencies = [ - "minimp3-sys", - "slice-deque", - "thiserror", -] - -[[package]] -name = "minimp3-sys" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e21c73734c69dc95696c9ed8926a2b393171d98b3f5f5935686a26a487ab9b90" -dependencies = [ - "cc", -] - [[package]] name = "miniz_oxide" -version = "0.5.3" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" dependencies = [ "libc", "log", "wasi", - "windows-sys 0.36.1", + "windows-sys 0.45.0", ] [[package]] @@ -2232,20 +2066,7 @@ checksum = "96d868f654c72e75f8687572699cdabe755f03effbb62542768e995d5b8d699d" dependencies = [ "bitflags", "jni-sys", - "ndk-sys 0.2.2", - "num_enum", - "thiserror", -] - -[[package]] -name = "ndk" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2032c77e030ddee34a6787a64166008da93f6a352b629261d0fee232b8742dd4" -dependencies = [ - "bitflags", - "jni-sys", - "ndk-sys 0.3.0", + "ndk-sys", "num_enum", "thiserror", ] @@ -2265,25 +2086,10 @@ dependencies = [ "lazy_static", "libc", "log", - "ndk 0.5.0", + "ndk", "ndk-context", "ndk-macro", - "ndk-sys 0.2.2", -] - -[[package]] -name = "ndk-glue" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d0c4a7b83860226e6b4183edac21851f05d5a51756e97a1144b7f5a6b63e65f" -dependencies = [ - "lazy_static", - "libc", - "log", - "ndk 0.6.0", - "ndk-context", - "ndk-macro", - "ndk-sys 0.3.0", + "ndk-sys", ] [[package]] @@ -2305,15 +2111,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121" -[[package]] -name = "ndk-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e5a6ae77c8ee183dcbbba6150e2e6b9f3f4196a7666c02a715a95692ec1fa97" -dependencies = [ - "jni-sys", -] - [[package]] name = "nibble_vec" version = "0.1.0" @@ -2333,38 +2130,51 @@ dependencies = [ "cc", "cfg-if 1.0.0", "libc", - "memoffset", + "memoffset 0.6.5", ] [[package]] name = "nix" -version = "0.23.1" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" +checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" dependencies = [ "bitflags", "cc", "cfg-if 1.0.0", "libc", - "memoffset", + "memoffset 0.6.5", ] [[package]] name = "nix" -version = "0.24.1" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f17df307904acd05aa8e32e97bb20f2a0df1728bbc2d771ae8f9a90463441e9" +checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" dependencies = [ "bitflags", "cfg-if 1.0.0", "libc", + "memoffset 0.6.5", +] + +[[package]] +name = "nix" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" +dependencies = [ + "bitflags", + "cfg-if 1.0.0", + "libc", + "static_assertions", ] [[package]] name = "nom" -version = "7.1.1" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", "minimal-lexical", @@ -2372,9 +2182,18 @@ dependencies = [ [[package]] name = "nonempty" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09f1f8e5676e1a1f2ee8b21f38238e1243c827531c9435624c7bfb305102cee4" +checksum = "aeaf4ad7403de93e699c191202f017118df734d3850b01e13a3a8b2e6953d3c9" + +[[package]] +name = "normpath" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "972dec05f98e7c787ede35d7a9ea4735eb7788c299287352757b3def6cc1f7b5" +dependencies = [ + "windows-sys 0.45.0", +] [[package]] name = "nu-ansi-term" @@ -2386,17 +2205,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "num-derive" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "num-traits" version = "0.2.15" @@ -2404,32 +2212,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", + "libm", ] [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ - "hermit-abi", + "hermit-abi 0.2.6", "libc", ] [[package]] name = "num_enum" -version = "0.5.7" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9" +checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.5.7" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" +checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -2437,15 +2246,6 @@ dependencies = [ "syn", ] -[[package]] -name = "num_threads" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" -dependencies = [ - "libc", -] - [[package]] name = "objc" version = "0.2.7" @@ -2487,54 +2287,22 @@ dependencies = [ [[package]] name = "object" -version = "0.29.0" +version = "0.30.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" dependencies = [ "crc32fast", "flate2", - "hashbrown 0.12.3", + "hashbrown 0.13.2", "indexmap", "memchr", ] -[[package]] -name = "oboe" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27f63c358b4fa0fbcfefd7c8be5cfc39c08ce2389f5325687e7762a48d30a5c1" -dependencies = [ - "jni", - "ndk 0.6.0", - "ndk-context", - "num-derive", - "num-traits", - "oboe-sys", -] - -[[package]] -name = "oboe-sys" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3370abb7372ed744232c12954d920d1a40f1c4686de9e79e800021ef492294bd" -dependencies = [ - "cc", -] - -[[package]] -name = "ogg" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e" -dependencies = [ - "byteorder", -] - [[package]] name = "once_cell" -version = "1.17.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "oorandom" @@ -2544,18 +2312,18 @@ checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] name = "ordered-float" -version = "3.0.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96bcbab4bfea7a59c2c0fe47211a1ac4e3e96bea6eb446d704f310bc5c732ae2" +checksum = "d84eb1409416d254e4a9c8fa56cc24701755025b458f0fcd8e59e1f5f40c23bf" dependencies = [ "num-traits", ] [[package]] name = "os_str_bytes" -version = "6.1.0" +version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" [[package]] name = "output_vt100" @@ -2574,29 +2342,29 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "owned_ttf_parser" -version = "0.15.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb1e509cfe7a12db2a90bfa057dfcdbc55a347f5da677c506b53dd099cfec9d" +checksum = "e25e9fb15717794fae58ab55c26e044103aad13186fbb625893f9a3bbcc24228" dependencies = [ "ttf-parser", ] [[package]] name = "packed_struct" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c48e482b9a59ad6c2cdb06f7725e7bd33fe3525baaf4699fde7bfea6a5b77b1" +checksum = "36b29691432cc9eff8b282278473b63df73bea49bc3ec5e67f31a3ae9c3ec190" dependencies = [ - "bitvec 0.22.3", + "bitvec", "packed_struct_codegen", "serde", ] [[package]] name = "packed_struct_codegen" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e3692b867ec1d48ccb441e951637a2cc3130d0912c0059e48319e1c83e44bc" +checksum = "9cd6706dfe50d53e0f6aa09e12c034c44faacd23e966ae5a209e8bdb8f179f98" dependencies = [ "proc-macro2", "quote", @@ -2605,9 +2373,9 @@ dependencies = [ [[package]] name = "page_size" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eebde548fbbf1ea81a99b128872779c437752fb99f217c45245e1a61dcd9edcd" +checksum = "1b7663cbd190cfd818d08efa8497f6cd383076688c49a391ef7c0d03cd12b561" dependencies = [ "libc", "winapi", @@ -2645,7 +2413,7 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", - "parking_lot_core 0.8.5", + "parking_lot_core 0.8.6", ] [[package]] @@ -2655,14 +2423,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.3", + "parking_lot_core 0.9.7", ] [[package]] name = "parking_lot_core" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" dependencies = [ "cfg-if 1.0.0", "instant", @@ -2674,23 +2442,17 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.3" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall", "smallvec", - "windows-sys 0.36.1", + "windows-sys 0.45.0", ] -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" - [[package]] name = "peg" version = "0.8.1" @@ -2720,15 +2482,15 @@ checksum = "9fa00462b37ead6d11a82c9d568b26682d78e0477dc02d1966c013af80969739" [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pest" -version = "2.3.1" +version = "2.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb779fcf4bb850fbbb0edc96ff6cf34fd90c4b1a112ce042653280d9a7364048" +checksum = "8cbd939b234e95d72bc393d51788aec68aeeb5d51e748ca08ff3aad58cb722f7" dependencies = [ "thiserror", "ucd-trie", @@ -2736,9 +2498,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.3.1" +version = "2.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "502b62a6d0245378b04ffe0a7fb4f4419a4815fce813bd8a0ec89a56e07d67b1" +checksum = "a81186863f3d0a27340815be8f2078dd8050b14cd71913db9fbda795e5f707d7" dependencies = [ "pest", "pest_generator", @@ -2746,9 +2508,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.3.1" +version = "2.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451e629bf49b750254da26132f1a5a9d11fd8a95a3df51d15c4abd1ba154cb6c" +checksum = "75a1ef20bf3193c15ac345acb32e26b3dc3223aff4d77ae4fc5359567683796b" dependencies = [ "pest", "pest_meta", @@ -2759,13 +2521,13 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.3.1" +version = "2.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcec162c71c45e269dfc3fc2916eaeb97feab22993a21bcce4721d08cd7801a6" +checksum = "5e3b284b1f13a20dc5ebc90aff59a51b8d7137c221131b52a7260c08cbc1cc80" dependencies = [ "once_cell", "pest", - "sha1", + "sha2", ] [[package]] @@ -2824,9 +2586,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "plotters" @@ -2848,18 +2610,18 @@ checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" [[package]] name = "plotters-svg" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0918736323d1baff32ee0eade54984f6f201ad7e97d5cfb5d6ab4a358529615" +checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" dependencies = [ "plotters-backend", ] [[package]] name = "ppv-lite86" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "pretty_assertions" @@ -2875,58 +2637,34 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.1.3" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ - "thiserror", - "toml", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", + "once_cell", + "toml_edit", ] [[package]] name = "proc-macro2" -version = "1.0.40" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" dependencies = [ "unicode-ident", ] [[package]] name = "profiling" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f61dcf0b917cd75d4521d7343d1ffff3d1583054133c9b5cbea3375c703c40d" +checksum = "74605f360ce573babfe43964cbe520294dcb081afbf8c108fc6e23036b4da2df" [[package]] name = "proptest" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0d9cc07f18492d879586c92b485def06bc850da3118075cd45d50e9c95b0e5" +checksum = "29f1b898011ce9595050a68e60f90bad083ff2987a695a42357134c8381fba70" dependencies = [ "bit-set", "bitflags", @@ -2940,6 +2678,7 @@ dependencies = [ "regex-syntax", "rusty-fork", "tempfile", + "unarray", ] [[package]] @@ -2965,15 +2704,6 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" -[[package]] -name = "quick-xml" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8533f14c8382aaad0d592c812ac3b826162128b65662331e1127b45c3d18536b" -dependencies = [ - "memchr", -] - [[package]] name = "quickcheck" version = "1.0.3" @@ -2998,19 +2728,13 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.20" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ "proc-macro2", ] -[[package]] -name = "radium" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb" - [[package]] name = "radium" version = "0.7.0" @@ -3050,9 +2774,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] @@ -3077,9 +2801,9 @@ dependencies = [ [[package]] name = "range-alloc" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e935c45e09cc6dcf00d2f0b2d630a58f4095320223d47fc68918722f0538b6" +checksum = "9c8a99fddc9f0ba0a85884b8d14e3592853e787d581ca1816c91349b10e4eeab" [[package]] name = "raw-window-handle" @@ -3092,21 +2816,19 @@ dependencies = [ [[package]] name = "rayon" -version = "1.5.3" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" dependencies = [ - "autocfg", - "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.9.3" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -3116,9 +2838,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.13" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] @@ -3136,9 +2858,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" dependencies = [ "aho-corasick", "memchr", @@ -3156,9 +2878,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.27" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "remove_dir_all" @@ -3171,15 +2893,18 @@ dependencies = [ [[package]] name = "remove_dir_all" -version = "0.7.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "882f368737489ea543bc5c340e6f3d34a28c39980bd9a979e47322b26f60ac40" +checksum = "7174320e07c29945955cedd70b865995b286847111c8308d349a1f3a9e3af555" dependencies = [ + "aligned", + "cfg-if 1.0.0", + "cvt", + "fs_at", + "lazy_static", "libc", - "log", - "num_cpus", - "rayon", - "winapi", + "normpath", + "windows-sys 0.45.0", ] [[package]] @@ -3204,11 +2929,11 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.13" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c" +checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9" dependencies = [ - "base64", + "base64 0.21.0", "bytes", "encoding_rs", "futures-core", @@ -3258,9 +2983,9 @@ dependencies = [ [[package]] name = "rlimit" -version = "0.6.2" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc0bf25554376fd362f54332b8410a625c71f15445bca32ffdfdf4ec9ac91726" +checksum = "f8a29d87a652dc4d43c586328706bb5cdff211f3f39a530f240b53f7221dab8e" dependencies = [ "libc", ] @@ -3307,25 +3032,46 @@ dependencies = [ "winapi", ] +[[package]] +name = "roc_bitcode" +version = "0.0.1" +dependencies = [ + "dunce", + "roc_command_utils", + "tempfile", +] + +[[package]] +name = "roc_bitcode_bc" +version = "0.0.1" +dependencies = [ + "dunce", + "roc_command_utils", + "tempfile", +] + [[package]] name = "roc_build" version = "0.0.1" dependencies = [ "bumpalo", - "const_format", + "indoc", "inkwell", "libloading", - "roc_builtins", + "roc_bitcode", "roc_can", "roc_collections", + "roc_command_utils", "roc_constrain", "roc_error_macros", "roc_gen_dev", "roc_gen_llvm", "roc_gen_wasm", + "roc_linker", "roc_load", "roc_module", "roc_mono", + "roc_packaging", "roc_parse", "roc_problem", "roc_region", @@ -3335,7 +3081,6 @@ dependencies = [ "roc_target", "roc_types", "roc_unify", - "roc_utils", "serde_json", "target-lexicon", "tempfile", @@ -3346,12 +3091,10 @@ dependencies = [ name = "roc_builtins" version = "0.0.1" dependencies = [ - "dunce", "roc_collections", "roc_module", "roc_region", "roc_target", - "roc_utils", "tempfile", ] @@ -3359,7 +3102,7 @@ dependencies = [ name = "roc_can" version = "0.0.1" dependencies = [ - "bitvec 1.0.1", + "bitvec", "bumpalo", "indoc", "pretty_assertions", @@ -3381,11 +3124,11 @@ name = "roc_cli" version = "0.0.1" dependencies = [ "bumpalo", - "clap 3.2.20", + "clap 3.2.23", "cli_utils", "const_format", "criterion", - "errno", + "errno 0.3.0", "indoc", "inkwell", "libc", @@ -3397,6 +3140,7 @@ dependencies = [ "roc_builtins", "roc_can", "roc_collections", + "roc_command_utils", "roc_docs", "roc_editor", "roc_error_macros", @@ -3416,7 +3160,6 @@ dependencies = [ "roc_target", "roc_test_utils", "roc_tracing", - "roc_utils", "roc_wasm_interp", "serial_test", "signal-hook", @@ -3433,8 +3176,8 @@ dependencies = [ "bumpalo", "palette", "roc_ast", + "roc_error_utils", "roc_module", - "roc_utils", "serde", "snafu", ] @@ -3443,15 +3186,19 @@ dependencies = [ name = "roc_collections" version = "0.0.1" dependencies = [ - "bitvec 1.0.1", + "bitvec", "bumpalo", "fnv", - "hashbrown 0.12.3", + "hashbrown 0.13.2", "im", "im-rc", "wyhash", ] +[[package]] +name = "roc_command_utils" +version = "0.0.1" + [[package]] name = "roc_constrain" version = "0.0.1" @@ -3490,7 +3237,6 @@ dependencies = [ name = "roc_derive_key" version = "0.0.1" dependencies = [ - "roc_can", "roc_collections", "roc_error_macros", "roc_module", @@ -3527,7 +3273,7 @@ dependencies = [ name = "roc_docs_cli" version = "0.0.1" dependencies = [ - "clap 3.2.20", + "clap 3.2.23", "libc", "roc_docs", ] @@ -3559,6 +3305,7 @@ dependencies = [ "roc_can", "roc_code_markup", "roc_collections", + "roc_command_utils", "roc_load", "roc_module", "roc_packaging", @@ -3569,8 +3316,6 @@ dependencies = [ "roc_solve", "roc_types", "roc_unify", - "roc_utils", - "rodio", "serde", "snafu", "tempfile", @@ -3586,6 +3331,13 @@ dependencies = [ name = "roc_error_macros" version = "0.0.1" +[[package]] +name = "roc_error_utils" +version = "0.0.1" +dependencies = [ + "snafu", +] + [[package]] name = "roc_exhaustive" version = "0.0.1" @@ -3641,6 +3393,7 @@ dependencies = [ "inkwell", "morphic_lib", "roc_alias_analysis", + "roc_bitcode_bc", "roc_builtins", "roc_collections", "roc_debug_flags", @@ -3657,7 +3410,7 @@ dependencies = [ name = "roc_gen_wasm" version = "0.0.1" dependencies = [ - "bitvec 1.0.1", + "bitvec", "bumpalo", "roc_builtins", "roc_collections", @@ -3674,7 +3427,6 @@ name = "roc_glue" version = "0.0.1" dependencies = [ "bumpalo", - "clap 3.2.20", "cli_utils", "dircpy", "fnv", @@ -3692,7 +3444,6 @@ dependencies = [ "roc_reporting", "roc_std", "roc_target", - "roc_test_utils", "roc_tracing", "roc_types", "strum", @@ -3705,8 +3456,9 @@ dependencies = [ name = "roc_highlight" version = "0.0.1" dependencies = [ - "peg", - "roc_code_markup", + "html-escape", + "roc_parse", + "roc_region", ] [[package]] @@ -3738,15 +3490,15 @@ dependencies = [ "indoc", "libc", "mach_object", - "memmap2 0.5.7", + "memmap2 0.5.10", "object", - "roc_build", "roc_collections", "roc_error_macros", "roc_load", "roc_mono", "roc_packaging", "roc_reporting", + "roc_target", "serde", "target-lexicon", "tempfile", @@ -3822,9 +3574,9 @@ dependencies = [ name = "roc_mono" version = "0.0.1" dependencies = [ - "bitvec 1.0.1", + "bitvec", "bumpalo", - "hashbrown 0.12.3", + "hashbrown 0.13.2", "parking_lot 0.12.1", "roc_builtins", "roc_can", @@ -3856,8 +3608,6 @@ dependencies = [ "bumpalo", "flate2", "fs_extra", - "indoc", - "pretty_assertions", "reqwest", "roc_error_macros", "roc_parse", @@ -3881,7 +3631,6 @@ dependencies = [ "roc_collections", "roc_module", "roc_region", - "roc_test_utils", ] [[package]] @@ -3983,7 +3732,6 @@ dependencies = [ "strip-ansi-escapes", "target-lexicon", "tempfile", - "test_gen", ] [[package]] @@ -3993,7 +3741,9 @@ dependencies = [ "bumpalo", "console_error_panic_hook", "futures", + "getrandom", "js-sys", + "roc_bitcode", "roc_builtins", "roc_collections", "roc_gen_wasm", @@ -4003,7 +3753,6 @@ dependencies = [ "roc_reporting", "roc_target", "roc_types", - "roc_utils", "tempfile", "wasi_libc_sys", "wasm-bindgen", @@ -4101,6 +3850,12 @@ name = "roc_std" version = "0.0.1" dependencies = [ "arrayvec 0.7.2", + "libc", + "pretty_assertions", + "quickcheck", + "quickcheck_macros", + "serde", + "serde_json", "static_assertions", ] @@ -4118,7 +3873,7 @@ name = "roc_test_utils" version = "0.0.1" dependencies = [ "pretty_assertions", - "remove_dir_all 0.7.0", + "remove_dir_all 0.8.1", ] [[package]] @@ -4150,30 +3905,21 @@ name = "roc_unify" version = "0.0.1" dependencies = [ "bitflags", - "roc_can", "roc_collections", "roc_debug_flags", "roc_error_macros", "roc_module", - "roc_solve_problem", "roc_tracing", "roc_types", ] [[package]] -name = "roc_utils" +name = "roc_wasm_interp" version = "0.0.1" dependencies = [ - "snafu", -] - -[[package]] -name = "roc_wasm_interp" -version = "0.1.0" -dependencies = [ - "bitvec 1.0.1", + "bitvec", "bumpalo", - "clap 3.2.20", + "clap 3.2.23", "rand", "roc_wasm_module", ] @@ -4182,24 +3928,11 @@ dependencies = [ name = "roc_wasm_module" version = "0.0.1" dependencies = [ - "bitvec 1.0.1", + "bitvec", "bumpalo", "roc_error_macros", ] -[[package]] -name = "rodio" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0939e9f626e6c6f1989adb6226a039c855ca483053f0ee7c98b90e41cf731e" -dependencies = [ - "claxon", - "cpal", - "hound", - "lewton", - "minimp3", -] - [[package]] name = "rustc-demangle" version = "0.1.21" @@ -4218,28 +3951,28 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.12", + "semver 1.0.16", ] [[package]] name = "rustix" -version = "0.35.7" +version = "0.36.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51cc38aa10f6bbb377ed28197aa052aa4e2b762c22be9d3153d01822587e787" +checksum = "fd5c6ff11fecd55b40746d1995a02f2eb375bf8c00d192d521ee09f42bef37bc" dependencies = [ "bitflags", - "errno", + "errno 0.2.8", "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.36.1", + "windows-sys 0.45.0", ] [[package]] name = "rustls" -version = "0.20.7" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "539a2bfe908f471bfa933876bd1eb6a19cf2176d375f82ef7f99530a40e48c2c" +checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" dependencies = [ "log", "ring", @@ -4249,18 +3982,18 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0864aeff53f8c05aa08d86e5ef839d3dfcf07aeba2db32f12db0ef716e87bd55" +checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" dependencies = [ - "base64", + "base64 0.21.0", ] [[package]] name = "rustversion" -version = "1.0.7" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0a5f7c728f5d284929a1cccb5bc19884422bfe6ef4d6c409da2c41838983fcf" +checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" [[package]] name = "rusty-fork" @@ -4281,13 +4014,13 @@ source = "git+https://github.com/roc-lang/rustyline?rev=e74333c#e74333c0d618896b dependencies = [ "bitflags", "cfg-if 1.0.0", - "clipboard-win 4.4.1", + "clipboard-win 4.5.0", "dirs-next", "fd-lock", "libc", "log", "memchr", - "nix 0.23.1", + "nix 0.23.2", "radix_trie", "scopeguard", "smallvec", @@ -4308,9 +4041,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.10" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" [[package]] name = "same-file" @@ -4323,9 +4056,9 @@ dependencies = [ [[package]] name = "scoped-tls" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "scopeguard" @@ -4354,9 +4087,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.12" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2333e6df6d6598f2b1974829f853c2b4c5f4a6e503c10af918081aa6f8564e1" +checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" [[package]] name = "semver-parser" @@ -4369,18 +4102,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.144" +version = "1.0.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" +checksum = "3a382c72b4ba118526e187430bb4963cd6d55051ebf13d9b25574d379cc98d20" dependencies = [ "serde_derive", ] [[package]] name = "serde-xml-rs" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65162e9059be2f6a3421ebbb4fef3e74b7d9e7c60c50a0e292c6239f19f1edfa" +checksum = "fb3aa78ecda1ebc9ec9847d5d3aba7d618823446a049ba2491940506da6e2782" dependencies = [ "log", "serde", @@ -4400,9 +4133,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.144" +version = "1.0.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" +checksum = "1ef476a5790f0f6decbc66726b6e5d63680ed518283e64c7df415989d880954f" dependencies = [ "proc-macro2", "quote", @@ -4411,11 +4144,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.85" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" +checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea" dependencies = [ - "itoa 1.0.2", + "itoa", "ryu", "serde", ] @@ -4427,16 +4160,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.2", + "itoa", "ryu", "serde", ] [[package]] name = "serde_yaml" -version = "0.8.25" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec0091e1f5aa338283ce049bd9dfefd55e1f168ac233e85c1ffe0038fb48cbe" +checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" dependencies = [ "indexmap", "ryu", @@ -4446,9 +4179,9 @@ dependencies = [ [[package]] name = "serial_test" -version = "0.9.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92761393ee4dc3ff8f4af487bd58f4307c9329bbedea02cac0089ad9c411e153" +checksum = "538c30747ae860d6fb88330addbbd3e0ddbe46d662d032855596d8a8ca260611" dependencies = [ "dashmap", "futures", @@ -4460,32 +4193,20 @@ dependencies = [ [[package]] name = "serial_test_derive" -version = "0.9.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b6f5d1c3087fb119617cff2966fe3808a80e5eb59a8c1601d5994d66f4346a5" +checksum = "079a83df15f85d89a68d64ae1238f142f172b1fa915d0d76b26a7cba1b659a69" dependencies = [ - "proc-macro-error", "proc-macro2", "quote", "syn", ] -[[package]] -name = "sha1" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "006769ba83e921b3085caa8334186b00cf92b4cb1a6cf4632fbccc8eff5c7549" -dependencies = [ - "cfg-if 1.0.0", - "cpufeatures", - "digest", -] - [[package]] name = "sha2" -version = "0.10.2" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -4501,17 +4222,11 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "shlex" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" - [[package]] name = "signal-hook" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" +checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" dependencies = [ "libc", "signal-hook-registry", @@ -4519,18 +4234,18 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" dependencies = [ "libc", ] [[package]] name = "similar" -version = "2.1.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e24979f63a11545f5f2c60141afe249d4f19f84581ea2138065e400941d83d3" +checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" [[package]] name = "siphasher" @@ -4550,19 +4265,11 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" - -[[package]] -name = "slice-deque" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31ef6ee280cdefba6d2d0b4b78a84a1c1a3f3a4cec98c2d4231c8bc225de0f25" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" dependencies = [ - "libc", - "mach", - "winapi", + "autocfg", ] [[package]] @@ -4576,9 +4283,20 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "smart-default" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "smithay-client-toolkit" @@ -4609,8 +4327,8 @@ dependencies = [ "dlib", "lazy_static", "log", - "memmap2 0.5.7", - "nix 0.24.1", + "memmap2 0.5.10", + "nix 0.24.3", "pkg-config", "wayland-client", "wayland-cursor", @@ -4629,9 +4347,9 @@ dependencies = [ [[package]] name = "snafu" -version = "0.7.1" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5177903bf45656592d9eb5c0e22f408fc023aae51dbe2088889b71633ba451f2" +checksum = "cb0656e7e3ffb70f6c39b3c2a86332bb74aa3c679da781642590f3c1118c5045" dependencies = [ "backtrace", "doc-comment", @@ -4640,9 +4358,9 @@ dependencies = [ [[package]] name = "snafu-derive" -version = "0.7.1" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "410b26ed97440d90ced3e2488c868d56a86e2064f5d7d6f417909b286afe25e5" +checksum = "475b3bbe5245c26f2d8a6f62d67c1f30eb9fffeccee721c45d162c3ebbdf81b2" dependencies = [ "heck", "proc-macro2", @@ -4652,9 +4370,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" dependencies = [ "libc", "winapi", @@ -4676,18 +4394,18 @@ dependencies = [ "num-traits", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "stdweb" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e" - [[package]] name = "str-buf" version = "1.0.6" @@ -4739,9 +4457,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.99" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", @@ -4767,19 +4485,19 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.4" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02424087780c9b71cc96799eaeddff35af2bc513278cda5c99fc1f5d026d3c1" +checksum = "8ae9980cab1db3fceee2f6c6f643d5d8de2997c58ee8d25fb0cc8a9e9e7348e5" [[package]] name = "tempfile" -version = "3.3.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" dependencies = [ "cfg-if 1.0.0", - "fastrand", "libc", + "rand", "redox_syscall", "remove_dir_all 0.5.3", "winapi", @@ -4787,31 +4505,19 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] -[[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 = "test_derive" version = "0.0.1" dependencies = [ "bumpalo", - "indoc", "insta", - "pretty_assertions", "roc_builtins", "roc_can", "roc_collections", @@ -4841,10 +4547,12 @@ dependencies = [ "lazy_static", "libc", "libloading", + "roc_bitcode", "roc_build", "roc_builtins", "roc_can", "roc_collections", + "roc_command_utils", "roc_constrain", "roc_debug_flags", "roc_error_macros", @@ -4864,7 +4572,6 @@ dependencies = [ "roc_target", "roc_types", "roc_unify", - "roc_utils", "roc_wasm_interp", "roc_wasm_module", "target-lexicon", @@ -4927,24 +4634,24 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.31" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" +checksum = "a5ab016db510546d856297882807df8da66a16fb8c4101cb8b30054b0d5b2d9c" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.31" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" +checksum = "5420d42e90af0c38c3290abcca25b9b3bdf379fc9f55c528f53a269d9c9a267e" dependencies = [ "proc-macro2", "quote", @@ -4953,10 +4660,11 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.4" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" dependencies = [ + "cfg-if 1.0.0", "once_cell", ] @@ -4971,21 +4679,30 @@ dependencies = [ [[package]] name = "time" -version = "0.3.11" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c91f41dcb2f096c05f0873d667dceec1087ce5bcf984ec8ffb19acddbb3217" +checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" dependencies = [ - "itoa 1.0.2", - "libc", - "num_threads", + "itoa", + "serde", + "time-core", "time-macros", ] [[package]] -name = "time-macros" -version = "0.2.4" +name = "time-core" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + +[[package]] +name = "time-macros" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36" +dependencies = [ + "time-core", +] [[package]] name = "tinytemplate" @@ -5008,15 +4725,15 @@ dependencies = [ [[package]] name = "tinyvec_macros" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.24.1" +version = "1.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d9f76183f91ecfb55e1d7d5602bd1d979e38a3a522fe900241cf195624d67ae" +checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64" dependencies = [ "autocfg", "bytes", @@ -5026,7 +4743,7 @@ dependencies = [ "num_cpus", "pin-project-lite", "socket2", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] @@ -5042,9 +4759,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.4" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" +checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" dependencies = [ "bytes", "futures-core", @@ -5056,13 +4773,30 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" + +[[package]] +name = "toml_edit" +version = "0.19.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a1eb0622d28f4b9c90adc4ea4b2b46b47663fde9ac5fafcb14a1369d5508825" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + [[package]] name = "tower-service" version = "0.3.2" @@ -5071,9 +4805,9 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.36" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if 1.0.0", "pin-project-lite", @@ -5094,9 +4828,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ "proc-macro2", "quote", @@ -5144,15 +4878,15 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "ttf-parser" -version = "0.15.2" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b3e06c9b9d80ed6b745c7159c40b311ad2916abb34a49e9be2653b90db0d8dd" +checksum = "0609f771ad9c6155384897e1df4d948e692667cc0588548b68eb44d052b27633" [[package]] name = "twox-hash" @@ -5167,21 +4901,27 @@ dependencies = [ [[package]] name = "typed-arena" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0685c84d5d54d1c26f7d3eb96cd41550adb97baed141a761cf335d3d33bcd0ae" +checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" [[package]] name = "typenum" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "ucd-trie" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" + +[[package]] +name = "unarray" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89570599c4fe5585de2b388aab47e99f7fa4e9238a1399f707a02e356058141c" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicase" @@ -5194,15 +4934,15 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.8" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" +checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" [[package]] name = "unicode-ident" -version = "1.0.1" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" [[package]] name = "unicode-normalization" @@ -5215,21 +4955,21 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "unicode-xid" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] name = "untrusted" @@ -5239,15 +4979,21 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22fe195a4f217c25b25cb5058ced57059824a678474874038dc88d211bf508d3" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", "idna", "percent-encoding", ] +[[package]] +name = "utf8-width" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5190c9442dcdaf0ddd50f37420417d219ae5261bbf5db120d0f9bab996c9cba1" + [[package]] name = "utf8parse" version = "0.2.0" @@ -5256,22 +5002,21 @@ checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372" [[package]] name = "uuid" -version = "1.1.2" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f" +checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" dependencies = [ "getrandom", ] [[package]] name = "valgrind" -version = "0.1.0" +version = "0.0.1" dependencies = [ "bumpalo", "cli_utils", "indoc", "roc_build", - "roc_cli", "roc_linker", "roc_load", "roc_mono", @@ -5370,14 +5115,14 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" name = "wasi_libc_sys" version = "0.0.1" dependencies = [ - "roc_utils", + "roc_command_utils", ] [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -5385,9 +5130,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ "bumpalo", "log", @@ -5400,9 +5145,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.33" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -5412,9 +5157,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5422,9 +5167,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", @@ -5435,20 +5180,20 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "wayland-client" -version = "0.29.4" +version = "0.29.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91223460e73257f697d9e23d401279123d36039a3f7a449e983f123292d4458f" +checksum = "3f3b068c05a039c9f755f881dc50f01732214f5685e379829759088967c46715" dependencies = [ "bitflags", "downcast-rs", "libc", - "nix 0.22.3", + "nix 0.24.3", "scoped-tls", "wayland-commons", "wayland-scanner", @@ -5457,11 +5202,11 @@ dependencies = [ [[package]] name = "wayland-commons" -version = "0.29.4" +version = "0.29.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94f6e5e340d7c13490eca867898c4cec5af56c27a5ffe5c80c6fc4708e22d33e" +checksum = "8691f134d584a33a6606d9d717b95c4fa20065605f798a3f350d78dced02a902" dependencies = [ - "nix 0.22.3", + "nix 0.24.3", "once_cell", "smallvec", "wayland-sys", @@ -5469,20 +5214,20 @@ dependencies = [ [[package]] name = "wayland-cursor" -version = "0.29.4" +version = "0.29.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c52758f13d5e7861fc83d942d3d99bf270c83269575e52ac29e5b73cb956a6bd" +checksum = "6865c6b66f13d6257bef1cd40cbfe8ef2f150fb8ebbdb1e8e873455931377661" dependencies = [ - "nix 0.22.3", + "nix 0.24.3", "wayland-client", "xcursor", ] [[package]] name = "wayland-protocols" -version = "0.29.4" +version = "0.29.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60147ae23303402e41fe034f74fb2c35ad0780ee88a1c40ac09a3be1e7465741" +checksum = "b950621f9354b322ee817a23474e479b34be96c2e909c14f7bc0100e9a970bc6" dependencies = [ "bitflags", "wayland-client", @@ -5492,9 +5237,9 @@ dependencies = [ [[package]] name = "wayland-scanner" -version = "0.29.4" +version = "0.29.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39a1ed3143f7a143187156a2ab52742e89dac33245ba505c17224df48939f9e0" +checksum = "8f4303d8fa22ab852f789e75a967f0a2cdc430a607751c0499bada3e451cbd53" dependencies = [ "proc-macro2", "quote", @@ -5503,9 +5248,9 @@ dependencies = [ [[package]] name = "wayland-sys" -version = "0.29.4" +version = "0.29.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9341df79a8975679188e37dab3889bfa57c44ac2cb6da166f519a81cbe452d4" +checksum = "be12ce1a3c39ec7dba25594b97b42cb3195d54953ddb9d3d95a7c3902bc6e9d4" dependencies = [ "dlib", "lazy_static", @@ -5534,9 +5279,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.22.5" +version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368bfe657969fb01238bb756d351dcade285e0f6fcbd36dcb23359a5169975be" +checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" dependencies = [ "webpki", ] @@ -5669,25 +5414,21 @@ dependencies = [ "winapi", ] +[[package]] +name = "winapi-wsapoll" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e" +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.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" -dependencies = [ - "windows_aarch64_msvc 0.36.1", - "windows_i686_gnu 0.36.1", - "windows_i686_msvc 0.36.1", - "windows_x86_64_gnu 0.36.1", - "windows_x86_64_msvc 0.36.1", -] - [[package]] name = "windows-sys" version = "0.42.0" @@ -5695,85 +5436,79 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ "windows_aarch64_gnullvm", - "windows_aarch64_msvc 0.42.0", - "windows_i686_gnu 0.42.0", - "windows_i686_msvc 0.42.0", - "windows_x86_64_gnu 0.42.0", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.42.0", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" [[package]] name = "windows_aarch64_msvc" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" [[package]] name = "windows_i686_gnu" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" [[package]] name = "windows_i686_msvc" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" [[package]] name = "windows_x86_64_gnu" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" [[package]] name = "windows_x86_64_msvc" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" [[package]] name = "winit" @@ -5792,9 +5527,9 @@ dependencies = [ "libc", "log", "mio", - "ndk 0.5.0", - "ndk-glue 0.5.2", - "ndk-sys 0.2.2", + "ndk", + "ndk-glue", + "ndk-sys", "objc", "parking_lot 0.11.2", "percent-encoding", @@ -5808,6 +5543,15 @@ dependencies = [ "x11-dl", ] +[[package]] +name = "winnow" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee7b2c67f962bf5042bfd8b6a916178df33a26eec343ae064cb8e069f638fa6f" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.10.1" @@ -5828,42 +5572,55 @@ dependencies = [ [[package]] name = "wyz" -version = "0.4.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "129e027ad65ce1453680623c3fb5163cbf7107bfe1aa32257e7d0e63f9ced188" -dependencies = [ - "tap", -] - -[[package]] -name = "wyz" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b31594f29d27036c383b53b59ed3476874d518f0efb151b27a4c275141390e" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" dependencies = [ "tap", ] [[package]] name = "x11-clipboard" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a7468a5768fea473e6c8c0d4b60d6d7001a64acceaac267207ca0281e1337e8" +checksum = "0827f86aa910c4e73329a4f619deabe88ebb4b042370bf023c2d5d8b4eb54695" dependencies = [ - "xcb", + "x11rb", ] [[package]] name = "x11-dl" -version = "2.19.1" +version = "2.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea26926b4ce81a6f5d9d0f3a0bc401e5a37c6ae14a1bfaa8ff6099ca80038c59" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" dependencies = [ - "lazy_static", "libc", + "once_cell", "pkg-config", ] +[[package]] +name = "x11rb" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "592b4883219f345e712b3209c62654ebda0bb50887f330cbd018d0f654bfd507" +dependencies = [ + "gethostname", + "nix 0.24.3", + "winapi", + "winapi-wsapoll", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56b245751c0ac9db0e006dc812031482784e434630205a93c73cfefcaabeac67" +dependencies = [ + "nix 0.24.3", +] + [[package]] name = "xattr" version = "0.2.3" @@ -5873,17 +5630,6 @@ dependencies = [ "libc", ] -[[package]] -name = "xcb" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b127bf5bfe9dbb39118d6567e3773d4bbc795411a8e1ef7b7e056bccac0011a9" -dependencies = [ - "bitflags", - "libc", - "quick-xml", -] - [[package]] name = "xcursor" version = "0.3.4" diff --git a/Cargo.toml b/Cargo.toml index 14154895c7..acb726ba3f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,44 +1,40 @@ [workspace] members = [ - "crates/compiler/*", - "crates/vendor/*", - "crates/glue", - "crates/editor", - "crates/ast", - "crates/cli", - "crates/code_markup", - "crates/highlight", - "crates/error_macros", - "crates/reporting", - "crates/packaging", - "crates/repl_cli", - "crates/repl_eval", - "crates/repl_test", - "crates/repl_wasm", - "crates/repl_expect", - "crates/test_utils", - "crates/valgrind", - "crates/tracing", - "crates/utils", - "crates/docs", - "crates/docs_cli", - "crates/linker", - "crates/wasi-libc-sys", - "crates/wasm_module", - "crates/wasm_interp", + "crates/compiler/*", + "crates/vendor/*", + "crates/glue", + "crates/editor", + "crates/ast", + "crates/cli", + "crates/cli_utils", + "crates/code_markup", + "crates/highlight", + "crates/error_macros", + "crates/reporting", + "crates/packaging", + "crates/repl_cli", + "crates/repl_eval", + "crates/repl_test", + "crates/repl_wasm", + "crates/repl_expect", + "crates/roc_std", + "crates/test_utils", + "crates/valgrind", + "crates/tracing", + "crates/utils/*", + "crates/docs", + "crates/docs_cli", + "crates/linker", + "crates/wasi-libc-sys", + "crates/wasm_module", + "crates/wasm_interp", ] + exclude = [ - "ci/benchmarks/bench-runner", - # Examples sometimes have Rust hosts in their platforms. The compiler should ignore those. - "crates/cli_testing_examples", - "examples", - # Ignore building these normally. They are only imported by tests. - # The tests will still correctly build them. - "crates/cli_utils", - "crates/compiler/test_mono_macros", - "crates/compiler/str", - # `cargo build` would cause roc_std to be built with default features which errors on windows - "crates/roc_std", + "ci/benchmarks/bench-runner", + # Examples sometimes have Rust hosts in their platforms. The compiler should ignore those. + "crates/cli_testing_examples", + "examples", ] # Needed to be able to run `cargo run -p roc_cli --no-default-features` - # see www/build.sh for more. @@ -47,6 +43,13 @@ exclude = [ # workspace, and without `resolver = "2"` here, you can't use `-p` like this. resolver = "2" +[workspace.package] +authors = ["The Roc Contributors"] +edition = "2021" +license = "UPL-1.0" +repository = "https://github.com/roc-lang/roc" +version = "0.0.1" + [workspace.dependencies] # NOTE: roc-lang/inkwell is a fork of TheDan64/inkwell which does not change anything. # @@ -65,72 +68,120 @@ resolver = "2" # commit of TheDan64/inkwell, push a new tag which points to the latest commit, # change the tag value in this Cargo.toml to point to that tag, and `cargo update`. # This way, GitHub Actions works and nobody's builds get broken. -inkwell = { git = "https://github.com/roc-lang/inkwell", branch = "inkwell-llvm-15", features = [ "llvm13-0" ] } +inkwell = { git = "https://github.com/roc-lang/inkwell", branch = "inkwell-llvm-15", features = ["llvm13-0"] } -arrayvec = "0.7.2" +arrayvec = "0.7.2" # update roc_std/Cargo.toml on change +base64-url = "1.4.13" bincode = "1.3.3" +bitflags = "1.3.2" bitvec = "1.0.1" -bumpalo = { version = "3.11.1", features = ["collections"] } -capstone = "0.11.0" -clap = { version = "3.2.20", default-features = false, features = ["std", "color", "suggestions"] } -const_format = { version = "0.2.23", features = ["const_generics"] } -criterion = { git = "https://github.com/Anton-4/criterion.rs", features = ["html_reports"]} +blake3 = "1.3.3" +brotli = "3.3.4" # used for decompressing tarballs over HTTPS, if the server supports brotli +bumpalo = { version = "3.12.0", features = ["collections"] } +bytemuck = { version = "1.13.1", features = ["derive"] } +capstone = { version = "0.11.0", default-features = false } +cgmath = "0.18.0" +clap = { version = "3.2.23", default-features = false, features = ["std", "color", "suggestions"] } +colored = "2.0.0" +confy = { git = 'https://github.com/rust-cli/confy', features = ["yaml_conf"], default-features = false } +console_error_panic_hook = "0.1.7" +const_format = { version = "0.2.30", features = ["const_generics"] } +copypasta = "0.8.2" +criterion = { git = "https://github.com/Anton-4/criterion.rs", features = ["html_reports"] } +criterion-perf-events = { git = "https://github.com/Anton-4/criterion-perf-events" } crossbeam = "0.8.2" +dircpy = "0.3.14" distance = "0.4.0" encode_unicode = "1.0.0" -errno = "0.2.8" +errno = "0.3.0" +flate2 = "1.0.25" fnv = "1.0.7" -fs_extra = "1.2.0" -hashbrown = { version = "0.12.3", features = [ "bumpalo" ] } -iced-x86 = { version = "1.15.0", default-features = false, features = ["std", "decoder", "op_code_info", "instr_info"] } -im = "15.0.0" -im-rc = "15.0.0" -indoc = "1.0.7" -insta = "1.20.0" +fs_extra = "1.3.0" +futures = "0.3.26" +glyph_brush = "0.7.7" +hashbrown = { version = "0.13.2", features = ["bumpalo"] } +iced-x86 = { version = "1.18.0", default-features = false, features = ["std", "decoder", "op_code_info", "instr_info"] } +im = "15.1.0" +im-rc = "15.1.0" +indexmap = "1.9.2" +indoc = "1.0.9" +insta = "1.28.0" +js-sys = "0.3.61" lazy_static = "1.4.0" -libc = "0.2.135" -libloading = "0.7.1" +libc = "0.2.139" # update roc_std/Cargo.toml on change +libfuzzer-sys = "0.4" +libloading = "0.7.4" +log = "0.4.17" mach_object = "0.1" maplit = "1.0.2" -memmap2 = "0.5.7" -mimalloc = { version = "0.1.26", default-features = false } -packed_struct = "0.10.0" -page_size = "0.4.2" +memmap2 = "0.5.10" +mimalloc = { version = "0.1.34", default-features = false } +nonempty = "0.8.1" +object = { version = "0.30.3", features = ["read", "write"] } +packed_struct = "0.10.1" +page_size = "0.5.0" +palette = "0.6.1" parking_lot = "0.12" peg = "0.8.1" -pretty_assertions = "1.3.0" -quickcheck = "1.0.3" -quickcheck_macros = "1.0.0" -regex = "1.5.5" -rustyline = {git = "https://github.com/roc-lang/rustyline", rev = "e74333c"} -rustyline-derive = {git = "https://github.com/roc-lang/rustyline", rev = "e74333c"} -serde = { version = "1.0.144", features = ["derive"] } -signal-hook = "0.3.14" -snafu = { version = "0.7.1", features = ["backtraces"] } -static_assertions = "1.1.0" +perfcnt = "0.8.0" +pest = "2.5.6" +pest_derive = "2.5.6" +pretty_assertions = "1.3.0" # update roc_std/Cargo.toml on change +proc-macro2 = "1.0.51" +proptest = "1.1.0" +pulldown-cmark = { version = "0.9.2", default-features = false } +quickcheck = "1.0.3" # update roc_std/Cargo.toml on change +quickcheck_macros = "1.0.0" # update roc_std/Cargo.toml on change +quote = "1.0.23" +rand = "0.8.5" +regex = "1.7.1" +remove_dir_all = "0.8.1" +reqwest = { version = "0.11.14", default-features = false, features = ["blocking", "rustls-tls"] } # default-features=false removes libopenssl as a dependency on Linux, which might not be available! +rlimit = "0.9.1" +rustyline = { git = "https://github.com/roc-lang/rustyline", rev = "e74333c" } +rustyline-derive = { git = "https://github.com/roc-lang/rustyline", rev = "e74333c" } +serde = { version = "1.0.153", features = ["derive"] } # update roc_std/Cargo.toml on change +serde-xml-rs = "0.6.0" +serde_json = "1.0.94" # update roc_std/Cargo.toml on change +serial_test = "1.0.0" +signal-hook = "0.3.15" +snafu = { version = "0.7.4", features = ["backtraces"] } +static_assertions = "1.1.0" # update roc_std/Cargo.toml on change strip-ansi-escapes = "0.1.1" strum = { version = "0.24.1", features = ["derive"] } -target-lexicon = "0.12.3" -tempfile = "3.2.0" -unicode-segmentation = "1.10.0" +strum_macros = "0.24.3" +syn = { version = "1.0.109", features = ["full", "extra-traits"] } +tar = "0.4.38" +target-lexicon = "0.12.6" +tempfile = "=3.2.0" +threadpool = "1.8.1" +tracing = { version = "0.1.37", features = ["release_max_level_off"] } +tracing-appender = "0.2.2" +tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } +unicode-segmentation = "1.10.1" +uuid = { version = "1.3.0", features = ["v4"] } walkdir = "2.3.2" +wasm-bindgen = "0.2.84" +wasm-bindgen-futures = "0.4.34" +wgpu = "0.12.0" +wgpu_glyph = "0.16.0" +winapi = { version = "0.3.9", features = ["memoryapi"] } +winit = "0.26.1" wyhash = "0.5.0" -# TODO: Deal with the update of object to 0.27. -# It looks like it breaks linking the generated objects. -# Probably just need to specify an extra field that used to be implicit or something. -object = { version = "0.29.0", features = ["read", "write"] } - # Optimizations based on https://deterministic.space/high-performance-rust.html [profile.release] -lto = "thin" codegen-units = 1 # debug = true # enable when profiling [profile.bench] -lto = "thin" codegen-units = 1 +lto = "thin" [profile.release-with-debug] -inherits = "release" debug = true +inherits = "release" + +[profile.release-with-lto] +lto = "thin" # TODO: We could consider full here since this is only used for packaged release on github. +inherits = "release" diff --git a/README.md b/README.md index ce97c84612..0a1fd4e396 100644 --- a/README.md +++ b/README.md @@ -12,12 +12,24 @@ If you'd like to get involved in contributing to the language, the Zulip chat is ## Sponsors -We are very grateful to our sponsors [NoRedInk](https://www.noredink.com/), [rwx](https://www.rwx.com), and [Tweede golf](https://tweedegolf.nl/en). +We are very grateful for our corporate sponsors [Vendr](https://www.vendr.com/), [rwx](https://www.rwx.com), and [Tweede golf](https://tweedegolf.nl/en). -[NoRedInk logo](https://www.noredink.com/) +[Vendr logo](https://www.vendr.com)      [rwx logo](https://www.rwx.com)      [tweede golf logo](https://tweedegolf.nl/en) -If you or your employer would like to sponsor Roc's development, please [DM Richard Feldman on Zulip](https://roc.zulipchat.com/#narrow/pm-with/281383-user281383)! +If you would like your company to become a corporate sponsor of Roc's development, please [DM Richard Feldman on Zulip](https://roc.zulipchat.com/#narrow/pm-with/281383-user281383)! + +We'd also like to express our gratitude to each and every one of our fantastic [GitHub sponsors](https://github.com/sponsors/roc-lang/)! A special thanks to those sponsoring $25/month or more: + +* [Christopher Dolan](https://github.com/cdolan) +* [Nick Gravgaard](https://github.com/nickgravgaard) +* [Aaron White](https://github.com/aaronwhite) +* [Zeljko Nesic](https://github.com/popara) +* [Shritesh Bhattarai](https://github.com/shritesh) +* [Richard Feldman](https://github.com/rtfeldman) +* [Ayaz Hafiz](https://github.com/ayazhafiz) + +Thank you all so much for helping Roc progress! diff --git a/ci/benchmarks/bench-runner/Cargo.lock b/ci/benchmarks/bench-runner/Cargo.lock deleted file mode 100644 index 465b503f3f..0000000000 --- a/ci/benchmarks/bench-runner/Cargo.lock +++ /dev/null @@ -1,422 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "aho-corasick" -version = "0.7.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" -dependencies = [ - "memchr", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - -[[package]] -name = "bench-runner" -version = "0.0.1" -dependencies = [ - "clap", - "data-encoding", - "is_executable", - "regex", - "ring", -] - -[[package]] -name = "bitflags" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" - -[[package]] -name = "bumpalo" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" - -[[package]] -name = "cc" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "clap" -version = "3.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85a35a599b11c089a7f49105658d089b8f2cf0882993c17daf6de15285c2c35d" -dependencies = [ - "atty", - "bitflags", - "clap_derive", - "clap_lex", - "indexmap", - "lazy_static", - "strsim", - "termcolor", - "textwrap", -] - -[[package]] -name = "clap_derive" -version = "3.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3aab4734e083b809aaf5794e14e756d1c798d2c69c7f7de7a09a2f5214993c1" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "clap_lex" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213" -dependencies = [ - "os_str_bytes", -] - -[[package]] -name = "data-encoding" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57" - -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" - -[[package]] -name = "heck" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "indexmap" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "is_executable" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa9acdc6d67b75e626ad644734e8bc6df893d9cd2a834129065d3dd6158ea9c8" -dependencies = [ - "winapi", -] - -[[package]] -name = "js-sys" -version = "0.3.51" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83bdfbace3a0e81a4253f73b49e960b053e396a11012cbd49b9b74d6a2b67062" -dependencies = [ - "wasm-bindgen", -] - -[[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.98" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" - -[[package]] -name = "log" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "memchr" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" - -[[package]] -name = "once_cell" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" - -[[package]] -name = "os_str_bytes" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "quote" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "regex" -version = "1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.6.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" - -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin", - "untrusted", - "web-sys", - "winapi", -] - -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "syn" -version = "1.0.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "termcolor" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "textwrap" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" - -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wasm-bindgen" -version = "0.2.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b33f6a0694ccfea53d94db8b2ed1c3a8a4c86dd936b13b9f0a15ec4a451b900" -dependencies = [ - "bumpalo", - "lazy_static", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "088169ca61430fe1e58b8096c24975251700e7b1f6fd91cc9d59b04fb9b18bd4" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f" - -[[package]] -name = "web-sys" -version = "0.3.51" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e828417b379f3df7111d3a2a9e5753706cae29c41f7c4029ee9fd77f3e09e582" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -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" diff --git a/ci/benchmarks/bench-runner/Cargo.toml b/ci/benchmarks/bench-runner/Cargo.toml index 0534892f3c..477b6672ae 100644 --- a/ci/benchmarks/bench-runner/Cargo.toml +++ b/ci/benchmarks/bench-runner/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] clap = { version = "3.1.15", features = ["derive"] } -regex = "1.5.5" +data-encoding = "2.3.2" is_executable = "1.0.1" +regex = "1.5.5" ring = "0.16.20" -data-encoding = "2.3.2" \ No newline at end of file diff --git a/ci/package_release.sh b/ci/package_release.sh index ea4f9c1495..e99680f3e5 100755 --- a/ci/package_release.sh +++ b/ci/package_release.sh @@ -3,7 +3,7 @@ # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/ set -euxo pipefail -cp target/release/roc ./roc # to be able to delete "target" later +cp target/release-with-lto/roc ./roc # to be able to delete "target" later # delete unnecessary files and folders git clean -fdx --exclude roc diff --git a/crates/README.md b/crates/README.md index 209992db82..db2dc86d80 100644 --- a/crates/README.md +++ b/crates/README.md @@ -60,7 +60,6 @@ The compiler includes the following sub-crates; - `roc_serialize` provides helpers for serializing and deserializing to/from bytes. - `roc_solve` The entry point of Roc's [type inference](https://en.wikipedia.org/wiki/Type_inference) system. Implements type inference and specialization of abilities. - `roc_solve_problem` provides types to describe problems that can occur during solving. -- `roc_str` provides `Roc` styled collection [reference counting](https://en.wikipedia.org/wiki/Reference_counting). See [README.md](./compiler/str/README.md) for more information. - `test_derive` Tests Roc's auto-derivers. - `test_gen` contains all of Roc's [code generation](https://en.wikipedia.org/wiki/Code_generation_(compiler)) tests. See [README.md](./compiler/test_gen/README.md) for more information. - `test_mono` Tests Roc's generation of the mono intermediate representation. diff --git a/crates/ast/Cargo.toml b/crates/ast/Cargo.toml index a42b2c14ae..801af48e14 100644 --- a/crates/ast/Cargo.toml +++ b/crates/ast/Cargo.toml @@ -1,39 +1,39 @@ [package] name = "roc_ast" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "AST as used by the editor and (soon) docs. In contrast to the compiler, these types do not keep track of a location in a file." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] -roc_builtins = { path = "../compiler/builtins"} +roc_builtins = { path = "../compiler/builtins" } roc_can = { path = "../compiler/can" } roc_collections = { path = "../compiler/collections" } -roc_region = { path = "../compiler/region" } +roc_error_macros = { path = "../error_macros" } +roc_load = { path = "../compiler/load" } roc_module = { path = "../compiler/module" } +roc_packaging = { path = "../packaging" } roc_parse = { path = "../compiler/parse" } roc_problem = { path = "../compiler/problem" } -roc_types = { path = "../compiler/types" } -roc_unify = { path = "../compiler/unify"} -roc_solve = { path = "../compiler/solve"} -roc_load = { path = "../compiler/load" } -roc_target = { path = "../compiler/roc_target" } -roc_error_macros = { path = "../error_macros" } -roc_packaging = { path = "../packaging" } +roc_region = { path = "../compiler/region" } roc_reporting = { path = "../reporting" } +roc_solve = { path = "../compiler/solve" } +roc_target = { path = "../compiler/roc_target" } +roc_types = { path = "../compiler/types" } +roc_unify = { path = "../compiler/unify" } ven_graph = { path = "../vendor/pathfinding" } arrayvec.workspace = true bumpalo.workspace = true +libc.workspace = true page_size.workspace = true snafu.workspace = true -libc.workspace = true [dev-dependencies] indoc.workspace = true [target.'cfg(windows)'.dependencies] -winapi = { version = "0.3.9", features = ["memoryapi"]} - +winapi.workspace = true diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 6d005614b6..fa34d167f3 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -1,87 +1,81 @@ [package] name = "roc_cli" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -repository = "https://github.com/roc-lang/roc" -edition = "2021" description = "The Roc binary that brings together all functionality in the Roc toolset." default-run = "roc" +authors.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +version.workspace = true + [[bin]] +bench = false name = "roc" path = "src/main.rs" test = false -bench = false [features] default = ["target-aarch64", "target-x86_64", "target-wasm32", "editor"] -wasm32-cli-run = ["target-wasm32", "run-wasm32"] i386-cli-run = ["target-x86"] +wasm32-cli-run = ["target-wasm32", "run-wasm32"] editor = ["roc_editor"] run-wasm32 = ["roc_wasm_interp"] # Compiling for a different target than the current machine can cause linker errors. -target-arm = ["roc_build/target-arm", "roc_repl_cli/target-arm"] target-aarch64 = ["roc_build/target-aarch64", "roc_repl_cli/target-aarch64"] +target-arm = ["roc_build/target-arm", "roc_repl_cli/target-arm"] +target-wasm32 = ["roc_build/target-wasm32", "roc_repl_cli/target-wasm32"] target-x86 = ["roc_build/target-x86", "roc_repl_cli/target-x86"] target-x86_64 = ["roc_build/target-x86_64", "roc_repl_cli/target-x86_64"] -target-wasm32 = ["roc_build/target-wasm32", "roc_repl_cli/target-wasm32"] -target-all = [ - "target-aarch64", - "target-arm", - "target-x86", - "target-x86_64", - "target-wasm32" -] +target-all = ["target-aarch64", "target-arm", "target-x86", "target-x86_64", "target-wasm32"] sanitizers = ["roc_build/sanitizers"] [dependencies] -roc_collections = { path = "../compiler/collections" } +roc_build = { path = "../compiler/build" } +roc_builtins = { path = "../compiler/builtins" } roc_can = { path = "../compiler/can" } +roc_collections = { path = "../compiler/collections" } roc_docs = { path = "../docs" } +roc_editor = { path = "../editor", optional = true } +roc_error_macros = { path = "../error_macros" } +roc_fmt = { path = "../compiler/fmt" } +roc_gen_llvm = { path = "../compiler/gen_llvm" } roc_glue = { path = "../glue" } +roc_linker = { path = "../linker" } +roc_load = { path = "../compiler/load" } +roc_module = { path = "../compiler/module" } +roc_mono = { path = "../compiler/mono" } +roc_packaging = { path = "../packaging" } roc_parse = { path = "../compiler/parse" } roc_region = { path = "../compiler/region" } -roc_module = { path = "../compiler/module" } -roc_builtins = { path = "../compiler/builtins" } -roc_mono = { path = "../compiler/mono" } -roc_load = { path = "../compiler/load" } -roc_build = { path = "../compiler/build" } -roc_fmt = { path = "../compiler/fmt" } -roc_target = { path = "../compiler/roc_target" } -roc_packaging = { path = "../packaging" } -roc_reporting = { path = "../reporting" } -roc_error_macros = { path = "../error_macros" } -roc_editor = { path = "../editor", optional = true } -roc_linker = { path = "../linker" } roc_repl_cli = { path = "../repl_cli", optional = true } +roc_reporting = { path = "../reporting" } +roc_target = { path = "../compiler/roc_target" } roc_tracing = { path = "../tracing" } -roc_gen_llvm = {path = "../compiler/gen_llvm"} roc_wasm_interp = { path = "../wasm_interp", optional = true } ven_pretty = { path = "../vendor/pretty" } -indoc.workspace = true +bumpalo.workspace = true clap.workspace = true const_format.workspace = true -mimalloc.workspace = true -bumpalo.workspace = true -libc.workspace = true errno.workspace = true +indoc.workspace = true +inkwell.workspace = true +libc.workspace = true +libloading.workspace = true +mimalloc.workspace = true +signal-hook.workspace = true +strum.workspace = true target-lexicon.workspace = true tempfile.workspace = true -strum.workspace = true -libloading.workspace = true -signal-hook.workspace = true - -inkwell.workspace = true # for now, uses unix/libc functions that windows does not support [target.'cfg(not(windows))'.dependencies] @@ -89,14 +83,15 @@ roc_repl_expect = { path = "../repl_expect" } [dev-dependencies] -pretty_assertions = "1.3.0" -roc_test_utils = { path = "../test_utils" } -roc_utils = { path = "../utils" } -indoc = "1.0.7" -serial_test = "0.9.0" -criterion = { git = "https://github.com/Anton-4/criterion.rs"} cli_utils = { path = "../cli_utils" } -parking_lot = "0.12" +roc_test_utils = { path = "../test_utils" } +roc_command_utils = { path = "../utils/command" } + +criterion.workspace = true +indoc.workspace = true +parking_lot.workspace = true +pretty_assertions.workspace = true +serial_test.workspace = true [[bench]] name = "time_bench" diff --git a/crates/cli/src/build.rs b/crates/cli/src/build.rs deleted file mode 100644 index 3b1a673eb0..0000000000 --- a/crates/cli/src/build.rs +++ /dev/null @@ -1,628 +0,0 @@ -use bumpalo::Bump; -use roc_build::{ - link::{ - legacy_host_filename, link, preprocess_host_wasm32, preprocessed_host_filename, - rebuild_host, LinkType, LinkingStrategy, - }, - program::{self, CodeGenBackend, CodeGenOptions}, -}; -use roc_builtins::bitcode; -use roc_load::{ - EntryPoint, ExecutionMode, ExpectMetadata, LoadConfig, LoadMonomorphizedError, LoadedModule, - LoadingProblem, Threading, -}; -use roc_mono::ir::OptLevel; -use roc_packaging::cache::RocCacheDir; -use roc_reporting::{ - cli::Problems, - report::{RenderTarget, DEFAULT_PALETTE}, -}; -use roc_target::TargetInfo; -use std::{ - path::Path, - time::{Duration, Instant}, -}; -use std::{path::PathBuf, thread::JoinHandle}; -use target_lexicon::Triple; - -fn report_timing(buf: &mut String, label: &str, duration: Duration) { - use std::fmt::Write; - - writeln!( - buf, - " {:9.3} ms {}", - duration.as_secs_f64() * 1000.0, - label, - ) - .unwrap() -} - -pub struct BuiltFile<'a> { - pub binary_path: PathBuf, - pub problems: Problems, - pub total_time: Duration, - pub expect_metadata: ExpectMetadata<'a>, -} - -pub enum BuildOrdering { - /// Run up through typechecking first; continue building iff that is successful. - BuildIfChecks, - /// Always build the Roc binary, even if there are type errors. - AlwaysBuild, -} - -#[derive(Debug)] -#[allow(clippy::large_enum_variant)] -pub enum BuildFileError<'a> { - LoadingProblem(LoadingProblem<'a>), - ErrorModule { - module: LoadedModule, - total_time: Duration, - }, -} - -impl<'a> BuildFileError<'a> { - fn from_mono_error(error: LoadMonomorphizedError<'a>, compilation_start: Instant) -> Self { - match error { - LoadMonomorphizedError::LoadingProblem(problem) => { - BuildFileError::LoadingProblem(problem) - } - LoadMonomorphizedError::ErrorModule(module) => BuildFileError::ErrorModule { - module, - total_time: compilation_start.elapsed(), - }, - } - } -} - -pub fn standard_load_config( - target: &Triple, - order: BuildOrdering, - threading: Threading, -) -> LoadConfig { - let target_info = TargetInfo::from(target); - - let exec_mode = match order { - BuildOrdering::BuildIfChecks => ExecutionMode::ExecutableIfCheck, - BuildOrdering::AlwaysBuild => ExecutionMode::Executable, - }; - - LoadConfig { - target_info, - render: RenderTarget::ColorTerminal, - palette: DEFAULT_PALETTE, - threading, - exec_mode, - } -} - -#[allow(clippy::too_many_arguments)] -pub fn build_file<'a>( - arena: &'a Bump, - target: &Triple, - app_module_path: PathBuf, - code_gen_options: CodeGenOptions, - emit_timings: bool, - link_type: LinkType, - linking_strategy: LinkingStrategy, - prebuilt_requested: bool, - wasm_dev_stack_bytes: Option, - roc_cache_dir: RocCacheDir<'_>, - load_config: LoadConfig, -) -> Result, BuildFileError<'a>> { - let compilation_start = Instant::now(); - - // Step 1: compile the app and generate the .o file - let loaded = - roc_load::load_and_monomorphize(arena, app_module_path.clone(), roc_cache_dir, load_config) - .map_err(|e| BuildFileError::from_mono_error(e, compilation_start))?; - - build_loaded_file( - arena, - target, - app_module_path, - code_gen_options, - emit_timings, - link_type, - linking_strategy, - prebuilt_requested, - wasm_dev_stack_bytes, - loaded, - compilation_start, - ) -} - -#[allow(clippy::too_many_arguments)] -fn build_loaded_file<'a>( - arena: &'a Bump, - target: &Triple, - app_module_path: PathBuf, - code_gen_options: CodeGenOptions, - emit_timings: bool, - link_type: LinkType, - linking_strategy: LinkingStrategy, - prebuilt_requested: bool, - wasm_dev_stack_bytes: Option, - loaded: roc_load::MonomorphizedModule<'a>, - compilation_start: Instant, -) -> Result, BuildFileError<'a>> { - let operating_system = roc_target::OperatingSystem::from(target.operating_system); - - let platform_main_roc = match &loaded.entry_point { - EntryPoint::Executable { platform_path, .. } => platform_path.to_path_buf(), - _ => unreachable!(), - }; - - // the preprocessed host is stored beside the platform's main.roc - let preprocessed_host_path = if linking_strategy == LinkingStrategy::Legacy { - if let roc_target::OperatingSystem::Wasi = operating_system { - // when compiling a wasm application, we implicitly assume here that the host is in zig - // and has a file called "host.zig" - platform_main_roc.with_file_name("host.zig") - } else { - platform_main_roc.with_file_name(legacy_host_filename(target).unwrap()) - } - } else { - platform_main_roc.with_file_name(preprocessed_host_filename(target).unwrap()) - }; - - // For example, if we're loading the platform from a URL, it's automatically prebuilt - // even if the --prebuilt-platform=true CLI flag wasn't set. - let is_platform_prebuilt = prebuilt_requested || loaded.uses_prebuilt_platform; - - let cwd = app_module_path.parent().unwrap(); - let mut output_exe_path = cwd.join(&*loaded.output_path); - - if let Some(extension) = operating_system.executable_file_ext() { - output_exe_path.set_extension(extension); - } - - // We don't need to spawn a rebuild thread when using a prebuilt host. - let rebuild_thread = if matches!(link_type, LinkType::Dylib | LinkType::None) { - None - } else if is_platform_prebuilt { - if !preprocessed_host_path.exists() { - invalid_prebuilt_platform(prebuilt_requested, preprocessed_host_path); - - std::process::exit(1); - } - - if linking_strategy == LinkingStrategy::Surgical { - // Copy preprocessed host to executable location. - // The surgical linker will modify that copy in-place. - std::fs::copy(&preprocessed_host_path, output_exe_path.as_path()).unwrap(); - } - - None - } else { - // TODO this should probably be moved before load_and_monomorphize. - // To do this we will need to preprocess files just for their exported symbols. - // Also, we should no longer need to do this once we have platforms on - // a package repository, as we can then get prebuilt platforms from there. - - let exposed_values = loaded - .exposed_to_host - .values - .keys() - .map(|x| x.as_str(&loaded.interns).to_string()) - .collect(); - - let exposed_closure_types = loaded - .exposed_to_host - .closure_types - .iter() - .map(|x| { - format!( - "{}_{}", - x.module_string(&loaded.interns), - x.as_str(&loaded.interns) - ) - }) - .collect(); - - let join_handle = spawn_rebuild_thread( - code_gen_options.opt_level, - linking_strategy, - platform_main_roc.clone(), - preprocessed_host_path.clone(), - output_exe_path.clone(), - target, - exposed_values, - exposed_closure_types, - ); - - Some(join_handle) - }; - - let buf = &mut String::with_capacity(1024); - - let mut it = loaded.timings.iter().peekable(); - while let Some((module_id, module_timing)) = it.next() { - let module_name = loaded.interns.module_name(*module_id); - - buf.push_str(" "); - - if module_name.is_empty() { - // the App module - buf.push_str("Application Module"); - } else { - buf.push_str(module_name); - } - - buf.push('\n'); - - use std::fmt::Write; - write!(buf, "{}", module_timing).unwrap(); - - if it.peek().is_some() { - buf.push('\n'); - } - } - - // This only needs to be mutable for report_problems. This can't be done - // inside a nested scope without causing a borrow error! - let mut loaded = loaded; - let problems = program::report_problems_monomorphized(&mut loaded); - let loaded = loaded; - - enum HostRebuildTiming { - BeforeApp(u128), - ConcurrentWithApp(JoinHandle), - } - - let opt_rebuild_timing = if let Some(rebuild_thread) = rebuild_thread { - if linking_strategy == LinkingStrategy::Additive { - let rebuild_duration = rebuild_thread - .join() - .expect("Failed to (re)build platform."); - - if emit_timings && !is_platform_prebuilt { - println!( - "Finished rebuilding the platform in {} ms\n", - rebuild_duration - ); - } - - Some(HostRebuildTiming::BeforeApp(rebuild_duration)) - } else { - Some(HostRebuildTiming::ConcurrentWithApp(rebuild_thread)) - } - } else { - None - }; - - let (roc_app_bytes, code_gen_timing, expect_metadata) = program::gen_from_mono_module( - arena, - loaded, - &app_module_path, - target, - code_gen_options, - &preprocessed_host_path, - wasm_dev_stack_bytes, - ); - - buf.push('\n'); - buf.push_str(" "); - buf.push_str("Code Generation"); - buf.push('\n'); - - report_timing( - buf, - "Generate Assembly from Mono IR", - code_gen_timing.code_gen, - ); - - let compilation_end = compilation_start.elapsed(); - let size = roc_app_bytes.len(); - - if emit_timings { - println!( - "\n\nCompilation finished!\n\nHere's how long each module took to compile:\n\n{}", - buf - ); - - println!( - "Finished compilation and code gen in {} ms\n\nProduced a app.o file of size {:?}\n", - compilation_end.as_millis(), - size, - ); - } - - if let Some(HostRebuildTiming::ConcurrentWithApp(thread)) = opt_rebuild_timing { - let rebuild_duration = thread.join().expect("Failed to (re)build platform."); - - if emit_timings && !is_platform_prebuilt { - println!( - "Finished rebuilding the platform in {} ms\n", - rebuild_duration - ); - } - } - - // Step 2: link the prebuilt platform and compiled app - let link_start = Instant::now(); - - match (linking_strategy, link_type) { - (LinkingStrategy::Surgical, _) => { - roc_linker::link_preprocessed_host( - target, - &platform_main_roc, - &roc_app_bytes, - &output_exe_path, - ); - } - (LinkingStrategy::Additive, _) | (LinkingStrategy::Legacy, LinkType::None) => { - // Just copy the object file to the output folder. - output_exe_path.set_extension(operating_system.object_file_ext()); - std::fs::write(&output_exe_path, &*roc_app_bytes).unwrap(); - } - (LinkingStrategy::Legacy, _) => { - let app_o_file = tempfile::Builder::new() - .prefix("roc_app") - .suffix(&format!(".{}", operating_system.object_file_ext())) - .tempfile() - .map_err(|err| todo!("TODO Gracefully handle tempfile creation error {:?}", err))?; - let app_o_file = app_o_file.path(); - - std::fs::write(app_o_file, &*roc_app_bytes).unwrap(); - - let builtins_host_tempfile = - bitcode::host_tempfile().expect("failed to write host builtins object to tempfile"); - - let mut inputs = vec![app_o_file.to_str().unwrap()]; - - if !matches!(link_type, LinkType::Dylib | LinkType::None) { - // the host has been compiled into a .o or .obj file - inputs.push(preprocessed_host_path.as_path().to_str().unwrap()); - } - - if matches!(code_gen_options.backend, program::CodeGenBackend::Assembly) { - inputs.push(builtins_host_tempfile.path().to_str().unwrap()); - } - - let (mut child, _) = link(target, output_exe_path.clone(), &inputs, link_type) - .map_err(|_| todo!("gracefully handle `ld` failing to spawn."))?; - - let exit_status = child - .wait() - .map_err(|_| todo!("gracefully handle error after `ld` spawned"))?; - - // Extend the lifetime of the tempfile so it doesn't get dropped - // (and thus deleted) before the child process is done using it! - let _ = builtins_host_tempfile; - - if !exit_status.success() { - todo!( - "gracefully handle `ld` (or `zig` in the case of wasm with --optimize) returning exit code {:?}", - exit_status.code() - ); - } - } - } - - let linking_time = link_start.elapsed(); - - if emit_timings { - println!("Finished linking in {} ms\n", linking_time.as_millis()); - } - - let total_time = compilation_start.elapsed(); - - Ok(BuiltFile { - binary_path: output_exe_path, - problems, - total_time, - expect_metadata, - }) -} - -fn invalid_prebuilt_platform(prebuilt_requested: bool, preprocessed_host_path: PathBuf) { - let prefix = match prebuilt_requested { - true => "Because I was run with --prebuilt-platform=true, ", - false => "", - }; - - eprintln!( - indoc::indoc!( - r#" - {}I was expecting this file to exist: - - {} - - However, it was not there! - - If you have the platform's source code locally, you may be able to generate it by re-running this command with --prebuilt-platform=false - "# - ), - prefix, - preprocessed_host_path.to_string_lossy(), - ); -} - -#[allow(clippy::too_many_arguments)] -fn spawn_rebuild_thread( - opt_level: OptLevel, - linking_strategy: LinkingStrategy, - platform_main_roc: PathBuf, - preprocessed_host_path: PathBuf, - output_exe_path: PathBuf, - target: &Triple, - exported_symbols: Vec, - exported_closure_types: Vec, -) -> std::thread::JoinHandle { - let thread_local_target = target.clone(); - std::thread::spawn(move || { - // Printing to stderr because we want stdout to contain only the output of the roc program. - // We are aware of the trade-offs. - // `cargo run` follows the same approach - eprintln!("🔨 Rebuilding platform..."); - - let rebuild_host_start = Instant::now(); - - match linking_strategy { - LinkingStrategy::Additive => { - let host_dest = rebuild_host( - opt_level, - &thread_local_target, - platform_main_roc.as_path(), - None, - ); - - preprocess_host_wasm32(host_dest.as_path(), &preprocessed_host_path); - } - LinkingStrategy::Surgical => { - roc_linker::build_and_preprocess_host( - opt_level, - &thread_local_target, - platform_main_roc.as_path(), - preprocessed_host_path.as_path(), - exported_symbols, - exported_closure_types, - ); - - // Copy preprocessed host to executable location. - // The surgical linker will modify that copy in-place. - std::fs::copy(&preprocessed_host_path, output_exe_path.as_path()).unwrap(); - } - LinkingStrategy::Legacy => { - rebuild_host( - opt_level, - &thread_local_target, - platform_main_roc.as_path(), - None, - ); - } - } - - rebuild_host_start.elapsed().as_millis() - }) -} - -#[allow(clippy::too_many_arguments)] -pub fn check_file<'a>( - arena: &'a Bump, - roc_file_path: PathBuf, - emit_timings: bool, - roc_cache_dir: RocCacheDir<'_>, - threading: Threading, -) -> Result<(Problems, Duration), LoadingProblem<'a>> { - let compilation_start = Instant::now(); - - // only used for generating errors. We don't do code generation, so hardcoding should be fine - // we need monomorphization for when exhaustiveness checking - let target_info = TargetInfo::default_x86_64(); - - // Step 1: compile the app and generate the .o file - - let load_config = LoadConfig { - target_info, - // TODO: expose this from CLI? - render: RenderTarget::ColorTerminal, - palette: DEFAULT_PALETTE, - threading, - exec_mode: ExecutionMode::Check, - }; - let mut loaded = - roc_load::load_and_typecheck(arena, roc_file_path, roc_cache_dir, load_config)?; - - let buf = &mut String::with_capacity(1024); - - let mut it = loaded.timings.iter().peekable(); - while let Some((module_id, module_timing)) = it.next() { - let module_name = loaded.interns.module_name(*module_id); - - buf.push_str(" "); - - if module_name.is_empty() { - // the App module - buf.push_str("Application Module"); - } else { - buf.push_str(module_name); - } - - buf.push('\n'); - - report_timing(buf, "Read .roc file from disk", module_timing.read_roc_file); - report_timing(buf, "Parse header", module_timing.parse_header); - report_timing(buf, "Parse body", module_timing.parse_body); - report_timing(buf, "Canonicalize", module_timing.canonicalize); - report_timing(buf, "Constrain", module_timing.constrain); - report_timing(buf, "Solve", module_timing.solve); - report_timing(buf, "Other", module_timing.other()); - buf.push('\n'); - report_timing(buf, "Total", module_timing.total()); - - if it.peek().is_some() { - buf.push('\n'); - } - } - - let compilation_end = compilation_start.elapsed(); - - if emit_timings { - println!( - "\n\nCompilation finished!\n\nHere's how long each module took to compile:\n\n{}", - buf - ); - - println!("Finished checking in {} ms\n", compilation_end.as_millis(),); - } - - Ok(( - program::report_problems_typechecked(&mut loaded), - compilation_end, - )) -} - -pub fn build_str_test<'a>( - arena: &'a Bump, - app_module_path: &Path, - app_module_source: &'a str, - assume_prebuild: bool, -) -> Result, BuildFileError<'a>> { - let triple = target_lexicon::Triple::host(); - - let code_gen_options = CodeGenOptions { - backend: CodeGenBackend::Llvm, - opt_level: OptLevel::Normal, - emit_debug_info: false, - }; - - let emit_timings = false; - let link_type = LinkType::Executable; - let linking_strategy = LinkingStrategy::Surgical; - let wasm_dev_stack_bytes = None; - - let roc_cache_dir = roc_packaging::cache::RocCacheDir::Disallowed; - let build_ordering = BuildOrdering::AlwaysBuild; - let threading = Threading::AtMost(2); - - let load_config = standard_load_config(&triple, build_ordering, threading); - - let compilation_start = std::time::Instant::now(); - - // Step 1: compile the app and generate the .o file - let loaded = roc_load::load_and_monomorphize_from_str( - arena, - PathBuf::from("valgrind_test.roc"), - app_module_source, - app_module_path.to_path_buf(), - roc_cache_dir, - load_config, - ) - .map_err(|e| BuildFileError::from_mono_error(e, compilation_start))?; - - build_loaded_file( - arena, - &triple, - app_module_path.to_path_buf(), - code_gen_options, - emit_timings, - link_type, - linking_strategy, - assume_prebuild, - wasm_dev_stack_bytes, - loaded, - compilation_start, - ) -} diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index 6d48900d05..6ee50b0a6d 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -3,11 +3,12 @@ #[macro_use] extern crate const_format; -use build::BuiltFile; use bumpalo::Bump; use clap::{Arg, ArgMatches, Command, ValueSource}; use roc_build::link::{LinkType, LinkingStrategy}; -use roc_build::program::{CodeGenBackend, CodeGenOptions}; +use roc_build::program::{ + standard_load_config, BuildFileError, BuildOrdering, BuiltFile, CodeGenBackend, CodeGenOptions, +}; use roc_error_macros::{internal_error, user_error}; use roc_load::{ExpectMetadata, LoadingProblem, Threading}; use roc_mono::ir::OptLevel; @@ -29,12 +30,9 @@ use target_lexicon::{ #[cfg(not(target_os = "linux"))] use tempfile::TempDir; -pub mod build; mod format; pub use format::format; -use crate::build::{standard_load_config, BuildFileError, BuildOrdering}; - const DEFAULT_ROC_FILENAME: &str = "main.roc"; pub const CMD_BUILD: &str = "build"; @@ -332,6 +330,7 @@ pub fn build_app<'a>() -> Command<'a> { Arg::new(DIRECTORY_OR_FILES) .multiple_values(true) .required(false) + .allow_invalid_utf8(true) .help("(optional) The directory or files to open on launch"), ), ) @@ -520,7 +519,7 @@ pub fn build( roc_cache_dir: RocCacheDir<'_>, link_type: LinkType, ) -> io::Result { - use build::build_file; + use roc_build::program::build_file; use BuildConfig::*; let filename = matches.value_of_os(ROC_FILE).unwrap(); diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index debaa4f7f4..1e1a581007 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -1,6 +1,6 @@ //! The `roc` binary that brings together all functionality in the Roc toolset. use roc_build::link::LinkType; -use roc_cli::build::check_file; +use roc_build::program::check_file; use roc_cli::{ build_app, format, test, BuildConfig, FormatMode, Target, CMD_BUILD, CMD_CHECK, CMD_DEV, CMD_DOCS, CMD_EDIT, CMD_FORMAT, CMD_GEN_STUB_LIB, CMD_GLUE, CMD_REPL, CMD_RUN, CMD_TEST, diff --git a/crates/cli/tests/cli_run.rs b/crates/cli/tests/cli_run.rs index 964289cf96..db09af8380 100644 --- a/crates/cli/tests/cli_run.rs +++ b/crates/cli/tests/cli_run.rs @@ -533,6 +533,7 @@ mod cli_run { } #[test] + #[serial(zig_platform)] #[cfg_attr(windows, ignore)] fn platform_switching_zig() { test_roc_app_slim( @@ -676,6 +677,7 @@ mod cli_run { } #[cfg_attr(windows, ignore)] // flaky error; issue #5024 + #[serial(breakout)] #[test] fn breakout() { test_roc_app_slim( @@ -688,6 +690,7 @@ mod cli_run { } #[test] + #[serial(breakout)] fn breakout_hello_gui() { test_roc_app_slim( "examples/gui/breakout", @@ -862,6 +865,7 @@ mod cli_run { #[test] #[serial(parser_package)] + #[serial(zig_platform)] #[cfg_attr(windows, ignore)] fn parse_movies_csv() { test_roc_app_slim( diff --git a/crates/cli/tests/editor.rs b/crates/cli/tests/editor.rs index 054e48065d..6b6cc80253 100644 --- a/crates/cli/tests/editor.rs +++ b/crates/cli/tests/editor.rs @@ -10,13 +10,22 @@ mod editor_launch_test { use cli_utils::helpers::build_roc_bin_cached; use roc_cli::CMD_EDIT; - use roc_utils::root_dir; + use roc_command_utils::root_dir; use std::io::Read; - // ignored because we don't want to bring up the editor window during regular tests, only on specific CI machines - #[ignore] + #[ignore = "we don't want to bring up the editor window during regular tests, only on specific CI machines"] #[test] - fn launch() { + fn launch_test() { + launch(None); + + // with a file arg + launch(Some("roc-projects/new-roc-project-1/main.roc")); + + // with a folder arg + launch(Some("roc-projects/new-roc-project-1")); + } + + fn launch(arg_path_str_opt: Option<&str>) { let root_dir = root_dir(); // The editor expects to be run from the root of the repo, so it can find the cli-platform to init a new project folder. @@ -25,8 +34,14 @@ mod editor_launch_test { let roc_binary_path = build_roc_bin_cached(); + let mut cmd_args = vec![CMD_EDIT]; + + if let Some(arg_path_str) = arg_path_str_opt { + cmd_args.push(arg_path_str) + } + let mut roc_process = Command::new(roc_binary_path) - .arg(CMD_EDIT) + .args(cmd_args) .stdout(Stdio::piped()) .spawn() .expect("Failed to start editor from cli."); diff --git a/crates/cli_utils/Cargo.toml b/crates/cli_utils/Cargo.toml index 3ac3952ece..2530866df5 100644 --- a/crates/cli_utils/Cargo.toml +++ b/crates/cli_utils/Cargo.toml @@ -1,27 +1,25 @@ [package] name = "cli_utils" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -repository = "https://github.com/roc-lang/roc" -edition = "2021" description = "Provides shared code for cli tests and benchmarks." -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +authors.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +version.workspace = true [dependencies] roc_collections = { path = "../compiler/collections" } -roc_reporting = { path = "../reporting" } roc_load = { path = "../compiler/load" } roc_module = { path = "../compiler/module" } -roc_utils = { path = "../utils" } +roc_reporting = { path = "../reporting" } +roc_command_utils = { path = "../utils/command" } -bumpalo = { version = "3.8.0", features = ["collections"] } -criterion = { git = "https://github.com/Anton-4/criterion.rs"} -serde = { version = "1.0.130", features = ["derive"] } -serde-xml-rs = "0.5.1" -strip-ansi-escapes = "0.1.1" -tempfile = "3.2.0" +bumpalo.workspace = true +criterion.workspace = true +serde-xml-rs.workspace = true +serde.workspace = true +tempfile.workspace = true [target.'cfg(unix)'.dependencies] -rlimit = "0.6.2" +rlimit.workspace = true diff --git a/crates/cli_utils/src/helpers.rs b/crates/cli_utils/src/helpers.rs index a48ba3423e..7895bfb1af 100644 --- a/crates/cli_utils/src/helpers.rs +++ b/crates/cli_utils/src/helpers.rs @@ -4,9 +4,7 @@ extern crate roc_load; extern crate roc_module; extern crate tempfile; -use roc_utils::cargo; -use roc_utils::pretty_command_string; -use roc_utils::root_dir; +use roc_command_utils::{cargo, pretty_command_string, root_dir}; use serde::Deserialize; use serde_xml_rs::from_str; use std::env; @@ -387,7 +385,7 @@ pub fn cli_testing_dir(dir_name: &str) -> PathBuf { // Descend into examples/{dir_name} path.push("crates"); path.push("cli_testing_examples"); - path.extend(dir_name.split("/")); // Make slashes cross-target + path.extend(dir_name.split('/')); // Make slashes cross-target path } @@ -396,7 +394,7 @@ pub fn cli_testing_dir(dir_name: &str) -> PathBuf { pub fn dir_path_from_root(dir_name: &str) -> PathBuf { let mut path = root_dir(); - path.extend(dir_name.split("/")); // Make slashes cross-target + path.extend(dir_name.split('/')); // Make slashes cross-target path } @@ -419,7 +417,7 @@ pub fn fixtures_dir(dir_name: &str) -> PathBuf { path.push("cli"); path.push("tests"); path.push("fixtures"); - path.extend(dir_name.split("/")); // Make slashes cross-target + path.extend(dir_name.split('/')); // Make slashes cross-target path } diff --git a/crates/code_markup/Cargo.toml b/crates/code_markup/Cargo.toml index d8d63f7a4a..4a784234b1 100644 --- a/crates/code_markup/Cargo.toml +++ b/crates/code_markup/Cargo.toml @@ -1,16 +1,19 @@ [package] name = "roc_code_markup" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Our own markup language for Roc code. Used by the editor and the docs." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] roc_ast = { path = "../ast" } roc_module = { path = "../compiler/module" } -roc_utils = { path = "../utils" } -serde = { version = "1.0.144", features = ["derive"] } -palette = "0.6.1" -snafu = { version = "0.7.1", features = ["backtraces"] } -bumpalo = { version = "3.11.1", features = ["collections"] } +roc_error_utils = { path = "../utils/error" } + +palette.workspace = true + +bumpalo.workspace = true +serde.workspace = true +snafu.workspace = true diff --git a/crates/code_markup/src/markup/nodes.rs b/crates/code_markup/src/markup/nodes.rs index 9f1551d1e4..4ff045dea4 100644 --- a/crates/code_markup/src/markup/nodes.rs +++ b/crates/code_markup/src/markup/nodes.rs @@ -16,7 +16,7 @@ use roc_ast::{ lang::{core::ast::ASTNodeId, env::Env}, mem_pool::pool_str::PoolStr, }; -use roc_utils::{index_of, slice_get}; +use roc_error_utils::{index_of, slice_get}; use std::fmt; use std::fmt::Write; diff --git a/crates/code_markup/src/markup_error.rs b/crates/code_markup/src/markup_error.rs index 89ac7c45d7..5e888652d2 100644 --- a/crates/code_markup/src/markup_error.rs +++ b/crates/code_markup/src/markup_error.rs @@ -1,4 +1,4 @@ -use roc_utils::util_error::UtilError; +use roc_error_utils::UtilError; use snafu::{Backtrace, NoneError, ResultExt, Snafu}; use crate::slow_pool::MarkNodeId; diff --git a/crates/compiler/alias_analysis/Cargo.toml b/crates/compiler/alias_analysis/Cargo.toml index cabe3ca143..3d6fd4987b 100644 --- a/crates/compiler/alias_analysis/Cargo.toml +++ b/crates/compiler/alias_analysis/Cargo.toml @@ -1,15 +1,17 @@ [package] -authors = ["The Roc Contributors"] -edition = "2021" -license = "UPL-1.0" name = "roc_alias_analysis" -version = "0.0.1" + +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true [dependencies] -morphic_lib = {path = "../../vendor/morphic_lib"} -roc_collections = {path = "../collections"} -roc_error_macros = {path = "../../error_macros"} -roc_module = {path = "../module"} -roc_mono = {path = "../mono"} -roc_debug_flags = {path = "../debug_flags"} +morphic_lib = { path = "../../vendor/morphic_lib" } +roc_collections = { path = "../collections" } +roc_debug_flags = { path = "../debug_flags" } +roc_error_macros = { path = "../../error_macros" } +roc_module = { path = "../module" } +roc_mono = { path = "../mono" } + bumpalo.workspace = true diff --git a/crates/compiler/alias_analysis/src/lib.rs b/crates/compiler/alias_analysis/src/lib.rs index c00b2313d8..5534e5c50b 100644 --- a/crates/compiler/alias_analysis/src/lib.rs +++ b/crates/compiler/alias_analysis/src/lib.rs @@ -188,20 +188,28 @@ where let func_name = FuncName(&bytes); if let HostExposedLayouts::HostExposed { aliases, .. } = &proc.host_exposed_layouts { - for (_, (symbol, top_level, layout)) in aliases { - match layout { + for (_, hels) in aliases { + match hels.raw_function_layout { RawFunctionLayout::Function(_, _, _) => { - let it = top_level.arguments.iter().copied(); - let bytes = - func_name_bytes_help(*symbol, it, Niche::NONE, top_level.result); + let it = hels.proc_layout.arguments.iter().copied(); + let bytes = func_name_bytes_help( + hels.symbol, + it, + Niche::NONE, + hels.proc_layout.result, + ); - host_exposed_functions.push((bytes, top_level.arguments)); + host_exposed_functions.push((bytes, hels.proc_layout.arguments)); } RawFunctionLayout::ZeroArgumentThunk(_) => { - let bytes = - func_name_bytes_help(*symbol, [], Niche::NONE, top_level.result); + let bytes = func_name_bytes_help( + hels.symbol, + [], + Niche::NONE, + hels.proc_layout.result, + ); - host_exposed_functions.push((bytes, top_level.arguments)); + host_exposed_functions.push((bytes, hels.proc_layout.arguments)); } } } diff --git a/crates/compiler/arena_pool/Cargo.toml b/crates/compiler/arena_pool/Cargo.toml index 1afb7e4eb3..ab35ee4d37 100644 --- a/crates/compiler/arena_pool/Cargo.toml +++ b/crates/compiler/arena_pool/Cargo.toml @@ -1,11 +1,12 @@ [package] name = "arena-pool" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -repository = "https://github.com/roc-lang/roc" -edition = "2021" description = "An implementation of an arena allocator designed for the compiler's workloads." +authors.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +version.workspace = true + [dependencies] roc_error_macros = { path = "../../error_macros" } diff --git a/crates/compiler/build/Cargo.toml b/crates/compiler/build/Cargo.toml index ac04bd5cef..2dae039b57 100644 --- a/crates/compiler/build/Cargo.toml +++ b/crates/compiler/build/Cargo.toml @@ -1,52 +1,55 @@ [package] name = "roc_build" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Responsible for coordinating building and linking of a Roc app with its host." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] -roc_collections = { path = "../collections" } +roc_bitcode = { path = "../builtins/bitcode" } roc_can = { path = "../can" } -roc_parse = { path = "../parse" } -roc_region = { path = "../region" } -roc_module = { path = "../module" } -roc_problem = { path = "../problem" } -roc_types = { path = "../types" } -roc_builtins = { path = "../builtins" } +roc_collections = { path = "../collections" } roc_constrain = { path = "../constrain" } -roc_unify = { path = "../unify" } -roc_solve_problem = { path = "../solve_problem" } -roc_mono = { path = "../mono" } -roc_load = { path = "../load" } -roc_target = { path = "../roc_target" } +roc_error_macros = { path = "../../error_macros" } +roc_gen_dev = { path = "../gen_dev", default-features = false } roc_gen_llvm = { path = "../gen_llvm" } roc_gen_wasm = { path = "../gen_wasm" } -roc_gen_dev = { path = "../gen_dev", default-features = false } +roc_linker = { path = "../../linker" } +roc_load = { path = "../load" } +roc_module = { path = "../module" } +roc_mono = { path = "../mono" } +roc_packaging = { path = "../../packaging" } +roc_parse = { path = "../parse" } +roc_problem = { path = "../problem" } +roc_region = { path = "../region" } roc_reporting = { path = "../../reporting" } -roc_error_macros = { path = "../../error_macros" } +roc_solve_problem = { path = "../solve_problem" } roc_std = { path = "../../roc_std" } -roc_utils = { path = "../../utils" } +roc_target = { path = "../roc_target" } +roc_types = { path = "../types" } +roc_unify = { path = "../unify" } +roc_command_utils = { path = "../../utils/command" } wasi_libc_sys = { path = "../../wasi-libc-sys" } -const_format.workspace = true bumpalo.workspace = true -libloading.workspace = true -tempfile.workspace = true -target-lexicon.workspace = true +indoc.workspace = true inkwell.workspace = true +libloading.workspace = true +target-lexicon.workspace = true +tempfile.workspace = true [target.'cfg(target_os = "macos")'.dependencies] -serde_json = "1.0.85" +serde_json.workspace = true [features] -target-arm = [] target-aarch64 = ["roc_gen_dev/target-aarch64"] +target-arm = [] +target-wasm32 = [] target-x86 = [] target-x86_64 = ["roc_gen_dev/target-x86_64"] -target-wasm32 = [] # This is used to enable fuzzing and sanitizers. # Example use is describe here: https://github.com/bhansconnect/roc-fuzz diff --git a/crates/compiler/build/src/link.rs b/crates/compiler/build/src/link.rs index 2c136c721c..6798dc65d6 100644 --- a/crates/compiler/build/src/link.rs +++ b/crates/compiler/build/src/link.rs @@ -1,11 +1,8 @@ use crate::target::{arch_str, target_zig_str}; -use const_format::concatcp; use libloading::{Error, Library}; -use roc_builtins::bitcode; +use roc_command_utils::{cargo, clang, get_lib_path, rustup, zig}; use roc_error_macros::internal_error; use roc_mono::ir::OptLevel; -use roc_utils::{cargo, clang, zig}; -use roc_utils::{get_lib_path, rustup}; use std::collections::HashMap; use std::fs::DirEntry; use std::io; @@ -15,13 +12,7 @@ use std::{env, fs}; use target_lexicon::{Architecture, OperatingSystem, Triple}; use wasi_libc_sys::{WASI_COMPILER_RT_PATH, WASI_LIBC_PATH}; -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum LinkType { - // These numbers correspond to the --lib and --no-link flags - Executable = 0, - Dylib = 1, - None = 2, -} +pub use roc_linker::LinkType; #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum LinkingStrategy { @@ -61,134 +52,15 @@ pub fn link( } } -const PRECOMPILED_HOST_EXT: &str = "rh1"; // Short for "roc host version 1" (so we can change format in the future) - -const WASM_TARGET_STR: &str = "wasm32"; -const LINUX_X86_64_TARGET_STR: &str = "linux-x86_64"; -const LINUX_ARM64_TARGET_STR: &str = "linux-arm64"; -const MACOS_ARM64_TARGET_STR: &str = "macos-arm64"; -const MACOS_X86_64_TARGET_STR: &str = "macos-x86_64"; -const WINDOWS_X86_64_TARGET_STR: &str = "windows-x86_64"; -const WINDOWS_X86_32_TARGET_STR: &str = "windows-x86_32"; -const WIDNOWS_ARM64_TARGET_STR: &str = "windows-arm64"; - -pub const fn preprocessed_host_filename(target: &Triple) -> Option<&'static str> { - // Don't try to split this match off in a different function, it will not work with concatcp - match target { - Triple { - architecture: Architecture::Wasm32, - .. - } => Some(concatcp!(WASM_TARGET_STR, '.', PRECOMPILED_HOST_EXT)), - Triple { - operating_system: OperatingSystem::Linux, - architecture: Architecture::X86_64, - .. - } => Some(concatcp!( - LINUX_X86_64_TARGET_STR, - '.', - PRECOMPILED_HOST_EXT - )), - Triple { - operating_system: OperatingSystem::Linux, - architecture: Architecture::Aarch64(_), - .. - } => Some(concatcp!(LINUX_ARM64_TARGET_STR, '.', PRECOMPILED_HOST_EXT)), - Triple { - operating_system: OperatingSystem::Darwin, - architecture: Architecture::Aarch64(_), - .. - } => Some(concatcp!(MACOS_ARM64_TARGET_STR, '.', PRECOMPILED_HOST_EXT)), - Triple { - operating_system: OperatingSystem::Darwin, - architecture: Architecture::X86_64, - .. - } => Some(concatcp!( - MACOS_X86_64_TARGET_STR, - '.', - PRECOMPILED_HOST_EXT - )), - Triple { - operating_system: OperatingSystem::Windows, - architecture: Architecture::X86_64, - .. - } => Some(concatcp!( - WINDOWS_X86_64_TARGET_STR, - '.', - PRECOMPILED_HOST_EXT - )), - Triple { - operating_system: OperatingSystem::Windows, - architecture: Architecture::X86_32(_), - .. - } => Some(concatcp!( - WINDOWS_X86_32_TARGET_STR, - '.', - PRECOMPILED_HOST_EXT - )), - Triple { - operating_system: OperatingSystem::Windows, - architecture: Architecture::Aarch64(_), - .. - } => Some(concatcp!( - WIDNOWS_ARM64_TARGET_STR, - '.', - PRECOMPILED_HOST_EXT - )), - _ => None, - } -} - -pub fn get_target_triple_str(target: &Triple) -> Option<&'static str> { - match target { - Triple { - architecture: Architecture::Wasm32, - .. - } => Some(WASM_TARGET_STR), - Triple { - operating_system: OperatingSystem::Linux, - architecture: Architecture::X86_64, - .. - } => Some(LINUX_X86_64_TARGET_STR), - Triple { - operating_system: OperatingSystem::Linux, - architecture: Architecture::Aarch64(_), - .. - } => Some(LINUX_ARM64_TARGET_STR), - Triple { - operating_system: OperatingSystem::Darwin, - architecture: Architecture::Aarch64(_), - .. - } => Some(MACOS_ARM64_TARGET_STR), - Triple { - operating_system: OperatingSystem::Darwin, - architecture: Architecture::X86_64, - .. - } => Some(MACOS_X86_64_TARGET_STR), - Triple { - operating_system: OperatingSystem::Windows, - architecture: Architecture::X86_64, - .. - } => Some(WINDOWS_X86_64_TARGET_STR), - Triple { - operating_system: OperatingSystem::Windows, - architecture: Architecture::X86_32(_), - .. - } => Some(WINDOWS_X86_32_TARGET_STR), - Triple { - operating_system: OperatingSystem::Windows, - architecture: Architecture::Aarch64(_), - .. - } => Some(WIDNOWS_ARM64_TARGET_STR), - _ => None, - } -} - /// Same format as the precompiled host filename, except with a file extension like ".o" or ".obj" pub fn legacy_host_filename(target: &Triple) -> Option { let os = roc_target::OperatingSystem::from(target.operating_system); let ext = os.object_file_ext(); - Some(preprocessed_host_filename(target)?.replace(PRECOMPILED_HOST_EXT, ext)) + Some( + roc_linker::preprocessed_host_filename(target)? + .replace(roc_linker::PRECOMPILED_HOST_EXT, ext), + ) } fn find_zig_str_path() -> PathBuf { @@ -682,7 +554,7 @@ pub fn rebuild_host( let env_cpath = env::var("CPATH").unwrap_or_else(|_| "".to_string()); let builtins_host_tempfile = - bitcode::host_tempfile().expect("failed to write host builtins object to tempfile"); + roc_bitcode::host_tempfile().expect("failed to write host builtins object to tempfile"); if zig_host_src.exists() { // Compile host.zig @@ -1561,8 +1433,8 @@ pub fn preprocess_host_wasm32(host_input_path: &Path, preprocessed_host_path: &P (but seems to be an unofficial API) */ - let builtins_host_tempfile = - bitcode::host_wasm_tempfile().expect("failed to write host builtins object to tempfile"); + let builtins_host_tempfile = roc_bitcode::host_wasm_tempfile() + .expect("failed to write host builtins object to tempfile"); let mut zig_cmd = zig(); let args = &[ diff --git a/crates/compiler/build/src/program.rs b/crates/compiler/build/src/program.rs index 2a3bbcecbc..36deda4663 100644 --- a/crates/compiler/build/src/program.rs +++ b/crates/compiler/build/src/program.rs @@ -1,13 +1,29 @@ +use crate::link::{ + legacy_host_filename, link, preprocess_host_wasm32, rebuild_host, LinkType, LinkingStrategy, +}; +use bumpalo::Bump; use inkwell::memory_buffer::MemoryBuffer; use roc_error_macros::internal_error; use roc_gen_llvm::llvm::build::{module_from_builtins, LlvmBackendMode}; use roc_gen_llvm::llvm::externs::add_default_roc_externs; -use roc_load::{EntryPoint, ExpectMetadata, LoadedModule, MonomorphizedModule}; +use roc_load::{ + EntryPoint, ExecutionMode, ExpectMetadata, LoadConfig, LoadMonomorphizedError, LoadedModule, + LoadingProblem, MonomorphizedModule, Threading, +}; use roc_mono::ir::{OptLevel, SingleEntryPoint}; -use roc_reporting::cli::{report_problems, Problems}; +use roc_packaging::cache::RocCacheDir; +use roc_reporting::{ + cli::{report_problems, Problems}, + report::{RenderTarget, DEFAULT_PALETTE}, +}; +use roc_target::TargetInfo; use std::ops::Deref; -use std::path::{Path, PathBuf}; -use std::time::{Duration, Instant}; +use std::{ + path::{Path, PathBuf}, + thread::JoinHandle, + time::{Duration, Instant}, +}; +use target_lexicon::Triple; #[cfg(feature = "target-wasm32")] use roc_collections::all::MutSet; @@ -579,3 +595,627 @@ fn gen_from_mono_module_dev_assembly<'a>( }, ) } + +fn report_timing(buf: &mut String, label: &str, duration: Duration) { + use std::fmt::Write; + + writeln!( + buf, + " {:9.3} ms {}", + duration.as_secs_f64() * 1000.0, + label, + ) + .unwrap() +} + +pub struct BuiltFile<'a> { + pub binary_path: PathBuf, + pub problems: Problems, + pub total_time: Duration, + pub expect_metadata: ExpectMetadata<'a>, +} + +pub enum BuildOrdering { + /// Run up through typechecking first; continue building iff that is successful. + BuildIfChecks, + /// Always build the Roc binary, even if there are type errors. + AlwaysBuild, +} + +#[derive(Debug)] +#[allow(clippy::large_enum_variant)] +pub enum BuildFileError<'a> { + LoadingProblem(LoadingProblem<'a>), + ErrorModule { + module: LoadedModule, + total_time: Duration, + }, +} + +impl<'a> BuildFileError<'a> { + fn from_mono_error(error: LoadMonomorphizedError<'a>, compilation_start: Instant) -> Self { + match error { + LoadMonomorphizedError::LoadingProblem(problem) => { + BuildFileError::LoadingProblem(problem) + } + LoadMonomorphizedError::ErrorModule(module) => BuildFileError::ErrorModule { + module, + total_time: compilation_start.elapsed(), + }, + } + } +} + +pub fn standard_load_config( + target: &Triple, + order: BuildOrdering, + threading: Threading, +) -> LoadConfig { + let target_info = TargetInfo::from(target); + + let exec_mode = match order { + BuildOrdering::BuildIfChecks => ExecutionMode::ExecutableIfCheck, + BuildOrdering::AlwaysBuild => ExecutionMode::Executable, + }; + + LoadConfig { + target_info, + render: RenderTarget::ColorTerminal, + palette: DEFAULT_PALETTE, + threading, + exec_mode, + } +} + +#[allow(clippy::too_many_arguments)] +pub fn build_file<'a>( + arena: &'a Bump, + target: &Triple, + app_module_path: PathBuf, + code_gen_options: CodeGenOptions, + emit_timings: bool, + link_type: LinkType, + linking_strategy: LinkingStrategy, + prebuilt_requested: bool, + wasm_dev_stack_bytes: Option, + roc_cache_dir: RocCacheDir<'_>, + load_config: LoadConfig, +) -> Result, BuildFileError<'a>> { + let compilation_start = Instant::now(); + + // Step 1: compile the app and generate the .o file + let loaded = + roc_load::load_and_monomorphize(arena, app_module_path.clone(), roc_cache_dir, load_config) + .map_err(|e| BuildFileError::from_mono_error(e, compilation_start))?; + + build_loaded_file( + arena, + target, + app_module_path, + code_gen_options, + emit_timings, + link_type, + linking_strategy, + prebuilt_requested, + wasm_dev_stack_bytes, + loaded, + compilation_start, + ) +} + +#[allow(clippy::too_many_arguments)] +fn build_loaded_file<'a>( + arena: &'a Bump, + target: &Triple, + app_module_path: PathBuf, + code_gen_options: CodeGenOptions, + emit_timings: bool, + link_type: LinkType, + linking_strategy: LinkingStrategy, + prebuilt_requested: bool, + wasm_dev_stack_bytes: Option, + loaded: roc_load::MonomorphizedModule<'a>, + compilation_start: Instant, +) -> Result, BuildFileError<'a>> { + let operating_system = roc_target::OperatingSystem::from(target.operating_system); + + let platform_main_roc = match &loaded.entry_point { + EntryPoint::Executable { platform_path, .. } => platform_path.to_path_buf(), + _ => unreachable!(), + }; + + // the preprocessed host is stored beside the platform's main.roc + let preprocessed_host_path = if linking_strategy == LinkingStrategy::Legacy { + if let roc_target::OperatingSystem::Wasi = operating_system { + // when compiling a wasm application, we implicitly assume here that the host is in zig + // and has a file called "host.zig" + platform_main_roc.with_file_name("host.zig") + } else { + platform_main_roc.with_file_name(legacy_host_filename(target).unwrap()) + } + } else { + platform_main_roc.with_file_name(roc_linker::preprocessed_host_filename(target).unwrap()) + }; + + // For example, if we're loading the platform from a URL, it's automatically prebuilt + // even if the --prebuilt-platform=true CLI flag wasn't set. + let is_platform_prebuilt = prebuilt_requested || loaded.uses_prebuilt_platform; + + let cwd = app_module_path.parent().unwrap(); + let mut output_exe_path = cwd.join(&*loaded.output_path); + + if let Some(extension) = operating_system.executable_file_ext() { + output_exe_path.set_extension(extension); + } + + // We don't need to spawn a rebuild thread when using a prebuilt host. + let rebuild_thread = if matches!(link_type, LinkType::Dylib | LinkType::None) { + None + } else if is_platform_prebuilt { + if !preprocessed_host_path.exists() { + invalid_prebuilt_platform(prebuilt_requested, preprocessed_host_path); + + std::process::exit(1); + } + + if linking_strategy == LinkingStrategy::Surgical { + // Copy preprocessed host to executable location. + // The surgical linker will modify that copy in-place. + std::fs::copy(&preprocessed_host_path, output_exe_path.as_path()).unwrap(); + } + + None + } else { + // TODO this should probably be moved before load_and_monomorphize. + // To do this we will need to preprocess files just for their exported symbols. + // Also, we should no longer need to do this once we have platforms on + // a package repository, as we can then get prebuilt platforms from there. + + let exposed_values = loaded + .exposed_to_host + .values + .keys() + .map(|x| x.as_str(&loaded.interns).to_string()) + .collect(); + + let exposed_closure_types = loaded + .exposed_to_host + .closure_types + .iter() + .map(|x| { + format!( + "{}_{}", + x.module_string(&loaded.interns), + x.as_str(&loaded.interns) + ) + }) + .collect(); + + let join_handle = spawn_rebuild_thread( + code_gen_options.opt_level, + linking_strategy, + platform_main_roc.clone(), + preprocessed_host_path.clone(), + output_exe_path.clone(), + target, + exposed_values, + exposed_closure_types, + ); + + Some(join_handle) + }; + + let buf = &mut String::with_capacity(1024); + + let mut it = loaded.timings.iter().peekable(); + while let Some((module_id, module_timing)) = it.next() { + let module_name = loaded.interns.module_name(*module_id); + + buf.push_str(" "); + + if module_name.is_empty() { + // the App module + buf.push_str("Application Module"); + } else { + buf.push_str(module_name); + } + + buf.push('\n'); + + use std::fmt::Write; + write!(buf, "{}", module_timing).unwrap(); + + if it.peek().is_some() { + buf.push('\n'); + } + } + + // This only needs to be mutable for report_problems. This can't be done + // inside a nested scope without causing a borrow error! + let mut loaded = loaded; + let problems = report_problems_monomorphized(&mut loaded); + let loaded = loaded; + + enum HostRebuildTiming { + BeforeApp(u128), + ConcurrentWithApp(JoinHandle), + } + + let opt_rebuild_timing = if let Some(rebuild_thread) = rebuild_thread { + if linking_strategy == LinkingStrategy::Additive { + let rebuild_duration = rebuild_thread + .join() + .expect("Failed to (re)build platform."); + + if emit_timings && !is_platform_prebuilt { + println!( + "Finished rebuilding the platform in {} ms\n", + rebuild_duration + ); + } + + Some(HostRebuildTiming::BeforeApp(rebuild_duration)) + } else { + Some(HostRebuildTiming::ConcurrentWithApp(rebuild_thread)) + } + } else { + None + }; + + let (roc_app_bytes, code_gen_timing, expect_metadata) = gen_from_mono_module( + arena, + loaded, + &app_module_path, + target, + code_gen_options, + &preprocessed_host_path, + wasm_dev_stack_bytes, + ); + + buf.push('\n'); + buf.push_str(" "); + buf.push_str("Code Generation"); + buf.push('\n'); + + report_timing( + buf, + "Generate Assembly from Mono IR", + code_gen_timing.code_gen, + ); + + let compilation_end = compilation_start.elapsed(); + let size = roc_app_bytes.len(); + + if emit_timings { + println!( + "\n\nCompilation finished!\n\nHere's how long each module took to compile:\n\n{}", + buf + ); + + println!( + "Finished compilation and code gen in {} ms\n\nProduced a app.o file of size {:?}\n", + compilation_end.as_millis(), + size, + ); + } + + if let Some(HostRebuildTiming::ConcurrentWithApp(thread)) = opt_rebuild_timing { + let rebuild_duration = thread.join().expect("Failed to (re)build platform."); + + if emit_timings && !is_platform_prebuilt { + println!( + "Finished rebuilding the platform in {} ms\n", + rebuild_duration + ); + } + } + + // Step 2: link the prebuilt platform and compiled app + let link_start = Instant::now(); + + match (linking_strategy, link_type) { + (LinkingStrategy::Surgical, _) => { + roc_linker::link_preprocessed_host( + target, + &platform_main_roc, + &roc_app_bytes, + &output_exe_path, + ); + } + (LinkingStrategy::Additive, _) | (LinkingStrategy::Legacy, LinkType::None) => { + // Just copy the object file to the output folder. + output_exe_path.set_extension(operating_system.object_file_ext()); + std::fs::write(&output_exe_path, &*roc_app_bytes).unwrap(); + } + (LinkingStrategy::Legacy, _) => { + let app_o_file = tempfile::Builder::new() + .prefix("roc_app") + .suffix(&format!(".{}", operating_system.object_file_ext())) + .tempfile() + .map_err(|err| todo!("TODO Gracefully handle tempfile creation error {:?}", err))?; + let app_o_file = app_o_file.path(); + + std::fs::write(app_o_file, &*roc_app_bytes).unwrap(); + + let builtins_host_tempfile = roc_bitcode::host_tempfile() + .expect("failed to write host builtins object to tempfile"); + + let mut inputs = vec![app_o_file.to_str().unwrap()]; + + if !matches!(link_type, LinkType::Dylib | LinkType::None) { + // the host has been compiled into a .o or .obj file + inputs.push(preprocessed_host_path.as_path().to_str().unwrap()); + } + + if matches!(code_gen_options.backend, CodeGenBackend::Assembly) { + inputs.push(builtins_host_tempfile.path().to_str().unwrap()); + } + + let (mut child, _) = link(target, output_exe_path.clone(), &inputs, link_type) + .map_err(|_| todo!("gracefully handle `ld` failing to spawn."))?; + + let exit_status = child + .wait() + .map_err(|_| todo!("gracefully handle error after `ld` spawned"))?; + + // Extend the lifetime of the tempfile so it doesn't get dropped + // (and thus deleted) before the child process is done using it! + let _ = builtins_host_tempfile; + + if !exit_status.success() { + todo!( + "gracefully handle `ld` (or `zig` in the case of wasm with --optimize) returning exit code {:?}", + exit_status.code() + ); + } + } + } + + let linking_time = link_start.elapsed(); + + if emit_timings { + println!("Finished linking in {} ms\n", linking_time.as_millis()); + } + + let total_time = compilation_start.elapsed(); + + Ok(BuiltFile { + binary_path: output_exe_path, + problems, + total_time, + expect_metadata, + }) +} + +fn invalid_prebuilt_platform(prebuilt_requested: bool, preprocessed_host_path: PathBuf) { + let prefix = match prebuilt_requested { + true => "Because I was run with --prebuilt-platform=true, ", + false => "", + }; + + eprintln!( + indoc::indoc!( + r#" + {}I was expecting this file to exist: + + {} + + However, it was not there! + + If you have the platform's source code locally, you may be able to generate it by re-running this command with --prebuilt-platform=false + "# + ), + prefix, + preprocessed_host_path.to_string_lossy(), + ); +} + +#[allow(clippy::too_many_arguments)] +fn spawn_rebuild_thread( + opt_level: OptLevel, + linking_strategy: LinkingStrategy, + platform_main_roc: PathBuf, + preprocessed_host_path: PathBuf, + output_exe_path: PathBuf, + target: &Triple, + exported_symbols: Vec, + exported_closure_types: Vec, +) -> std::thread::JoinHandle { + let thread_local_target = target.clone(); + std::thread::spawn(move || { + // Printing to stderr because we want stdout to contain only the output of the roc program. + // We are aware of the trade-offs. + // `cargo run` follows the same approach + eprintln!("🔨 Rebuilding platform..."); + + let rebuild_host_start = Instant::now(); + + match linking_strategy { + LinkingStrategy::Additive => { + let host_dest = rebuild_host( + opt_level, + &thread_local_target, + platform_main_roc.as_path(), + None, + ); + + preprocess_host_wasm32(host_dest.as_path(), &preprocessed_host_path); + } + LinkingStrategy::Surgical => { + build_and_preprocess_host( + opt_level, + &thread_local_target, + platform_main_roc.as_path(), + preprocessed_host_path.as_path(), + exported_symbols, + exported_closure_types, + ); + + // Copy preprocessed host to executable location. + // The surgical linker will modify that copy in-place. + std::fs::copy(&preprocessed_host_path, output_exe_path.as_path()).unwrap(); + } + LinkingStrategy::Legacy => { + rebuild_host( + opt_level, + &thread_local_target, + platform_main_roc.as_path(), + None, + ); + } + } + + rebuild_host_start.elapsed().as_millis() + }) +} + +pub fn build_and_preprocess_host( + opt_level: OptLevel, + target: &Triple, + platform_main_roc: &Path, + preprocessed_host_path: &Path, + exposed_to_host: Vec, + exported_closure_types: Vec, +) { + let (stub_lib, stub_dll_symbols) = roc_linker::generate_stub_lib_from_loaded( + target, + platform_main_roc, + exposed_to_host, + exported_closure_types, + ); + rebuild_host(opt_level, target, platform_main_roc, Some(&stub_lib)); + + roc_linker::preprocess_host( + target, + platform_main_roc, + preprocessed_host_path, + &stub_lib, + &stub_dll_symbols, + ) +} + +#[allow(clippy::too_many_arguments)] +pub fn check_file<'a>( + arena: &'a Bump, + roc_file_path: PathBuf, + emit_timings: bool, + roc_cache_dir: RocCacheDir<'_>, + threading: Threading, +) -> Result<(Problems, Duration), LoadingProblem<'a>> { + let compilation_start = Instant::now(); + + // only used for generating errors. We don't do code generation, so hardcoding should be fine + // we need monomorphization for when exhaustiveness checking + let target_info = TargetInfo::default_x86_64(); + + // Step 1: compile the app and generate the .o file + + let load_config = LoadConfig { + target_info, + // TODO: expose this from CLI? + render: RenderTarget::ColorTerminal, + palette: DEFAULT_PALETTE, + threading, + exec_mode: ExecutionMode::Check, + }; + let mut loaded = + roc_load::load_and_typecheck(arena, roc_file_path, roc_cache_dir, load_config)?; + + let buf = &mut String::with_capacity(1024); + + let mut it = loaded.timings.iter().peekable(); + while let Some((module_id, module_timing)) = it.next() { + let module_name = loaded.interns.module_name(*module_id); + + buf.push_str(" "); + + if module_name.is_empty() { + // the App module + buf.push_str("Application Module"); + } else { + buf.push_str(module_name); + } + + buf.push('\n'); + + report_timing(buf, "Read .roc file from disk", module_timing.read_roc_file); + report_timing(buf, "Parse header", module_timing.parse_header); + report_timing(buf, "Parse body", module_timing.parse_body); + report_timing(buf, "Canonicalize", module_timing.canonicalize); + report_timing(buf, "Constrain", module_timing.constrain); + report_timing(buf, "Solve", module_timing.solve); + report_timing(buf, "Other", module_timing.other()); + buf.push('\n'); + report_timing(buf, "Total", module_timing.total()); + + if it.peek().is_some() { + buf.push('\n'); + } + } + + let compilation_end = compilation_start.elapsed(); + + if emit_timings { + println!( + "\n\nCompilation finished!\n\nHere's how long each module took to compile:\n\n{}", + buf + ); + + println!("Finished checking in {} ms\n", compilation_end.as_millis(),); + } + + Ok((report_problems_typechecked(&mut loaded), compilation_end)) +} + +pub fn build_str_test<'a>( + arena: &'a Bump, + app_module_path: &Path, + app_module_source: &'a str, + assume_prebuild: bool, +) -> Result, BuildFileError<'a>> { + let triple = target_lexicon::Triple::host(); + + let code_gen_options = CodeGenOptions { + backend: CodeGenBackend::Llvm, + opt_level: OptLevel::Normal, + emit_debug_info: false, + }; + + let emit_timings = false; + let link_type = LinkType::Executable; + let linking_strategy = LinkingStrategy::Surgical; + let wasm_dev_stack_bytes = None; + + let roc_cache_dir = roc_packaging::cache::RocCacheDir::Disallowed; + let build_ordering = BuildOrdering::AlwaysBuild; + let threading = Threading::AtMost(2); + + let load_config = standard_load_config(&triple, build_ordering, threading); + + let compilation_start = std::time::Instant::now(); + + // Step 1: compile the app and generate the .o file + let loaded = roc_load::load_and_monomorphize_from_str( + arena, + PathBuf::from("valgrind_test.roc"), + app_module_source, + app_module_path.to_path_buf(), + roc_cache_dir, + load_config, + ) + .map_err(|e| BuildFileError::from_mono_error(e, compilation_start))?; + + build_loaded_file( + arena, + &triple, + app_module_path.to_path_buf(), + code_gen_options, + emit_timings, + link_type, + linking_strategy, + assume_prebuild, + wasm_dev_stack_bytes, + loaded, + compilation_start, + ) +} diff --git a/crates/compiler/builtins/Cargo.toml b/crates/compiler/builtins/Cargo.toml index ca3a5b38f8..852a085a9f 100644 --- a/crates/compiler/builtins/Cargo.toml +++ b/crates/compiler/builtins/Cargo.toml @@ -1,23 +1,17 @@ [package] name = "roc_builtins" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Provides the Roc functions and modules that are implicitly imported into every module." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] roc_collections = { path = "../collections" } -roc_region = { path = "../region" } roc_module = { path = "../module" } +roc_region = { path = "../region" } roc_target = { path = "../roc_target" } -roc_utils = { path = "../../utils" } + tempfile.workspace = true -[build-dependencies] -# dunce can be removed once ziglang/zig#5109 is fixed -dunce = "1.0.3" -roc_utils = { path = "../../utils" } - -[target.'cfg(target_os = "macos")'.build-dependencies] -tempfile.workspace = true diff --git a/crates/compiler/builtins/bitcode/Cargo.toml b/crates/compiler/builtins/bitcode/Cargo.toml new file mode 100644 index 0000000000..46ef041619 --- /dev/null +++ b/crates/compiler/builtins/bitcode/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "roc_bitcode" +description = "Compiles the zig bitcode to `.o` for builtins" + +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + +[dependencies] +tempfile.workspace = true + +[build-dependencies] +roc_command_utils = { path = "../../../utils/command" } +# dunce can be removed once ziglang/zig#5109 is fixed +dunce = "1.0.3" + +[target.'cfg(target_os = "macos")'.build-dependencies] +tempfile.workspace = true diff --git a/crates/compiler/builtins/bitcode/bc/Cargo.toml b/crates/compiler/builtins/bitcode/bc/Cargo.toml new file mode 100644 index 0000000000..d6b8113443 --- /dev/null +++ b/crates/compiler/builtins/bitcode/bc/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "roc_bitcode_bc" +description = "Compiles the zig bitcode to `.bc` for llvm" + +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + +[build-dependencies] +roc_command_utils = { path = "../../../../utils/command" } +# dunce can be removed once ziglang/zig#5109 is fixed +dunce = "1.0.3" + +[target.'cfg(target_os = "macos")'.build-dependencies] +tempfile.workspace = true diff --git a/crates/compiler/builtins/bitcode/bc/build.rs b/crates/compiler/builtins/bitcode/bc/build.rs new file mode 100644 index 0000000000..bda982ccd6 --- /dev/null +++ b/crates/compiler/builtins/bitcode/bc/build.rs @@ -0,0 +1,154 @@ +use roc_command_utils::{pretty_command_string, zig}; +use std::fs; +use std::io; +use std::path::Path; +use std::str; +use std::{env, path::PathBuf, process::Command}; + +#[cfg(target_os = "macos")] +use tempfile::tempdir; + +/// To debug the zig code with debug prints, we need to disable the wasm code gen +const DEBUG: bool = false; + +fn main() { + println!("cargo:rerun-if-changed=build.rs"); + + // "." is relative to where "build.rs" is + // dunce can be removed once ziglang/zig#5109 is fixed + let bitcode_path = dunce::canonicalize(Path::new(".")).unwrap().join(".."); + + // workaround for github.com/ziglang/zig/issues/9711 + #[cfg(target_os = "macos")] + let zig_cache_dir = tempdir().expect("Failed to create temp directory for zig cache"); + #[cfg(target_os = "macos")] + std::env::set_var("ZIG_GLOBAL_CACHE_DIR", zig_cache_dir.path().as_os_str()); + + // LLVM .bc FILES + + generate_bc_file(&bitcode_path, "ir", "builtins-host"); + + if !DEBUG { + generate_bc_file(&bitcode_path, "ir-wasm32", "builtins-wasm32"); + } + + generate_bc_file(&bitcode_path, "ir-i386", "builtins-i386"); + generate_bc_file(&bitcode_path, "ir-x86_64", "builtins-x86_64"); + generate_bc_file( + &bitcode_path, + "ir-windows-x86_64", + "builtins-windows-x86_64", + ); + + get_zig_files(bitcode_path.as_path(), &|path| { + let path: &Path = path; + println!( + "cargo:rerun-if-changed={}", + path.to_str().expect("Failed to convert path to str") + ); + }) + .unwrap(); + + #[cfg(target_os = "macos")] + zig_cache_dir + .close() + .expect("Failed to delete temp dir zig_cache_dir."); +} + +fn generate_bc_file(bitcode_path: &Path, zig_object: &str, file_name: &str) { + let mut ll_path = bitcode_path.join(file_name); + ll_path.set_extension("ll"); + let dest_ir_host = ll_path.to_str().expect("Invalid dest ir path"); + + println!("Compiling host ir to: {}", dest_ir_host); + + let mut bc_path = bitcode_path.join(file_name); + bc_path.set_extension("bc"); + let dest_bc_64bit = bc_path.to_str().expect("Invalid dest bc path"); + println!("Compiling 64-bit bitcode to: {}", dest_bc_64bit); + + // workaround for github.com/ziglang/zig/issues/9711 + #[cfg(target_os = "macos")] + let _ = fs::remove_dir_all("./zig-cache"); + + let mut zig_cmd = zig(); + + zig_cmd + .current_dir(bitcode_path) + .args(["build", zig_object, "-Drelease=true"]); + + run_command(zig_cmd, 0); +} + +pub fn get_lib_dir() -> PathBuf { + // Currently we have the OUT_DIR variable which points to `/target/debug/build/roc_builtins-*/out/`. + // So we just need to add "/bitcode" to that. + let dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + + // create dir if it does not exist + fs::create_dir_all(&dir).expect("Failed to make $OUT_DIR/ dir."); + + dir +} + +fn run_command(mut command: Command, flaky_fail_counter: usize) { + let command_str = pretty_command_string(&command); + let command_str = command_str.to_string_lossy(); + + let output_result = command.output(); + + match output_result { + Ok(output) => match output.status.success() { + true => (), + false => { + let error_str = match str::from_utf8(&output.stderr) { + Ok(stderr) => stderr.to_string(), + Err(_) => format!("Failed to run \"{}\"", command_str), + }; + + // Flaky test errors that only occur sometimes on MacOS ci server. + if error_str.contains("FileNotFound") + || error_str.contains("unable to save cached ZIR code") + || error_str.contains("LLVM failed to emit asm") + { + if flaky_fail_counter == 10 { + panic!("{} failed 10 times in a row. The following error is unlikely to be a flaky error: {}", command_str, error_str); + } else { + run_command(command, flaky_fail_counter + 1) + } + } else if error_str + .contains("lld-link: error: failed to write the output file: Permission denied") + { + panic!("{} failed with:\n\n {}\n\nWorkaround:\n\n Re-run the cargo command that triggered this build.\n\n", command_str, error_str); + } else { + panic!("{} failed with:\n\n {}\n", command_str, error_str); + } + } + }, + Err(reason) => panic!("{} failed: {}", command_str, reason), + } +} + +fn get_zig_files(dir: &Path, cb: &dyn Fn(&Path)) -> io::Result<()> { + if dir.is_dir() { + for entry in fs::read_dir(dir)? { + let entry = entry?; + let path_buf = entry.path(); + if path_buf.is_dir() { + if !path_buf.ends_with("zig-cache") { + get_zig_files(&path_buf, cb).unwrap(); + } + } else { + let path = path_buf.as_path(); + + match path.extension() { + Some(osstr) if osstr == "zig" => { + cb(path); + } + _ => {} + } + } + } + } + Ok(()) +} diff --git a/crates/compiler/builtins/bitcode/bc/src/lib.rs b/crates/compiler/builtins/bitcode/bc/src/lib.rs new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/crates/compiler/builtins/bitcode/bc/src/lib.rs @@ -0,0 +1 @@ + diff --git a/crates/compiler/builtins/build.rs b/crates/compiler/builtins/bitcode/build.rs similarity index 80% rename from crates/compiler/builtins/build.rs rename to crates/compiler/builtins/bitcode/build.rs index 0e10b07627..40ed60021c 100644 --- a/crates/compiler/builtins/build.rs +++ b/crates/compiler/builtins/bitcode/build.rs @@ -1,11 +1,9 @@ -use roc_utils::zig; -use std::env; +use roc_command_utils::{pretty_command_string, zig}; use std::fs; use std::io; use std::path::Path; -use std::path::PathBuf; -use std::process::Command; use std::str; +use std::{env, path::PathBuf, process::Command}; #[cfg(target_os = "macos")] use tempfile::tempdir; @@ -18,8 +16,7 @@ fn main() { // "." is relative to where "build.rs" is // dunce can be removed once ziglang/zig#5109 is fixed - let build_script_dir_path = dunce::canonicalize(Path::new(".")).unwrap(); - let bitcode_path = build_script_dir_path.join("bitcode"); + let bitcode_path = dunce::canonicalize(Path::new(".")).unwrap(); // workaround for github.com/ziglang/zig/issues/9711 #[cfg(target_os = "macos")] @@ -27,22 +24,6 @@ fn main() { #[cfg(target_os = "macos")] std::env::set_var("ZIG_GLOBAL_CACHE_DIR", zig_cache_dir.path().as_os_str()); - // LLVM .bc FILES - - generate_bc_file(&bitcode_path, "ir", "builtins-host"); - - if !DEBUG { - generate_bc_file(&bitcode_path, "ir-wasm32", "builtins-wasm32"); - } - - generate_bc_file(&bitcode_path, "ir-i386", "builtins-i386"); - generate_bc_file(&bitcode_path, "ir-x86_64", "builtins-x86_64"); - generate_bc_file( - &bitcode_path, - "ir-windows-x86_64", - "builtins-windows-x86_64", - ); - // OBJECT FILES #[cfg(windows)] const BUILTINS_HOST_FILE: &str = "builtins-host.obj"; @@ -107,38 +88,13 @@ fn generate_object_file(bitcode_path: &Path, zig_object: &str, object_file_name: } } -fn generate_bc_file(bitcode_path: &Path, zig_object: &str, file_name: &str) { - let mut ll_path = bitcode_path.join(file_name); - ll_path.set_extension("ll"); - let dest_ir_host = ll_path.to_str().expect("Invalid dest ir path"); - - println!("Compiling host ir to: {}", dest_ir_host); - - let mut bc_path = bitcode_path.join(file_name); - bc_path.set_extension("bc"); - let dest_bc_64bit = bc_path.to_str().expect("Invalid dest bc path"); - println!("Compiling 64-bit bitcode to: {}", dest_bc_64bit); - - // workaround for github.com/ziglang/zig/issues/9711 - #[cfg(target_os = "macos")] - let _ = fs::remove_dir_all("./bitcode/zig-cache"); - - let mut zig_cmd = zig(); - - zig_cmd - .current_dir(bitcode_path) - .args(["build", zig_object, "-Drelease=true"]); - - run_command(zig_cmd, 0); -} - pub fn get_lib_dir() -> PathBuf { // Currently we have the OUT_DIR variable which points to `/target/debug/build/roc_builtins-*/out/`. // So we just need to add "/bitcode" to that. - let dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()).join("bitcode"); + let dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); // create dir if it does not exist - fs::create_dir_all(&dir).expect("Failed to make $OUT_DIR/bitcode dir."); + fs::create_dir_all(&dir).expect("Failed to make $OUT_DIR/ dir."); dir } @@ -192,7 +148,7 @@ fn cp_unless_zig_cache(src_dir: &Path, target_dir: &Path) -> io::Result<()> { } fn run_command(mut command: Command, flaky_fail_counter: usize) { - let command_str = roc_utils::pretty_command_string(&command); + let command_str = pretty_command_string(&command); let command_str = command_str.to_string_lossy(); let output_result = command.output(); diff --git a/crates/compiler/builtins/bitcode/src/lib.rs b/crates/compiler/builtins/bitcode/src/lib.rs new file mode 100644 index 0000000000..58efea062e --- /dev/null +++ b/crates/compiler/builtins/bitcode/src/lib.rs @@ -0,0 +1,65 @@ +use tempfile::NamedTempFile; + +const HOST_WASM: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/builtins-wasm32.o")); +// TODO: in the future, we should use Zig's cross-compilation to generate and store these +// for all targets, so that we can do cross-compilation! +#[cfg(unix)] +const HOST_UNIX: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/builtins-host.o")); +#[cfg(windows)] +const HOST_WINDOWS: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/builtins-windows-x86_64.obj")); + +pub fn host_wasm_tempfile() -> std::io::Result { + let tempfile = tempfile::Builder::new() + .prefix("host_bitcode") + .suffix(".wasm") + .rand_bytes(8) + .tempfile()?; + + std::fs::write(tempfile.path(), HOST_WASM)?; + + Ok(tempfile) +} + +#[cfg(unix)] +fn host_unix_tempfile() -> std::io::Result { + let tempfile = tempfile::Builder::new() + .prefix("host_bitcode") + .suffix(".o") + .rand_bytes(8) + .tempfile()?; + + std::fs::write(tempfile.path(), HOST_UNIX)?; + + Ok(tempfile) +} + +#[cfg(windows)] +fn host_windows_tempfile() -> std::io::Result { + let tempfile = tempfile::Builder::new() + .prefix("host_bitcode") + .suffix(".obj") + .rand_bytes(8) + .tempfile()?; + + std::fs::write(tempfile.path(), HOST_WINDOWS)?; + + Ok(tempfile) +} + +pub fn host_tempfile() -> std::io::Result { + #[cfg(unix)] + { + host_unix_tempfile() + } + + #[cfg(windows)] + { + host_windows_tempfile() + } + + #[cfg(not(any(windows, unix)))] + { + unreachable!() + } +} diff --git a/crates/compiler/builtins/bitcode/src/main.zig b/crates/compiler/builtins/bitcode/src/main.zig index 56a403a8c8..95566a3ea2 100644 --- a/crates/compiler/builtins/bitcode/src/main.zig +++ b/crates/compiler/builtins/bitcode/src/main.zig @@ -67,6 +67,8 @@ const NUMBERS = INTEGERS ++ FLOATS; comptime { exportNumFn(num.bytesToU16C, "bytes_to_u16"); exportNumFn(num.bytesToU32C, "bytes_to_u32"); + exportNumFn(num.bytesToU64C, "bytes_to_u64"); + exportNumFn(num.bytesToU128C, "bytes_to_u128"); inline for (INTEGERS) |T, i| { num.exportPow(T, ROC_BUILTINS ++ "." ++ NUM ++ ".pow_int."); @@ -86,6 +88,10 @@ comptime { num.exportMulWithOverflow(T, WIDEINTS[i], ROC_BUILTINS ++ "." ++ NUM ++ ".mul_with_overflow."); num.exportMulOrPanic(T, WIDEINTS[i], ROC_BUILTINS ++ "." ++ NUM ++ ".mul_or_panic."); num.exportMulSaturatedInt(T, WIDEINTS[i], ROC_BUILTINS ++ "." ++ NUM ++ ".mul_saturated."); + + num.exportCountLeadingZeroBits(T, ROC_BUILTINS ++ "." ++ NUM ++ ".count_leading_zero_bits."); + num.exportCountTrailingZeroBits(T, ROC_BUILTINS ++ "." ++ NUM ++ ".count_trailing_zero_bits."); + num.exportCountOneBits(T, ROC_BUILTINS ++ "." ++ NUM ++ ".count_one_bits."); } inline for (INTEGERS) |FROM| { diff --git a/crates/compiler/builtins/bitcode/src/num.zig b/crates/compiler/builtins/bitcode/src/num.zig index cb8c2498f2..dbbf87c1cf 100644 --- a/crates/compiler/builtins/bitcode/src/num.zig +++ b/crates/compiler/builtins/bitcode/src/num.zig @@ -236,6 +236,24 @@ fn bytesToU32(arg: RocList, position: usize) u32 { return @bitCast(u32, [_]u8{ bytes[position], bytes[position + 1], bytes[position + 2], bytes[position + 3] }); } +pub fn bytesToU64C(arg: RocList, position: usize) callconv(.C) u64 { + return @call(.{ .modifier = always_inline }, bytesToU64, .{ arg, position }); +} + +fn bytesToU64(arg: RocList, position: usize) u64 { + const bytes = @ptrCast([*]const u8, arg.bytes); + return @bitCast(u64, [_]u8{ bytes[position], bytes[position + 1], bytes[position + 2], bytes[position + 3], bytes[position + 4], bytes[position + 5], bytes[position + 6], bytes[position + 7] }); +} + +pub fn bytesToU128C(arg: RocList, position: usize) callconv(.C) u128 { + return @call(.{ .modifier = always_inline }, bytesToU128, .{ arg, position }); +} + +fn bytesToU128(arg: RocList, position: usize) u128 { + const bytes = @ptrCast([*]const u8, arg.bytes); + return @bitCast(u128, [_]u8{ bytes[position], bytes[position + 1], bytes[position + 2], bytes[position + 3], bytes[position + 4], bytes[position + 5], bytes[position + 6], bytes[position + 7], bytes[position + 8], bytes[position + 9], bytes[position + 10], bytes[position + 11], bytes[position + 12], bytes[position + 13], bytes[position + 14], bytes[position + 15] }); +} + fn addWithOverflow(comptime T: type, self: T, other: T) WithOverflow(T) { switch (@typeInfo(T)) { .Int => { @@ -460,3 +478,30 @@ pub fn exportMulOrPanic(comptime T: type, comptime W: type, comptime name: []con }.func; @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); } + +pub fn exportCountLeadingZeroBits(comptime T: type, comptime name: []const u8) void { + comptime var f = struct { + fn func(self: T) callconv(.C) usize { + return @as(usize, @clz(T, self)); + } + }.func; + @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); +} + +pub fn exportCountTrailingZeroBits(comptime T: type, comptime name: []const u8) void { + comptime var f = struct { + fn func(self: T) callconv(.C) usize { + return @as(usize, @ctz(T, self)); + } + }.func; + @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); +} + +pub fn exportCountOneBits(comptime T: type, comptime name: []const u8) void { + comptime var f = struct { + fn func(self: T) callconv(.C) usize { + return @as(usize, @popCount(T, self)); + } + }.func; + @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); +} diff --git a/crates/compiler/builtins/bitcode/src/str.zig b/crates/compiler/builtins/bitcode/src/str.zig index 7f18d2b7e7..954dde1660 100644 --- a/crates/compiler/builtins/bitcode/src/str.zig +++ b/crates/compiler/builtins/bitcode/src/str.zig @@ -2159,125 +2159,45 @@ test "isWhitespace" { pub fn strTrim(input_string: RocStr) callconv(.C) RocStr { var string = input_string; - if (!string.isEmpty()) { - const bytes_ptr = string.asU8ptrMut(); - - const leading_bytes = countLeadingWhitespaceBytes(string); - const original_len = string.len(); - - if (original_len == leading_bytes) { - string.deinit(); - return RocStr.empty(); - } - - const trailing_bytes = countTrailingWhitespaceBytes(string); - const new_len = original_len - leading_bytes - trailing_bytes; - - if (string.isSmallStr() or !string.isRefcountOne()) { - // consume the input string; this will not free the - // bytes because the string is small or shared - const result = RocStr.init(string.asU8ptr() + leading_bytes, new_len); - - string.decref(); - - return result; - } else { - // nonempty, large, and unique: shift everything over in-place if necessary. - // Note: must use memmove over memcpy, because the bytes definitely overlap! - if (leading_bytes > 0) { - // Zig doesn't seem to have `memmove` in the stdlib anymore; this is based on: - // https://github.com/ziglang/zig/blob/52ba2c3a43a88a4db30cff47f2f3eff8c3d5be19/lib/std/special/c.zig#L115 - // Copyright Andrew Kelley, MIT licensed. - const src = bytes_ptr + leading_bytes; - var index: usize = 0; - - while (index != new_len) : (index += 1) { - bytes_ptr[index] = src[index]; - } - } - - var new_string = string; - new_string.str_len = new_len; - - return new_string; - } + if (string.isEmpty()) { + string.deinit(); + return RocStr.empty(); } - return RocStr.empty(); -} + const bytes_ptr = string.asU8ptrMut(); -pub fn strTrimLeft(string: RocStr) callconv(.C) RocStr { - if (string.str_bytes) |bytes_ptr| { - const leading_bytes = countLeadingWhitespaceBytes(string); - const original_len = string.len(); + const leading_bytes = countLeadingWhitespaceBytes(string); + const original_len = string.len(); - if (original_len == leading_bytes) { - string.deinit(); - return RocStr.empty(); - } - - const new_len = original_len - leading_bytes; - - if (string.isSmallStr() or !string.isRefcountOne()) { - // if the trimmed string fits in a small string, - // make the result a small string and decref the original string - const result = RocStr.init(string.asU8ptr() + leading_bytes, new_len); - - string.decref(); - - return result; - } else { - // nonempty, large, and unique: shift everything over in-place if necessary. - // Note: must use memmove over memcpy, because the bytes definitely overlap! - if (leading_bytes > 0) { - // Zig doesn't seem to have `memmove` in the stdlib anymore; this is based on: - // https://github.com/ziglang/zig/blob/52ba2c3a43a88a4db30cff47f2f3eff8c3d5be19/lib/std/special/c.zig#L115 - // Copyright Andrew Kelley, MIT licensed. - const src = bytes_ptr + leading_bytes; - var index: usize = 0; - - while (index != new_len) : (index += 1) { - bytes_ptr[index] = src[index]; - } - } - - var new_string = string; - new_string.str_len = new_len; - - return new_string; - } + if (original_len == leading_bytes) { + string.deinit(); + return RocStr.empty(); } - return RocStr.empty(); -} + const trailing_bytes = countTrailingWhitespaceBytes(string); + const new_len = original_len - leading_bytes - trailing_bytes; -pub fn strTrimRight(string: RocStr) callconv(.C) RocStr { - if (string.str_bytes) |bytes_ptr| { - const trailing_bytes = countTrailingWhitespaceBytes(string); - const original_len = string.len(); + if (string.isSmallStr() or !string.isRefcountOne()) { + // consume the input string; this will not free the + // bytes because the string is small or shared + const result = RocStr.init(string.asU8ptr() + leading_bytes, new_len); - if (original_len == trailing_bytes) { - string.deinit(); - return RocStr.empty(); - } + string.decref(); - const new_len = original_len - trailing_bytes; + return result; + } else { + // nonempty, large, and unique: shift everything over in-place if necessary. + // Note: must use memmove over memcpy, because the bytes definitely overlap! + if (leading_bytes > 0) { + // Zig doesn't seem to have `memmove` in the stdlib anymore; this is based on: + // https://github.com/ziglang/zig/blob/52ba2c3a43a88a4db30cff47f2f3eff8c3d5be19/lib/std/special/c.zig#L115 + // Copyright Andrew Kelley, MIT licensed. + const src = bytes_ptr + leading_bytes; + var index: usize = 0; - if (string.isSmallStr() or !string.isRefcountOne()) { - const result = RocStr.init(string.asU8ptr(), new_len); - - string.decref(); - - return result; - } - - // nonempty, large, and unique: - - var i: usize = 0; - while (i < new_len) : (i += 1) { - const dest = bytes_ptr + i; - const source = dest; - @memcpy(dest, source, 1); + while (index != new_len) : (index += 1) { + bytes_ptr[index] = src[index]; + } } var new_string = string; @@ -2285,8 +2205,99 @@ pub fn strTrimRight(string: RocStr) callconv(.C) RocStr { return new_string; } +} - return RocStr.empty(); +pub fn strTrimLeft(input_string: RocStr) callconv(.C) RocStr { + var string = input_string; + + if (string.isEmpty()) { + string.deinit(); + return RocStr.empty(); + } + + const bytes_ptr = string.asU8ptrMut(); + + const leading_bytes = countLeadingWhitespaceBytes(string); + const original_len = string.len(); + + if (original_len == leading_bytes) { + string.deinit(); + return RocStr.empty(); + } + + const new_len = original_len - leading_bytes; + + if (string.isSmallStr() or !string.isRefcountOne()) { + // if the trimmed string fits in a small string, + // make the result a small string and decref the original string + const result = RocStr.init(string.asU8ptr() + leading_bytes, new_len); + + string.decref(); + + return result; + } else { + // nonempty, large, and unique: shift everything over in-place if necessary. + // Note: must use memmove over memcpy, because the bytes definitely overlap! + if (leading_bytes > 0) { + // Zig doesn't seem to have `memmove` in the stdlib anymore; this is based on: + // https://github.com/ziglang/zig/blob/52ba2c3a43a88a4db30cff47f2f3eff8c3d5be19/lib/std/special/c.zig#L115 + // Copyright Andrew Kelley, MIT licensed. + const src = bytes_ptr + leading_bytes; + var index: usize = 0; + + while (index != new_len) : (index += 1) { + bytes_ptr[index] = src[index]; + } + } + + var new_string = string; + new_string.str_len = new_len; + + return new_string; + } +} + +pub fn strTrimRight(input_string: RocStr) callconv(.C) RocStr { + var string = input_string; + + if (string.isEmpty()) { + string.deinit(); + return RocStr.empty(); + } + + const bytes_ptr = string.asU8ptrMut(); + + const trailing_bytes = countTrailingWhitespaceBytes(string); + const original_len = string.len(); + + if (original_len == trailing_bytes) { + string.deinit(); + return RocStr.empty(); + } + + const new_len = original_len - trailing_bytes; + + if (string.isSmallStr() or !string.isRefcountOne()) { + const result = RocStr.init(string.asU8ptr(), new_len); + + string.decref(); + + return result; + } + + // nonempty, large, and unique: + + var i: usize = 0; + while (i < new_len) : (i += 1) { + const dest = bytes_ptr + i; + const source = dest; + @memcpy(dest, source, 1); + } + + var new_string = string; + new_string.str_len = new_len; + + return new_string; } fn countLeadingWhitespaceBytes(string: RocStr) usize { diff --git a/crates/compiler/builtins/bitcode/tests/bitcode_test.rs b/crates/compiler/builtins/bitcode/tests/bitcode_test.rs deleted file mode 100644 index 515e2d309b..0000000000 --- a/crates/compiler/builtins/bitcode/tests/bitcode_test.rs +++ /dev/null @@ -1,64 +0,0 @@ -#[macro_use] -extern crate pretty_assertions; - -#[cfg(test)] -mod bitcode { - use roc_builtins_bitcode::{count_segments_, str_split_}; - - #[test] - fn count_segments() { - assert_eq!( - count_segments_((&"hello there").as_bytes(), (&"hello").as_bytes()), - 2 - ); - assert_eq!( - count_segments_((&"a\nb\nc").as_bytes(), (&"\n").as_bytes()), - 3 - ); - assert_eq!( - count_segments_((&"str").as_bytes(), (&"delimiter").as_bytes()), - 1 - ); - } - - #[test] - fn str_split() { - fn splits_to(string: &str, delimiter: &str, expectation: &[&[u8]]) { - assert_eq!( - str_split_( - &mut [(&"").as_bytes()].repeat(expectation.len()), - &string.as_bytes(), - &delimiter.as_bytes() - ), - expectation - ); - } - - splits_to( - "a!b!c", - "!", - &[(&"a").as_bytes(), (&"b").as_bytes(), (&"c").as_bytes()], - ); - - splits_to( - "a!?b!?c!?", - "!?", - &[ - (&"a").as_bytes(), - (&"b").as_bytes(), - (&"c").as_bytes(), - (&"").as_bytes(), - ], - ); - - splits_to("abc", "!", &[(&"abc").as_bytes()]); - - splits_to( - "tttttghittttt", - "ttttt", - &[(&"").as_bytes(), (&"ghi").as_bytes(), (&"").as_bytes()], - ); - - splits_to("def", "!!!!!!", &[(&"def").as_bytes()]); - } -} diff --git a/crates/compiler/builtins/roc/Bool.roc b/crates/compiler/builtins/roc/Bool.roc index bb95805069..d5942e7d73 100644 --- a/crates/compiler/builtins/roc/Bool.roc +++ b/crates/compiler/builtins/roc/Bool.roc @@ -49,23 +49,25 @@ false = @Bool False ## gate. The infix operator `&&` can also be used as shorthand for ## `Bool.and`. ## -## expect (Bool.and Bool.true Bool.true) == Bool.true -## expect (Bool.true && Bool.true) == Bool.true -## expect (Bool.false && Bool.true) == Bool.false -## expect (Bool.true && Bool.false) == Bool.false -## expect (Bool.false && Bool.false) == Bool.false +## ``` +## expect (Bool.and Bool.true Bool.true) == Bool.true +## expect (Bool.true && Bool.true) == Bool.true +## expect (Bool.false && Bool.true) == Bool.false +## expect (Bool.true && Bool.false) == Bool.false +## expect (Bool.false && Bool.false) == Bool.false +## ``` ## ## **Performance Note** that in Roc the `&&` and `||` work the same way as any ## other function. However, in some languages `&&` and `||` are special-cased. ## In these languages the compiler will skip evaluating the expression after the ## first operator under certain circumstances. For example an expression like ## `enablePets && likesDogs user` would compile to. -## -## if enablePets then -## likesDogs user -## else -## Bool.false -## +## ``` +## if enablePets then +## likesDogs user +## else +## Bool.false +## ``` ## Roc does not do this because conditionals like `if` and `when` have a ## performance cost. Calling a function can sometimes be faster across the board ## than doing an `if` to decide whether to skip calling it. @@ -74,13 +76,13 @@ and : Bool, Bool -> Bool ## Returns `Bool.true` when either input is a `Bool.true`. This is equivalent to ## the logic [OR](https://en.wikipedia.org/wiki/Logical_disjunction) gate. ## The infix operator `||` can also be used as shorthand for `Bool.or`. -## -## expect (Bool.or Bool.false Bool.true) == Bool.true -## expect (Bool.true || Bool.true) == Bool.true -## expect (Bool.false || Bool.true) == Bool.true -## expect (Bool.true || Bool.false) == Bool.true -## expect (Bool.false || Bool.false) == Bool.false -## +## ``` +## expect (Bool.or Bool.false Bool.true) == Bool.true +## expect (Bool.true || Bool.true) == Bool.true +## expect (Bool.false || Bool.true) == Bool.true +## expect (Bool.true || Bool.false) == Bool.true +## expect (Bool.false || Bool.false) == Bool.false +## ``` ## **Performance Note** that in Roc the `&&` and `||` work the same way as any ## other functions. However, in some languages `&&` and `||` are special-cased. ## Refer to the note in `Bool.and` for more detail. @@ -89,9 +91,10 @@ or : Bool, Bool -> Bool ## Returns `Bool.false` when given `Bool.true`, and vice versa. This is ## equivalent to the logic [NOT](https://en.wikipedia.org/wiki/Negation) ## gate. The operator `!` can also be used as shorthand for `Bool.not`. -## -## expect (Bool.not Bool.false) == Bool.true -## expect (!Bool.false) == Bool.true +## ``` +## expect (Bool.not Bool.false) == Bool.true +## expect (!Bool.false) == Bool.true +## ``` not : Bool -> Bool ## This will call the function `Bool.isEq` on the inputs, and then `Bool.not` @@ -101,10 +104,11 @@ not : Bool -> Bool ## ## **Note** that `isNotEq` does not accept arguments whose types contain ## functions. -## -## expect (Bool.isNotEq Bool.false Bool.true) == Bool.true -## expect (Bool.false != Bool.false) == Bool.false -## expect "Apples" != "Oranges" +## ``` +## expect (Bool.isNotEq Bool.false Bool.true) == Bool.true +## expect (Bool.false != Bool.false) == Bool.false +## expect "Apples" != "Oranges" +## ``` isNotEq : a, a -> Bool | a has Eq isNotEq = \a, b -> structuralNotEq a b diff --git a/crates/compiler/builtins/roc/Box.roc b/crates/compiler/builtins/roc/Box.roc index f4e0158e85..5bebae160a 100644 --- a/crates/compiler/builtins/roc/Box.roc +++ b/crates/compiler/builtins/roc/Box.roc @@ -6,13 +6,15 @@ interface Box ## the value from the stack to the heap. This may provide a performance ## optimization for advanced use cases with large values. A platform may require ## that some values are boxed. -## -## expect Box.unbox (Box.box "Stack Faster") == "Stack Faster" +## ``` +## expect Box.unbox (Box.box "Stack Faster") == "Stack Faster" +## ``` box : a -> Box a ## Returns a boxed value. -## -## expect Box.unbox (Box.box "Stack Faster") == "Stack Faster" +## ``` +## expect Box.unbox (Box.box "Stack Faster") == "Stack Faster" +## ``` unbox : Box a -> a # # we'd need reset/reuse for box for this to be efficient diff --git a/crates/compiler/builtins/roc/Dict.roc b/crates/compiler/builtins/roc/Dict.roc index 1f82705a4e..4ec4db533c 100644 --- a/crates/compiler/builtins/roc/Dict.roc +++ b/crates/compiler/builtins/roc/Dict.roc @@ -45,15 +45,15 @@ interface Dict ## ## Here's an example of a dictionary which uses a city's name as the key, and ## its population as the associated value. -## -## populationByCity = -## Dict.empty {} -## |> Dict.insert "London" 8_961_989 -## |> Dict.insert "Philadelphia" 1_603_797 -## |> Dict.insert "Shanghai" 24_870_895 -## |> Dict.insert "Delhi" 16_787_941 -## |> Dict.insert "Amsterdam" 872_680 -## +## ``` +## populationByCity = +## Dict.empty {} +## |> Dict.insert "London" 8_961_989 +## |> Dict.insert "Philadelphia" 1_603_797 +## |> Dict.insert "Shanghai" 24_870_895 +## |> Dict.insert "Delhi" 16_787_941 +## |> Dict.insert "Amsterdam" 872_680 +## ``` ## ### Accessing keys or values ## ## We can use [Dict.keys] and [Dict.values] functions to get only the keys or @@ -66,13 +66,13 @@ interface Dict ## ### Removing ## ## We can remove an element from the dictionary, like so: -## -## populationByCity -## |> Dict.remove "Philadelphia" -## |> Dict.keys -## == -## ["London", "Amsterdam", "Shanghai", "Delhi"] -## +## ``` +## populationByCity +## |> Dict.remove "Philadelphia" +## |> Dict.keys +## == +## ["London", "Amsterdam", "Shanghai", "Delhi"] +## ``` ## Notice that the order has changed. Philadelphia was not only removed from the ## list, but Amsterdam - the last entry we inserted - has been moved into the ## spot where Philadelphia was previously. This is exactly what [Dict.remove] @@ -125,36 +125,39 @@ withCapacity = \_ -> empty {} ## Returns a dictionary containing the key and value provided as input. -## -## expect -## Dict.single "A" "B" -## |> Bool.isEq (Dict.insert (Dict.empty {}) "A" "B") +## ``` +## expect +## Dict.single "A" "B" +## |> Bool.isEq (Dict.insert (Dict.empty {}) "A" "B") +## ``` single : k, v -> Dict k v | k has Hash & Eq single = \k, v -> insert (empty {}) k v ## Returns dictionary with the keys and values specified by the input [List]. -## -## expect -## Dict.single 1 "One" -## |> Dict.insert 2 "Two" -## |> Dict.insert 3 "Three" -## |> Dict.insert 4 "Four" -## |> Bool.isEq (Dict.fromList [T 1 "One", T 2 "Two", T 3 "Three", T 4 "Four"]) +## ``` +## expect +## Dict.single 1 "One" +## |> Dict.insert 2 "Two" +## |> Dict.insert 3 "Three" +## |> Dict.insert 4 "Four" +## |> Bool.isEq (Dict.fromList [T 1 "One", T 2 "Two", T 3 "Three", T 4 "Four"]) +## ``` fromList : List (T k v) -> Dict k v | k has Hash & Eq fromList = \data -> # TODO: make this efficient. Should just set data and then set all indicies in the hashmap. List.walk data (empty {}) (\dict, T k v -> insert dict k v) ## Returns the number of values in the dictionary. -## -## expect -## Dict.empty {} -## |> Dict.insert "One" "A Song" -## |> Dict.insert "Two" "Candy Canes" -## |> Dict.insert "Three" "Boughs of Holly" -## |> Dict.len -## |> Bool.isEq 3 +## ``` +## expect +## Dict.empty {} +## |> Dict.insert "One" "A Song" +## |> Dict.insert "Two" "Candy Canes" +## |> Dict.insert "Three" "Boughs of Holly" +## |> Dict.len +## |> Bool.isEq 3 +## ``` len : Dict k v -> Nat | k has Hash & Eq len = \@Dict { size } -> size @@ -180,13 +183,14 @@ clear = \@Dict { metadata, dataIndices, data } -> ## Iterate through the keys and values in the dictionary and call the provided ## function with signature `state, k, v -> state` for each value, with an ## initial `state` value provided for the first call. -## -## expect -## Dict.empty {} -## |> Dict.insert "Apples" 12 -## |> Dict.insert "Orange" 24 -## |> Dict.walk 0 (\count, _, qty -> count + qty) -## |> Bool.isEq 36 +## ``` +## expect +## Dict.empty {} +## |> Dict.insert "Apples" 12 +## |> Dict.insert "Orange" 24 +## |> Dict.walk 0 (\count, _, qty -> count + qty) +## |> Bool.isEq 36 +## ``` walk : Dict k v, state, (state, k, v -> state) -> state | k has Hash & Eq walk = \@Dict { data }, initialState, transform -> List.walk data initialState (\state, T k v -> transform state k v) @@ -208,14 +212,15 @@ walkUntil = \@Dict { data }, initialState, transform -> ## Get the value for a given key. If there is a value for the specified key it ## will return [Ok value], otherwise return [Err KeyNotFound]. +## ``` +## dictionary = +## Dict.empty {} +## |> Dict.insert 1 "Apple" +## |> Dict.insert 2 "Orange" ## -## dictionary = -## Dict.empty {} -## |> Dict.insert 1 "Apple" -## |> Dict.insert 2 "Orange" -## -## expect Dict.get dictionary 1 == Ok "Apple" -## expect Dict.get dictionary 2000 == Err KeyNotFound +## expect Dict.get dictionary 1 == Ok "Apple" +## expect Dict.get dictionary 2000 == Err KeyNotFound +## ``` get : Dict k v, k -> Result v [KeyNotFound] | k has Hash & Eq get = \@Dict { metadata, dataIndices, data }, key -> hashKey = @@ -237,12 +242,13 @@ get = \@Dict { metadata, dataIndices, data }, key -> Err KeyNotFound ## Check if the dictionary has a value for a specified key. -## -## expect -## Dict.empty {} -## |> Dict.insert 1234 "5678" -## |> Dict.contains 1234 -## |> Bool.isEq Bool.true +## ``` +## expect +## Dict.empty {} +## |> Dict.insert 1234 "5678" +## |> Dict.contains 1234 +## |> Bool.isEq Bool.true +## ``` contains : Dict k v, k -> Bool | k has Hash & Eq contains = \@Dict { metadata, dataIndices, data }, key -> hashKey = @@ -261,12 +267,13 @@ contains = \@Dict { metadata, dataIndices, data }, key -> Bool.false ## Insert a value into the dictionary at a specified key. -## -## expect -## Dict.empty {} -## |> Dict.insert "Apples" 12 -## |> Dict.get "Apples" -## |> Bool.isEq (Ok 12) +## ``` +## expect +## Dict.empty {} +## |> Dict.insert "Apples" 12 +## |> Dict.get "Apples" +## |> Bool.isEq (Ok 12) +## ``` insert : Dict k v, k, v -> Dict k v | k has Hash & Eq insert = \@Dict { metadata, dataIndices, data, size }, key, value -> hashKey = @@ -305,13 +312,14 @@ insert = \@Dict { metadata, dataIndices, data, size }, key, value -> insertNotFoundHelper rehashedDict key value h1Key h2Key ## Remove a value from the dictionary for a specified key. -## -## expect -## Dict.empty {} -## |> Dict.insert "Some" "Value" -## |> Dict.remove "Some" -## |> Dict.len -## |> Bool.isEq 0 +## ``` +## expect +## Dict.empty {} +## |> Dict.insert "Some" "Value" +## |> Dict.remove "Some" +## |> Dict.len +## |> Bool.isEq 0 +## ``` remove : Dict k v, k -> Dict k v | k has Hash & Eq remove = \@Dict { metadata, dataIndices, data, size }, key -> # TODO: change this from swap remove to tombstone and test is performance is still good. @@ -345,16 +353,17 @@ remove = \@Dict { metadata, dataIndices, data, size }, key -> ## performance optimisation for the use case of providing a default when a value ## is missing. This is more efficient than doing both a `Dict.get` and then a ## `Dict.insert` call, and supports being piped. +## ``` +## alterValue : [Present Bool, Missing] -> [Present Bool, Missing] +## alterValue = \possibleValue -> +## when possibleValue is +## Missing -> Present Bool.false +## Present value -> if value then Missing else Present Bool.true ## -## alterValue : [Present Bool, Missing] -> [Present Bool, Missing] -## alterValue = \possibleValue -> -## when possibleValue is -## Missing -> Present Bool.false -## Present value -> if value then Missing else Present Bool.true -## -## expect Dict.update (Dict.empty {}) "a" alterValue == Dict.single "a" Bool.false -## expect Dict.update (Dict.single "a" Bool.false) "a" alterValue == Dict.single "a" Bool.true -## expect Dict.update (Dict.single "a" Bool.true) "a" alterValue == Dict.empty {} +## expect Dict.update (Dict.empty {}) "a" alterValue == Dict.single "a" Bool.false +## expect Dict.update (Dict.single "a" Bool.false) "a" alterValue == Dict.single "a" Bool.true +## expect Dict.update (Dict.single "a" Bool.true) "a" alterValue == Dict.empty {} +## ``` update : Dict k v, k, ([Present v, Missing] -> [Present v, Missing]) -> Dict k v | k has Hash & Eq update = \dict, key, alter -> # TODO: look into optimizing by merging substeps and reducing lookups. @@ -369,42 +378,45 @@ update = \dict, key, alter -> ## Returns the keys and values of a dictionary as a [List]. ## This requires allocating a temporary list, prefer using [Dict.toList] or [Dict.walk] instead. -## -## expect -## Dict.single 1 "One" -## |> Dict.insert 2 "Two" -## |> Dict.insert 3 "Three" -## |> Dict.insert 4 "Four" -## |> Dict.toList -## |> Bool.isEq [T 1 "One", T 2 "Two", T 3 "Three", T 4 "Four"] +## ``` +## expect +## Dict.single 1 "One" +## |> Dict.insert 2 "Two" +## |> Dict.insert 3 "Three" +## |> Dict.insert 4 "Four" +## |> Dict.toList +## |> Bool.isEq [T 1 "One", T 2 "Two", T 3 "Three", T 4 "Four"] +## ``` toList : Dict k v -> List (T k v) | k has Hash & Eq toList = \@Dict { data } -> data ## Returns the keys of a dictionary as a [List]. ## This requires allocating a temporary [List], prefer using [Dict.toList] or [Dict.walk] instead. -## -## expect -## Dict.single 1 "One" -## |> Dict.insert 2 "Two" -## |> Dict.insert 3 "Three" -## |> Dict.insert 4 "Four" -## |> Dict.keys -## |> Bool.isEq [1,2,3,4] +## ``` +## expect +## Dict.single 1 "One" +## |> Dict.insert 2 "Two" +## |> Dict.insert 3 "Three" +## |> Dict.insert 4 "Four" +## |> Dict.keys +## |> Bool.isEq [1,2,3,4] +## ``` keys : Dict k v -> List k | k has Hash & Eq keys = \@Dict { data } -> List.map data (\T k _ -> k) ## Returns the values of a dictionary as a [List]. ## This requires allocating a temporary [List], prefer using [Dict.toList] or [Dict.walk] instead. -## -## expect -## Dict.single 1 "One" -## |> Dict.insert 2 "Two" -## |> Dict.insert 3 "Three" -## |> Dict.insert 4 "Four" -## |> Dict.values -## |> Bool.isEq ["One","Two","Three","Four"] +## ``` +## expect +## Dict.single 1 "One" +## |> Dict.insert 2 "Two" +## |> Dict.insert 3 "Three" +## |> Dict.insert 4 "Four" +## |> Dict.values +## |> Bool.isEq ["One","Two","Three","Four"] +## ``` values : Dict k v -> List v | k has Hash & Eq values = \@Dict { data } -> List.map data (\T _ v -> v) @@ -414,24 +426,25 @@ values = \@Dict { data } -> ## both dictionaries will be combined. Note that where there are pairs ## with the same key, the value contained in the second input will be ## retained, and the value in the first input will be removed. +## ``` +## first = +## Dict.single 1 "Not Me" +## |> Dict.insert 2 "And Me" ## -## first = -## Dict.single 1 "Not Me" -## |> Dict.insert 2 "And Me" +## second = +## Dict.single 1 "Keep Me" +## |> Dict.insert 3 "Me Too" +## |> Dict.insert 4 "And Also Me" ## -## second = -## Dict.single 1 "Keep Me" -## |> Dict.insert 3 "Me Too" -## |> Dict.insert 4 "And Also Me" +## expected = +## Dict.single 1 "Keep Me" +## |> Dict.insert 2 "And Me" +## |> Dict.insert 3 "Me Too" +## |> Dict.insert 4 "And Also Me" ## -## expected = -## Dict.single 1 "Keep Me" -## |> Dict.insert 2 "And Me" -## |> Dict.insert 3 "Me Too" -## |> Dict.insert 4 "And Also Me" -## -## expect -## Dict.insertAll first second == expected +## expect +## Dict.insertAll first second == expected +## ``` insertAll : Dict k v, Dict k v -> Dict k v | k has Hash & Eq insertAll = \xs, ys -> walk ys xs insert @@ -441,18 +454,19 @@ insertAll = \xs, ys -> ## that are in both dictionaries. Note that where there are pairs with ## the same key, the value contained in the first input will be retained, ## and the value in the second input will be removed. +## ``` +## first = +## Dict.single 1 "Keep Me" +## |> Dict.insert 2 "And Me" ## -## first = -## Dict.single 1 "Keep Me" -## |> Dict.insert 2 "And Me" +## second = +## Dict.single 1 "Keep Me" +## |> Dict.insert 2 "And Me" +## |> Dict.insert 3 "But Not Me" +## |> Dict.insert 4 "Or Me" ## -## second = -## Dict.single 1 "Keep Me" -## |> Dict.insert 2 "And Me" -## |> Dict.insert 3 "But Not Me" -## |> Dict.insert 4 "Or Me" -## -## expect Dict.keepShared first second == first +## expect Dict.keepShared first second == first +## ``` keepShared : Dict k v, Dict k v -> Dict k v | k has Hash & Eq keepShared = \xs, ys -> walk @@ -469,21 +483,22 @@ keepShared = \xs, ys -> ## using the [set difference](https://en.wikipedia.org/wiki/Complement_(set_theory)#Relative_complement) ## of the values. This means that we will be left with only those pairs that ## are in the first dictionary and whose keys are not in the second. +## ``` +## first = +## Dict.single 1 "Keep Me" +## |> Dict.insert 2 "And Me" +## |> Dict.insert 3 "Remove Me" ## -## first = -## Dict.single 1 "Keep Me" -## |> Dict.insert 2 "And Me" -## |> Dict.insert 3 "Remove Me" +## second = +## Dict.single 3 "Remove Me" +## |> Dict.insert 4 "I do nothing..." ## -## second = -## Dict.single 3 "Remove Me" -## |> Dict.insert 4 "I do nothing..." +## expected = +## Dict.single 1 "Keep Me" +## |> Dict.insert 2 "And Me" ## -## expected = -## Dict.single 1 "Keep Me" -## |> Dict.insert 2 "And Me" -## -## expect Dict.removeAll first second == expected +## expect Dict.removeAll first second == expected +## ``` removeAll : Dict k v, Dict k v -> Dict k v | k has Hash & Eq removeAll = \xs, ys -> walk ys xs (\state, k, _ -> remove state k) diff --git a/crates/compiler/builtins/roc/Json.roc b/crates/compiler/builtins/roc/Json.roc index aa01c37c1c..197b6fc5f4 100644 --- a/crates/compiler/builtins/roc/Json.roc +++ b/crates/compiler/builtins/roc/Json.roc @@ -191,16 +191,42 @@ encodeTag = \name, payload -> List.append bytesWithPayload (Num.toU8 ']') |> List.append (Num.toU8 '}') +isEscapeSequence : U8, U8 -> Bool +isEscapeSequence = \a, b -> + when P a b is + P '\\' 'b' -> Bool.true # Backspace + P '\\' 'f' -> Bool.true # Form feed + P '\\' 'n' -> Bool.true # Newline + P '\\' 'r' -> Bool.true # Carriage return + P '\\' 't' -> Bool.true # Tab + P '\\' '"' -> Bool.true # Double quote + P '\\' '\\' -> Bool.true # Backslash + _ -> Bool.false + takeWhile = \list, predicate -> helper = \{ taken, rest } -> - when List.first rest is - Ok elem -> - if predicate elem then - helper { taken: List.append taken elem, rest: List.split rest 1 |> .others } + when rest is + [a, b, ..] -> + if isEscapeSequence a b then + helper { + taken: taken |> List.append a |> List.append b, + rest: List.drop rest 2, + } + else if predicate a then + helper { + taken: List.append taken a, + rest: List.dropFirst rest, + } else { taken, rest } - Err _ -> { taken, rest } + [a, ..] if predicate a -> + helper { + taken: List.append taken a, + rest: List.dropFirst rest, + } + + _ -> { taken, rest } helper { taken: [], rest: list } @@ -341,7 +367,6 @@ jsonString = \bytes -> if before == ['"'] then - # TODO: handle escape sequences { taken: strSequence, rest } = takeWhile afterStartingQuote \n -> n != '"' when Str.fromUtf8 strSequence is @@ -358,42 +383,30 @@ decodeString = Decode.custom \bytes, @Json {} -> jsonString bytes decodeList = \decodeElem -> Decode.custom \bytes, @Json {} -> + decodeElems = \chunk, accum -> when Decode.decodeWith chunk decodeElem (@Json {}) is { result, rest } -> when result is - Ok val -> - # TODO: handle spaces before ',' - { before: afterElem, others } = List.split rest 1 - - if - afterElem == [','] - then - decodeElems others (List.append accum val) - else - Done (List.append accum val) rest - Err e -> Errored e rest + Ok val -> + restWithoutWhitespace = eatWhitespace rest + when restWithoutWhitespace is + [',', ..] -> decodeElems (eatWhitespace (List.dropFirst restWithoutWhitespace)) (List.append accum val) + _ -> Done (List.append accum val) restWithoutWhitespace - { before, others: afterStartingBrace } = List.split bytes 1 + when bytes is + ['[', ']'] -> { result: Ok [], rest: List.drop bytes 2 } + ['[', ..] -> + when decodeElems (eatWhitespace (List.dropFirst bytes)) [] is + Errored e rest -> { result: Err e, rest } + Done vals rest -> + when rest is + [']', ..] -> { result: Ok vals, rest: List.dropFirst rest } + _ -> { result: Err TooShort, rest } - if - before == ['['] - then - # TODO: empty lists - when decodeElems afterStartingBrace [] is - Errored e rest -> { result: Err e, rest } - Done vals rest -> - { before: maybeEndingBrace, others: afterEndingBrace } = List.split rest 1 - - if - maybeEndingBrace == [']'] - then - { result: Ok vals, rest: afterEndingBrace } - else - { result: Err TooShort, rest } - else - { result: Err TooShort, rest: bytes } + _ -> + { result: Err TooShort, rest: bytes } parseExactChar : List U8, U8 -> DecodeResult {} parseExactChar = \bytes, char -> @@ -463,3 +476,82 @@ decodeRecord = \initialState, stepField, finalizer -> Decode.custom \bytes, @Jso when finalizer endStateResult is Ok val -> { result: Ok val, rest: afterRecordBytes } Err e -> { result: Err e, rest: afterRecordBytes } + +# Helper to eat leading Json whitespace characters +eatWhitespace = \input -> + when input is + [' ', ..] -> eatWhitespace (List.dropFirst input) + ['\n', ..] -> eatWhitespace (List.dropFirst input) + ['\r', ..] -> eatWhitespace (List.dropFirst input) + ['\t', ..] -> eatWhitespace (List.dropFirst input) + _ -> input + +# Test eating Json whitespace +expect + input = Str.toUtf8 " \n\r\tabc" + actual = eatWhitespace input + expected = Str.toUtf8 "abc" + actual == expected + +# Test json string decoding with escapes +expect + input = Str.toUtf8 "\"a\r\nbc\\\"xz\"" + expected = Ok "a\r\nbc\\\"xz" + actual = Decode.fromBytes input fromUtf8 + actual == expected + +# Test json string encoding with escapes +expect + input = "a\r\nbc\\\"xz" + expected = Str.toUtf8 "\"a\r\nbc\\\"xz\"" + actual = Encode.toBytes input toUtf8 + actual == expected + +# Test json array decode empty list +expect + input = Str.toUtf8 "[ ]" + expected = [] + + actual : List U8 + actual = Decode.fromBytes input fromUtf8 |> Result.withDefault [] + + actual == expected + +# Test json array decoding into integers +expect + input = Str.toUtf8 "[ 1,\n2,\t3]" + expected = [1, 2, 3] + + actual : List U8 + actual = Decode.fromBytes input fromUtf8 |> Result.withDefault [] + + actual == expected + +# Test json array decoding into strings ignoring whitespace around values +expect + input = Str.toUtf8 "[\r\"one\" ,\t\"two\"\n,\n\"3\"\t]" + expected = ["one", "two", "3"] + + actual : List Str + actual = + Decode.fromBytes input fromUtf8 + |> Result.onErr handleJsonDecodeError + |> Result.withDefault [] + + actual == expected + +# Helper for tests to handle Json decoding errors +handleJsonDecodeError = \err -> + when err is + Leftover bytes -> + when Str.fromUtf8 bytes is + Ok bs -> crash "ERROR: bytes left \(bs)" + Err _ -> + ls = + bytes + |> List.map Num.toStr + |> Str.joinWith "," + + crash "ERROR: bytes left \(ls)" + + TooShort -> crash "ERROR: input too short" diff --git a/crates/compiler/builtins/roc/List.roc b/crates/compiler/builtins/roc/List.roc index 0090457e7b..eb608a0c1a 100644 --- a/crates/compiler/builtins/roc/List.roc +++ b/crates/compiler/builtins/roc/List.roc @@ -73,11 +73,11 @@ interface List ## Types ## A sequential list of values. -## -## >>> [1, 2, 3] # a list of numbers -## >>> ["a", "b", "c"] # a list of strings -## >>> [[1.1], [], [2.2, 3.3]] # a list of lists of numbers -## +## ``` +## [1, 2, 3] # a list of numbers +## ["a", "b", "c"] # a list of strings +## [[1.1], [], [2.2, 3.3]] # a list of lists of numbers +## ``` ## The maximum size of a [List] is limited by the amount of heap memory available ## to the current process. If there is not enough memory available, attempting to ## create the list could crash. (On Linux, where [overcommit](https://www.etalabs.net/overcommit.html) @@ -105,11 +105,11 @@ interface List ## will be immediately freed. ## ## Let's look at an example. +## ``` +## ratings = [5, 4, 3] ## -## ratings = [5, 4, 3] -## -## { foo: ratings, bar: ratings } -## +## { foo: ratings, bar: ratings } +## ``` ## The first line binds the name `ratings` to the list `[5, 4, 3]`. The list ## begins with a refcount of 1, because so far only `ratings` is referencing it. ## @@ -118,14 +118,14 @@ interface List ## refcount getting incremented from 1 to 3. ## ## Let's turn this example into a function. +## ``` +## getRatings = \first -> +## ratings = [first, 4, 3] ## -## getRatings = \first -> -## ratings = [first, 4, 3] -## -## { foo: ratings, bar: ratings } -## -## getRatings 5 +## { foo: ratings, bar: ratings } ## +## getRatings 5 +## ``` ## At the end of the `getRatings` function, when the record gets returned, ## the original `ratings =` binding has gone out of scope and is no longer ## accessible. (Trying to reference `ratings` outside the scope of the @@ -140,23 +140,23 @@ interface List ## list, and that list has a refcount of 2. ## ## Let's change the last line to be `(getRatings 5).bar` instead of `getRatings 5`: +## ``` +## getRatings = \first -> +## ratings = [first, 4, 3] ## -## getRatings = \first -> -## ratings = [first, 4, 3] -## -## { foo: ratings, bar: ratings } -## -## (getRatings 5).bar +## { foo: ratings, bar: ratings } ## +## (getRatings 5).bar +## ``` ## Now, when this expression returns, only the `bar` field of the record will ## be returned. This will mean that the `foo` field becomes inaccessible, causing ## the list's refcount to get decremented from 2 to 1. At this point, the list is back ## where it started: there is only 1 reference to it. ## ## Finally let's suppose the final line were changed to this: -## -## List.first (getRatings 5).bar -## +## ``` +## List.first (getRatings 5).bar +## ``` ## This call to [List.first] means that even the list in the `bar` field has become ## inaccessible. As such, this line will cause the list's refcount to get ## decremented all the way to 0. At that point, nothing is referencing the list @@ -167,25 +167,25 @@ interface List ## and then with a list of lists, to see how they differ. ## ## Here's the example using a list of numbers. +## ``` +## nums = [1, 2, 3, 4, 5, 6, 7] ## -## nums = [1, 2, 3, 4, 5, 6, 7] -## -## first = List.first nums -## last = List.last nums -## -## first +## first = List.first nums +## last = List.last nums ## +## first +## ``` ## It makes a list, calls [List.first] and [List.last] on it, and then returns `first`. ## ## Here's the equivalent code with a list of lists: +## ``` +## lists = [[1], [2, 3], [], [4, 5, 6, 7]] ## -## lists = [[1], [2, 3], [], [4, 5, 6, 7]] -## -## first = List.first lists -## last = List.last lists -## -## first +## first = List.first lists +## last = List.last lists ## +## first +## ``` ## TODO explain how in the former example, when we go to free `nums` at the end, ## we can free it immediately because there are no other refcounts. However, ## in the case of `lists`, we have to iterate through the list and decrement @@ -206,10 +206,11 @@ interface List ## * Roc's compiler optimizes many list operations into in-place mutations behind the scenes, depending on how the list is being used. For example, [List.map], [List.keepIf], and [List.set] can all be optimized to perform in-place mutations. ## * If possible, it is usually best for performance to use large lists in a way where the optimizer can turn them into in-place mutations. If this is not possible, a persistent data structure might be faster - but this is a rare enough scenario that it would not be good for the average Roc program's performance if this were the way [List] worked by default. Instead, you can look outside Roc's standard modules for an implementation of a persistent data structure - likely built using [List] under the hood! ## Check if the list is empty. +## ``` +## List.isEmpty [1, 2, 3] ## -## >>> List.isEmpty [1, 2, 3] -## -## >>> List.isEmpty [] +## List.isEmpty [] +## ``` isEmpty : List a -> Bool isEmpty = \list -> List.len list == 0 @@ -237,9 +238,9 @@ replace = \list, index, newValue -> { list, value: newValue } ## Replaces the element at the given index with a replacement. -## -## >>> List.set ["a", "b", "c"] 1 "B" -## +## ``` +## List.set ["a", "b", "c"] 1 "B" +## ``` ## If the given index is outside the bounds of the list, returns the original ## list unmodified. ## @@ -249,11 +250,12 @@ set = \list, index, value -> (List.replace list index value).list ## Add a single element to the end of a list. +## ``` +## List.append [1, 2, 3] 4 ## -## >>> List.append [1, 2, 3] 4 -## -## >>> [0, 1, 2] -## >>> |> List.append 3 +## [0, 1, 2] +## |> List.append 3 +## ``` append : List a, a -> List a append = \list, element -> list @@ -268,11 +270,12 @@ append = \list, element -> appendUnsafe : List a, a -> List a ## Add a single element to the beginning of a list. +## ``` +## List.prepend [1, 2, 3] 0 ## -## >>> List.prepend [1, 2, 3] 0 -## -## >>> [2, 3, 4] -## >>> |> List.prepend 1 +## [2, 3, 4] +## |> List.prepend 1 +## ``` prepend : List a, a -> List a ## Returns the length of the list - the number of elements it contains. @@ -289,11 +292,12 @@ withCapacity : Nat -> List a reserve : List a, Nat -> List a ## Put two lists together. +## ``` +## List.concat [1, 2, 3] [4, 5] ## -## >>> List.concat [1, 2, 3] [4, 5] -## -## >>> [0, 1, 2] -## >>> |> List.concat [3, 4] +## [0, 1, 2] +## |> List.concat [3, 4] +## ``` concat : List a, List a -> List a ## Returns the last element in the list, or `ListWasEmpty` if it was empty. @@ -306,17 +310,15 @@ last = \list -> ## A list with a single element in it. ## ## This is useful in pipelines, like so: -## -## websites = -## Str.concat domain ".com" -## |> List.single -## +## ``` +## websites = +## Str.concat domain ".com" +## |> List.single +## ``` single : a -> List a single = \x -> [x] ## Returns a list with the given length, where every element is the given value. -## -## repeat : a, Nat -> List a repeat = \value, count -> repeatHelp value count (List.withCapacity count) @@ -329,8 +331,9 @@ repeatHelp = \value, count, accum -> accum ## Returns the list with its elements reversed. -## -## >>> List.reverse [1, 2, 3] +## ``` +## List.reverse [1, 2, 3] +## ``` reverse : List a -> List a reverse = \list -> reverseHelp list 0 (Num.subSaturated (List.len list) 1) @@ -342,12 +345,11 @@ reverseHelp = \list, left, right -> list ## Join the given lists together into one list. -## -## >>> List.join [[1, 2, 3], [4, 5], [], [6, 7]] -## -## >>> List.join [[], []] -## -## >>> List.join [] +## ``` +## List.join [[1, 2, 3], [4, 5], [], [6, 7]] +## List.join [[], []] +## List.join [] +## ``` join : List (List a) -> List a join = \lists -> totalLength = @@ -366,10 +368,10 @@ contains = \list, needle -> ## which updates the `state`. It returns the final `state` at the end. ## ## You can use it in a pipeline: -## -## [2, 4, 8] -## |> List.walk 0 Num.add -## +## ``` +## [2, 4, 8] +## |> List.walk 0 Num.add +## ``` ## This returns 14 because: ## * `state` starts at 0 ## * Each `step` runs `Num.add state elem`, and the return value becomes the new `state`. @@ -385,10 +387,10 @@ contains = \list, needle -> ## 6 | 8 | 14 ## ## The following returns -6: -## -## [1, 2, 3] -## |> List.walk 0 Num.sub -## +## ``` +## [1, 2, 3] +## |> List.walk 0 Num.sub +## ``` ## Note that in other languages, `walk` is sometimes called `reduce`, ## `fold`, `foldLeft`, or `foldl`. walk : List elem, state, (state, elem -> state) -> state @@ -494,9 +496,9 @@ all = \list, predicate -> ## Run the given function on each element of a list, and return all the ## elements for which the function returned `Bool.true`. -## -## >>> List.keepIf [1, 2, 3, 4] (\num -> num > 2) -## +## ``` +## List.keepIf [1, 2, 3, 4] (\num -> num > 2) +## ``` ## ## Performance Details ## ## [List.keepIf] always returns a list that takes up exactly the same amount @@ -531,9 +533,9 @@ keepIfHelp = \list, predicate, kept, index, length -> ## Run the given function on each element of a list, and return all the ## elements for which the function returned `Bool.false`. -## -## >>> List.dropIf [1, 2, 3, 4] (\num -> num > 2) -## +## ``` +## List.dropIf [1, 2, 3, 4] (\num -> num > 2) +## ``` ## ## Performance Details ## ## `List.dropIf` has the same performance characteristics as [List.keepIf]. @@ -556,12 +558,13 @@ countIf = \list, predicate -> ## This works like [List.map], except only the transformed values that are ## wrapped in `Ok` are kept. Any that are wrapped in `Err` are dropped. +## ``` +## List.keepOks [["a", "b"], [], [], ["c", "d", "e"]] List.last ## -## >>> List.keepOks [["a", "b"], [], [], ["c", "d", "e"]] List.last +## fn = \str -> if Str.isEmpty str then Err StrWasEmpty else Ok (Str.len str) ## -## >>> fn = \str -> if Str.isEmpty str then Err StrWasEmpty else Ok (Str.len str) -## >>> -## >>> List.keepOks ["", "a", "bc", "", "d", "ef", ""] +## List.keepOks ["", "a", "bc", "", "d", "ef", ""] +## ``` keepOks : List before, (before -> Result after *) -> List after keepOks = \list, toResult -> walker = \accum, element -> @@ -573,12 +576,13 @@ keepOks = \list, toResult -> ## This works like [List.map], except only the transformed values that are ## wrapped in `Err` are kept. Any that are wrapped in `Ok` are dropped. +## ``` +## List.keepErrs [["a", "b"], [], [], ["c", "d", "e"]] List.last ## -## >>> List.keepErrs [["a", "b"], [], [], ["c", "d", "e"]] List.last +## fn = \str -> if Str.isEmpty str then Err StrWasEmpty else Ok (Str.len str) ## -## >>> fn = \str -> if Str.isEmpty str then Err StrWasEmpty else Ok (Str.len str) -## >>> -## >>> List.keepErrs ["", "a", "bc", "", "d", "ef", ""] +## List.keepErrs ["", "a", "bc", "", "d", "ef", ""] +## ``` keepErrs : List before, (before -> Result * after) -> List after keepErrs = \list, toResult -> walker = \accum, element -> @@ -590,10 +594,11 @@ keepErrs = \list, toResult -> ## Convert each element in the list to something new, by calling a conversion ## function on each of them. Then return a new list of the converted values. +## ``` +## List.map [1, 2, 3] (\num -> num + 1) ## -## > List.map [1, 2, 3] (\num -> num + 1) -## -## > List.map ["", "a", "bc"] Str.isEmpty +## List.map ["", "a", "bc"] Str.isEmpty +## ``` map : List a, (a -> b) -> List b ## Run a transformation function on the first element of each list, @@ -602,8 +607,9 @@ map : List a, (a -> b) -> List b ## ## Some languages have a function named `zip`, which does something similar to ## calling [List.map2] passing two lists and `Pair`: -## -## >>> zipped = List.map2 ["a", "b", "c"] [1, 2, 3] Pair +## ``` +## zipped = List.map2 ["a", "b", "c"] [1, 2, 3] Pair +## ``` map2 : List a, List b, (a, b -> c) -> List c ## Run a transformation function on the first element of each list, @@ -640,92 +646,110 @@ mapWithIndexHelp = \src, dest, func, index, length -> ## Returns a list of all the integers between `start` and `end`. ## ## To include the `start` and `end` integers themselves, use `At` like so: -## -## List.range { start: At 2, end: At 5 } # returns [2, 3, 4, 5] -## +## ``` +## List.range { start: At 2, end: At 5 } # returns [2, 3, 4, 5] +## ``` ## To exclude them, use `After` and `Before`, like so: -## -## List.range { start: After 2, end: Before 5 } # returns [3, 4] -## +## ``` +## List.range { start: After 2, end: Before 5 } # returns [3, 4] +## ``` ## You can have the list end at a certain length rather than a certain integer: -## -## List.range { start: At 6, end: Length 4 } # returns [6, 7, 8, 9] -## +## ``` +## List.range { start: At 6, end: Length 4 } # returns [6, 7, 8, 9] +## ``` ## If `step` is specified, each integer increases by that much. (`step: 1` is the default.) -## -## List.range { start: After 0, end: Before 9, step: 3 } # returns [3, 6] -## +## ``` +## List.range { start: After 0, end: Before 9, step: 3 } # returns [3, 6] +## ``` +## List.range will also generate a reversed list if step is negative or end comes before start: +## ``` +## List.range { start: At 5, end: At 2 } # returns [5, 4, 3, 2] +## ``` ## All of these options are compatible with the others. For example, you can use `At` or `After` ## with `start` regardless of what `end` and `step` are set to. range : _ range = \{ start, end, step ? 0 } -> - { incByStep, stepIsPositive } = + { calcNext, stepIsPositive } = if step == 0 then when T start end is T (At x) (At y) | T (At x) (Before y) | T (After x) (At y) | T (After x) (Before y) -> if x < y then { - incByStep: \i -> i + 1, + calcNext: \i -> Num.addChecked i 1, stepIsPositive: Bool.true, } else { - incByStep: \i -> i - 1, + calcNext: \i -> Num.subChecked i 1, stepIsPositive: Bool.false, } T (At _) (Length _) | T (After _) (Length _) -> { - incByStep: \i -> i + 1, + calcNext: \i -> Num.addChecked i 1, stepIsPositive: Bool.true, } else { - incByStep: \i -> i + step, + calcNext: \i -> Num.addChecked i step, stepIsPositive: step > 0, } inclusiveStart = when start is - At x -> x - After x -> incByStep x + At x -> Ok x + After x -> calcNext x when end is At at -> - isComplete = + isValid = if stepIsPositive then - \i -> i > at + \i -> i <= at else - \i -> i < at + \i -> i >= at # TODO: switch to List.withCapacity - rangeHelp [] inclusiveStart incByStep isComplete + rangeHelp [] inclusiveStart calcNext isValid Before before -> - isComplete = + isValid = if stepIsPositive then - \i -> i >= before + \i -> i < before else - \i -> i <= before + \i -> i > before # TODO: switch to List.withCapacity - rangeHelp [] inclusiveStart incByStep isComplete + rangeHelp [] inclusiveStart calcNext isValid Length l -> - rangeLengthHelp (List.withCapacity l) inclusiveStart l incByStep + rangeLengthHelp (List.withCapacity l) inclusiveStart l calcNext -rangeHelp = \accum, i, incByStep, isComplete -> - if isComplete i then - accum - else - # TODO: change this to List.appendUnsafe once capacity is set correctly - rangeHelp (List.append accum i) (incByStep i) incByStep isComplete +rangeHelp = \accum, i, calcNext, isValid -> + when i is + Ok val -> + if isValid val then + # TODO: change this to List.appendUnsafe once capacity is set correctly + rangeHelp (List.append accum val) (calcNext val) calcNext isValid + else + accum -rangeLengthHelp = \accum, i, remaining, incByStep -> + Err _ -> + # We went past the end of the numeric range and there is no next. + # return the generated list. + accum + +rangeLengthHelp = \accum, i, remaining, calcNext -> if remaining == 0 then accum else - rangeLengthHelp (List.appendUnsafe accum i) (incByStep i) (remaining - 1) incByStep + when i is + Ok val -> + rangeLengthHelp (List.appendUnsafe accum val) (calcNext val) (remaining - 1) calcNext + + Err _ -> + # We went past the end of the numeric range and there is no next. + # The list is not the correct length yet, so we must crash. + crash "List.range: failed to generate enough elements to fill the range before overflowing the numeric type" expect List.range { start: At 0, end: At 4 } == [0, 1, 2, 3, 4] @@ -754,6 +778,18 @@ expect expect List.range { start: At 4, end: Length 5, step: -3 } == [4, 1, -2, -5, -8] +expect + List.range { start: After 250u8, end: At 255 } == [251, 252, 253, 254, 255] + +expect + List.range { start: After 250u8, end: At 255, step: 10 } == [] + +expect + List.range { start: After 250u8, end: At 245, step: 10 } == [] + +expect + List.range { start: At 4, end: At 0 } == [4, 3, 2, 1, 0] + ## Sort with a custom comparison function sortWith : List a, (a, a -> [LT, EQ, GT]) -> List a @@ -795,14 +831,14 @@ dropLast = \list -> List.dropAt list (Num.subSaturated (List.len list) 1) ## Returns the given number of elements from the beginning of the list. -## -## >>> List.takeFirst [1, 2, 3, 4, 5, 6, 7, 8] 4 -## +## ``` +## List.takeFirst [1, 2, 3, 4, 5, 6, 7, 8] 4 +## ``` ## If there are fewer elements in the list than the requested number, ## returns the entire list. -## -## >>> List.takeFirst [1, 2] 5 -## +## ``` +## List.takeFirst [1, 2] 5 +## ``` ## To *remove* elements from the beginning of the list, use `List.takeLast`. ## ## To remove elements from both the beginning and end of the list, @@ -824,14 +860,14 @@ takeFirst = \list, outputLength -> List.sublist list { start: 0, len: outputLength } ## Returns the given number of elements from the end of the list. -## -## >>> List.takeLast [1, 2, 3, 4, 5, 6, 7, 8] 4 -## +## ``` +## List.takeLast [1, 2, 3, 4, 5, 6, 7, 8] 4 +## ``` ## If there are fewer elements in the list than the requested number, ## returns the entire list. -## -## >>> List.takeLast [1, 2] 5 -## +## ``` +## List.takeLast [1, 2] 5 +## ``` ## To *remove* elements from the end of the list, use `List.takeFirst`. ## ## To remove elements from both the beginning and end of the list, @@ -971,13 +1007,13 @@ findLastIndex = \list, matches -> ## including a total of `len` elements. ## ## If `start` is outside the bounds of the given list, returns the empty list. -## -## >>> List.sublist [1, 2, 3] { start: 4, len: 0 } -## +## ``` +## List.sublist [1, 2, 3] { start: 4, len: 0 } +## ``` ## If more elements are requested than exist in the list, returns as many as it can. -## -## >>> List.sublist [1, 2, 3, 4, 5] { start: 2, len: 10 } -## +## ``` +## List.sublist [1, 2, 3, 4, 5] { start: 2, len: 10 } +## ``` ## > If you want a sublist which goes all the way to the end of the list, no ## > matter how long the list is, `List.takeLast` can do that more efficiently. ## @@ -993,7 +1029,9 @@ sublist = \list, config -> sublistLowlevel : List elem, Nat, Nat -> List elem ## Intersperses `sep` between the elements of `list` -## >>> List.intersperse 9 [1, 2, 3] # [1, 9, 2, 9, 3] +## ``` +## List.intersperse 9 [1, 2, 3] # [1, 9, 2, 9, 3] +## ``` intersperse : List elem, elem -> List elem intersperse = \list, sep -> capacity = 2 * List.len list @@ -1051,8 +1089,9 @@ split = \elements, userSplitIndex -> ## Returns the elements before the first occurrence of a delimiter, as well as the ## remaining elements after that occurrence. If the delimiter is not found, returns `Err`. -## -## List.splitFirst [Foo, Z, Bar, Z, Baz] Z == Ok { before: [Foo], after: [Bar, Baz] } +## ``` +## List.splitFirst [Foo, Z, Bar, Z, Baz] Z == Ok { before: [Foo], after: [Bar, Z, Baz] } +## ``` splitFirst : List elem, elem -> Result { before : List elem, after : List elem } [NotFound] | elem has Eq splitFirst = \list, delimiter -> when List.findFirstIndex list (\elem -> elem == delimiter) is @@ -1066,8 +1105,9 @@ splitFirst = \list, delimiter -> ## Returns the elements before the last occurrence of a delimiter, as well as the ## remaining elements after that occurrence. If the delimiter is not found, returns `Err`. -## -## List.splitLast [Foo, Z, Bar, Z, Baz] Z == Ok { before: [Foo, Bar], after: [Baz] } +## ``` +## List.splitLast [Foo, Z, Bar, Z, Baz] Z == Ok { before: [Foo, Z, Bar], after: [Baz] } +## ``` splitLast : List elem, elem -> Result { before : List elem, after : List elem } [NotFound] | elem has Eq splitLast = \list, delimiter -> when List.findLastIndex list (\elem -> elem == delimiter) is diff --git a/crates/compiler/builtins/roc/Num.roc b/crates/compiler/builtins/roc/Num.roc index eef9cf4741..48575fd3fd 100644 --- a/crates/compiler/builtins/roc/Num.roc +++ b/crates/compiler/builtins/roc/Num.roc @@ -68,6 +68,9 @@ interface Num compare, pow, powInt, + countLeadingZeroBits, + countTrailingZeroBits, + countOneBits, addWrap, addChecked, addSaturated, @@ -86,6 +89,8 @@ interface Num intCast, bytesToU16, bytesToU32, + bytesToU64, + bytesToU128, divCeil, divCeilChecked, divTrunc, @@ -151,9 +156,9 @@ interface Num ## Represents a number that could be either an [Int] or a [Frac]. ## ## This is useful for functions that can work on either, for example [Num.add], whose type is: -## -## add : Num a, Num a -> Num a -## +## ``` +## add : Num a, Num a -> Num a +## ``` ## The number 1.5 technically has the type `Num (Fraction *)`, so when you pass ## two of them to [Num.add], the answer you get is `3.0 : Num (Fraction *)`. ## @@ -191,9 +196,9 @@ interface Num ## ## If this default of [I64] is not big enough for your purposes, ## you can add an `i128` to the end of the number literal, like so: -## -## >>> Num.toStr 5_000_000_000i128 -## +## ``` +## Num.toStr 5_000_000_000i128 +## ``` ## This `i128` suffix specifies that you want this number literal to be ## an [I128] instead of a `Num *`. All the other numeric types have ## suffixes just like `i128`; here are some other examples: @@ -259,15 +264,11 @@ Num range := range ## ## All number literals without decimal points are compatible with [Int] values. ## -## >>> 1 -## -## >>> 0 -## ## You can optionally put underscores in your [Int] literals. ## They have no effect on the number's value, but can make large numbers easier to read. -## -## >>> 1_000_000 -## +## ``` +## 1_000_000 +## ``` ## Integers come in two flavors: *signed* and *unsigned*. ## ## * *Unsigned* integers can never be negative. The lowest value they can hold is zero. @@ -342,16 +343,16 @@ Int range : Num (Integer range) ## ## If you don't specify a type, Roc will default to using [Dec] because it's ## the least error-prone overall. For example, suppose you write this: -## -## wasItPrecise = 0.1 + 0.2 == 0.3 -## +## ``` +## wasItPrecise = 0.1 + 0.2 == 0.3 +## ``` ## The value of `wasItPrecise` here will be `Bool.true`, because Roc uses [Dec] ## by default when there are no types specified. ## ## In contrast, suppose we use `f32` or `f64` for one of these numbers: -## -## wasItPrecise = 0.1f64 + 0.2 == 0.3 -## +## ``` +## wasItPrecise = 0.1f64 + 0.2 == 0.3 +## ``` ## Here, `wasItPrecise` will be `Bool.false` because the entire calculation will have ## been done in a base-2 floating point calculation, which causes noticeable ## precision loss in this case. @@ -492,15 +493,14 @@ Dec : Num (FloatingPoint Decimal) ## ## This is the same as calling `Num.format {}` - so for more details on ## exact formatting, see `Num.format`. -## -## >>> Num.toStr 42 -## +## ``` +## Num.toStr 42 +## ``` ## Only [Frac] values will include a decimal point, and they will always include one. -## -## >>> Num.toStr 4.2 -## -## >>> Num.toStr 4.0 -## +## ``` +## Num.toStr 4.2 +## Num.toStr 4.0 +## ``` ## When this function is given a non-[finite](Num.isFinite) ## [F64] or [F32] value, the returned string will be `"NaN"`, `"∞"`, or `"-∞"`. ## @@ -510,6 +510,8 @@ intCast : Int a -> Int b bytesToU16Lowlevel : List U8, Nat -> U16 bytesToU32Lowlevel : List U8, Nat -> U32 +bytesToU64Lowlevel : List U8, Nat -> U64 +bytesToU128Lowlevel : List U8, Nat -> U128 bytesToU16 : List U8, Nat -> Result U16 [OutOfBounds] bytesToU16 = \bytes, index -> @@ -531,6 +533,26 @@ bytesToU32 = \bytes, index -> else Err OutOfBounds +bytesToU64 : List U8, Nat -> Result U64 [OutOfBounds] +bytesToU64 = \bytes, index -> + # we need at least 7 more bytes + offset = 7 + + if index + offset < List.len bytes then + Ok (bytesToU64Lowlevel bytes index) + else + Err OutOfBounds + +bytesToU128 : List U8, Nat -> Result U128 [OutOfBounds] +bytesToU128 = \bytes, index -> + # we need at least 15 more bytes + offset = 15 + + if index + offset < List.len bytes then + Ok (bytesToU128Lowlevel bytes index) + else + Err OutOfBounds + compare : Num a, Num a -> [LT, EQ, GT] ## Returns `Bool.true` if the first number is less than the second. @@ -539,9 +561,10 @@ compare : Num a, Num a -> [LT, EQ, GT] ## ## If either argument is [*NaN*](Num.isNaN), returns `Bool.false` no matter what. (*NaN* ## is [defined to be unordered](https://en.wikipedia.org/wiki/NaN#Comparison_with_NaN).) -## -## >>> 5 -## >>> |> Num.isLt 6 +## ``` +## 5 +## |> Num.isLt 6 +## ``` isLt : Num a, Num a -> Bool ## Returns `Bool.true` if the first number is greater than the second. @@ -550,9 +573,10 @@ isLt : Num a, Num a -> Bool ## ## If either argument is [*NaN*](Num.isNaN), returns `Bool.false` no matter what. (*NaN* ## is [defined to be unordered](https://en.wikipedia.org/wiki/NaN#Comparison_with_NaN).) -## -## >>> 6 -## >>> |> Num.isGt 5 +## ``` +## 6 +## |> Num.isGt 5 +## ``` isGt : Num a, Num a -> Bool ## Returns `Bool.true` if the first number is less than or equal to the second. @@ -601,15 +625,15 @@ toFrac : Num * -> Frac * ## * For a positive number, returns the same number. ## * For a negative number, returns the same number except positive. ## * For zero, returns zero. +## ``` +## Num.abs 4 ## -## >>> Num.abs 4 +## Num.abs -2.5 ## -## >>> Num.abs -2.5 -## -## >>> Num.abs 0 -## -## >>> Num.abs 0.0 +## Num.abs 0 ## +## Num.abs 0.0 +## ``` ## This is safe to use with any [Frac], but it can cause overflow when used with certain [Int] values. ## ## For example, calling #Num.abs on the lowest value of a signed integer (such as [Num.minI64] or [Num.minI32]) will cause overflow. @@ -620,15 +644,15 @@ toFrac : Num * -> Frac * abs : Num a -> Num a ## Return a negative number when given a positive one, and vice versa. +## ``` +## Num.neg 5 ## -## >>> Num.neg 5 +## Num.neg -2.5 ## -## >>> Num.neg -2.5 -## -## >>> Num.neg 0 -## -## >>> Num.neg 0.0 +## Num.neg 0 ## +## Num.neg 0.0 +## ``` ## This is safe to use with any [Frac], but it can cause overflow when used with certain [Int] values. ## ## For example, calling #Num.neg on the lowest value of a signed integer (such as [Num.minI64] or [Num.minI32]) will cause overflow. @@ -645,16 +669,16 @@ neg : Num a -> Num a ## (To add an [Int] and a [Frac], first convert one so that they both have the same type. There are functions in this module that can convert both [Int] to [Frac] and the other way around.) ## ## `a + b` is shorthand for `Num.add a b`. +## ``` +## 5 + 7 ## -## >>> 5 + 7 -## -## >>> Num.add 5 7 -## +## Num.add 5 7 +## ``` ## `Num.add` can be convenient in pipelines. -## -## >>> Frac.pi -## >>> |> Num.add 1.0 -## +## ``` +## Frac.pi +## |> Num.add 1.0 +## ``` ## If the answer to this operation can't fit in the return value (e.g. an ## [I8] answer that's higher than 127 or lower than -128), the result is an ## *overflow*. For [F64] and [F32], overflow results in an answer of either @@ -666,16 +690,16 @@ add : Num a, Num a -> Num a ## (To subtract an [Int] and a [Frac], first convert one so that they both have the same type. There are functions in this module that can convert both [Int] to [Frac] and the other way around.) ## ## `a - b` is shorthand for `Num.sub a b`. +## ``` +## 7 - 5 ## -## >>> 7 - 5 -## -## >>> Num.sub 7 5 -## +## Num.sub 7 5 +## ``` ## `Num.sub` can be convenient in pipelines. -## -## >>> Frac.pi -## >>> |> Num.sub 2.0 -## +## ``` +## Frac.pi +## |> Num.sub 2.0 +## ``` ## If the answer to this operation can't fit in the return value (e.g. an ## [I8] answer that's higher than 127 or lower than -128), the result is an ## *overflow*. For [F64] and [F32], overflow results in an answer of either @@ -687,16 +711,18 @@ sub : Num a, Num a -> Num a ## (To multiply an [Int] and a [Frac], first convert one so that they both have the same type. There are functions in this module that can convert both [Int] to [Frac] and the other way around.) ## ## `a * b` is shorthand for `Num.mul a b`. +## ``` +## 5 * 7 ## -## >>> 5 * 7 -## -## >>> Num.mul 5 7 +## Num.mul 5 7 +## ``` ## ## `Num.mul` can be convenient in pipelines. ## -## >>> Frac.pi -## >>> |> Num.mul 2.0 -## +## ``` +## Frac.pi +## |> Num.mul 2.0 +## ``` ## If the answer to this operation can't fit in the return value (e.g. an ## [I8] answer that's higher than 127 or lower than -128), the result is an ## *overflow*. For [F64] and [F32], overflow results in an answer of either @@ -731,14 +757,15 @@ atan : Frac a -> Frac a ## > this standard, deviating from these rules has a significant performance ## > cost! Since the most common reason to choose [F64] or [F32] over [Dec] is ## > access to hardware-accelerated performance, Roc follows these rules exactly. +## ``` +## Num.sqrt 4.0 ## -## >>> Num.sqrt 4.0 +## Num.sqrt 1.5 ## -## >>> Num.sqrt 1.5 +## Num.sqrt 0.0 ## -## >>> Num.sqrt 0.0 -## -## >>> Num.sqrt -4.0f64 +## Num.sqrt -4.0f64 +## ``` sqrt : Frac a -> Frac a sqrtChecked : Frac a -> Result (Frac a) [SqrtOfNegative] @@ -748,6 +775,7 @@ sqrtChecked = \x -> else Ok (Num.sqrt x) +## Natural logarithm log : Frac a -> Frac a logChecked : Frac a -> Result (Frac a) [LogNeedsPositive] @@ -778,15 +806,16 @@ logChecked = \x -> ## ## To divide an [Int] and a [Frac], first convert the [Int] to a [Frac] using ## one of the functions in this module like #toDec. +## ``` +## 5.0 / 7.0 ## -## >>> 5.0 / 7.0 -## -## >>> Num.div 5 7 -## +## Num.div 5 7 +## ``` ## `Num.div` can be convenient in pipelines. -## -## >>> Num.pi -## >>> |> Num.div 2.0 +## ``` +## Num.pi +## |> Num.div 2.0 +## ``` div : Frac a, Frac a -> Frac a divChecked : Frac a, Frac a -> Result (Frac a) [DivByZero] @@ -812,15 +841,15 @@ divCeilChecked = \a, b -> ## Division by zero is undefined in mathematics. As such, you should make ## sure never to pass zero as the denomaintor to this function! If you do, ## it will crash. +## ``` +## 5 // 7 ## -## >>> 5 // 7 +## Num.divTrunc 5 7 ## -## >>> Num.divTrunc 5 7 -## -## >>> 8 // -3 -## -## >>> Num.divTrunc 8 -3 +## 8 // -3 ## +## Num.divTrunc 8 -3 +## ``` divTrunc : Int a, Int a -> Int a divTruncChecked : Int a, Int a -> Result (Int a) [DivByZero] @@ -833,14 +862,15 @@ divTruncChecked = \a, b -> ## Obtain the remainder (truncating modulo) from the division of two integers. ## ## `a % b` is shorthand for `Num.rem a b`. +## ``` +## 5 % 7 ## -## >>> 5 % 7 +## Num.rem 5 7 ## -## >>> Num.rem 5 7 +## -8 % -3 ## -## >>> -8 % -3 -## -## >>> Num.rem -8 -3 +## Num.rem -8 -3 +## ``` rem : Int a, Int a -> Int a remChecked : Int a, Int a -> Result (Int a) [DivByZero] @@ -860,24 +890,24 @@ bitwiseOr : Int a, Int a -> Int a ## ## The least significant bits always become 0. This means that shifting left is ## like multiplying by factors of two for unsigned integers. +## ``` +## shiftLeftBy 0b0000_0011 2 == 0b0000_1100 ## -## >>> shiftLeftBy 0b0000_0011 2 == 0b0000_1100 -## -## >>> 0b0000_0101 |> shiftLeftBy 2 == 0b0000_1100 -## +## 0b0000_0101 |> shiftLeftBy 2 == 0b0000_1100 +## ``` ## In some languages `shiftLeftBy` is implemented as a binary operator `<<`. shiftLeftBy : Int a, U8 -> Int a ## Bitwise arithmetic shift of a number by another ## ## The most significant bits are copied from the current. +## ``` +## shiftRightBy 0b0000_0011 2 == 0b0000_1100 ## -## >>> shiftRightBy 0b0000_0011 2 == 0b0000_1100 -## -## >>> 0b0001_0100 |> shiftRightBy 2 == 0b0000_0101 -## -## >>> 0b1001_0000 |> shiftRightBy 2 == 0b1110_0100 +## 0b0001_0100 |> shiftRightBy 2 == 0b0000_0101 ## +## 0b1001_0000 |> shiftRightBy 2 == 0b1110_0100 +## ``` ## In some languages `shiftRightBy` is implemented as a binary operator `>>>`. shiftRightBy : Int a, U8 -> Int a @@ -885,13 +915,13 @@ shiftRightBy : Int a, U8 -> Int a ## ## The most significant bits always become 0. This means that shifting left is ## like dividing by factors of two for unsigned integers. +## ``` +## shiftRightBy 0b0010_1000 2 == 0b0000_1010 ## -## >>> shiftRightBy 0b0010_1000 2 == 0b0000_1010 -## -## >>> 0b0010_1000 |> shiftRightBy 2 == 0b0000_1010 -## -## >>> 0b1001_0000 |> shiftRightBy 2 == 0b0010_0100 +## 0b0010_1000 |> shiftRightBy 2 == 0b0000_1010 ## +## 0b1001_0000 |> shiftRightBy 2 == 0b0010_0100 +## ``` ## In some languages `shiftRightBy` is implemented as a binary operator `>>`. shiftRightZfBy : Int a, U8 -> Int a @@ -912,21 +942,60 @@ pow : Frac a, Frac a -> Frac a ## ## For a [Frac] alternative to this function, which supports negative exponents, ## see #Num.exp. +## ``` +## Num.exp 5 0 ## -## >>> Num.exp 5 0 +## Num.exp 5 1 ## -## >>> Num.exp 5 1 -## -## >>> Num.exp 5 2 -## -## >>> Num.exp 5 6 +## Num.exp 5 2 ## +## Num.exp 5 6 +## ``` ## ## Performance Notes ## ## Be careful! It is very easy for this function to produce an answer ## so large it causes an overflow. powInt : Int a, Int a -> Int a +## Counts the number of most-significant (leading in a big-Endian sense) zeroes in an integer. +## +## ``` +## Num.countLeadingZeroBits 0b0001_1100u8 +## +## 3 +## +## Num.countLeadingZeroBits 0b0000_0000u8 +## +## 8 +## ``` +countLeadingZeroBits : Int a -> Nat + +## Counts the number of least-significant (trailing in a big-Endian sense) zeroes in an integer. +## +## ``` +## Num.countTrailingZeroBits 0b0001_1100u8 +## +## 2 +## +## Num.countTrailingZeroBits 0b0000_0000u8 +## +## 8 +## ``` +countTrailingZeroBits : Int a -> Nat + +## Counts the number of set bits in an integer. +## +## ``` +## Num.countOneBits 0b0001_1100u8 +## +## 3 +## +## Num.countOneBits 0b0000_0000u8 +## +## 0 +## ``` +countOneBits : Int a -> Nat + addWrap : Int range, Int range -> Int range ## Add two numbers, clamping on the maximum representable number rather than @@ -1261,164 +1330,3 @@ toU128Checked : Int * -> Result U128 [OutOfBounds] toNatChecked : Int * -> Result Nat [OutOfBounds] toF32Checked : Num * -> Result F32 [OutOfBounds] toF64Checked : Num * -> Result F64 [OutOfBounds] - -# Special Floating-Point operations -## When given a [F64] or [F32] value, returns `Bool.false` if that value is -## [*NaN*](Num.isNaN), ∞ or -∞, and `Bool.true` otherwise. -## -## Always returns `Bool.true` when given a [Dec]. -## -## This is the opposite of #isInfinite, except when given [*NaN*](Num.isNaN). Both -## #isFinite and #isInfinite return `Bool.false` for [*NaN*](Num.isNaN). -# isFinite : Frac * -> Bool -## When given a [F64] or [F32] value, returns `Bool.true` if that value is either -## ∞ or -∞, and `Bool.false` otherwise. -## -## Always returns `Bool.false` when given a [Dec]. -## -## This is the opposite of #isFinite, except when given [*NaN*](Num.isNaN). Both -## #isFinite and #isInfinite return `Bool.false` for [*NaN*](Num.isNaN). -# isInfinite : Frac * -> Bool -## When given a [F64] or [F32] value, returns `Bool.true` if that value is -## *NaN* ([not a number](https://en.wikipedia.org/wiki/NaN)), and `Bool.false` otherwise. -## -## Always returns `Bool.false` when given a [Dec]. -## -## >>> Num.isNaN 12.3 -## -## >>> Num.isNaN (Num.pow -1 0.5) -## -## *NaN* is unusual from other numberic values in that: -## * *NaN* is not equal to any other number, even itself. [Bool.isEq] always returns `Bool.false` if either argument is *NaN*. -## * *NaN* has no ordering, so [isLt], [isLte], [isGt], and [isGte] always return `Bool.false` if either argument is *NaN*. -## -## These rules come from the [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754) -## floating point standard. Because almost all modern processors are built to -## this standard, deviating from these rules has a significant performance -## cost! Since the most common reason to choose [F64] or [F32] over [Dec] is -## access to hardware-accelerated performance, Roc follows these rules exactly. -## -## Note that you should never put a *NaN* into a [Set], or use it as the key in -## a [Dict]. The result is entries that can never be removed from those -## collections! See the documentation for [Set.insert] and [Dict.insert] for details. -# isNaN : Frac * -> Bool -## Returns the higher of two numbers. -## -## If either argument is [*NaN*](Num.isNaN), returns `Bool.false` no matter what. (*NaN* -## is [defined to be unordered](https://en.wikipedia.org/wiki/NaN#Comparison_with_NaN).) -# max : Num a, Num a -> Num a -## Returns the lower of two numbers. -## -## If either argument is [*NaN*](Num.isNaN), returns `Bool.false` no matter what. (*NaN* -## is [defined to be unordered](https://en.wikipedia.org/wiki/NaN#Comparison_with_NaN).) -# min : Num a, Num a -> Num a -# Branchless implementation that works for all numeric types: -# -# let is_lt = arg1 < arg2; -# let is_eq = arg1 == arg2; -# return (is_lt as i8 - is_eq as i8) + 1; -# -# 1, 1 -> (0 - 1) + 1 == 0 # Eq -# 5, 1 -> (0 - 0) + 1 == 1 # Gt -# 1, 5 -> (1 - 0) + 1 == 2 # Lt -## Returns `Lt` if the first number is less than the second, `Gt` if -## the first is greater than the second, and `Eq` if they're equal. -## -## Although this can be passed to `List.sort`, you'll get better performance -## by using `List.sortAsc` or `List.sortDesc` instead. -# compare : Num a, Num a -> [Lt, Eq, Gt] -## [Endianness](https://en.wikipedia.org/wiki/Endianness) -# Endi : [Big, Little, Native] -## The `Endi` argument does not matter for [U8] and [I8], since they have -## only one byte. -# toBytes : Num *, Endi -> List U8 -## when Num.parseBytes bytes Big is -## Ok { val: f64, rest } -> ... -## Err (ExpectedNum (Frac Binary64)) -> ... -# parseBytes : List U8, Endi -> Result { val : Num a, rest : List U8 } [ExpectedNum a]* -## when Num.fromBytes bytes Big is -## Ok f64 -> ... -## Err (ExpectedNum (Frac Binary64)) -> ... -# fromBytes : List U8, Endi -> Result (Num a) [ExpectedNum a]* -# Bit shifts -## [Logical bit shift](https://en.wikipedia.org/wiki/Bitwise_operation#Logical_shift) left. -## -## `a << b` is shorthand for `Num.shl a b`. -# shl : Int a, Int a -> Int a -## [Arithmetic bit shift](https://en.wikipedia.org/wiki/Bitwise_operation#Arithmetic_shift) left. -## -## This is called `shlWrap` because any bits shifted -## off the beginning of the number will be wrapped around to -## the end. (In contrast, #shl replaces discarded bits with zeroes.) -# shlWrap : Int a, Int a -> Int a -## [Logical bit shift](https://en.wikipedia.org/wiki/Bitwise_operation#Logical_shift) right. -## -## `a >> b` is shorthand for `Num.shr a b`. -# shr : Int a, Int a -> Int a -## [Arithmetic bit shift](https://en.wikipedia.org/wiki/Bitwise_operation#Arithmetic_shift) right. -## -## This is called `shrWrap` because any bits shifted -## off the end of the number will be wrapped around to -## the beginning. (In contrast, #shr replaces discarded bits with zeroes.) -# shrWrap : Int a, Int a -> Int a -# ## Convert a number into a [Str], formatted with the given options. -# ## -# ## Default options: -# ## * `base: Decimal` -# ## * `notation: Standard` -# ## * `decimalMark: HideForIntegers "."` -# ## * `decimalDigits: { min: 0, max: All }` -# ## * `minIntDigits: 1` -# ## * `wholeSep: { mark: ",", places: 3 }` -# ## -# ## ## Options -# ## -# ## -# ## ### decimalMark -# ## -# ## * `AlwaysShow` always shows the decimal mark, no matter what. -# ## * `HideForIntegers` hides the decimal mark if all the numbers after the decimal mark are 0. -# ## -# ## The [Str] included in either of these represents the mark itself. -# ## -# ## ### `decimalDigits -# ## -# ## With 0 decimal digits, the decimal mark will still be rendered if -# ## `decimalMark` is set to `AlwaysShow`. -# ## -# ## If `max` is less than `min`, then first the number will be truncated to `max` -# ## digits, and then zeroes will be added afterwards until it reaches `min` digits. -# ## -# ## >>> Num.format 1.23 { decPlaces: 0, decPointVis: AlwaysShow } -# ## -# ## ### minIntDigits -# ## -# ## If the integer portion of number is fewer than this many digits, zeroes will -# ## be added in front of it until there are at least `minWholeDigits` digits. -# ## -# ## If this is set to zero, then numbers less than 1 will begin with `"."` -# ## rather than `"0."`. -# ## -# ## ### wholeSep -# ## -# ## Examples: -# ## -# ## In some countries (e.g. USA and UK), a comma is used to separate thousands: -# ## >>> Num.format 1_000_000 { pf: Decimal, wholeSep: { mark: ",", places: 3 } } -# ## -# ## Sometimes when rendering bits, it's nice to group them into groups of 4: -# ## >>> Num.format 1_000_000 { pf: Binary, wholeSep: { mark: " ", places: 4 } } -# ## -# ## It's also common to render hexadecimal in groups of 2: -# ## >>> Num.format 1_000_000 { pf: Hexadecimal, wholeSep: { mark: " ", places: 2 } } -# format : -# Num *, -# { -# base ? [Decimal, Hexadecimal, Octal, Binary], -# notation ? [Standard, Scientific], -# decimalMark ? [AlwaysShow Str, HideForIntegers], -# decimalDigits ? { min : U16, max : [All, Trunc U16, Round U16, Floor U16, Ceil U16] }, -# minWholeDigits ? U16, -# wholeSep ? { mark : Str, places : U64 } -# } -# -> Str diff --git a/crates/compiler/builtins/roc/Result.roc b/crates/compiler/builtins/roc/Result.roc index 967c901567..e28c216bf6 100644 --- a/crates/compiler/builtins/roc/Result.roc +++ b/crates/compiler/builtins/roc/Result.roc @@ -7,8 +7,9 @@ interface Result Result ok err : [Ok ok, Err err] ## Return `Bool.true` if the result indicates a success, else return `Bool.false` -## -## >>> Result.isOk (Ok 5) +## ``` +## Result.isOk (Ok 5) +## ``` isOk : Result ok err -> Bool isOk = \result -> when result is @@ -16,8 +17,9 @@ isOk = \result -> Err _ -> Bool.false ## Return `Bool.true` if the result indicates a failure, else return `Bool.false` -## -## >>> Result.isErr (Err "uh oh") +## ``` +## Result.isErr (Err "uh oh") +## ``` isErr : Result ok err -> Bool isErr = \result -> when result is @@ -26,10 +28,10 @@ isErr = \result -> ## If the result is `Ok`, return the value it holds. Otherwise, return ## the given default value. -## -## >>> Result.withDefault (Ok 7) 42 -## -## >>> Result.withDefault (Err "uh oh") 42 +## ``` +## Result.withDefault (Ok 7) 42 +## Result.withDefault (Err "uh oh") 42 +## ``` withDefault : Result ok err, ok -> ok withDefault = \result, default -> when result is @@ -40,10 +42,10 @@ withDefault = \result, default -> ## function on it. Then return a new `Ok` holding the transformed value. ## ## (If the result is `Err`, this has no effect. Use [mapErr] to transform an `Err`.) -## -## >>> Result.map (Ok 12) Num.negate -## -## >>> Result.map (Err "yipes!") Num.negate +## ``` +## Result.map (Ok 12) Num.negate +## Result.map (Err "yipes!") Num.negate +## ``` ## ## `map` functions like this are common in Roc, and they all work similarly. ## See for example [List.map], `Set.map`, and `Dict.map`. @@ -57,10 +59,10 @@ map = \result, transform -> ## function on it. Then return a new `Err` holding the transformed value. ## ## (If the result is `Ok`, this has no effect. Use [map] to transform an `Ok`.) -## -## >>> Result.mapErr (Err "yipes!") Str.isEmpty -## -## >>> Result.mapErr (Ok 12) Str.isEmpty +## ``` +## Result.mapErr (Err "yipes!") Str.isEmpty +## Result.mapErr (Ok 12) Str.isEmpty +## ``` mapErr : Result ok a, (a -> b) -> Result ok b mapErr = \result, transform -> when result is @@ -71,10 +73,10 @@ mapErr = \result, transform -> ## function on the value the `Ok` holds. Then return that new result. ## ## (If the result is `Err`, this has no effect. Use `onErr` to transform an `Err`.) -## -## >>> Result.try (Ok -1) \num -> if num < 0 then Err "negative!" else Ok -num -## -## >>> Result.try (Err "yipes!") \num -> if num < 0 then Err "negative!" else Ok -num +## ``` +## Result.try (Ok -1) \num -> if num < 0 then Err "negative!" else Ok -num +## Result.try (Err "yipes!") \num -> if num < 0 then Err "negative!" else Ok -num +## ``` try : Result a err, (a -> Result b err) -> Result b err try = \result, transform -> when result is @@ -85,10 +87,10 @@ try = \result, transform -> ## function on the value the `Err` holds. Then return that new result. ## ## (If the result is `Ok`, this has no effect. Use `try` to transform an `Ok`.) -## -## >>> Result.onErr (Ok 10) \errorNum -> Str.toNat errorNum -## -## >>> Result.onErr (Err "42") \errorNum -> Str.toNat errorNum +## ``` +## Result.onErr (Ok 10) \errorNum -> Str.toNat errorNum +## Result.onErr (Err "42") \errorNum -> Str.toNat errorNum +## ``` onErr : Result a err, (err -> Result a otherErr) -> Result a otherErr onErr = \result, transform -> when result is diff --git a/crates/compiler/builtins/roc/Str.roc b/crates/compiler/builtins/roc/Str.roc index 3e5d7090e3..53fd231c44 100644 --- a/crates/compiler/builtins/roc/Str.roc +++ b/crates/compiler/builtins/roc/Str.roc @@ -4,11 +4,11 @@ ## ## Unicode can represent text values which span multiple languages, symbols, and emoji. ## Here are some valid Roc strings: -## +## ``` ## "Roc!" ## "鹏" ## "🕊" -## +## ``` ## Every Unicode string is a sequence of [extended grapheme clusters](http://www.unicode.org/glossary/#extended_grapheme_cluster). ## An extended grapheme cluster represents what a person reading a string might ## call a "character" - like "A" or "ö" or "👩‍👩‍👦‍👦". @@ -17,11 +17,11 @@ ## term "grapheme" as a shorthand for the more precise "extended grapheme cluster." ## ## You can get the number of graphemes in a string by calling `Str.countGraphemes` on it: -## -## Str.countGraphemes "Roc!" -## Str.countGraphemes "折り紙" -## Str.countGraphemes "🕊" -## +## ``` +## Str.countGraphemes "Roc!" +## Str.countGraphemes "折り紙" +## Str.countGraphemes "🕊" +## ``` ## > The `countGraphemes` function walks through the entire string to get its answer, ## > so if you want to check whether a string is empty, you'll get much better performance ## > by calling `Str.isEmpty myStr` instead of `Str.countGraphemes myStr == 0`. @@ -31,9 +31,9 @@ ## If you put a `\` in a Roc string literal, it begins an *escape sequence*. ## An escape sequence is a convenient way to insert certain strings into other strings. ## For example, suppose you write this Roc string: -## -## "I took the one less traveled by,\nAnd that has made all the difference." -## +## ``` +## "I took the one less traveled by,\nAnd that has made all the difference." +## ``` ## The `"\n"` in the middle will insert a line break into this string. There are ## other ways of getting a line break in there, but `"\n"` is the most common. ## @@ -58,12 +58,11 @@ ## * `\v` - [vertical tab](https://en.wikipedia.org/wiki/Tab_key#Tab_characters) ## ## You can also use escape sequences to insert named strings into other strings, like so: -## -## name = "Lee" -## city = "Roctown" -## -## greeting = "Hello there, \(name)! Welcome to \(city)." -## +## ``` +## name = "Lee" +## city = "Roctown" +## greeting = "Hello there, \(name)! Welcome to \(city)." +## ``` ## Here, `greeting` will become the string `"Hello there, Lee! Welcome to Roctown."`. ## This is known as [string interpolation](https://en.wikipedia.org/wiki/String_interpolation), ## and you can use it as many times as you like inside a string. The name @@ -138,16 +137,18 @@ Utf8ByteProblem : [ Utf8Problem : { byteIndex : Nat, problem : Utf8ByteProblem } ## Returns [Bool.true] if the string is empty, and [Bool.false] otherwise. -## -## expect Str.isEmpty "hi!" == Bool.false -## expect Str.isEmpty "" == Bool.true +## ``` +## expect Str.isEmpty "hi!" == Bool.false +## expect Str.isEmpty "" == Bool.true +## ``` isEmpty : Str -> Bool ## Concatenates two strings together. -## -## expect Str.concat "ab" "cd" == "abcd" -## expect Str.concat "hello" "" == "hello" -## expect Str.concat "" "" == "" +## ``` +## expect Str.concat "ab" "cd" == "abcd" +## expect Str.concat "hello" "" == "hello" +## expect Str.concat "" "" == "" +## ``` concat : Str, Str -> Str ## Returns a string of the specified capacity without any content. @@ -155,9 +156,10 @@ withCapacity : Nat -> Str ## Combines a [List] of strings into a single string, with a separator ## string in between each. -## -## expect Str.joinWith ["one", "two", "three"] ", " == "one, two, three" -## expect Str.joinWith ["1", "2", "3", "4"] "." == "1.2.3.4" +## ``` +## expect Str.joinWith ["one", "two", "three"] ", " == "one, two, three" +## expect Str.joinWith ["1", "2", "3", "4"] "." == "1.2.3.4" +## ``` joinWith : List Str, Str -> Str ## Split a string around a separator. @@ -165,20 +167,22 @@ joinWith : List Str, Str -> Str ## Passing `""` for the separator is not useful; ## it returns the original string wrapped in a [List]. To split a string ## into its individual [graphemes](https://stackoverflow.com/a/27331885/4200103), use `Str.graphemes` -## -## expect Str.split "1,2,3" "," == ["1","2","3"] -## expect Str.split "1,2,3" "" == ["1,2,3"] +## ``` +## expect Str.split "1,2,3" "," == ["1","2","3"] +## expect Str.split "1,2,3" "" == ["1,2,3"] +## ``` split : Str, Str -> List Str ## Repeats a string the given number of times. -## -## expect Str.repeat "z" 3 == "zzz" -## expect Str.repeat "na" 8 == "nananananananana" -## +## ``` +## expect Str.repeat "z" 3 == "zzz" +## expect Str.repeat "na" 8 == "nananananananana" +## ``` ## Returns `""` when given `""` for the string or `0` for the count. -## -## expect Str.repeat "" 10 == "" -## expect Str.repeat "anything" 0 == "" +## ``` +## expect Str.repeat "" 10 == "" +## expect Str.repeat "anything" 0 == "" +## ``` repeat : Str, Nat -> Str ## Counts the number of [extended grapheme clusters](http://www.unicode.org/glossary/#extended_grapheme_cluster) @@ -186,11 +190,11 @@ repeat : Str, Nat -> Str ## ## Note that the number of extended grapheme clusters can be different from the number ## of visual glyphs rendered! Consider the following examples: -## -## expect Str.countGraphemes "Roc" == 3 -## expect Str.countGraphemes "👩‍👩‍👦‍👦" == 4 -## expect Str.countGraphemes "🕊" == 1 -## +## ``` +## expect Str.countGraphemes "Roc" == 3 +## expect Str.countGraphemes "👩‍👩‍👦‍👦" == 4 +## expect Str.countGraphemes "🕊" == 1 +## ``` ## Note that "👩‍👩‍👦‍👦" takes up 4 graphemes (even though visually it appears as a single ## glyph) because under the hood it's represented using an emoji modifier sequence. ## In contrast, "🕊" only takes up 1 grapheme because under the hood it's represented @@ -205,11 +209,11 @@ graphemes : Str -> List Str ## ## If the given string is empty, or if the given [U32] is not a valid ## code point, returns [Bool.false]. -## -## expect Str.startsWithScalar "鹏 means 'roc'" 40527 # "鹏" is Unicode scalar 40527 -## expect !Str.startsWithScalar "9" 9 # the Unicode scalar for "9" is 57, not 9 -## expect !Str.startsWithScalar "" 40527 -## +## ``` +## expect Str.startsWithScalar "鹏 means 'roc'" 40527 # "鹏" is Unicode scalar 40527 +## expect !Str.startsWithScalar "9" 9 # the Unicode scalar for "9" is 57, not 9 +## expect !Str.startsWithScalar "" 40527 +## ``` ## **Performance Note:** This runs slightly faster than [Str.startsWith], so ## if you want to check whether a string begins with something that's representable ## in a single code point, you can use (for example) `Str.startsWithScalar '鹏'` @@ -225,36 +229,39 @@ startsWithScalar : Str, U32 -> Bool ## ## (Roc strings contain only scalar values, not [surrogate code points](https://unicode.org/glossary/#surrogate_code_point), ## so this is equivalent to returning a list of the string's [code points](https://unicode.org/glossary/#code_point).) -## -## expect Str.toScalars "Roc" == [82, 111, 99] -## expect Str.toScalars "鹏" == [40527] -## expect Str.toScalars "சி" == [2970, 3007] -## expect Str.toScalars "🐦" == [128038] -## expect Str.toScalars "👩‍👩‍👦‍👦" == [128105, 8205, 128105, 8205, 128102, 8205, 128102] -## expect Str.toScalars "I ♥ Roc" == [73, 32, 9829, 32, 82, 111, 99] -## expect Str.toScalars "" == [] +## ``` +## expect Str.toScalars "Roc" == [82, 111, 99] +## expect Str.toScalars "鹏" == [40527] +## expect Str.toScalars "சி" == [2970, 3007] +## expect Str.toScalars "🐦" == [128038] +## expect Str.toScalars "👩‍👩‍👦‍👦" == [128105, 8205, 128105, 8205, 128102, 8205, 128102] +## expect Str.toScalars "I ♥ Roc" == [73, 32, 9829, 32, 82, 111, 99] +## expect Str.toScalars "" == [] +## ``` toScalars : Str -> List U32 ## Returns a [List] of the string's [U8] UTF-8 [code units](https://unicode.org/glossary/#code_unit). ## (To split the string into a [List] of smaller [Str] values instead of [U8] values, ## see [Str.split].) -## -## expect Str.toUtf8 "Roc" == [82, 111, 99] -## expect Str.toUtf8 "鹏" == [233, 185, 143] -## expect Str.toUtf8 "சி" == [224, 174, 154, 224, 174, 191] -## expect Str.toUtf8 "🐦" == [240, 159, 144, 166] +## ``` +## expect Str.toUtf8 "Roc" == [82, 111, 99] +## expect Str.toUtf8 "鹏" == [233, 185, 143] +## expect Str.toUtf8 "சி" == [224, 174, 154, 224, 174, 191] +## expect Str.toUtf8 "🐦" == [240, 159, 144, 166] +## ``` toUtf8 : Str -> List U8 ## Converts a [List] of [U8] UTF-8 [code units](https://unicode.org/glossary/#code_unit) to a string. ## ## Returns `Err` if the given bytes are invalid UTF-8, and returns `Ok ""` when given `[]`. -## -## expect Str.fromUtf8 [82, 111, 99] == Ok "Roc" -## expect Str.fromUtf8 [233, 185, 143] == Ok "鹏" -## expect Str.fromUtf8 [224, 174, 154, 224, 174, 191] == Ok "சி" -## expect Str.fromUtf8 [240, 159, 144, 166] == Ok "🐦" -## expect Str.fromUtf8 [] == Ok "" -## expect Str.fromUtf8 [255] |> Result.isErr +## ``` +## expect Str.fromUtf8 [82, 111, 99] == Ok "Roc" +## expect Str.fromUtf8 [233, 185, 143] == Ok "鹏" +## expect Str.fromUtf8 [224, 174, 154, 224, 174, 191] == Ok "சி" +## expect Str.fromUtf8 [240, 159, 144, 166] == Ok "🐦" +## expect Str.fromUtf8 [] == Ok "" +## expect Str.fromUtf8 [255] |> Result.isErr +## ``` fromUtf8 : List U8 -> Result Str [BadUtf8 Utf8ByteProblem Nat] fromUtf8 = \bytes -> result = fromUtf8RangeLowlevel bytes 0 (List.len bytes) @@ -266,8 +273,9 @@ fromUtf8 = \bytes -> ## Encode part of a [List] of [U8] UTF-8 [code units](https://unicode.org/glossary/#code_unit) ## into a [Str] -## -## expect Str.fromUtf8Range [72, 105, 80, 103] { start : 0, count : 2 } == Ok "Hi" +## ``` +## expect Str.fromUtf8Range [72, 105, 80, 103] { start : 0, count : 2 } == Ok "Hi" +## ``` fromUtf8Range : List U8, { start : Nat, count : Nat } -> Result Str [BadUtf8 Utf8ByteProblem Nat, OutOfBounds] fromUtf8Range = \bytes, config -> if config.start + config.count <= List.len bytes then @@ -290,57 +298,65 @@ FromUtf8Result : { fromUtf8RangeLowlevel : List U8, Nat, Nat -> FromUtf8Result ## Check if the given [Str] starts with a value. -## -## expect Str.startsWith "ABC" "A" == Bool.true -## expect Str.startsWith "ABC" "X" == Bool.false +## ``` +## expect Str.startsWith "ABC" "A" == Bool.true +## expect Str.startsWith "ABC" "X" == Bool.false +## ``` startsWith : Str, Str -> Bool ## Check if the given [Str] ends with a value. -## -## expect Str.endsWith "ABC" "C" == Bool.true -## expect Str.endsWith "ABC" "X" == Bool.false +## ``` +## expect Str.endsWith "ABC" "C" == Bool.true +## expect Str.endsWith "ABC" "X" == Bool.false +## ``` endsWith : Str, Str -> Bool ## Return the [Str] with all whitespace removed from both the beginning ## as well as the end. -## -## expect Str.trim " Hello \n\n" == "Hello" +## ``` +## expect Str.trim " Hello \n\n" == "Hello" +## ``` trim : Str -> Str ## Return the [Str] with all whitespace removed from the beginning. -## -## expect Str.trimLeft " Hello \n\n" == "Hello \n\n" +## ``` +## expect Str.trimLeft " Hello \n\n" == "Hello \n\n" +## ``` trimLeft : Str -> Str ## Return the [Str] with all whitespace removed from the end. -## -## expect Str.trimRight " Hello \n\n" == " Hello" +## ``` +## expect Str.trimRight " Hello \n\n" == " Hello" +## ``` trimRight : Str -> Str ## Encode a [Str] to a [Dec]. A [Dec] value is a 128-bit decimal ## [fixed-point number](https://en.wikipedia.org/wiki/Fixed-point_arithmetic). -## -## expect Str.toDec "10" == Ok 10dec -## expect Str.toDec "-0.25" == Ok -0.25dec -## expect Str.toDec "not a number" == Err InvalidNumStr +## ``` +## expect Str.toDec "10" == Ok 10dec +## expect Str.toDec "-0.25" == Ok -0.25dec +## expect Str.toDec "not a number" == Err InvalidNumStr +## ``` toDec : Str -> Result Dec [InvalidNumStr] toDec = \string -> strToNumHelp string ## Encode a [Str] to a [F64]. A [F64] value is a 64-bit ## [floating-point number](https://en.wikipedia.org/wiki/IEEE_754) and can be ## specified with a `f64` suffix. -## -## expect Str.toF64 "0.10" == Ok 0.10f64 -## expect Str.toF64 "not a number" == Err InvalidNumStr +## ``` +## expect Str.toF64 "0.10" == Ok 0.10f64 +## expect Str.toF64 "not a number" == Err InvalidNumStr +## ``` toF64 : Str -> Result F64 [InvalidNumStr] toF64 = \string -> strToNumHelp string ## Encode a [Str] to a [F32].A [F32] value is a 32-bit ## [floating-point number](https://en.wikipedia.org/wiki/IEEE_754) and can be ## specified with a `f32` suffix. -## -## expect Str.toF32 "0.10" == Ok 0.10f32 -## expect Str.toF32 "not a number" == Err InvalidNumStr +## ``` +## expect Str.toF32 "0.10" == Ok 0.10f32 +## expect Str.toF32 "not a number" == Err InvalidNumStr +## ``` toF32 : Str -> Result F32 [InvalidNumStr] toF32 = \string -> strToNumHelp string @@ -356,20 +372,22 @@ toF32 = \string -> strToNumHelp string ## Calling `Str.toNat "9_000_000_000"` on a 64-bit system will return ## the [Nat] value of 9_000_000_000. This is because on a 64-bit system, [Nat] can ## hold up to `Num.maxU64`, and 9_000_000_000 is smaller than `Num.maxU64`. -## -## expect Str.toNat "9_000_000_000" == Ok 9000000000 -## expect Str.toNat "not a number" == Err InvalidNumStr +## ``` +## expect Str.toNat "9_000_000_000" == Ok 9000000000 +## expect Str.toNat "not a number" == Err InvalidNumStr +## ``` toNat : Str -> Result Nat [InvalidNumStr] toNat = \string -> strToNumHelp string ## Encode a [Str] to an unsigned [U128] integer. A [U128] value can hold numbers ## from `0` to `340_282_366_920_938_463_463_374_607_431_768_211_455` (over ## 340 undecillion). It can be specified with a u128 suffix. -## -## expect Str.toU128 "1500" == Ok 1500u128 -## expect Str.toU128 "0.1" == Err InvalidNumStr -## expect Str.toU128 "-1" == Err InvalidNumStr -## expect Str.toU128 "not a number" == Err InvalidNumStr +## ``` +## expect Str.toU128 "1500" == Ok 1500u128 +## expect Str.toU128 "0.1" == Err InvalidNumStr +## expect Str.toU128 "-1" == Err InvalidNumStr +## expect Str.toU128 "not a number" == Err InvalidNumStr +## ``` toU128 : Str -> Result U128 [InvalidNumStr] toU128 = \string -> strToNumHelp string @@ -377,96 +395,105 @@ toU128 = \string -> strToNumHelp string ## from `-170_141_183_460_469_231_731_687_303_715_884_105_728` to ## `170_141_183_460_469_231_731_687_303_715_884_105_727`. It can be specified ## with a i128 suffix. -## -## expect Str.toI128 "1500" == Ok 1500i128 -## expect Str.toI128 "-1" == Ok -1i128 -## expect Str.toI128 "0.1" == Err InvalidNumStr -## expect Str.toI128 "not a number" == Err InvalidNumStr +## ``` +## expect Str.toI128 "1500" == Ok 1500i128 +## expect Str.toI128 "-1" == Ok -1i128 +## expect Str.toI128 "0.1" == Err InvalidNumStr +## expect Str.toI128 "not a number" == Err InvalidNumStr +## ``` toI128 : Str -> Result I128 [InvalidNumStr] toI128 = \string -> strToNumHelp string ## Encode a [Str] to an unsigned [U64] integer. A [U64] value can hold numbers ## from `0` to `18_446_744_073_709_551_615` (over 18 quintillion). It ## can be specified with a u64 suffix. -## -## expect Str.toU64 "1500" == Ok 1500u64 -## expect Str.toU64 "0.1" == Err InvalidNumStr -## expect Str.toU64 "-1" == Err InvalidNumStr -## expect Str.toU64 "not a number" == Err InvalidNumStr +## ``` +## expect Str.toU64 "1500" == Ok 1500u64 +## expect Str.toU64 "0.1" == Err InvalidNumStr +## expect Str.toU64 "-1" == Err InvalidNumStr +## expect Str.toU64 "not a number" == Err InvalidNumStr +## ``` toU64 : Str -> Result U64 [InvalidNumStr] toU64 = \string -> strToNumHelp string ## Encode a [Str] to a signed [I64] integer. A [I64] value can hold numbers ## from `-9_223_372_036_854_775_808` to `9_223_372_036_854_775_807`. It can be ## specified with a i64 suffix. -## -## expect Str.toI64 "1500" == Ok 1500i64 -## expect Str.toI64 "-1" == Ok -1i64 -## expect Str.toI64 "0.1" == Err InvalidNumStr -## expect Str.toI64 "not a number" == Err InvalidNumStr +## ``` +## expect Str.toI64 "1500" == Ok 1500i64 +## expect Str.toI64 "-1" == Ok -1i64 +## expect Str.toI64 "0.1" == Err InvalidNumStr +## expect Str.toI64 "not a number" == Err InvalidNumStr +## ``` toI64 : Str -> Result I64 [InvalidNumStr] toI64 = \string -> strToNumHelp string ## Encode a [Str] to an unsigned [U32] integer. A [U32] value can hold numbers ## from `0` to `4_294_967_295` (over 4 billion). It can be specified with ## a u32 suffix. -## -## expect Str.toU32 "1500" == Ok 1500u32 -## expect Str.toU32 "0.1" == Err InvalidNumStr -## expect Str.toU32 "-1" == Err InvalidNumStr -## expect Str.toU32 "not a number" == Err InvalidNumStr +## ``` +## expect Str.toU32 "1500" == Ok 1500u32 +## expect Str.toU32 "0.1" == Err InvalidNumStr +## expect Str.toU32 "-1" == Err InvalidNumStr +## expect Str.toU32 "not a number" == Err InvalidNumStr +## ``` toU32 : Str -> Result U32 [InvalidNumStr] toU32 = \string -> strToNumHelp string ## Encode a [Str] to a signed [I32] integer. A [I32] value can hold numbers ## from `-2_147_483_648` to `2_147_483_647`. It can be ## specified with a i32 suffix. -## -## expect Str.toI32 "1500" == Ok 1500i32 -## expect Str.toI32 "-1" == Ok -1i32 -## expect Str.toI32 "0.1" == Err InvalidNumStr -## expect Str.toI32 "not a number" == Err InvalidNumStr +## ``` +## expect Str.toI32 "1500" == Ok 1500i32 +## expect Str.toI32 "-1" == Ok -1i32 +## expect Str.toI32 "0.1" == Err InvalidNumStr +## expect Str.toI32 "not a number" == Err InvalidNumStr +## ``` toI32 : Str -> Result I32 [InvalidNumStr] toI32 = \string -> strToNumHelp string ## Encode a [Str] to an unsigned [U16] integer. A [U16] value can hold numbers ## from `0` to `65_535`. It can be specified with a u16 suffix. -## -## expect Str.toU16 "1500" == Ok 1500u16 -## expect Str.toU16 "0.1" == Err InvalidNumStr -## expect Str.toU16 "-1" == Err InvalidNumStr -## expect Str.toU16 "not a number" == Err InvalidNumStr +## ``` +## expect Str.toU16 "1500" == Ok 1500u16 +## expect Str.toU16 "0.1" == Err InvalidNumStr +## expect Str.toU16 "-1" == Err InvalidNumStr +## expect Str.toU16 "not a number" == Err InvalidNumStr +## ``` toU16 : Str -> Result U16 [InvalidNumStr] toU16 = \string -> strToNumHelp string ## Encode a [Str] to a signed [I16] integer. A [I16] value can hold numbers ## from `-32_768` to `32_767`. It can be ## specified with a i16 suffix. -## -## expect Str.toI16 "1500" == Ok 1500i16 -## expect Str.toI16 "-1" == Ok -1i16 -## expect Str.toI16 "0.1" == Err InvalidNumStr -## expect Str.toI16 "not a number" == Err InvalidNumStr +## ``` +## expect Str.toI16 "1500" == Ok 1500i16 +## expect Str.toI16 "-1" == Ok -1i16 +## expect Str.toI16 "0.1" == Err InvalidNumStr +## expect Str.toI16 "not a number" == Err InvalidNumStr +## ``` toI16 : Str -> Result I16 [InvalidNumStr] toI16 = \string -> strToNumHelp string ## Encode a [Str] to an unsigned [U8] integer. A [U8] value can hold numbers ## from `0` to `255`. It can be specified with a u8 suffix. -## -## expect Str.toU8 "250" == Ok 250u8 -## expect Str.toU8 "-0.1" == Err InvalidNumStr -## expect Str.toU8 "not a number" == Err InvalidNumStr -## expect Str.toU8 "1500" == Err InvalidNumStr +## ``` +## expect Str.toU8 "250" == Ok 250u8 +## expect Str.toU8 "-0.1" == Err InvalidNumStr +## expect Str.toU8 "not a number" == Err InvalidNumStr +## expect Str.toU8 "1500" == Err InvalidNumStr +## ``` toU8 : Str -> Result U8 [InvalidNumStr] toU8 = \string -> strToNumHelp string ## Encode a [Str] to a signed [I8] integer. A [I8] value can hold numbers ## from `-128` to `127`. It can be ## specified with a i8 suffix. -## -## expect Str.toI8 "-15" == Ok -15i8 -## expect Str.toI8 "150.00" == Err InvalidNumStr -## expect Str.toI8 "not a number" == Err InvalidNumStr +## ``` +## expect Str.toI8 "-15" == Ok -15i8 +## expect Str.toI8 "150.00" == Err InvalidNumStr +## expect Str.toI8 "not a number" == Err InvalidNumStr +## ``` toI8 : Str -> Result I8 [InvalidNumStr] toI8 = \string -> strToNumHelp string @@ -474,8 +501,9 @@ toI8 = \string -> strToNumHelp string getUnsafe : Str, Nat -> U8 ## Gives the number of bytes in a [Str] value. -## -## expect Str.countUtf8Bytes "Hello World" == 11 +## ``` +## expect Str.countUtf8Bytes "Hello World" == 11 +## ``` countUtf8Bytes : Str -> Nat ## string slice that does not do bounds checking or utf-8 verification @@ -483,9 +511,10 @@ substringUnsafe : Str, Nat, Nat -> Str ## Returns the given [Str] with each occurrence of a substring replaced. ## Returns [Err NotFound] if the substring is not found. -## -## expect Str.replaceEach "foo/bar/baz" "/" "_" == Ok "foo_bar_baz" -## expect Str.replaceEach "not here" "/" "_" == Err NotFound +## ``` +## expect Str.replaceEach "foo/bar/baz" "/" "_" == Ok "foo_bar_baz" +## expect Str.replaceEach "not here" "/" "_" == Err NotFound +## ``` replaceEach : Str, Str, Str -> Result Str [NotFound] replaceEach = \haystack, needle, flower -> when splitFirst haystack needle is @@ -515,9 +544,10 @@ expect Str.replaceEach "abXdeXghi" "X" "_" == Ok "ab_de_ghi" ## Returns the given [Str] with the first occurrence of a substring replaced. ## Returns [Err NotFound] if the substring is not found. -## -## expect Str.replaceFirst "foo/bar/baz" "/" "_" == Ok "foo_bar/baz" -## expect Str.replaceFirst "no slashes here" "/" "_" == Err NotFound +## ``` +## expect Str.replaceFirst "foo/bar/baz" "/" "_" == Ok "foo_bar/baz" +## expect Str.replaceFirst "no slashes here" "/" "_" == Err NotFound +## ``` replaceFirst : Str, Str, Str -> Result Str [NotFound] replaceFirst = \haystack, needle, flower -> when splitFirst haystack needle is @@ -530,9 +560,10 @@ expect Str.replaceFirst "abXdeXghi" "X" "_" == Ok "ab_deXghi" ## Returns the given [Str] with the last occurrence of a substring replaced. ## Returns [Err NotFound] if the substring is not found. -## -## expect Str.replaceLast "foo/bar/baz" "/" "_" == Ok "foo/bar_baz" -## expect Str.replaceLast "no slashes here" "/" "_" == Err NotFound +## ``` +## expect Str.replaceLast "foo/bar/baz" "/" "_" == Ok "foo/bar_baz" +## expect Str.replaceLast "no slashes here" "/" "_" == Err NotFound +## ``` replaceLast : Str, Str, Str -> Result Str [NotFound] replaceLast = \haystack, needle, flower -> when splitLast haystack needle is @@ -546,9 +577,10 @@ expect Str.replaceLast "abXdeXghi" "X" "_" == Ok "abXde_ghi" ## Returns the given [Str] before the first occurrence of a [delimiter](https://www.computerhope.com/jargon/d/delimite.htm), as well ## as the rest of the string after that occurrence. ## Returns [ Err NotFound] if the delimiter is not found. -## -## expect Str.splitFirst "foo/bar/baz" "/" == Ok { before: "foo", after: "bar/baz" } -## expect Str.splitFirst "no slashes here" "/" == Err NotFound +## ``` +## expect Str.splitFirst "foo/bar/baz" "/" == Ok { before: "foo", after: "bar/baz" } +## expect Str.splitFirst "no slashes here" "/" == Err NotFound +## ``` splitFirst : Str, Str -> Result { before : Str, after : Str } [NotFound] splitFirst = \haystack, needle -> when firstMatch haystack needle is @@ -599,9 +631,10 @@ firstMatchHelp = \haystack, needle, index, lastPossible -> ## Returns the given [Str] before the last occurrence of a delimiter, as well as ## the rest of the string after that occurrence. ## Returns [Err NotFound] if the delimiter is not found. -## -## expect Str.splitLast "foo/bar/baz" "/" == Ok { before: "foo/bar", after: "baz" } -## expect Str.splitLast "no slashes here" "/" == Err NotFound +## ``` +## expect Str.splitLast "foo/bar/baz" "/" == Ok { before: "foo/bar", after: "baz" } +## expect Str.splitLast "no slashes here" "/" == Err NotFound +## ``` splitLast : Str, Str -> Result { before : Str, after : Str } [NotFound] splitLast = \haystack, needle -> when lastMatch haystack needle is @@ -690,10 +723,11 @@ matchesAtHelp = \state -> ## Walks over the `UTF-8` bytes of the given [Str] and calls a function to update ## state for each byte. The index for that byte in the string is provided ## to the update function. -## -## f : List U8, U8, Nat -> List U8 -## f = \state, byte, _ -> List.append state byte -## expect Str.walkUtf8WithIndex "ABC" [] f == [65, 66, 67] +## ``` +## f : List U8, U8, Nat -> List U8 +## f = \state, byte, _ -> List.append state byte +## expect Str.walkUtf8WithIndex "ABC" [] f == [65, 66, 67] +## ``` walkUtf8WithIndex : Str, state, (state, U8, Nat -> state) -> state walkUtf8WithIndex = \string, state, step -> walkUtf8WithIndexHelp string state step 0 (Str.countUtf8Bytes string) @@ -716,9 +750,10 @@ appendScalarUnsafe : Str, U32 -> Str ## Append a [U32] scalar to the given string. If the given scalar is not a valid ## unicode value, it returns [Err InvalidScalar]. -## -## expect Str.appendScalar "H" 105 == Ok "Hi" -## expect Str.appendScalar "😢" 0xabcdef == Err InvalidScalar +## ``` +## expect Str.appendScalar "H" 105 == Ok "Hi" +## expect Str.appendScalar "😢" 0xabcdef == Err InvalidScalar +## ``` appendScalar : Str, U32 -> Result Str [InvalidScalar] appendScalar = \string, scalar -> if isValidScalar scalar then @@ -734,10 +769,11 @@ getScalarUnsafe : Str, Nat -> { scalar : U32, bytesParsed : Nat } ## Walks over the unicode [U32] values for the given [Str] and calls a function ## to update state for each. -## -## f : List U32, U32 -> List U32 -## f = \state, scalar -> List.append state scalar -## expect Str.walkScalars "ABC" [] f == [65, 66, 67] +## ``` +## f : List U32, U32 -> List U32 +## f = \state, scalar -> List.append state scalar +## expect Str.walkScalars "ABC" [] f == [65, 66, 67] +## ``` walkScalars : Str, state, (state, U32 -> state) -> state walkScalars = \string, init, step -> walkScalarsHelp string init step 0 (Str.countUtf8Bytes string) @@ -754,16 +790,17 @@ walkScalarsHelp = \string, state, step, index, length -> ## Walks over the unicode [U32] values for the given [Str] and calls a function ## to update state for each. -## -## f : List U32, U32 -> [Break (List U32), Continue (List U32)] -## f = \state, scalar -> -## check = 66 -## if scalar == check then -## Break [check] -## else -## Continue (List.append state scalar) -## expect Str.walkScalarsUntil "ABC" [] f == [66] -## expect Str.walkScalarsUntil "AxC" [] f == [65, 120, 67] +## ``` +## f : List U32, U32 -> [Break (List U32), Continue (List U32)] +## f = \state, scalar -> +## check = 66 +## if scalar == check then +## Break [check] +## else +## Continue (List.append state scalar) +## expect Str.walkScalarsUntil "ABC" [] f == [66] +## expect Str.walkScalarsUntil "AxC" [] f == [65, 120, 67] +## ``` walkScalarsUntil : Str, state, (state, U32 -> [Break state, Continue state]) -> state walkScalarsUntil = \string, init, step -> walkScalarsUntilHelp string init step 0 (Str.countUtf8Bytes string) @@ -795,7 +832,8 @@ strToNumHelp = \string -> Err InvalidNumStr ## Adds a prefix to the given [Str]. -## -## expect Str.withPrefix "Awesome" "Roc" == "RocAwesome" +## ``` +## expect Str.withPrefix "Awesome" "Roc" == "RocAwesome" +## ``` withPrefix : Str, Str -> Str withPrefix = \str, prefix -> Str.concat prefix str diff --git a/crates/compiler/builtins/src/bitcode.rs b/crates/compiler/builtins/src/bitcode.rs index 99b19dfddd..69782f2afa 100644 --- a/crates/compiler/builtins/src/bitcode.rs +++ b/crates/compiler/builtins/src/bitcode.rs @@ -1,73 +1,6 @@ use roc_module::symbol::Symbol; use roc_target::TargetInfo; use std::ops::Index; -use tempfile::NamedTempFile; - -pub const HOST_WASM: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/bitcode/builtins-wasm32.o")); -// TODO: in the future, we should use Zig's cross-compilation to generate and store these -// for all targets, so that we can do cross-compilation! -#[cfg(unix)] -pub const HOST_UNIX: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/bitcode/builtins-host.o")); -#[cfg(windows)] -pub const HOST_WINDOWS: &[u8] = include_bytes!(concat!( - env!("OUT_DIR"), - "/bitcode/builtins-windows-x86_64.obj" -)); - -pub fn host_wasm_tempfile() -> std::io::Result { - let tempfile = tempfile::Builder::new() - .prefix("host_bitcode") - .suffix(".wasm") - .rand_bytes(8) - .tempfile()?; - - std::fs::write(tempfile.path(), HOST_WASM)?; - - Ok(tempfile) -} - -#[cfg(unix)] -fn host_unix_tempfile() -> std::io::Result { - let tempfile = tempfile::Builder::new() - .prefix("host_bitcode") - .suffix(".o") - .rand_bytes(8) - .tempfile()?; - - std::fs::write(tempfile.path(), HOST_UNIX)?; - - Ok(tempfile) -} - -#[cfg(windows)] -fn host_windows_tempfile() -> std::io::Result { - let tempfile = tempfile::Builder::new() - .prefix("host_bitcode") - .suffix(".obj") - .rand_bytes(8) - .tempfile()?; - - std::fs::write(tempfile.path(), HOST_WINDOWS)?; - - Ok(tempfile) -} - -pub fn host_tempfile() -> std::io::Result { - #[cfg(unix)] - { - host_unix_tempfile() - } - - #[cfg(windows)] - { - host_windows_tempfile() - } - - #[cfg(not(any(windows, unix)))] - { - unreachable!() - } -} #[derive(Debug, Default, Copy, Clone)] pub struct IntrinsicName { @@ -356,8 +289,16 @@ pub const NUM_MUL_CHECKED_INT: IntrinsicName = int_intrinsic!("roc_builtins.num. pub const NUM_MUL_CHECKED_FLOAT: IntrinsicName = float_intrinsic!("roc_builtins.num.mul_with_overflow"); +pub const NUM_COUNT_LEADING_ZERO_BITS: IntrinsicName = + int_intrinsic!("roc_builtins.num.count_leading_zero_bits"); +pub const NUM_COUNT_TRAILING_ZERO_BITS: IntrinsicName = + int_intrinsic!("roc_builtins.num.count_trailing_zero_bits"); +pub const NUM_COUNT_ONE_BITS: IntrinsicName = int_intrinsic!("roc_builtins.num.count_one_bits"); + pub const NUM_BYTES_TO_U16: &str = "roc_builtins.num.bytes_to_u16"; pub const NUM_BYTES_TO_U32: &str = "roc_builtins.num.bytes_to_u32"; +pub const NUM_BYTES_TO_U64: &str = "roc_builtins.num.bytes_to_u64"; +pub const NUM_BYTES_TO_U128: &str = "roc_builtins.num.bytes_to_u128"; pub const STR_INIT: &str = "roc_builtins.str.init"; pub const STR_COUNT_SEGMENTS: &str = "roc_builtins.str.count_segments"; diff --git a/crates/compiler/can/Cargo.toml b/crates/compiler/can/Cargo.toml index 16efe76ab7..986c5fd732 100644 --- a/crates/compiler/can/Cargo.toml +++ b/crates/compiler/can/Cargo.toml @@ -1,28 +1,29 @@ [package] name = "roc_can" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Canonicalize a roc abstract syntax tree, resolving symbols, re-ordering definitions, and preparing a module for type inference." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] roc_collections = { path = "../collections" } roc_error_macros = { path = "../../error_macros" } roc_exhaustive = { path = "../exhaustive" } -roc_region = { path = "../region" } roc_module = { path = "../module" } roc_parse = { path = "../parse" } roc_problem = { path = "../problem" } -roc_types = { path = "../types" } +roc_region = { path = "../region" } roc_serialize = { path = "../serialize" } - -bumpalo.workspace = true -static_assertions.workspace = true -bitvec.workspace = true +roc_types = { path = "../types" } ven_pretty = { path = "../../vendor/pretty" } +bitvec.workspace = true +bumpalo.workspace = true +static_assertions.workspace = true + [dev-dependencies] -pretty_assertions.workspace = true indoc.workspace = true +pretty_assertions.workspace = true diff --git a/crates/compiler/can/src/builtins.rs b/crates/compiler/can/src/builtins.rs index 4e5b9f95b2..8cf8fa8ae5 100644 --- a/crates/compiler/can/src/builtins.rs +++ b/crates/compiler/can/src/builtins.rs @@ -187,6 +187,8 @@ map_symbol_to_lowlevel_and_arity! { NumAsin; NUM_ASIN; 1, NumBytesToU16; NUM_BYTES_TO_U16_LOWLEVEL; 2, NumBytesToU32; NUM_BYTES_TO_U32_LOWLEVEL; 2, + NumBytesToU64; NUM_BYTES_TO_U64_LOWLEVEL; 2, + NumBytesToU128; NUM_BYTES_TO_U128_LOWLEVEL; 2, NumBitwiseAnd; NUM_BITWISE_AND; 2, NumBitwiseXor; NUM_BITWISE_XOR; 2, NumBitwiseOr; NUM_BITWISE_OR; 2, @@ -194,6 +196,9 @@ map_symbol_to_lowlevel_and_arity! { NumShiftRightBy; NUM_SHIFT_RIGHT; 2, NumShiftRightZfBy; NUM_SHIFT_RIGHT_ZERO_FILL; 2, NumToStr; NUM_TO_STR; 1, + NumCountLeadingZeroBits; NUM_COUNT_LEADING_ZERO_BITS; 1, + NumCountTrailingZeroBits; NUM_COUNT_TRAILING_ZERO_BITS; 1, + NumCountOneBits; NUM_COUNT_ONE_BITS; 1, Eq; BOOL_STRUCTURAL_EQ; 2, NotEq; BOOL_STRUCTURAL_NOT_EQ; 2, diff --git a/crates/compiler/can/src/debug/pretty_print.rs b/crates/compiler/can/src/debug/pretty_print.rs index fa981db290..361cdf0b70 100644 --- a/crates/compiler/can/src/debug/pretty_print.rs +++ b/crates/compiler/can/src/debug/pretty_print.rs @@ -385,7 +385,15 @@ fn expr<'a>(c: &Ctx, p: EPrec, f: &'a Arena<'a>, e: &'a Expr) -> DocBuilder<'a, ), Crash { .. } => todo!(), ZeroArgumentTag { .. } => todo!(), - OpaqueRef { .. } => todo!(), + OpaqueRef { name, argument, .. } => maybe_paren!( + Free, + p, + || true, + pp_sym(c, f, *name) + .append(f.space()) + .append(expr(c, AppArg, f, &argument.1.value)) + .group() + ), Dbg { .. } => todo!(), Expect { .. } => todo!(), ExpectFx { .. } => todo!(), diff --git a/crates/compiler/collections/Cargo.toml b/crates/compiler/collections/Cargo.toml index 241bb44c04..5b2d493461 100644 --- a/crates/compiler/collections/Cargo.toml +++ b/crates/compiler/collections/Cargo.toml @@ -1,16 +1,17 @@ [package] name = "roc_collections" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Domain-specific collections created for the needs of the compiler." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] -fnv.workspace = true -im.workspace = true -im-rc.workspace = true -wyhash.workspace = true -bumpalo.workspace = true -hashbrown.workspace = true bitvec.workspace = true +bumpalo.workspace = true +fnv.workspace = true +hashbrown.workspace = true +im-rc.workspace = true +im.workspace = true +wyhash.workspace = true diff --git a/crates/compiler/constrain/Cargo.toml b/crates/compiler/constrain/Cargo.toml index a830ac3f37..01d9414867 100644 --- a/crates/compiler/constrain/Cargo.toml +++ b/crates/compiler/constrain/Cargo.toml @@ -1,18 +1,20 @@ [package] name = "roc_constrain" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Responsible for building the set of constraints that are used during type inference of a program, and for gathering context needed for pleasant error messages when a type error occurs." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] +roc_can = { path = "../can" } roc_collections = { path = "../collections" } roc_error_macros = { path = "../../error_macros" } -roc_region = { path = "../region" } roc_module = { path = "../module" } roc_parse = { path = "../parse" } roc_problem = { path = "../problem" } +roc_region = { path = "../region" } roc_types = { path = "../types" } -roc_can = { path = "../can" } -arrayvec = "0.7.2" + +arrayvec.workspace = true diff --git a/crates/compiler/debug_flags/Cargo.toml b/crates/compiler/debug_flags/Cargo.toml index 9e299039a4..b3b9b4bc15 100644 --- a/crates/compiler/debug_flags/Cargo.toml +++ b/crates/compiler/debug_flags/Cargo.toml @@ -1,9 +1,10 @@ [package] name = "roc_debug_flags" -version = "0.0.1" -edition = "2021" -authors = ["The Roc Contributors"] -license = "UPL-1.0" description = "Environment variables that can be toggled to aid debugging of the compiler itself." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] diff --git a/crates/compiler/derive/Cargo.toml b/crates/compiler/derive/Cargo.toml index 05d4dbdbbb..9aba2f51c7 100644 --- a/crates/compiler/derive/Cargo.toml +++ b/crates/compiler/derive/Cargo.toml @@ -1,25 +1,27 @@ [package] name = "roc_derive" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Provides auto-derivers for builtin abilities like `Hash` and `Decode`." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] -roc_collections = { path = "../collections" } -roc_error_macros = { path = "../../error_macros" } -roc_derive_key = { path = "../derive_key" } -roc_region = { path = "../region" } -roc_module = { path = "../module" } -roc_types = { path = "../types" } roc_can = { path = "../can" } +roc_collections = { path = "../collections" } +roc_derive_key = { path = "../derive_key" } +roc_error_macros = { path = "../../error_macros" } +roc_module = { path = "../module" } +roc_region = { path = "../region" } +roc_types = { path = "../types" } roc_unify = { path = "../unify" } + bumpalo.workspace = true [features] -default = [] debug-derived-symbols = ["roc_module/debug-symbols"] +default = [] # Enables open extension variables for constructed records and tag unions. # This is not necessary for code generation, but may be necessary if you are # constraining and solving generated derived bodies. diff --git a/crates/compiler/derive_key/Cargo.toml b/crates/compiler/derive_key/Cargo.toml index a69689fd32..a8f9a5a826 100644 --- a/crates/compiler/derive_key/Cargo.toml +++ b/crates/compiler/derive_key/Cargo.toml @@ -1,14 +1,14 @@ [package] name = "roc_derive_key" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" + +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true [dependencies] roc_collections = { path = "../collections" } roc_error_macros = { path = "../../error_macros" } -roc_region = { path = "../region" } roc_module = { path = "../module" } +roc_region = { path = "../region" } roc_types = { path = "../types" } -roc_can = { path = "../can" } diff --git a/crates/compiler/exhaustive/Cargo.toml b/crates/compiler/exhaustive/Cargo.toml index 045e477d50..17d96fcd40 100644 --- a/crates/compiler/exhaustive/Cargo.toml +++ b/crates/compiler/exhaustive/Cargo.toml @@ -1,14 +1,15 @@ [package] name = "roc_exhaustive" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Provides exhaustiveness checking for Roc." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] roc_collections = { path = "../collections" } -roc_region = { path = "../region" } -roc_module = { path = "../module" } roc_error_macros = { path = "../../error_macros" } +roc_module = { path = "../module" } roc_problem = { path = "../problem" } +roc_region = { path = "../region" } diff --git a/crates/compiler/fmt/Cargo.toml b/crates/compiler/fmt/Cargo.toml index 4d0afff245..d72ce03678 100644 --- a/crates/compiler/fmt/Cargo.toml +++ b/crates/compiler/fmt/Cargo.toml @@ -1,14 +1,16 @@ [package] name = "roc_fmt" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "The roc code formatter." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] roc_collections = { path = "../collections" } -roc_region = { path = "../region" } roc_module = { path = "../module" } roc_parse = { path = "../parse" } -bumpalo.workspace = true +roc_region = { path = "../region" } + +bumpalo.workspace = true diff --git a/crates/compiler/fmt/src/collection.rs b/crates/compiler/fmt/src/collection.rs index 643928fcb1..3d241dafca 100644 --- a/crates/compiler/fmt/src/collection.rs +++ b/crates/compiler/fmt/src/collection.rs @@ -38,7 +38,7 @@ pub fn fmt_collection<'a, 'buf, T: ExtractSpaces<'a> + Formattable>( let braces_indent = indent; let item_indent = braces_indent + INDENT; if newline == Newlines::Yes { - buf.newline(); + buf.ensure_ends_with_newline(); } buf.indent(braces_indent); buf.push(start); diff --git a/crates/compiler/fmt/src/def.rs b/crates/compiler/fmt/src/def.rs index c2831e3923..d45e37b733 100644 --- a/crates/compiler/fmt/src/def.rs +++ b/crates/compiler/fmt/src/def.rs @@ -61,7 +61,7 @@ impl<'a> Formattable for TypeDef<'a> { &self, buf: &mut Buf<'buf>, _parens: Parens, - _newlines: Newlines, + newlines: Newlines, indent: u16, ) { use roc_parse::ast::TypeDef::*; @@ -97,22 +97,10 @@ impl<'a> Formattable for TypeDef<'a> { ann.format(buf, indent) } Opaque { - header: TypeHeader { name, vars }, + header, typ: ann, derived: has_abilities, } => { - buf.indent(indent); - buf.push_str(name.value); - - for var in *vars { - buf.spaces(1); - fmt_pattern(buf, &var.value, indent, Parens::NotNeeded); - buf.indent(indent); - } - - buf.push_str(" :="); - buf.spaces(1); - let ann_is_where_clause = matches!(ann.extract_spaces().item, TypeAnnotation::Where(..)); @@ -126,7 +114,7 @@ impl<'a> Formattable for TypeDef<'a> { let make_multiline = ann.is_multiline() || has_abilities_multiline; - ann.format(buf, indent); + fmt_general_def(header, buf, indent, ":=", &ann.value, newlines); if let Some(has_abilities) = has_abilities { buf.spaces(1); @@ -178,6 +166,29 @@ impl<'a> Formattable for TypeDef<'a> { } } +impl<'a> Formattable for TypeHeader<'a> { + fn is_multiline(&self) -> bool { + self.vars.iter().any(|v| v.is_multiline()) + } + + fn format_with_options<'buf>( + &self, + buf: &mut Buf<'buf>, + _parens: Parens, + _newlines: Newlines, + indent: u16, + ) { + buf.indent(indent); + buf.push_str(self.name.value); + + for var in self.vars.iter() { + buf.spaces(1); + fmt_pattern(buf, &var.value, indent, Parens::NotNeeded); + buf.indent(indent); + } + } +} + impl<'a> Formattable for ValueDef<'a> { fn is_multiline(&self) -> bool { use roc_parse::ast::ValueDef::*; @@ -204,63 +215,14 @@ impl<'a> Formattable for ValueDef<'a> { use roc_parse::ast::ValueDef::*; match self { Annotation(loc_pattern, loc_annotation) => { - loc_pattern.format(buf, indent); - buf.indent(indent); - - if loc_annotation.is_multiline() { - buf.push_str(" :"); - buf.spaces(1); - - let should_outdent = match loc_annotation.value { - TypeAnnotation::SpaceBefore(sub_def, spaces) => match sub_def { - TypeAnnotation::Record { .. } | TypeAnnotation::TagUnion { .. } => { - let is_only_newlines = spaces.iter().all(|s| s.is_newline()); - is_only_newlines && sub_def.is_multiline() - } - _ => false, - }, - TypeAnnotation::Record { .. } | TypeAnnotation::TagUnion { .. } => true, - _ => false, - }; - - if should_outdent { - match loc_annotation.value { - TypeAnnotation::SpaceBefore(sub_def, _) => { - sub_def.format_with_options( - buf, - Parens::NotNeeded, - Newlines::No, - indent, - ); - } - _ => { - loc_annotation.format_with_options( - buf, - Parens::NotNeeded, - Newlines::No, - indent, - ); - } - } - } else { - loc_annotation.format_with_options( - buf, - Parens::NotNeeded, - newlines, - indent + INDENT, - ); - } - } else { - buf.spaces(1); - buf.push(':'); - buf.spaces(1); - loc_annotation.format_with_options( - buf, - Parens::NotNeeded, - Newlines::No, - indent, - ); - } + fmt_general_def( + loc_pattern, + buf, + indent, + ":", + &loc_annotation.value, + newlines, + ); } Body(loc_pattern, loc_expr) => { fmt_body(buf, &loc_pattern.value, &loc_expr.value, indent); @@ -277,34 +239,7 @@ impl<'a> Formattable for ValueDef<'a> { body_pattern, body_expr, } => { - let is_type_multiline = ann_type.is_multiline(); - let is_type_function = matches!( - ann_type.value, - TypeAnnotation::Function(..) - | TypeAnnotation::SpaceBefore(TypeAnnotation::Function(..), ..) - | TypeAnnotation::SpaceAfter(TypeAnnotation::Function(..), ..) - ); - - let next_indent = if is_type_multiline { - indent + INDENT - } else { - indent - }; - - ann_pattern.format(buf, indent); - buf.push_str(" :"); - - if is_type_multiline && is_type_function { - ann_type.format_with_options( - buf, - Parens::NotNeeded, - Newlines::Yes, - next_indent, - ); - } else { - buf.spaces(1); - ann_type.format(buf, indent); - } + fmt_general_def(ann_pattern, buf, indent, ":", &ann_type.value, newlines); if let Some(comment_str) = comment { buf.push_str(" #"); @@ -319,6 +254,66 @@ impl<'a> Formattable for ValueDef<'a> { } } +fn fmt_general_def( + lhs: L, + buf: &mut Buf, + indent: u16, + sep: &str, + rhs: &TypeAnnotation, + newlines: Newlines, +) { + lhs.format(buf, indent); + buf.indent(indent); + + if rhs.is_multiline() { + buf.spaces(1); + buf.push_str(sep); + buf.spaces(1); + + let should_outdent = should_outdent(rhs); + + if should_outdent { + match rhs { + TypeAnnotation::SpaceBefore(sub_def, _) => { + sub_def.format_with_options(buf, Parens::NotNeeded, Newlines::No, indent); + } + _ => { + rhs.format_with_options(buf, Parens::NotNeeded, Newlines::No, indent); + } + } + } else { + rhs.format_with_options(buf, Parens::NotNeeded, newlines, indent + INDENT); + } + } else { + buf.spaces(1); + buf.push_str(sep); + buf.spaces(1); + rhs.format_with_options(buf, Parens::NotNeeded, Newlines::No, indent); + } +} + +fn should_outdent(mut rhs: &TypeAnnotation) -> bool { + loop { + match rhs { + TypeAnnotation::SpaceBefore(sub_def, spaces) => { + let is_only_newlines = spaces.iter().all(|s| s.is_newline()); + if !is_only_newlines || !sub_def.is_multiline() { + return false; + } + rhs = sub_def; + } + TypeAnnotation::Where(ann, _clauses) => { + if !ann.is_multiline() { + return false; + } + rhs = &ann.value; + } + TypeAnnotation::Record { .. } | TypeAnnotation::TagUnion { .. } => return true, + _ => return false, + } + } +} + fn fmt_dbg_in_def<'a, 'buf>( buf: &mut Buf<'buf>, condition: &'a Loc>, diff --git a/crates/compiler/fmt/src/expr.rs b/crates/compiler/fmt/src/expr.rs index 69d14f1ed3..8e716e1772 100644 --- a/crates/compiler/fmt/src/expr.rs +++ b/crates/compiler/fmt/src/expr.rs @@ -1,4 +1,4 @@ -use crate::annotation::{except_last, Formattable, Newlines, Parens}; +use crate::annotation::{except_last, is_collection_multiline, Formattable, Newlines, Parens}; use crate::collection::{fmt_collection, Braces}; use crate::def::fmt_defs; use crate::pattern::fmt_pattern; @@ -49,7 +49,7 @@ impl<'a> Formattable for Expr<'a> { // These expressions always have newlines Defs(_, _) | When(_, _) => true, - List(items) => items.iter().any(|loc_expr| loc_expr.is_multiline()), + List(items) => is_collection_multiline(items), Str(literal) => is_str_multiline(literal), Apply(loc_expr, args, _) => { @@ -96,9 +96,9 @@ impl<'a> Formattable for Expr<'a> { .any(|loc_pattern| loc_pattern.is_multiline()) } - Record(fields) => fields.iter().any(|loc_field| loc_field.is_multiline()), - Tuple(fields) => fields.iter().any(|loc_field| loc_field.is_multiline()), - RecordUpdate { fields, .. } => fields.iter().any(|loc_field| loc_field.is_multiline()), + Record(fields) => is_collection_multiline(fields), + Tuple(fields) => is_collection_multiline(fields), + RecordUpdate { fields, .. } => is_collection_multiline(fields), } } @@ -1319,7 +1319,7 @@ fn fmt_record<'a, 'buf>( let loc_fields = fields.items; let final_comments = fields.final_comments(); buf.indent(indent); - if loc_fields.is_empty() && final_comments.iter().all(|c| c.is_newline()) { + if loc_fields.is_empty() && final_comments.iter().all(|c| c.is_newline()) && update.is_none() { buf.push_str("{}"); } else { buf.push('{'); diff --git a/crates/compiler/gen_dev/Cargo.toml b/crates/compiler/gen_dev/Cargo.toml index 5225d9f3c5..12680ffdb3 100644 --- a/crates/compiler/gen_dev/Cargo.toml +++ b/crates/compiler/gen_dev/Cargo.toml @@ -1,28 +1,29 @@ [package] name = "roc_gen_dev" description = "The development backend for the Roc compiler" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" + +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true [dependencies] -roc_collections = { path = "../collections" } -roc_region = { path = "../region" } -roc_module = { path = "../module" } -roc_problem = { path = "../problem" } -roc_types = { path = "../types" } roc_builtins = { path = "../builtins" } -roc_unify = { path = "../unify" } -roc_solve = { path = "../solve" } -roc_mono = { path = "../mono" } -roc_target = { path = "../roc_target" } +roc_collections = { path = "../collections" } roc_error_macros = { path = "../../error_macros" } +roc_module = { path = "../module" } +roc_mono = { path = "../mono" } +roc_problem = { path = "../problem" } +roc_region = { path = "../region" } +roc_solve = { path = "../solve" } +roc_target = { path = "../roc_target" } +roc_types = { path = "../types" } +roc_unify = { path = "../unify" } bumpalo.workspace = true -target-lexicon.workspace = true object.workspace = true packed_struct.workspace = true +target-lexicon.workspace = true [dev-dependencies] roc_can = { path = "../can" } diff --git a/crates/compiler/gen_dev/README.md b/crates/compiler/gen_dev/README.md index 15cffb0bc4..b8b2d13ec5 100644 --- a/crates/compiler/gen_dev/README.md +++ b/crates/compiler/gen_dev/README.md @@ -105,10 +105,10 @@ This is the general procedure I follow with some helpful links: Also, sometimes it doesn't seem to generate things quite as you expect. - [Alternative Online Assembler](http://shell-storm.org/online/Online-Assembler-and-Disassembler/) - Like previous but with more architecture options. -- [x86 and amd64 instruction reference](https://www.felixcloutier.com/x86/) - +- [x86 and amd64 instruction reference](https://web.archive.org/web/20230221053750/https://www.felixcloutier.com/x86/) - Great for looking up x86_64 instructions and there bytes. Definitely missing information if you aren't used to reading it. -- [Intel 64 ISA Reference](https://software.intel.com/content/dam/develop/public/us/en/documents/325383-sdm-vol-2abcd.pdf) - +- [Intel 64 ISA Reference](https://community.intel.com/legacyfs/online/drupal_files/managed/a4/60/325383-sdm-vol-2abcd.pdf) - Super dense manual. Contains everything you would need to know for x86_64. Also is like 2000 pages. diff --git a/crates/compiler/gen_dev/src/generic64/aarch64.rs b/crates/compiler/gen_dev/src/generic64/aarch64.rs index 01ebac5c90..ae3842c4a4 100644 --- a/crates/compiler/gen_dev/src/generic64/aarch64.rs +++ b/crates/compiler/gen_dev/src/generic64/aarch64.rs @@ -2,10 +2,13 @@ use crate::generic64::{storage::StorageManager, Assembler, CallConv, RegTrait}; use crate::Relocation; use bumpalo::collections::Vec; use packed_struct::prelude::*; +use roc_builtins::bitcode::FloatWidth; use roc_error_macros::internal_error; use roc_module::symbol::Symbol; use roc_mono::layout::{InLayout, STLayoutInterner}; +use super::CompareOperation; + #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] #[allow(dead_code)] pub enum AArch64GeneralReg { @@ -609,9 +612,31 @@ impl Assembler for AArch64Assembler { } } #[inline(always)] + fn mov_reg32_base32(_buf: &mut Vec<'_, u8>, _dst: AArch64GeneralReg, _offset: i32) { + todo!() + } + #[inline(always)] + fn mov_reg16_base32(_buf: &mut Vec<'_, u8>, _dst: AArch64GeneralReg, _offset: i32) { + todo!() + } + #[inline(always)] + fn mov_reg8_base32(_buf: &mut Vec<'_, u8>, _dst: AArch64GeneralReg, _offset: i32) { + todo!() + } + #[inline(always)] fn mov_base32_freg64(_buf: &mut Vec<'_, u8>, _offset: i32, _src: AArch64FloatReg) { todo!("saving floating point reg to base offset for AArch64"); } + #[inline(always)] + fn movesd_mem64_offset32_freg64( + _buf: &mut Vec<'_, u8>, + _ptr: AArch64GeneralReg, + _offset: i32, + _src: AArch64FloatReg, + ) { + todo!() + } + #[inline(always)] fn mov_base32_reg64(buf: &mut Vec<'_, u8>, offset: i32, src: AArch64GeneralReg) { if offset < 0 { @@ -624,6 +649,19 @@ impl Assembler for AArch64Assembler { } } + #[inline(always)] + fn mov_base32_reg32(_buf: &mut Vec<'_, u8>, _offset: i32, _src: AArch64GeneralReg) { + todo!() + } + #[inline(always)] + fn mov_base32_reg16(_buf: &mut Vec<'_, u8>, _offset: i32, _src: AArch64GeneralReg) { + todo!() + } + #[inline(always)] + fn mov_base32_reg8(_buf: &mut Vec<'_, u8>, _offset: i32, _src: AArch64GeneralReg) { + todo!() + } + #[inline(always)] fn mov_reg64_mem64_offset32( buf: &mut Vec<'_, u8>, @@ -640,6 +678,41 @@ impl Assembler for AArch64Assembler { todo!("mem offsets over 32k for AArch64"); } } + #[inline(always)] + fn mov_reg32_mem32_offset32( + buf: &mut Vec<'_, u8>, + dst: AArch64GeneralReg, + src: AArch64GeneralReg, + offset: i32, + ) { + if offset < 0 { + todo!("negative mem offsets for AArch64"); + } else if offset < (0xFFF << 8) { + debug_assert!(offset % 8 == 0); + ldr_reg64_reg64_imm12(buf, dst, src, (offset as u16) >> 3); + } else { + todo!("mem offsets over 32k for AArch64"); + } + } + #[inline(always)] + fn mov_reg16_mem16_offset32( + _buf: &mut Vec<'_, u8>, + _dst: AArch64GeneralReg, + _src: AArch64GeneralReg, + _offset: i32, + ) { + todo!() + } + #[inline(always)] + fn mov_reg8_mem8_offset32( + _buf: &mut Vec<'_, u8>, + _dst: AArch64GeneralReg, + _src: AArch64GeneralReg, + _offset: i32, + ) { + todo!() + } + #[inline(always)] fn mov_mem64_offset32_reg64( buf: &mut Vec<'_, u8>, @@ -657,6 +730,36 @@ impl Assembler for AArch64Assembler { } } + #[inline(always)] + fn mov_mem32_offset32_reg32( + _buf: &mut Vec<'_, u8>, + _dst: AArch64GeneralReg, + _offset: i32, + _src: AArch64GeneralReg, + ) { + todo!() + } + + #[inline(always)] + fn mov_mem16_offset32_reg16( + _buf: &mut Vec<'_, u8>, + _dst: AArch64GeneralReg, + _offset: i32, + _src: AArch64GeneralReg, + ) { + todo!() + } + + #[inline(always)] + fn mov_mem8_offset32_reg8( + _buf: &mut Vec<'_, u8>, + _dst: AArch64GeneralReg, + _offset: i32, + _src: AArch64GeneralReg, + ) { + todo!() + } + #[inline(always)] fn movsx_reg64_base32(buf: &mut Vec<'_, u8>, dst: AArch64GeneralReg, offset: i32, size: u8) { debug_assert!(size <= 8); @@ -740,12 +843,12 @@ impl Assembler for AArch64Assembler { } #[inline(always)] fn sub_reg64_reg64_reg64( - _buf: &mut Vec<'_, u8>, - _dst: AArch64GeneralReg, - _src1: AArch64GeneralReg, - _src2: AArch64GeneralReg, + buf: &mut Vec<'_, u8>, + dst: AArch64GeneralReg, + src1: AArch64GeneralReg, + src2: AArch64GeneralReg, ) { - todo!("registers subtractions for AArch64"); + sub_reg64_reg64_reg64(buf, dst, src1, src2); } #[inline(always)] @@ -788,6 +891,18 @@ impl Assembler for AArch64Assembler { todo!("registers unsigned less than for AArch64"); } + #[inline(always)] + fn cmp_freg_freg_reg64( + _buf: &mut Vec<'_, u8>, + _dst: AArch64GeneralReg, + _src1: AArch64FloatReg, + _src2: AArch64FloatReg, + _width: FloatWidth, + _operation: CompareOperation, + ) { + todo!("registers float comparison for AArch64"); + } + #[inline(always)] fn igt_reg64_reg64_reg64( _buf: &mut Vec<'_, u8>, @@ -938,6 +1053,14 @@ impl Assembler for AArch64Assembler { { todo!("sar for AArch64") } + + fn sqrt_freg64_freg64(_buf: &mut Vec<'_, u8>, _dst: AArch64FloatReg, _src: AArch64FloatReg) { + todo!("sqrt") + } + + fn sqrt_freg32_freg32(_buf: &mut Vec<'_, u8>, _dst: AArch64FloatReg, _src: AArch64FloatReg) { + todo!("sqrt") + } } impl AArch64Assembler {} @@ -1354,6 +1477,19 @@ fn sub_reg64_reg64_imm12( buf.extend(inst.bytes()); } +/// `SUB Xd, Xm, Xn` -> Subtract Xm and Xn and place the result into Xd. +#[inline(always)] +fn sub_reg64_reg64_reg64( + buf: &mut Vec<'_, u8>, + dst: AArch64GeneralReg, + src1: AArch64GeneralReg, + src2: AArch64GeneralReg, +) { + let inst = ArithmeticShifted::new(true, false, ShiftType::LSL, 0, src2, src1, dst); + + buf.extend(inst.bytes()); +} + /// `RET Xn` -> Return to the address stored in Xn. #[inline(always)] fn ret_reg64(buf: &mut Vec<'_, u8>, xn: AArch64GeneralReg) { @@ -1574,6 +1710,34 @@ mod tests { ); } + #[test] + fn test_sub_reg64_reg64_reg64() { + disassembler_test!( + sub_reg64_reg64_reg64, + |reg1: AArch64GeneralReg, reg2: AArch64GeneralReg, reg3: AArch64GeneralReg| { + if reg2 == AArch64GeneralReg::ZRSP { + // When the second register is ZR, it gets disassembled as neg, + // which is an alias for sub. + format!( + "neg {}, {}", + reg1.capstone_string(UsesZR), + reg3.capstone_string(UsesZR) + ) + } else { + format!( + "sub {}, {}, {}", + reg1.capstone_string(UsesZR), + reg2.capstone_string(UsesZR), + reg3.capstone_string(UsesZR) + ) + } + }, + ALL_GENERAL_REGS, + ALL_GENERAL_REGS, + ALL_GENERAL_REGS + ); + } + #[test] fn test_ret_reg64() { disassembler_test!( diff --git a/crates/compiler/gen_dev/src/generic64/mod.rs b/crates/compiler/gen_dev/src/generic64/mod.rs index 778274b086..81e8f6bc7a 100644 --- a/crates/compiler/gen_dev/src/generic64/mod.rs +++ b/crates/compiler/gen_dev/src/generic64/mod.rs @@ -2,7 +2,7 @@ use crate::{ single_register_floats, single_register_int_builtins, single_register_integers, Backend, Env, Relocation, }; -use bumpalo::collections::Vec; +use bumpalo::collections::{CollectIn, Vec}; use roc_builtins::bitcode::{self, FloatWidth, IntWidth}; use roc_collections::all::MutMap; use roc_error_macros::internal_error; @@ -113,6 +113,13 @@ pub trait CallConv: Sized + Copy { // base32 is similar to stack based instructions but they reference the base/frame pointer. fn mov_freg64_base32(buf: &mut Vec<'_, u8>, dst: FloatReg, offset: i32); - fn mov_reg64_base32(buf: &mut Vec<'_, u8>, dst: GeneralReg, offset: i32); - fn mov_base32_freg64(buf: &mut Vec<'_, u8>, offset: i32, src: FloatReg); - fn mov_base32_reg64(buf: &mut Vec<'_, u8>, offset: i32, src: GeneralReg); + fn mov_reg64_base32(buf: &mut Vec<'_, u8>, dst: GeneralReg, offset: i32); + fn mov_reg32_base32(buf: &mut Vec<'_, u8>, dst: GeneralReg, offset: i32); + fn mov_reg16_base32(buf: &mut Vec<'_, u8>, dst: GeneralReg, offset: i32); + fn mov_reg8_base32(buf: &mut Vec<'_, u8>, dst: GeneralReg, offset: i32); + + fn mov_base32_freg64(buf: &mut Vec<'_, u8>, offset: i32, src: FloatReg); + + fn mov_base32_reg64(buf: &mut Vec<'_, u8>, offset: i32, src: GeneralReg); + fn mov_base32_reg32(buf: &mut Vec<'_, u8>, offset: i32, src: GeneralReg); + fn mov_base32_reg16(buf: &mut Vec<'_, u8>, offset: i32, src: GeneralReg); + fn mov_base32_reg8(buf: &mut Vec<'_, u8>, offset: i32, src: GeneralReg); + + // move from memory (a pointer) to register fn mov_reg64_mem64_offset32( buf: &mut Vec<'_, u8>, dst: GeneralReg, src: GeneralReg, offset: i32, ); + fn mov_reg32_mem32_offset32( + buf: &mut Vec<'_, u8>, + dst: GeneralReg, + src: GeneralReg, + offset: i32, + ); + fn mov_reg16_mem16_offset32( + buf: &mut Vec<'_, u8>, + dst: GeneralReg, + src: GeneralReg, + offset: i32, + ); + fn mov_reg8_mem8_offset32(buf: &mut Vec<'_, u8>, dst: GeneralReg, src: GeneralReg, offset: i32); + + // move from register to memory fn mov_mem64_offset32_reg64( buf: &mut Vec<'_, u8>, dst: GeneralReg, offset: i32, src: GeneralReg, ); + fn mov_mem32_offset32_reg32( + buf: &mut Vec<'_, u8>, + dst: GeneralReg, + offset: i32, + src: GeneralReg, + ); + fn mov_mem16_offset32_reg16( + buf: &mut Vec<'_, u8>, + dst: GeneralReg, + offset: i32, + src: GeneralReg, + ); + fn mov_mem8_offset32_reg8(buf: &mut Vec<'_, u8>, dst: GeneralReg, offset: i32, src: GeneralReg); + + fn movesd_mem64_offset32_freg64( + buf: &mut Vec<'_, u8>, + ptr: GeneralReg, + offset: i32, + src: FloatReg, + ); /// Sign extends the data at `offset` with `size` as it copies it to `dst` /// size must be less than or equal to 8. @@ -265,6 +317,9 @@ pub trait Assembler: Sized + Copy { fn mov_stack32_freg64(buf: &mut Vec<'_, u8>, offset: i32, src: FloatReg); fn mov_stack32_reg64(buf: &mut Vec<'_, u8>, offset: i32, src: GeneralReg); + fn sqrt_freg64_freg64(buf: &mut Vec<'_, u8>, dst: FloatReg, src: FloatReg); + fn sqrt_freg32_freg32(buf: &mut Vec<'_, u8>, dst: FloatReg, src: FloatReg); + fn neg_reg64_reg64(buf: &mut Vec<'_, u8>, dst: GeneralReg, src: GeneralReg); fn mul_freg32_freg32_freg32( buf: &mut Vec<'_, u8>, @@ -361,6 +416,15 @@ pub trait Assembler: Sized + Copy { src2: GeneralReg, ); + fn cmp_freg_freg_reg64( + buf: &mut Vec<'_, u8>, + dst: GeneralReg, + src1: FloatReg, + src2: FloatReg, + width: FloatWidth, + operation: CompareOperation, + ); + fn igt_reg64_reg64_reg64( buf: &mut Vec<'_, u8>, dst: GeneralReg, @@ -958,6 +1022,30 @@ impl< } } + fn build_num_sub_checked( + &mut self, + dst: &Symbol, + src1: &Symbol, + src2: &Symbol, + num_layout: &InLayout<'a>, + return_layout: &InLayout<'a>, + ) { + let function_name = match self.interner().get(*num_layout) { + Layout::Builtin(Builtin::Int(width)) => &bitcode::NUM_SUB_CHECKED_INT[width], + Layout::Builtin(Builtin::Float(width)) => &bitcode::NUM_SUB_CHECKED_FLOAT[width], + Layout::Builtin(Builtin::Decimal) => bitcode::DEC_SUB_WITH_OVERFLOW, + x => internal_error!("NumSubChecked is not defined for {:?}", x), + }; + + self.build_fn_call( + dst, + function_name.to_string(), + &[*src1, *src2], + &[*num_layout, *num_layout], + return_layout, + ) + } + fn build_num_mul(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &InLayout<'a>) { use Builtin::Int; @@ -1102,7 +1190,7 @@ impl< fn build_eq(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, arg_layout: &InLayout<'a>) { match *arg_layout { - single_register_int_builtins!() => { + single_register_int_builtins!() | Layout::BOOL => { let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst); let src1_reg = self .storage_manager @@ -1112,13 +1200,23 @@ impl< .load_to_general_reg(&mut self.buf, src2); ASM::eq_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg); } + Layout::STR => { + // use a zig call + self.build_fn_call( + dst, + bitcode::STR_EQUAL.to_string(), + &[*src1, *src2], + &[Layout::STR, Layout::STR], + &Layout::BOOL, + ) + } x => todo!("NumEq: layout, {:?}", x), } } fn build_neq(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, arg_layout: &InLayout<'a>) { - match self.layout_interner.get(*arg_layout) { - Layout::Builtin(Builtin::Int(IntWidth::I64 | IntWidth::U64)) => { + match *arg_layout { + single_register_int_builtins!() | Layout::BOOL => { let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst); let src1_reg = self .storage_manager @@ -1128,10 +1226,44 @@ impl< .load_to_general_reg(&mut self.buf, src2); ASM::neq_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg); } + Layout::STR => { + self.build_fn_call( + dst, + bitcode::STR_EQUAL.to_string(), + &[*src1, *src2], + &[Layout::STR, Layout::STR], + &Layout::BOOL, + ); + + // negate the result + let tmp = &Symbol::DEV_TMP; + let tmp_reg = self.storage_manager.claim_general_reg(&mut self.buf, tmp); + ASM::mov_reg64_imm64(&mut self.buf, tmp_reg, 164); + + let dst_reg = self.storage_manager.load_to_general_reg(&mut self.buf, dst); + ASM::neq_reg64_reg64_reg64(&mut self.buf, dst_reg, dst_reg, tmp_reg); + } x => todo!("NumNeq: layout, {:?}", x), } } + fn build_not(&mut self, dst: &Symbol, src: &Symbol, arg_layout: &InLayout<'a>) { + match *arg_layout { + Layout::BOOL => { + let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst); + let src_reg = self.storage_manager.load_to_general_reg(&mut self.buf, src); + + // Not would usually be implemented as `xor src, -1` followed by `and src, 1` + // but since our booleans are represented as `0x101010101010101` currently, we can simply XOR with that + let bool_val = [true as u8; 8]; + ASM::mov_reg64_imm64(&mut self.buf, dst_reg, i64::from_ne_bytes(bool_val)); + ASM::xor_reg64_reg64_reg64(&mut self.buf, src_reg, src_reg, dst_reg); + ASM::mov_reg64_reg64(&mut self.buf, dst_reg, src_reg); + } + x => todo!("Not: layout, {:?}", x), + } + } + fn build_num_lt( &mut self, dst: &Symbol, @@ -1160,6 +1292,20 @@ impl< .load_to_general_reg(&mut self.buf, src2); ASM::ult_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg); } + Layout::Builtin(Builtin::Float(width)) => { + let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst); + let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1); + let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2); + + ASM::cmp_freg_freg_reg64( + &mut self.buf, + dst_reg, + src1_reg, + src2_reg, + width, + CompareOperation::LessThan, + ); + } x => todo!("NumLt: layout, {:?}", x), } } @@ -1192,6 +1338,20 @@ impl< .load_to_general_reg(&mut self.buf, src2); ASM::ugt_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg); } + Layout::Builtin(Builtin::Float(width)) => { + let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst); + let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1); + let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2); + + ASM::cmp_freg_freg_reg64( + &mut self.buf, + dst_reg, + src1_reg, + src2_reg, + width, + CompareOperation::GreaterThan, + ); + } x => todo!("NumGt: layout, {:?}", x), } } @@ -1272,6 +1432,26 @@ impl< .load_to_general_reg(&mut self.buf, src2); ASM::lte_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg); } + Layout::F64 | Layout::F32 => { + let width = if *arg_layout == Layout::F64 { + FloatWidth::F64 + } else { + FloatWidth::F32 + }; + + let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst); + let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1); + let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2); + + ASM::cmp_freg_freg_reg64( + &mut self.buf, + dst_reg, + src1_reg, + src2_reg, + width, + CompareOperation::LessThanOrEqual, + ); + } x => todo!("NumLte: layout, {:?}", x), } } @@ -1294,6 +1474,26 @@ impl< .load_to_general_reg(&mut self.buf, src2); ASM::gte_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg); } + Layout::F64 | Layout::F32 => { + let width = if *arg_layout == Layout::F64 { + FloatWidth::F64 + } else { + FloatWidth::F32 + }; + + let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst); + let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1); + let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2); + + ASM::cmp_freg_freg_reg64( + &mut self.buf, + dst_reg, + src1_reg, + src2_reg, + width, + CompareOperation::GreaterThanOrEqual, + ); + } x => todo!("NumGte: layout, {:?}", x), } } @@ -1518,43 +1718,14 @@ impl< ASM::add_reg64_reg64_reg64(buf, tmp, tmp, list_ptr); let element_ptr = tmp; - match *ret_layout { - single_register_integers!() if ret_stack_size == 8 => { - let dst_reg = storage_manager.claim_general_reg(buf, dst); - ASM::mov_reg64_mem64_offset32(buf, dst_reg, element_ptr, 0); - } - single_register_floats!() => { - let dst_reg = storage_manager.claim_float_reg(buf, dst); - ASM::mov_freg64_freg64(buf, dst_reg, CC::FLOAT_RETURN_REGS[0]); - } - Layout::STR => { - // the `list_ptr` register is now unused, and we can use it as scratch space - let tmp_reg = list_ptr; - - Self::unbox_str_or_list( - buf, - storage_manager, - *dst, - element_ptr, - tmp_reg, - ); - } - other => { - // - match self.layout_interner.get(other) { - Layout::Boxed(_) => { - let dst_reg = storage_manager.claim_general_reg(buf, dst); - ASM::mov_reg64_reg64(buf, dst_reg, CC::GENERAL_RETURN_REGS[0]); - } - _ => { - todo!( - "cannot load {} from the heap yet", - self.layout_interner.dbg(other) - ); - } - } - } - } + Self::ptr_read( + buf, + storage_manager, + self.layout_interner, + element_ptr, + *ret_layout, + *dst, + ); }); }, ); @@ -1822,10 +1993,11 @@ impl< fn create_array( &mut self, sym: &Symbol, - element_layout: &InLayout<'a>, - elements: &'a [ListLiteralElement<'a>], + element_in_layout: &InLayout<'a>, + elements: &[ListLiteralElement<'a>], ) { - let element_width = self.layout_interner.stack_size(*element_layout) as u64; + let element_layout = self.layout_interner.get(*element_in_layout); + let element_width = self.layout_interner.stack_size(*element_in_layout) as u64; // load the total size of the data we want to store (excludes refcount) let data_bytes_symbol = Symbol::DEV_TMP; @@ -1855,54 +2027,34 @@ impl< .load_to_general_reg(&mut self.buf, &Symbol::DEV_TMP3); // Copy everything into output array. - let mut elem_offset = 0; + let mut element_offset = 0; for elem in elements { // TODO: this could be a lot faster when loading large lists // if we move matching on the element layout to outside this loop. // It also greatly bloats the code here. // Refactor this and switch to one external match. // We also could make loadining indivitual literals much faster - let elem_sym = match elem { - ListLiteralElement::Symbol(sym) => sym, + let element_symbol = match elem { + ListLiteralElement::Symbol(sym) => *sym, ListLiteralElement::Literal(lit) => { - self.load_literal(&Symbol::DEV_TMP, element_layout, lit); - &Symbol::DEV_TMP + self.load_literal(&Symbol::DEV_TMP, element_in_layout, lit); + Symbol::DEV_TMP } }; - // TODO: Expand to all types. - match self.layout_interner.get(*element_layout) { - Layout::Builtin(Builtin::Int(IntWidth::I64 | IntWidth::U64) | Builtin::Bool) => { - let sym_reg = self - .storage_manager - .load_to_general_reg(&mut self.buf, elem_sym); - ASM::mov_mem64_offset32_reg64(&mut self.buf, ptr_reg, elem_offset, sym_reg); - } - _ if element_width == 0 => {} - _ if element_width > 8 => { - let (from_offset, size) = self.storage_manager.stack_offset_and_size(elem_sym); - debug_assert!(from_offset % 8 == 0); - debug_assert!(size % 8 == 0); - debug_assert_eq!(size as u64, element_width); - self.storage_manager.with_tmp_general_reg( - &mut self.buf, - |_storage_manager, buf, tmp_reg| { - for i in (0..size as i32).step_by(8) { - ASM::mov_reg64_base32(buf, tmp_reg, from_offset + i); - ASM::mov_mem64_offset32_reg64( - buf, - ptr_reg, - elem_offset + i, - tmp_reg, - ); - } - }, - ); - } - x => todo!("copying data to list with layout, {:?}", x), - } - elem_offset += element_width as i32; - if elem_sym == &Symbol::DEV_TMP { - self.free_symbol(elem_sym); + + Self::ptr_write( + &mut self.buf, + &mut self.storage_manager, + ptr_reg, + element_offset, + element_width, + element_layout, + element_symbol, + ); + + element_offset += element_width as i32; + if element_symbol == Symbol::DEV_TMP { + self.free_symbol(&element_symbol); } } @@ -2000,38 +2152,15 @@ impl< let element_width = self.layout_interner.stack_size(element_layout) as u64; let element_offset = 0; - // TODO: Expand to all types. - match self.layout_interner.get(element_layout) { - Layout::Builtin(Builtin::Int(IntWidth::I64 | IntWidth::U64)) => { - let sym_reg = self - .storage_manager - .load_to_general_reg(&mut self.buf, &value); - ASM::mov_mem64_offset32_reg64(&mut self.buf, ptr_reg, element_offset, sym_reg); - } - _ if element_width == 0 => {} - _ if element_width > 8 => { - let (from_offset, size) = self.storage_manager.stack_offset_and_size(&value); - debug_assert!(from_offset % 8 == 0); - debug_assert!(size % 8 == 0); - debug_assert_eq!(size as u64, element_width); - self.storage_manager.with_tmp_general_reg( - &mut self.buf, - |_storage_manager, buf, tmp_reg| { - // a crude memcpy - for i in (0..size as i32).step_by(8) { - ASM::mov_reg64_base32(buf, tmp_reg, from_offset + i); - ASM::mov_mem64_offset32_reg64( - buf, - ptr_reg, - element_offset + i, - tmp_reg, - ); - } - }, - ); - } - x => todo!("copying data to list with layout, {:?}", x), - } + Self::ptr_write( + &mut self.buf, + &mut self.storage_manager, + ptr_reg, + element_offset, + element_width, + self.layout_interner.get(element_layout), + value, + ); if value == Symbol::DEV_TMP { self.free_symbol(&value); @@ -2049,25 +2178,14 @@ impl< .storage_manager .load_to_general_reg(&mut self.buf, &ptr); - let ret_stack_size = self.layout_interner.stack_size(element_layout); - - match element_layout { - single_register_integers!() if ret_stack_size == 8 => { - let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, &dst); - ASM::mov_reg64_mem64_offset32(&mut self.buf, dst_reg, ptr_reg, 0); - } - Layout::STR => { - self.storage_manager.with_tmp_general_reg( - &mut self.buf, - |storage_manager, buf, tmp_reg| { - Self::unbox_str_or_list(buf, storage_manager, dst, ptr_reg, tmp_reg); - }, - ); - } - _ => { - todo!("unboxing of {:?}", self.layout_interner.dbg(element_layout)) - } - } + Self::ptr_read( + &mut self.buf, + &mut self.storage_manager, + self.layout_interner, + ptr_reg, + element_layout, + dst, + ); } fn get_tag_id(&mut self, sym: &Symbol, structure: &Symbol, union_layout: &UnionLayout<'a>) { @@ -2116,6 +2234,33 @@ impl< let val = *x; ASM::mov_reg64_imm64(&mut self.buf, reg, i128::from_ne_bytes(val) as i64); } + ( + Literal::Int(bytes), + Layout::Builtin(Builtin::Int(IntWidth::I128 | IntWidth::U128)), + ) => { + self.storage_manager.with_tmp_general_reg( + &mut self.buf, + |storage_manager, buf, reg| { + let base_offset = storage_manager.claim_stack_area(sym, 16); + + let mut num_bytes = [0; 8]; + num_bytes.copy_from_slice(&bytes[..8]); + let num = i64::from_ne_bytes(num_bytes); + ASM::mov_reg64_imm64(buf, reg, num); + ASM::mov_base32_reg64(buf, base_offset, reg); + + num_bytes.copy_from_slice(&bytes[8..16]); + let num = i64::from_ne_bytes(num_bytes); + ASM::mov_reg64_imm64(buf, reg, num); + ASM::mov_base32_reg64(buf, base_offset + 8, reg); + }, + ); + } + (Literal::Byte(x), Layout::Builtin(Builtin::Int(IntWidth::U8 | IntWidth::I8))) => { + let reg = self.storage_manager.claim_general_reg(&mut self.buf, sym); + let val = *x; + ASM::mov_reg64_imm64(&mut self.buf, reg, val as i64); + } (Literal::Bool(x), Layout::Builtin(Builtin::Bool)) => { let reg = self.storage_manager.claim_general_reg(&mut self.buf, sym); let val = [*x as u8; 16]; @@ -2131,15 +2276,11 @@ impl< let val = *x as f32; ASM::mov_freg32_imm32(&mut self.buf, &mut self.relocs, reg, val); } - (Literal::Str(x), Layout::Builtin(Builtin::Str)) if x.len() < 24 => { - // Load small string. + (Literal::Decimal(bytes), Layout::Builtin(Builtin::Decimal)) => { self.storage_manager.with_tmp_general_reg( &mut self.buf, |storage_manager, buf, reg| { - let base_offset = storage_manager.claim_stack_area(sym, 24); - let mut bytes = [0; 24]; - bytes[..x.len()].copy_from_slice(x.as_bytes()); - bytes[23] = (x.len() as u8) | 0b1000_0000; + let base_offset = storage_manager.claim_stack_area(sym, 16); let mut num_bytes = [0; 8]; num_bytes.copy_from_slice(&bytes[..8]); @@ -2151,14 +2292,49 @@ impl< let num = i64::from_ne_bytes(num_bytes); ASM::mov_reg64_imm64(buf, reg, num); ASM::mov_base32_reg64(buf, base_offset + 8, reg); - - num_bytes.copy_from_slice(&bytes[16..]); - let num = i64::from_ne_bytes(num_bytes); - ASM::mov_reg64_imm64(buf, reg, num); - ASM::mov_base32_reg64(buf, base_offset + 16, reg); }, ); } + (Literal::Str(x), Layout::Builtin(Builtin::Str)) => { + if x.len() < 24 { + // Load small string. + self.storage_manager.with_tmp_general_reg( + &mut self.buf, + |storage_manager, buf, reg| { + let base_offset = storage_manager.claim_stack_area(sym, 24); + let mut bytes = [0; 24]; + bytes[..x.len()].copy_from_slice(x.as_bytes()); + bytes[23] = (x.len() as u8) | 0b1000_0000; + + let mut num_bytes = [0; 8]; + num_bytes.copy_from_slice(&bytes[..8]); + let num = i64::from_ne_bytes(num_bytes); + ASM::mov_reg64_imm64(buf, reg, num); + ASM::mov_base32_reg64(buf, base_offset, reg); + + num_bytes.copy_from_slice(&bytes[8..16]); + let num = i64::from_ne_bytes(num_bytes); + ASM::mov_reg64_imm64(buf, reg, num); + ASM::mov_base32_reg64(buf, base_offset + 8, reg); + + num_bytes.copy_from_slice(&bytes[16..]); + let num = i64::from_ne_bytes(num_bytes); + ASM::mov_reg64_imm64(buf, reg, num); + ASM::mov_base32_reg64(buf, base_offset + 16, reg); + }, + ); + } else { + // load large string (pretend it's a `List U8`). We should move this data into + // the binary eventually because our RC algorithm won't free this value + let elements: Vec<_> = x + .as_bytes() + .iter() + .map(|b| ListLiteralElement::Literal(Literal::Byte(*b))) + .collect_in(self.storage_manager.env.arena); + + self.create_array(sym, &Layout::U8, elements.into_bump_slice()) + } + } x => todo!("loading literal, {:?}", x), } } @@ -2398,6 +2574,18 @@ impl< } } } + + fn build_num_sqrt(&mut self, dst: Symbol, src: Symbol, float_width: FloatWidth) { + let buf = &mut self.buf; + + let dst_reg = self.storage_manager.claim_float_reg(buf, &dst); + let src_reg = self.storage_manager.load_to_float_reg(buf, &src); + + match float_width { + FloatWidth::F32 => ASM::sqrt_freg32_freg32(buf, dst_reg, src_reg), + FloatWidth::F64 => ASM::sqrt_freg64_freg64(buf, dst_reg, src_reg), + } + } } /// This impl block is for ir related instructions that need backend specific information. @@ -2445,6 +2633,115 @@ impl< ASM::mov_base32_reg64(buf, base_offset + 16, tmp_reg); } + fn ptr_read( + buf: &mut Vec<'a, u8>, + storage_manager: &mut StorageManager<'a, 'r, GeneralReg, FloatReg, ASM, CC>, + layout_interner: &STLayoutInterner<'a>, + ptr_reg: GeneralReg, + element_in_layout: InLayout<'a>, + dst: Symbol, + ) { + match layout_interner.get(element_in_layout) { + Layout::Builtin(builtin) => match builtin { + Builtin::Int(int_width) => match int_width { + IntWidth::I128 | IntWidth::U128 => { + // can we treat this as 2 u64's? + todo!() + } + IntWidth::I64 | IntWidth::U64 => { + let dst_reg = storage_manager.claim_general_reg(buf, &dst); + ASM::mov_reg64_mem64_offset32(buf, dst_reg, ptr_reg, 0); + } + IntWidth::I32 | IntWidth::U32 => { + let dst_reg = storage_manager.claim_general_reg(buf, &dst); + ASM::mov_reg32_mem32_offset32(buf, dst_reg, ptr_reg, 0); + } + IntWidth::I16 | IntWidth::U16 => { + let dst_reg = storage_manager.claim_general_reg(buf, &dst); + ASM::mov_reg16_mem16_offset32(buf, dst_reg, ptr_reg, 0); + } + IntWidth::I8 | IntWidth::U8 => { + let dst_reg = storage_manager.claim_general_reg(buf, &dst); + ASM::mov_reg8_mem8_offset32(buf, dst_reg, ptr_reg, 0); + } + }, + Builtin::Float(_) => { + let dst_reg = storage_manager.claim_float_reg(buf, &dst); + ASM::mov_freg64_freg64(buf, dst_reg, CC::FLOAT_RETURN_REGS[0]); + } + Builtin::Bool => { + // the same as an 8-bit integer + let dst_reg = storage_manager.claim_general_reg(buf, &dst); + ASM::mov_reg8_mem8_offset32(buf, dst_reg, ptr_reg, 0); + } + Builtin::Decimal => { + // same as 128-bit integer + } + Builtin::Str | Builtin::List(_) => { + storage_manager.with_tmp_general_reg(buf, |storage_manager, buf, tmp_reg| { + Self::unbox_str_or_list(buf, storage_manager, dst, ptr_reg, tmp_reg); + }); + } + }, + + Layout::Boxed(_) => { + // the same as 64-bit integer (for 64-bit targets) + let dst_reg = storage_manager.claim_general_reg(buf, &dst); + ASM::mov_reg64_mem64_offset32(buf, dst_reg, ptr_reg, 0); + } + + _ => todo!("unboxing of {:?}", layout_interner.dbg(element_in_layout)), + } + } + + fn ptr_write( + buf: &mut Vec<'a, u8>, + storage_manager: &mut StorageManager<'a, 'r, GeneralReg, FloatReg, ASM, CC>, + ptr_reg: GeneralReg, + element_offset: i32, + element_width: u64, + element_layout: Layout<'a>, + value: Symbol, + ) { + match element_layout { + Layout::Builtin(Builtin::Int(IntWidth::I64 | IntWidth::U64)) => { + let sym_reg = storage_manager.load_to_general_reg(buf, &value); + ASM::mov_mem64_offset32_reg64(buf, ptr_reg, element_offset, sym_reg); + } + Layout::Builtin(Builtin::Int(IntWidth::I32 | IntWidth::U32)) => { + let sym_reg = storage_manager.load_to_general_reg(buf, &value); + ASM::mov_mem32_offset32_reg32(buf, ptr_reg, element_offset, sym_reg); + } + Layout::Builtin(Builtin::Int(IntWidth::I16 | IntWidth::U16)) => { + let sym_reg = storage_manager.load_to_general_reg(buf, &value); + ASM::mov_mem16_offset32_reg16(buf, ptr_reg, element_offset, sym_reg); + } + Layout::Builtin(Builtin::Int(IntWidth::I8 | IntWidth::U8) | Builtin::Bool) => { + let sym_reg = storage_manager.load_to_general_reg(buf, &value); + ASM::mov_mem8_offset32_reg8(buf, ptr_reg, element_offset, sym_reg); + } + Layout::Builtin(Builtin::Float(FloatWidth::F64 | FloatWidth::F32)) => { + let sym_reg = storage_manager.load_to_float_reg(buf, &value); + ASM::movesd_mem64_offset32_freg64(buf, ptr_reg, element_offset, sym_reg); + } + _ if element_width == 0 => {} + _ if element_width > 8 => { + let (from_offset, size) = storage_manager.stack_offset_and_size(&value); + debug_assert!(from_offset % 8 == 0); + debug_assert!(size % 8 == 0); + debug_assert_eq!(size as u64, element_width); + storage_manager.with_tmp_general_reg(buf, |_storage_manager, buf, tmp_reg| { + // a crude memcpy + for i in (0..size as i32).step_by(8) { + ASM::mov_reg64_base32(buf, tmp_reg, from_offset + i); + ASM::mov_mem64_offset32_reg64(buf, ptr_reg, element_offset + i, tmp_reg); + } + }); + } + x => todo!("copying data to list with layout, {:?}", x), + } + } + /// Updates a jump instruction to a new offset and returns the number of bytes written. fn update_jmp_imm32_offset( &mut self, diff --git a/crates/compiler/gen_dev/src/generic64/storage.rs b/crates/compiler/gen_dev/src/generic64/storage.rs index 6c72b462a2..7e2eb7d4b4 100644 --- a/crates/compiler/gen_dev/src/generic64/storage.rs +++ b/crates/compiler/gen_dev/src/generic64/storage.rs @@ -9,7 +9,6 @@ use roc_collections::all::{MutMap, MutSet}; use roc_error_macros::internal_error; use roc_module::symbol::Symbol; use roc_mono::{ - borrow::Ownership, ir::{JoinPointId, Param}, layout::{ Builtin, InLayout, Layout, LayoutInterner, STLayoutInterner, TagIdIntType, UnionLayout, @@ -315,7 +314,7 @@ impl< reg: Some(Float(_)), .. }) => { - internal_error!("Cannot load floating point symbol into GeneralReg: {}", sym) + internal_error!("Cannot load floating point symbol into GeneralReg: {sym:?}") } Stack(Primitive { reg: None, @@ -350,8 +349,10 @@ impl< self.free_reference(sym); reg } - Stack(Complex { .. }) => { - internal_error!("Cannot load large values into general registers: {}", sym) + Stack(Complex { size, .. }) => { + internal_error!( + "Cannot load large values (size {size}) into general registers: {sym:?}", + ) } NoData => { internal_error!("Cannot load no data into general registers: {}", sym) @@ -448,7 +449,7 @@ impl< reg: Some(Float(_)), .. }) => { - internal_error!("Cannot load floating point symbol into GeneralReg: {}", sym) + internal_error!("Cannot load floating point symbol into GeneralReg: {sym:?}",) } Stack(Primitive { reg: None, @@ -458,19 +459,25 @@ impl< ASM::mov_reg64_base32(buf, reg, *base_offset); } Stack(ReferencedPrimitive { - base_offset, size, .. - }) if base_offset % 8 == 0 && *size == 8 => { - // The primitive is aligned and the data is exactly 8 bytes, treat it like regular stack. - ASM::mov_reg64_base32(buf, reg, *base_offset); + base_offset, + size, + sign_extend, + }) => { + debug_assert!(*size <= 8); + + if *sign_extend { + ASM::movsx_reg64_base32(buf, reg, *base_offset, *size as u8) + } else { + ASM::movzx_reg64_base32(buf, reg, *base_offset, *size as u8) + } } - Stack(ReferencedPrimitive { .. }) => { - todo!("loading referenced primitives") - } - Stack(Complex { .. }) => { - internal_error!("Cannot load large values into general registers: {}", sym) + Stack(Complex { size, .. }) => { + internal_error!( + "Cannot load large values (size {size}) into general registers: {sym:?}", + ) } NoData => { - internal_error!("Cannot load no data into general registers: {}", sym) + internal_error!("Cannot load no data into general registers: {:?}", sym) } } } @@ -553,7 +560,7 @@ impl< self.allocation_map.insert(*sym, owned_data); self.symbol_storage_map.insert( *sym, - Stack(if is_primitive(layout) { + Stack(if is_primitive(layout_interner, layout) { ReferencedPrimitive { base_offset: data_offset, size, @@ -739,15 +746,73 @@ impl< layout: &InLayout<'a>, ) { match layout_interner.get(*layout) { - Layout::Builtin(Builtin::Int(IntWidth::I64 | IntWidth::U64)) => { + Layout::Builtin(builtin) => match builtin { + Builtin::Int(int_width) => match int_width { + IntWidth::I128 | IntWidth::U128 => { + let (from_offset, size) = self.stack_offset_and_size(sym); + debug_assert_eq!(from_offset % 8, 0); + debug_assert_eq!(size % 8, 0); + debug_assert_eq!(size, layout_interner.stack_size(*layout)); + self.copy_to_stack_offset(buf, size, from_offset, to_offset) + } + IntWidth::I64 | IntWidth::U64 => { + debug_assert_eq!(to_offset % 8, 0); + let reg = self.load_to_general_reg(buf, sym); + ASM::mov_base32_reg64(buf, to_offset, reg); + } + IntWidth::I32 | IntWidth::U32 => { + debug_assert_eq!(to_offset % 4, 0); + let reg = self.load_to_general_reg(buf, sym); + ASM::mov_base32_reg32(buf, to_offset, reg); + } + IntWidth::I16 | IntWidth::U16 => { + debug_assert_eq!(to_offset % 2, 0); + let reg = self.load_to_general_reg(buf, sym); + ASM::mov_base32_reg16(buf, to_offset, reg); + } + IntWidth::I8 | IntWidth::U8 => { + let reg = self.load_to_general_reg(buf, sym); + ASM::mov_base32_reg8(buf, to_offset, reg); + } + }, + + Builtin::Float(float_width) => match float_width { + FloatWidth::F64 => { + debug_assert_eq!(to_offset % 8, 0); + let reg = self.load_to_float_reg(buf, sym); + ASM::mov_base32_freg64(buf, to_offset, reg); + } + FloatWidth::F32 => todo!(), + }, + Builtin::Bool => { + // same as 8-bit integer + let reg = self.load_to_general_reg(buf, sym); + ASM::mov_base32_reg8(buf, to_offset, reg); + } + Builtin::Decimal => todo!(), + Builtin::Str | Builtin::List(_) => { + let (from_offset, size) = self.stack_offset_and_size(sym); + debug_assert_eq!(from_offset % 8, 0); + debug_assert_eq!(size % 8, 0); + debug_assert_eq!(size, layout_interner.stack_size(*layout)); + self.copy_to_stack_offset(buf, size, from_offset, to_offset) + } + }, + Layout::Boxed(_) => { + // like a 64-bit integer debug_assert_eq!(to_offset % 8, 0); let reg = self.load_to_general_reg(buf, sym); ASM::mov_base32_reg64(buf, to_offset, reg); } - Layout::Builtin(Builtin::Float(FloatWidth::F64)) => { - debug_assert_eq!(to_offset % 8, 0); - let reg = self.load_to_float_reg(buf, sym); - ASM::mov_base32_freg64(buf, to_offset, reg); + Layout::LambdaSet(lambda_set) => { + // like its runtime representation + self.copy_symbol_to_stack_offset( + layout_interner, + buf, + to_offset, + sym, + &lambda_set.runtime_representation(), + ) } _ if layout_interner.stack_size(*layout) == 0 => {} // TODO: Verify this is always true. @@ -756,20 +821,64 @@ impl< // Later, it will be reloaded and stored in refcounted as needed. _ if layout_interner.stack_size(*layout) > 8 => { let (from_offset, size) = self.stack_offset_and_size(sym); - debug_assert!(from_offset % 8 == 0); - debug_assert!(size % 8 == 0); + debug_assert_eq!(from_offset % 8, 0); + debug_assert_eq!(size % 8, 0); debug_assert_eq!(size, layout_interner.stack_size(*layout)); - self.with_tmp_general_reg(buf, |_storage_manager, buf, reg| { - for i in (0..size as i32).step_by(8) { - ASM::mov_reg64_base32(buf, reg, from_offset + i); - ASM::mov_base32_reg64(buf, to_offset + i, reg); - } - }); + self.copy_to_stack_offset(buf, size, from_offset, to_offset) } x => todo!("copying data to the stack with layout, {:?}", x), } } + pub fn copy_to_stack_offset( + &mut self, + buf: &mut Vec<'a, u8>, + size: u32, + from_offset: i32, + to_offset: i32, + ) { + let mut copied = 0; + let size = size as i32; + + self.with_tmp_general_reg(buf, |_storage_manager, buf, reg| { + if size - copied >= 8 { + for _ in (0..(size - copied)).step_by(8) { + ASM::mov_reg64_base32(buf, reg, from_offset + copied); + ASM::mov_base32_reg64(buf, to_offset + copied, reg); + + copied += 8; + } + } + + if size - copied >= 4 { + for _ in (0..(size - copied)).step_by(4) { + ASM::mov_reg32_base32(buf, reg, from_offset + copied); + ASM::mov_base32_reg32(buf, to_offset + copied, reg); + + copied += 4; + } + } + + if size - copied >= 2 { + for _ in (0..(size - copied)).step_by(2) { + ASM::mov_reg16_base32(buf, reg, from_offset + copied); + ASM::mov_base32_reg16(buf, to_offset + copied, reg); + + copied += 2; + } + } + + if size - copied >= 1 { + for _ in (0..(size - copied)).step_by(1) { + ASM::mov_reg8_base32(buf, reg, from_offset + copied); + ASM::mov_base32_reg8(buf, to_offset + copied, reg); + + copied += 1; + } + } + }); + } + #[allow(dead_code)] /// Ensures that a register is free. If it is not free, data will be moved to make it free. pub fn ensure_reg_free( @@ -1008,15 +1117,10 @@ impl< param_storage.reserve(params.len()); for Param { symbol, - ownership, + ownership: _, layout, } in params { - if *ownership == Ownership::Borrowed { - // These probably need to be passed by pointer/reference? - // Otherwise, we probably need to copy back to the param at the end of the joinpoint. - todo!("joinpoints with borrowed parameters"); - } // Claim a location for every join point parameter to be loaded at. // Put everything on the stack for simplicity. match *layout { @@ -1331,6 +1435,15 @@ impl< } } -fn is_primitive(layout: InLayout<'_>) -> bool { - matches!(layout, single_register_layouts!()) +fn is_primitive(layout_interner: &mut STLayoutInterner<'_>, layout: InLayout<'_>) -> bool { + match layout { + single_register_layouts!() => true, + _ => match layout_interner.get(layout) { + Layout::Boxed(_) => true, + Layout::LambdaSet(lambda_set) => { + is_primitive(layout_interner, lambda_set.runtime_representation()) + } + _ => false, + }, + } } diff --git a/crates/compiler/gen_dev/src/generic64/x86_64.rs b/crates/compiler/gen_dev/src/generic64/x86_64.rs index c2c865f057..0f3902e951 100644 --- a/crates/compiler/gen_dev/src/generic64/x86_64.rs +++ b/crates/compiler/gen_dev/src/generic64/x86_64.rs @@ -4,10 +4,13 @@ use crate::{ single_register_layouts, Relocation, }; use bumpalo::collections::Vec; +use roc_builtins::bitcode::FloatWidth; use roc_error_macros::internal_error; use roc_module::symbol::Symbol; use roc_mono::layout::{InLayout, Layout, LayoutInterner, STLayoutInterner}; +use super::CompareOperation; + // Not sure exactly how I want to represent registers. // If we want max speed, we would likely make them structs that impl the same trait to avoid ifs. #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] @@ -261,59 +264,22 @@ impl CallConv for X86_64Syste args: &'a [(InLayout<'a>, Symbol)], ret_layout: &InLayout<'a>, ) { - let mut arg_offset = Self::SHADOW_SPACE_SIZE as i32 + 16; // 16 is the size of the pushed return address and base pointer. - let mut general_i = 0; - let mut float_i = 0; - if X86_64SystemV::returns_via_arg_pointer(layout_interner, ret_layout) { - storage_manager.ret_pointer_arg(Self::GENERAL_PARAM_REGS[0]); - general_i += 1; + let returns_via_pointer = + X86_64SystemV::returns_via_arg_pointer(layout_interner, ret_layout); + + let mut state = X64_64SystemVLoadArgs { + general_i: usize::from(returns_via_pointer), + float_i: 0, + // 16 is the size of the pushed return address and base pointer. + argument_offset: X86_64SystemV::SHADOW_SPACE_SIZE as i32 + 16, + }; + + if returns_via_pointer { + storage_manager.ret_pointer_arg(X86_64SystemV::GENERAL_PARAM_REGS[0]); } + for (in_layout, sym) in args.iter() { - let stack_size = layout_interner.stack_size(*in_layout); - match *in_layout { - single_register_integers!() => { - if general_i < Self::GENERAL_PARAM_REGS.len() { - storage_manager.general_reg_arg(sym, Self::GENERAL_PARAM_REGS[general_i]); - general_i += 1; - } else { - storage_manager.primitive_stack_arg(sym, arg_offset); - arg_offset += 8; - } - } - single_register_floats!() => { - if float_i < Self::FLOAT_PARAM_REGS.len() { - storage_manager.float_reg_arg(sym, Self::FLOAT_PARAM_REGS[float_i]); - float_i += 1; - } else { - storage_manager.primitive_stack_arg(sym, arg_offset); - arg_offset += 8; - } - } - _ if stack_size == 0 => { - storage_manager.no_data_arg(sym); - } - _ if stack_size > 16 => { - // TODO: Double check this. - storage_manager.complex_stack_arg(sym, arg_offset, stack_size); - arg_offset += stack_size as i32; - } - other => match layout_interner.get(other) { - Layout::Boxed(_) => { - // boxed layouts are pointers, which we treat as 64-bit integers - if general_i < Self::GENERAL_PARAM_REGS.len() { - storage_manager - .general_reg_arg(sym, Self::GENERAL_PARAM_REGS[general_i]); - general_i += 1; - } else { - storage_manager.primitive_stack_arg(sym, arg_offset); - arg_offset += 8; - } - } - _ => { - todo!("Loading args with layout {:?}", layout_interner.dbg(other)); - } - }, - } + state.load_arg(storage_manager, layout_interner, *sym, *in_layout); } } @@ -334,9 +300,8 @@ impl CallConv for X86_64Syste arg_layouts: &[InLayout<'a>], ret_layout: &InLayout<'a>, ) { - let mut tmp_stack_offset = Self::SHADOW_SPACE_SIZE as i32; let mut general_i = 0; - let mut float_i = 0; + if Self::returns_via_arg_pointer(layout_interner, ret_layout) { // Save space on the stack for the result we will be return. let base_offset = @@ -352,110 +317,17 @@ impl CallConv for X86_64Syste ); } - for (sym, layout) in args.iter().zip(arg_layouts.iter()) { - match *layout { - single_register_integers!() => { - if general_i < Self::GENERAL_PARAM_REGS.len() { - storage_manager.load_to_specified_general_reg( - buf, - sym, - Self::GENERAL_PARAM_REGS[general_i], - ); - general_i += 1; - } else { - // Copy to stack using return reg as buffer. - storage_manager.load_to_specified_general_reg( - buf, - sym, - Self::GENERAL_RETURN_REGS[0], - ); - X86_64Assembler::mov_stack32_reg64( - buf, - tmp_stack_offset, - Self::GENERAL_RETURN_REGS[0], - ); - tmp_stack_offset += 8; - } - } - single_register_floats!() => { - if float_i < Self::FLOAT_PARAM_REGS.len() { - storage_manager.load_to_specified_float_reg( - buf, - sym, - Self::FLOAT_PARAM_REGS[float_i], - ); - float_i += 1; - } else { - // Copy to stack using return reg as buffer. - storage_manager.load_to_specified_float_reg( - buf, - sym, - Self::FLOAT_RETURN_REGS[0], - ); - X86_64Assembler::mov_stack32_freg64( - buf, - tmp_stack_offset, - Self::FLOAT_RETURN_REGS[0], - ); - tmp_stack_offset += 8; - } - } - x if layout_interner.stack_size(x) == 0 => {} - x if layout_interner.stack_size(x) > 16 => { - // TODO: Double check this. - // Just copy onto the stack. - // Use return reg as buffer because it will be empty right now. - let (base_offset, size) = storage_manager.stack_offset_and_size(sym); - debug_assert_eq!(base_offset % 8, 0); - for i in (0..size as i32).step_by(8) { - X86_64Assembler::mov_reg64_base32( - buf, - Self::GENERAL_RETURN_REGS[0], - base_offset + i, - ); - X86_64Assembler::mov_stack32_reg64( - buf, - tmp_stack_offset + i, - Self::GENERAL_RETURN_REGS[0], - ); - } - tmp_stack_offset += size as i32; - } - other => { - // look at the layout in more detail - match layout_interner.get(other) { - Layout::Boxed(_) => { - // treat boxed like a 64-bit integer - if general_i < Self::GENERAL_PARAM_REGS.len() { - storage_manager.load_to_specified_general_reg( - buf, - sym, - Self::GENERAL_PARAM_REGS[general_i], - ); - general_i += 1; - } else { - // Copy to stack using return reg as buffer. - storage_manager.load_to_specified_general_reg( - buf, - sym, - Self::GENERAL_RETURN_REGS[0], - ); - X86_64Assembler::mov_stack32_reg64( - buf, - tmp_stack_offset, - Self::GENERAL_RETURN_REGS[0], - ); - tmp_stack_offset += 8; - } - } - _ => { - todo!("calling with arg type, {:?}", layout_interner.dbg(other)); - } - } - } - } + let mut state = X64_64SystemVStoreArgs { + general_i, + float_i: 0, + tmp_stack_offset: Self::SHADOW_SPACE_SIZE as i32, + }; + + for (sym, in_layout) in args.iter().zip(arg_layouts.iter()) { + state.store_arg(buf, storage_manager, layout_interner, *sym, *in_layout); } - storage_manager.update_fn_call_stack_size(tmp_stack_offset as u32); + + storage_manager.update_fn_call_stack_size(state.tmp_stack_offset as u32); } fn return_complex_symbol<'a, 'r>( @@ -562,6 +434,225 @@ impl CallConv for X86_64Syste } } +struct X64_64SystemVStoreArgs { + general_i: usize, + float_i: usize, + tmp_stack_offset: i32, +} + +impl X64_64SystemVStoreArgs { + const GENERAL_PARAM_REGS: &'static [X86_64GeneralReg] = X86_64SystemV::GENERAL_PARAM_REGS; + const GENERAL_RETURN_REGS: &'static [X86_64GeneralReg] = X86_64SystemV::GENERAL_RETURN_REGS; + + const FLOAT_PARAM_REGS: &'static [X86_64FloatReg] = X86_64SystemV::FLOAT_PARAM_REGS; + const FLOAT_RETURN_REGS: &'static [X86_64FloatReg] = X86_64SystemV::FLOAT_RETURN_REGS; + + fn store_arg<'a, 'r>( + &mut self, + buf: &mut Vec<'a, u8>, + storage_manager: &mut X86_64StorageManager<'a, 'r, X86_64SystemV>, + layout_interner: &mut STLayoutInterner<'a>, + sym: Symbol, + in_layout: InLayout<'a>, + ) { + match in_layout { + single_register_integers!() => self.store_arg_general(buf, storage_manager, sym), + single_register_floats!() => self.store_arg_float(buf, storage_manager, sym), + x if layout_interner.stack_size(x) == 0 => {} + x if layout_interner.stack_size(x) > 16 => { + // TODO: Double check this. + // Just copy onto the stack. + // Use return reg as buffer because it will be empty right now. + let (base_offset, size) = storage_manager.stack_offset_and_size(&sym); + debug_assert_eq!(base_offset % 8, 0); + for i in (0..size as i32).step_by(8) { + X86_64Assembler::mov_reg64_base32( + buf, + Self::GENERAL_RETURN_REGS[0], + base_offset + i, + ); + X86_64Assembler::mov_stack32_reg64( + buf, + self.tmp_stack_offset + i, + Self::GENERAL_RETURN_REGS[0], + ); + } + self.tmp_stack_offset += size as i32; + } + other => { + // look at the layout in more detail + match layout_interner.get(other) { + Layout::Boxed(_) => { + // treat boxed like a 64-bit integer + self.store_arg_general(buf, storage_manager, sym) + } + Layout::LambdaSet(lambda_set) => self.store_arg( + buf, + storage_manager, + layout_interner, + sym, + lambda_set.runtime_representation(), + ), + Layout::Struct { .. } => { + // for now, just also store this on the stack + let (base_offset, size) = storage_manager.stack_offset_and_size(&sym); + debug_assert_eq!(base_offset % 8, 0); + for i in (0..size as i32).step_by(8) { + X86_64Assembler::mov_reg64_base32( + buf, + Self::GENERAL_RETURN_REGS[0], + base_offset + i, + ); + X86_64Assembler::mov_stack32_reg64( + buf, + self.tmp_stack_offset + i, + Self::GENERAL_RETURN_REGS[0], + ); + } + self.tmp_stack_offset += size as i32; + } + _ => { + todo!("calling with arg type, {:?}", layout_interner.dbg(other)); + } + } + } + } + } + + fn store_arg_general<'a, 'r>( + &mut self, + buf: &mut Vec<'a, u8>, + storage_manager: &mut X86_64StorageManager<'a, 'r, X86_64SystemV>, + sym: Symbol, + ) { + if self.general_i < Self::GENERAL_PARAM_REGS.len() { + storage_manager.load_to_specified_general_reg( + buf, + &sym, + Self::GENERAL_PARAM_REGS[self.general_i], + ); + self.general_i += 1; + } else { + // Copy to stack using return reg as buffer. + storage_manager.load_to_specified_general_reg(buf, &sym, Self::GENERAL_RETURN_REGS[0]); + X86_64Assembler::mov_stack32_reg64( + buf, + self.tmp_stack_offset, + Self::GENERAL_RETURN_REGS[0], + ); + self.tmp_stack_offset += 8; + } + } + + fn store_arg_float<'a, 'r>( + &mut self, + buf: &mut Vec<'a, u8>, + storage_manager: &mut X86_64StorageManager<'a, 'r, X86_64SystemV>, + sym: Symbol, + ) { + if self.float_i < Self::FLOAT_PARAM_REGS.len() { + storage_manager.load_to_specified_float_reg( + buf, + &sym, + Self::FLOAT_PARAM_REGS[self.float_i], + ); + self.float_i += 1; + } else { + // Copy to stack using return reg as buffer. + storage_manager.load_to_specified_float_reg(buf, &sym, Self::FLOAT_RETURN_REGS[0]); + X86_64Assembler::mov_stack32_freg64( + buf, + self.tmp_stack_offset, + Self::FLOAT_RETURN_REGS[0], + ); + self.tmp_stack_offset += 8; + } + } +} + +struct X64_64SystemVLoadArgs { + general_i: usize, + float_i: usize, + argument_offset: i32, +} + +type X86_64StorageManager<'a, 'r, CallConv> = + StorageManager<'a, 'r, X86_64GeneralReg, X86_64FloatReg, X86_64Assembler, CallConv>; + +impl X64_64SystemVLoadArgs { + fn load_arg<'a, 'r>( + &mut self, + storage_manager: &mut X86_64StorageManager<'a, 'r, X86_64SystemV>, + layout_interner: &mut STLayoutInterner<'a>, + sym: Symbol, + in_layout: InLayout<'a>, + ) { + let stack_size = layout_interner.stack_size(in_layout); + match in_layout { + single_register_integers!() => self.load_arg_general(storage_manager, sym), + single_register_floats!() => self.load_arg_float(storage_manager, sym), + _ if stack_size == 0 => { + storage_manager.no_data_arg(&sym); + } + _ if stack_size > 16 => { + // TODO: Double check this. + storage_manager.complex_stack_arg(&sym, self.argument_offset, stack_size); + self.argument_offset += stack_size as i32; + } + other => match layout_interner.get(other) { + Layout::Boxed(_) => { + // boxed layouts are pointers, which we treat as 64-bit integers + self.load_arg_general(storage_manager, sym) + } + Layout::LambdaSet(lambda_set) => self.load_arg( + storage_manager, + layout_interner, + sym, + lambda_set.runtime_representation(), + ), + Layout::Struct { .. } => { + // for now, just also store this on the stack + storage_manager.complex_stack_arg(&sym, self.argument_offset, stack_size); + self.argument_offset += stack_size as i32; + } + _ => { + todo!("Loading args with layout {:?}", layout_interner.dbg(other)); + } + }, + } + } + + fn load_arg_general<'a, 'r>( + &mut self, + storage_manager: &mut X86_64StorageManager<'a, 'r, X86_64SystemV>, + sym: Symbol, + ) { + if self.general_i < X86_64SystemV::GENERAL_PARAM_REGS.len() { + let reg = X86_64SystemV::GENERAL_PARAM_REGS[self.general_i]; + storage_manager.general_reg_arg(&sym, reg); + self.general_i += 1; + } else { + storage_manager.primitive_stack_arg(&sym, self.argument_offset); + self.argument_offset += 8; + } + } + + fn load_arg_float<'a, 'r>( + &mut self, + storage_manager: &mut X86_64StorageManager<'a, 'r, X86_64SystemV>, + sym: Symbol, + ) { + if self.general_i < X86_64SystemV::GENERAL_PARAM_REGS.len() { + let reg = X86_64SystemV::FLOAT_PARAM_REGS[self.general_i]; + storage_manager.float_reg_arg(&sym, reg); + self.float_i += 1; + } else { + storage_manager.primitive_stack_arg(&sym, self.argument_offset); + self.argument_offset += 8; + } + } +} + impl X86_64SystemV { fn returns_via_arg_pointer<'a>( interner: &STLayoutInterner<'a>, @@ -705,14 +796,7 @@ impl CallConv for X86_64Windo #[inline(always)] fn load_args<'a, 'r>( _buf: &mut Vec<'a, u8>, - storage_manager: &mut StorageManager< - 'a, - 'r, - X86_64GeneralReg, - X86_64FloatReg, - X86_64Assembler, - X86_64WindowsFastcall, - >, + storage_manager: &mut X86_64StorageManager<'a, 'r, X86_64WindowsFastcall>, layout_interner: &mut STLayoutInterner<'a>, args: &'a [(InLayout<'a>, Symbol)], ret_layout: &InLayout<'a>, @@ -1271,18 +1355,55 @@ impl Assembler for X86_64Assembler { fn mov_freg64_base32(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, offset: i32) { movsd_freg64_base64_offset32(buf, dst, X86_64GeneralReg::RBP, offset) } + #[inline(always)] fn mov_reg64_base32(buf: &mut Vec<'_, u8>, dst: X86_64GeneralReg, offset: i32) { mov_reg64_base64_offset32(buf, dst, X86_64GeneralReg::RBP, offset) } + #[inline(always)] + fn mov_reg32_base32(buf: &mut Vec<'_, u8>, dst: X86_64GeneralReg, offset: i32) { + mov_reg32_base32_offset32(buf, dst, X86_64GeneralReg::RBP, offset) + } + #[inline(always)] + fn mov_reg16_base32(buf: &mut Vec<'_, u8>, dst: X86_64GeneralReg, offset: i32) { + mov_reg16_base16_offset32(buf, dst, X86_64GeneralReg::RBP, offset) + } + #[inline(always)] + fn mov_reg8_base32(buf: &mut Vec<'_, u8>, dst: X86_64GeneralReg, offset: i32) { + mov_reg8_base8_offset32(buf, dst, X86_64GeneralReg::RBP, offset) + } + #[inline(always)] fn mov_base32_freg64(buf: &mut Vec<'_, u8>, offset: i32, src: X86_64FloatReg) { movsd_base64_offset32_freg64(buf, X86_64GeneralReg::RBP, offset, src) } + + #[inline(always)] + fn movesd_mem64_offset32_freg64( + buf: &mut Vec<'_, u8>, + ptr: X86_64GeneralReg, + offset: i32, + src: X86_64FloatReg, + ) { + movsd_base64_offset32_freg64(buf, ptr, offset, src) + } + #[inline(always)] fn mov_base32_reg64(buf: &mut Vec<'_, u8>, offset: i32, src: X86_64GeneralReg) { mov_base64_offset32_reg64(buf, X86_64GeneralReg::RBP, offset, src) } + #[inline(always)] + fn mov_base32_reg32(buf: &mut Vec<'_, u8>, offset: i32, src: X86_64GeneralReg) { + mov_base32_offset32_reg32(buf, X86_64GeneralReg::RBP, offset, src) + } + #[inline(always)] + fn mov_base32_reg16(buf: &mut Vec<'_, u8>, offset: i32, src: X86_64GeneralReg) { + mov_base16_offset32_reg16(buf, X86_64GeneralReg::RBP, offset, src) + } + #[inline(always)] + fn mov_base32_reg8(buf: &mut Vec<'_, u8>, offset: i32, src: X86_64GeneralReg) { + mov_base8_offset32_reg8(buf, X86_64GeneralReg::RBP, offset, src) + } #[inline(always)] fn mov_reg64_mem64_offset32( @@ -1293,6 +1414,32 @@ impl Assembler for X86_64Assembler { ) { mov_reg64_base64_offset32(buf, dst, src, offset) } + #[inline(always)] + fn mov_reg32_mem32_offset32( + buf: &mut Vec<'_, u8>, + dst: X86_64GeneralReg, + src: X86_64GeneralReg, + offset: i32, + ) { + mov_reg32_base32_offset32(buf, dst, src, offset) + } + fn mov_reg16_mem16_offset32( + buf: &mut Vec<'_, u8>, + dst: X86_64GeneralReg, + src: X86_64GeneralReg, + offset: i32, + ) { + mov_reg16_base16_offset32(buf, dst, src, offset) + } + fn mov_reg8_mem8_offset32( + buf: &mut Vec<'_, u8>, + dst: X86_64GeneralReg, + src: X86_64GeneralReg, + offset: i32, + ) { + mov_reg8_base8_offset32(buf, dst, src, offset) + } + #[inline(always)] fn mov_mem64_offset32_reg64( buf: &mut Vec<'_, u8>, @@ -1303,12 +1450,44 @@ impl Assembler for X86_64Assembler { mov_base64_offset32_reg64(buf, dst, offset, src) } + #[inline(always)] + fn mov_mem32_offset32_reg32( + buf: &mut Vec<'_, u8>, + dst: X86_64GeneralReg, + offset: i32, + src: X86_64GeneralReg, + ) { + mov_base32_offset32_reg32(buf, dst, offset, src) + } + + #[inline(always)] + fn mov_mem16_offset32_reg16( + buf: &mut Vec<'_, u8>, + dst: X86_64GeneralReg, + offset: i32, + src: X86_64GeneralReg, + ) { + mov_base16_offset32_reg16(buf, dst, offset, src) + } + + #[inline(always)] + fn mov_mem8_offset32_reg8( + buf: &mut Vec<'_, u8>, + dst: X86_64GeneralReg, + offset: i32, + src: X86_64GeneralReg, + ) { + mov_base8_offset32_reg8(buf, dst, offset, src) + } + #[inline(always)] fn movsx_reg64_base32(buf: &mut Vec<'_, u8>, dst: X86_64GeneralReg, offset: i32, size: u8) { debug_assert!(size <= 8); match size { 8 => Self::mov_reg64_base32(buf, dst, offset), - 4 | 2 | 1 => todo!("sign extending {size} byte values"), + 4 => movsx_reg64_base32_offset32(buf, dst, X86_64GeneralReg::RBP, offset), + 2 => movsx_reg64_base16_offset32(buf, dst, X86_64GeneralReg::RBP, offset), + 1 => movsx_reg64_base8_offset32(buf, dst, X86_64GeneralReg::RBP, offset), _ => internal_error!("Invalid size for sign extension: {size}"), } } @@ -1317,7 +1496,12 @@ impl Assembler for X86_64Assembler { debug_assert!(size <= 8); match size { 8 => Self::mov_reg64_base32(buf, dst, offset), - 4 | 2 => todo!("zero extending {size} byte values"), + 4 => { + // The Intel documentation (3.4.1.1 General-Purpose Registers in 64-Bit Mode in manual Basic Architecture)) + // 32-bit operands generate a 32-bit result, zero-extended to a 64-bit result in the destination general-purpose register. + Self::mov_reg64_base32(buf, dst, offset) + } + 2 => movzx_reg64_base16_offset32(buf, dst, X86_64GeneralReg::RBP, offset), 1 => movzx_reg64_base8_offset32(buf, dst, X86_64GeneralReg::RBP, offset), _ => internal_error!("Invalid size for zero extension: {size}"), } @@ -1411,6 +1595,33 @@ impl Assembler for X86_64Assembler { setb_reg64(buf, dst); } + #[inline(always)] + fn cmp_freg_freg_reg64( + buf: &mut Vec<'_, u8>, + dst: X86_64GeneralReg, + src1: X86_64FloatReg, + src2: X86_64FloatReg, + width: FloatWidth, + operation: CompareOperation, + ) { + use CompareOperation::*; + + let (arg1, arg2) = match operation { + LessThan | LessThanOrEqual => (src1, src2), + GreaterThan | GreaterThanOrEqual => (src2, src1), + }; + + match width { + FloatWidth::F32 => cmp_freg32_freg32(buf, arg2, arg1), + FloatWidth::F64 => cmp_freg64_freg64(buf, arg2, arg1), + } + + match operation { + LessThan | GreaterThan => seta_reg64(buf, dst), + LessThanOrEqual | GreaterThanOrEqual => setae_reg64(buf, dst), + }; + } + #[inline(always)] fn igt_reg64_reg64_reg64( buf: &mut Vec<'_, u8>, @@ -1534,6 +1745,14 @@ impl Assembler for X86_64Assembler { { shift_reg64_reg64_reg64(buf, storage_manager, sar_reg64_reg64, dst, src1, src2) } + + fn sqrt_freg64_freg64(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64FloatReg) { + sqrtsd_freg64_freg64(buf, dst, src) + } + + fn sqrt_freg32_freg32(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64FloatReg) { + sqrtss_freg32_freg32(buf, dst, src) + } } fn shift_reg64_reg64_reg64<'a, 'r, ASM, CC>( @@ -1585,12 +1804,16 @@ impl X86_64Assembler { push_reg64(buf, reg); } } + +const GRP_4: u8 = 0x66; + const REX: u8 = 0x40; // see https://wiki.osdev.org/X86-64_Instruction_Encoding#Encoding /// If set, 64-bit operand size is used const REX_PREFIX_W: u8 = 0b1000; /// Extension to the MODRM.reg +/// Permits access to additional registers const REX_PREFIX_R: u8 = 0b0100; #[allow(unused)] /// Extension to the SIB.index field @@ -1598,7 +1821,7 @@ const REX_PREFIX_X: u8 = 0b0010; /// Extension to the MODRM.rm const REX_PREFIX_B: u8 = 0b0001; -/// Wide REX +/// Wide REX (64-bit) const REX_W: u8 = REX | REX_PREFIX_W; #[inline(always)] @@ -1900,6 +2123,90 @@ fn cmp_reg64_reg64(buf: &mut Vec<'_, u8>, dst: X86_64GeneralReg, src: X86_64Gene binop_reg64_reg64(0x39, buf, dst, src); } +#[inline(always)] +fn cmp_freg64_freg64(buf: &mut Vec<'_, u8>, src1: X86_64FloatReg, src2: X86_64FloatReg) { + let src1_high = src1 as u8 > 7; + let src1_mod = src1 as u8 % 8; + + let src2_high = src2 as u8 > 7; + let src2_mod = src2 as u8 % 8; + + if src1_high || src2_high { + buf.extend([ + 0x66, + 0x40 | ((src1_high as u8) << 2) | (src2_high as u8), + 0x0F, + 0x2E, + 0xC0 | (src1_mod << 3) | (src2_mod), + ]) + } else { + buf.extend([0x66, 0x0F, 0x2E, 0xC0 | (src1_mod << 3) | (src2_mod)]) + } +} + +#[inline(always)] +fn cmp_freg32_freg32(buf: &mut Vec<'_, u8>, src1: X86_64FloatReg, src2: X86_64FloatReg) { + let src1_high = src1 as u8 > 7; + let src1_mod = src1 as u8 % 8; + + let src2_high = src2 as u8 > 7; + let src2_mod = src2 as u8 % 8; + + if src1_high || src2_high { + buf.extend([ + 0x65, + 0x40 | ((src1_high as u8) << 2) | (src2_high as u8), + 0x0F, + 0x2E, + 0xC0 | (src1_mod << 3) | (src2_mod), + ]) + } else { + buf.extend([0x65, 0x0F, 0x2E, 0xC0 | (src1_mod << 3) | (src2_mod)]) + } +} + +#[inline(always)] +fn sqrtsd_freg64_freg64(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64FloatReg) { + let dst_high = dst as u8 > 7; + let dst_mod = dst as u8 % 8; + + let src_high = src as u8 > 7; + let src_mod = src as u8 % 8; + + if dst_high || src_high { + buf.extend([ + 0xF2, + 0x40 | ((dst_high as u8) << 2) | (src_high as u8), + 0x0F, + 0x51, + 0xC0 | (dst_mod << 3) | (src_mod), + ]) + } else { + buf.extend([0xF2, 0x0F, 0x51, 0xC0 | (dst_mod << 3) | (src_mod)]) + } +} + +#[inline(always)] +fn sqrtss_freg32_freg32(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64FloatReg) { + let dst_high = dst as u8 > 7; + let dst_mod = dst as u8 % 8; + + let src_high = src as u8 > 7; + let src_mod = src as u8 % 8; + + if dst_high || src_high { + buf.extend([ + 0xF3, + 0x40 | ((dst_high as u8) << 2) | (src_high as u8), + 0x0F, + 0x51, + 0xC0 | (dst_mod << 3) | (src_mod), + ]) + } else { + buf.extend([0xF3, 0x0F, 0x51, 0xC0 | (dst_mod << 3) | (src_mod)]) + } +} + /// `TEST r/m64,r64` -> AND r64 with r/m64; set SF, ZF, PF according to result. #[allow(dead_code)] #[inline(always)] @@ -2049,6 +2356,117 @@ fn mov_base64_offset32_reg64( buf.extend(offset.to_le_bytes()); } +/// `MOV r/m32,r32` -> Move r32 to r/m32, where m32 references a base + offset. +#[inline(always)] +fn mov_base32_offset32_reg32( + buf: &mut Vec<'_, u8>, + base: X86_64GeneralReg, + offset: i32, + src: X86_64GeneralReg, +) { + let rex = add_rm_extension(base, REX); + let rex = add_reg_extension(src, rex); + let src_mod = (src as u8 % 8) << 3; + let base_mod = base as u8 % 8; + buf.reserve(8); + buf.extend([rex, 0x89, 0x80 | src_mod | base_mod]); + // Using RSP or R12 requires a secondary index byte. + if base == X86_64GeneralReg::RSP || base == X86_64GeneralReg::R12 { + buf.push(0x24); + } + buf.extend(offset.to_le_bytes()); +} + +/// `MOV r/m16,r16` -> Move r16 to r/m16, where m16 references a base + offset. +#[inline(always)] +fn mov_base16_offset32_reg16( + buf: &mut Vec<'_, u8>, + base: X86_64GeneralReg, + offset: i32, + src: X86_64GeneralReg, +) { + let rex = add_rm_extension(base, REX); + let rex = add_reg_extension(src, rex); + let src_mod = (src as u8 % 8) << 3; + let base_mod = base as u8 % 8; + buf.reserve(8); + buf.extend([GRP_4, rex, 0x89, 0x80 | src_mod | base_mod]); + // Using RSP or R12 requires a secondary index byte. + if base == X86_64GeneralReg::RSP || base == X86_64GeneralReg::R12 { + buf.push(0x24); + } + buf.extend(offset.to_le_bytes()); +} + +/// `MOV r/m8,r8` -> Move r8 to r/m8, where m8 references a base + offset. +#[inline(always)] +fn mov_base8_offset32_reg8( + buf: &mut Vec<'_, u8>, + base: X86_64GeneralReg, + offset: i32, + src: X86_64GeneralReg, +) { + let rex = add_rm_extension(base, REX); + let rex = add_reg_extension(src, rex); + let src_mod = (src as u8 % 8) << 3; + let base_mod = base as u8 % 8; + buf.reserve(8); + buf.extend([rex, 0x88, 0x80 | src_mod | base_mod]); + // Using RSP or R12 requires a secondary index byte. + if base == X86_64GeneralReg::RSP || base == X86_64GeneralReg::R12 { + buf.push(0x24); + } + buf.extend(offset.to_le_bytes()); +} + +enum RegisterWidth { + W8, + W16, + W32, + W64, +} + +#[inline(always)] +fn mov_reg_base_offset32( + buf: &mut Vec<'_, u8>, + register_width: RegisterWidth, + dst: X86_64GeneralReg, + base: X86_64GeneralReg, + offset: i32, +) { + use RegisterWidth::*; + + let rex = match register_width { + W64 => REX_W, + _ => REX, + }; + + let rex = add_rm_extension(base, rex); + let rex = add_reg_extension(dst, rex); + + let dst_mod = (dst as u8 % 8) << 3; + let base_mod = base as u8 % 8; + let operands = 0x80 | dst_mod | base_mod; + + buf.reserve(8); + + let instruction = match register_width { + W8 => 0x8A, + W16 | W32 | W64 => 0x8B, + }; + + match register_width { + W16 => buf.extend([GRP_4, rex, instruction, operands]), + _ => buf.extend([rex, instruction, operands]), + }; + + // Using RSP or R12 requires a secondary index byte. + if base == X86_64GeneralReg::RSP || base == X86_64GeneralReg::R12 { + buf.push(0x24); + } + buf.extend(offset.to_le_bytes()); +} + /// `MOV r64,r/m64` -> Move r/m64 to r64, where m64 references a base + offset. #[inline(always)] fn mov_reg64_base64_offset32( @@ -2056,13 +2474,116 @@ fn mov_reg64_base64_offset32( dst: X86_64GeneralReg, base: X86_64GeneralReg, offset: i32, +) { + mov_reg_base_offset32(buf, RegisterWidth::W64, dst, base, offset) +} + +/// `MOV r/m32,r32` -> Move r32 to r/m32. +#[inline(always)] +fn mov_reg32_base32_offset32( + buf: &mut Vec<'_, u8>, + dst: X86_64GeneralReg, + base: X86_64GeneralReg, + offset: i32, +) { + mov_reg_base_offset32(buf, RegisterWidth::W32, dst, base, offset) +} + +/// `MOV r/m16,r16` -> Move r16 to r/m16. +#[inline(always)] +fn mov_reg16_base16_offset32( + buf: &mut Vec<'_, u8>, + dst: X86_64GeneralReg, + base: X86_64GeneralReg, + offset: i32, +) { + mov_reg_base_offset32(buf, RegisterWidth::W16, dst, base, offset) +} + +/// `MOV r/m8,r8` -> Move r8 to r/m8. +#[inline(always)] +fn mov_reg8_base8_offset32( + buf: &mut Vec<'_, u8>, + dst: X86_64GeneralReg, + base: X86_64GeneralReg, + offset: i32, +) { + mov_reg_base_offset32(buf, RegisterWidth::W8, dst, base, offset) +} + +#[inline(always)] +fn movsx_reg64_base_offset32( + buf: &mut Vec<'_, u8>, + dst: X86_64GeneralReg, + base: X86_64GeneralReg, + offset: i32, + opcode: &[u8], ) { let rex = add_rm_extension(base, REX_W); let rex = add_reg_extension(dst, rex); let dst_mod = (dst as u8 % 8) << 3; let base_mod = base as u8 % 8; - buf.reserve(8); - buf.extend([rex, 0x8B, 0x80 | dst_mod | base_mod]); + buf.reserve(9); + + // our output is a 64-bit value, so rex is always needed + buf.push(rex); + buf.extend(opcode); + buf.push(0x80 | dst_mod | base_mod); + + // Using RSP or R12 requires a secondary index byte. + if base == X86_64GeneralReg::RSP || base == X86_64GeneralReg::R12 { + buf.push(0x24); + } + buf.extend(offset.to_le_bytes()); +} + +/// `MOVSX r64,r/m32` -> Move r/m32 with sign extention to r64, where m32 references a base + offset. +#[inline(always)] +fn movsx_reg64_base32_offset32( + buf: &mut Vec<'_, u8>, + dst: X86_64GeneralReg, + base: X86_64GeneralReg, + offset: i32, +) { + movsx_reg64_base_offset32(buf, dst, base, offset, &[0x63]) +} + +/// `MOVSX r64,r/m16` -> Move r/m16 with sign extention to r64, where m16 references a base + offset. +#[inline(always)] +fn movsx_reg64_base16_offset32( + buf: &mut Vec<'_, u8>, + dst: X86_64GeneralReg, + base: X86_64GeneralReg, + offset: i32, +) { + movsx_reg64_base_offset32(buf, dst, base, offset, &[0x0F, 0xBF]) +} + +/// `MOVSX r64,r/m8` -> Move r/m8 with sign extention to r64, where m8 references a base + offset. +#[inline(always)] +fn movsx_reg64_base8_offset32( + buf: &mut Vec<'_, u8>, + dst: X86_64GeneralReg, + base: X86_64GeneralReg, + offset: i32, +) { + movsx_reg64_base_offset32(buf, dst, base, offset, &[0x0F, 0xBE]) +} + +#[inline(always)] +fn movzx_reg64_base_offset32( + buf: &mut Vec<'_, u8>, + dst: X86_64GeneralReg, + base: X86_64GeneralReg, + offset: i32, + opcode: u8, +) { + let rex = add_rm_extension(base, REX_W); + let rex = add_reg_extension(dst, rex); + let dst_mod = (dst as u8 % 8) << 3; + let base_mod = base as u8 % 8; + buf.reserve(9); + buf.extend([rex, 0x0F, opcode, 0x80 | dst_mod | base_mod]); // Using RSP or R12 requires a secondary index byte. if base == X86_64GeneralReg::RSP || base == X86_64GeneralReg::R12 { buf.push(0x24); @@ -2078,17 +2599,18 @@ fn movzx_reg64_base8_offset32( base: X86_64GeneralReg, offset: i32, ) { - let rex = add_rm_extension(base, REX_W); - let rex = add_reg_extension(dst, rex); - let dst_mod = (dst as u8 % 8) << 3; - let base_mod = base as u8 % 8; - buf.reserve(9); - buf.extend([rex, 0x0F, 0xB6, 0x80 | dst_mod | base_mod]); - // Using RSP or R12 requires a secondary index byte. - if base == X86_64GeneralReg::RSP || base == X86_64GeneralReg::R12 { - buf.push(0x24); - } - buf.extend(offset.to_le_bytes()); + movzx_reg64_base_offset32(buf, dst, base, offset, 0xB6) +} + +/// `MOVZX r64,r/m16` -> Move r/m16 with zero extention to r64, where m16 references a base + offset. +#[inline(always)] +fn movzx_reg64_base16_offset32( + buf: &mut Vec<'_, u8>, + dst: X86_64GeneralReg, + base: X86_64GeneralReg, + offset: i32, +) { + movzx_reg64_base_offset32(buf, dst, base, offset, 0xB7) } /// `MOVSD xmm1,xmm2` -> Move scalar double-precision floating-point value from xmm2 to xmm1 register. @@ -2357,6 +2879,12 @@ fn seta_reg64(buf: &mut Vec<'_, u8>, reg: X86_64GeneralReg) { set_reg64_help(0x97, buf, reg); } +/// `SETAE r/m64` -> Set byte if above or equal (CF=0). +#[inline(always)] +fn setae_reg64(buf: &mut Vec<'_, u8>, reg: X86_64GeneralReg) { + set_reg64_help(0x93, buf, reg); +} + /// `SETLE r/m64` -> Set byte if less or equal (ZF=1 or SF≠ OF). #[inline(always)] fn setle_reg64(buf: &mut Vec<'_, u8>, reg: X86_64GeneralReg) { @@ -2431,6 +2959,50 @@ mod tests { use capstone::prelude::*; impl X86_64GeneralReg { + #[allow(dead_code)] + fn low_32bits_string(&self) -> &str { + match self { + X86_64GeneralReg::RAX => "eax", + X86_64GeneralReg::RBX => "ebx", + X86_64GeneralReg::RCX => "ecx", + X86_64GeneralReg::RDX => "edx", + X86_64GeneralReg::RBP => "ebp", + X86_64GeneralReg::RSP => "esp", + X86_64GeneralReg::RDI => "edi", + X86_64GeneralReg::RSI => "esi", + X86_64GeneralReg::R8 => "r8d", + X86_64GeneralReg::R9 => "r9d", + X86_64GeneralReg::R10 => "r10d", + X86_64GeneralReg::R11 => "r11d", + X86_64GeneralReg::R12 => "r12d", + X86_64GeneralReg::R13 => "r13d", + X86_64GeneralReg::R14 => "r14d", + X86_64GeneralReg::R15 => "r15d", + } + } + + #[allow(dead_code)] + fn low_16bits_string(&self) -> &str { + match self { + X86_64GeneralReg::RAX => "ax", + X86_64GeneralReg::RBX => "bx", + X86_64GeneralReg::RCX => "cx", + X86_64GeneralReg::RDX => "dx", + X86_64GeneralReg::RBP => "bp", + X86_64GeneralReg::RSP => "sp", + X86_64GeneralReg::RDI => "di", + X86_64GeneralReg::RSI => "si", + X86_64GeneralReg::R8 => "r8w", + X86_64GeneralReg::R9 => "r9w", + X86_64GeneralReg::R10 => "r10w", + X86_64GeneralReg::R11 => "r11w", + X86_64GeneralReg::R12 => "r12w", + X86_64GeneralReg::R13 => "r13w", + X86_64GeneralReg::R14 => "r14w", + X86_64GeneralReg::R15 => "r15w", + } + } + #[allow(dead_code)] fn low_8bits_string(&self) -> &str { match self { @@ -2810,6 +3382,54 @@ mod tests { ); } + #[test] + fn test_mov_reg32_base32_offset32() { + disassembler_test!( + mov_reg32_base32_offset32, + |reg1, reg2, imm| format!( + "mov {}, dword ptr [{} + 0x{:x}]", + X86_64GeneralReg::low_32bits_string(®1), + reg2, + imm + ), + ALL_GENERAL_REGS, + ALL_GENERAL_REGS, + [TEST_I32] + ); + } + + #[test] + fn test_mov_reg16_base16_offset32() { + disassembler_test!( + mov_reg16_base16_offset32, + |reg1, reg2, imm| format!( + "mov {}, word ptr [{} + 0x{:x}]", + X86_64GeneralReg::low_16bits_string(®1), + reg2, + imm + ), + ALL_GENERAL_REGS, + ALL_GENERAL_REGS, + [TEST_I32] + ); + } + + #[test] + fn test_mov_reg8_base8_offset32() { + disassembler_test!( + mov_reg8_base8_offset32, + |reg1, reg2, imm| format!( + "mov {}, byte ptr [{} + 0x{:x}]", + X86_64GeneralReg::low_8bits_string(®1), + reg2, + imm + ), + ALL_GENERAL_REGS, + ALL_GENERAL_REGS, + [TEST_I32] + ); + } + #[test] fn test_mov_base64_offset32_reg64() { disassembler_test!( @@ -2821,6 +3441,98 @@ mod tests { ); } + #[test] + fn test_mov_base32_offset32_reg32() { + disassembler_test!( + mov_base32_offset32_reg32, + |reg1, imm, reg2| format!( + "mov dword ptr [{} + 0x{:x}], {}", + reg1, + imm, + X86_64GeneralReg::low_32bits_string(®2), + ), + ALL_GENERAL_REGS, + [TEST_I32], + ALL_GENERAL_REGS + ); + } + + #[test] + fn test_mov_base16_offset32_reg16() { + disassembler_test!( + mov_base16_offset32_reg16, + |reg1, imm, reg2| format!( + "mov word ptr [{} + 0x{:x}], {}", + reg1, + imm, + X86_64GeneralReg::low_16bits_string(®2), + ), + ALL_GENERAL_REGS, + [TEST_I32], + ALL_GENERAL_REGS + ); + } + + #[test] + fn test_mov_base8_offset32_reg8() { + disassembler_test!( + mov_base8_offset32_reg8, + |reg1, imm, reg2| format!( + "mov byte ptr [{} + 0x{:x}], {}", + reg1, + imm, + X86_64GeneralReg::low_8bits_string(®2), + ), + ALL_GENERAL_REGS, + [TEST_I32], + ALL_GENERAL_REGS + ); + } + + #[test] + fn test_movsx_reg64_base32_offset32() { + disassembler_test!( + movsx_reg64_base32_offset32, + |reg1, reg2, imm| format!("movsxd {}, dword ptr [{} + 0x{:x}]", reg1, reg2, imm), + ALL_GENERAL_REGS, + ALL_GENERAL_REGS, + [TEST_I32] + ); + } + + #[test] + fn test_movsx_reg64_base16_offset32() { + disassembler_test!( + movsx_reg64_base16_offset32, + |reg1, reg2, imm| format!("movsx {}, word ptr [{} + 0x{:x}]", reg1, reg2, imm), + ALL_GENERAL_REGS, + ALL_GENERAL_REGS, + [TEST_I32] + ); + } + + #[test] + fn test_movsx_reg64_base8_offset32() { + disassembler_test!( + movsx_reg64_base8_offset32, + |reg1, reg2, imm| format!("movsx {}, byte ptr [{} + 0x{:x}]", reg1, reg2, imm), + ALL_GENERAL_REGS, + ALL_GENERAL_REGS, + [TEST_I32] + ); + } + + #[test] + fn test_movzx_reg64_base16_offset32() { + disassembler_test!( + movzx_reg64_base16_offset32, + |reg1, reg2, imm| format!("movzx {}, word ptr [{} + 0x{:x}]", reg1, reg2, imm), + ALL_GENERAL_REGS, + ALL_GENERAL_REGS, + [TEST_I32] + ); + } + #[test] fn test_movzx_reg64_base8_offset32() { disassembler_test!( @@ -2939,4 +3651,24 @@ mod tests { fn test_push_reg64() { disassembler_test!(push_reg64, |reg| format!("push {}", reg), ALL_GENERAL_REGS); } + + #[test] + fn test_sqrt_freg64_freg64() { + disassembler_test!( + sqrtsd_freg64_freg64, + |dst, src| format!("sqrtsd {dst}, {src}"), + ALL_FLOAT_REGS, + ALL_FLOAT_REGS + ); + } + + #[test] + fn test_sqrt_freg32_freg32() { + disassembler_test!( + sqrtss_freg32_freg32, + |dst, src| format!("sqrtss {dst}, {src}"), + ALL_FLOAT_REGS, + ALL_FLOAT_REGS + ); + } } diff --git a/crates/compiler/gen_dev/src/lib.rs b/crates/compiler/gen_dev/src/lib.rs index f6d4fbaf06..1aba223c90 100644 --- a/crates/compiler/gen_dev/src/lib.rs +++ b/crates/compiler/gen_dev/src/lib.rs @@ -447,6 +447,9 @@ trait Backend<'a> { LowLevel::NumAddChecked => { self.build_num_add_checked(sym, &args[0], &args[1], &arg_layouts[0], ret_layout) } + LowLevel::NumSubChecked => { + self.build_num_sub_checked(sym, &args[0], &args[1], &arg_layouts[0], ret_layout) + } LowLevel::NumAcos => self.build_fn_call( sym, bitcode::NUM_ACOS[FloatWidth::F64].to_string(), @@ -551,6 +554,27 @@ trait Backend<'a> { ); self.build_num_sub_wrap(sym, &args[0], &args[1], ret_layout) } + LowLevel::NumSubSaturated => match self.interner().get(*ret_layout) { + Layout::Builtin(Builtin::Int(int_width)) => self.build_fn_call( + sym, + bitcode::NUM_SUB_SATURATED_INT[int_width].to_string(), + args, + arg_layouts, + ret_layout, + ), + Layout::Builtin(Builtin::Float(FloatWidth::F32)) => { + self.build_num_sub(sym, &args[0], &args[1], ret_layout) + } + Layout::Builtin(Builtin::Float(FloatWidth::F64)) => { + // saturated sub is just normal sub + self.build_num_sub(sym, &args[0], &args[1], ret_layout) + } + Layout::Builtin(Builtin::Decimal) => { + // self.load_args_and_call_zig(backend, bitcode::DEC_SUB_SATURATED) + todo!() + } + _ => internal_error!("invalid return type"), + }, LowLevel::NumBitwiseAnd => { if let Layout::Builtin(Builtin::Int(int_width)) = self.interner().get(*ret_layout) { self.build_int_bitwise_and(sym, &args[0], &args[1], int_width) @@ -572,6 +596,20 @@ trait Backend<'a> { internal_error!("bitwise xor on a non-integer") } } + LowLevel::And => { + if let Layout::Builtin(Builtin::Bool) = self.interner().get(*ret_layout) { + self.build_int_bitwise_and(sym, &args[0], &args[1], IntWidth::U8) + } else { + internal_error!("bitwise and on a non-integer") + } + } + LowLevel::Or => { + if let Layout::Builtin(Builtin::Bool) = self.interner().get(*ret_layout) { + self.build_int_bitwise_or(sym, &args[0], &args[1], IntWidth::U8) + } else { + internal_error!("bitwise or on a non-integer") + } + } LowLevel::NumShiftLeftBy => { if let Layout::Builtin(Builtin::Int(int_width)) = self.interner().get(*ret_layout) { self.build_int_shift_left(sym, &args[0], &args[1], int_width) @@ -623,6 +661,15 @@ trait Backend<'a> { ); self.build_neq(sym, &args[0], &args[1], &arg_layouts[0]) } + LowLevel::Not => { + debug_assert_eq!(1, args.len(), "Not: expected to have exactly one argument"); + debug_assert_eq!( + Layout::BOOL, + *ret_layout, + "Not: expected to have return layout of type Bool" + ); + self.build_not(sym, &args[0], &arg_layouts[0]) + } LowLevel::NumLt => { debug_assert_eq!( 2, @@ -704,6 +751,30 @@ trait Backend<'a> { ); self.build_num_gte(sym, &args[0], &args[1], &arg_layouts[0]) } + LowLevel::NumLogUnchecked => { + let float_width = match arg_layouts[0] { + Layout::F64 => FloatWidth::F64, + Layout::F32 => FloatWidth::F32, + _ => unreachable!("invalid layout for sqrt"), + }; + + self.build_fn_call( + sym, + bitcode::NUM_LOG[float_width].to_string(), + args, + arg_layouts, + ret_layout, + ) + } + LowLevel::NumSqrtUnchecked => { + let float_width = match arg_layouts[0] { + Layout::F64 => FloatWidth::F64, + Layout::F32 => FloatWidth::F32, + _ => unreachable!("invalid layout for sqrt"), + }; + + self.build_num_sqrt(*sym, args[0], float_width); + } LowLevel::NumRound => self.build_fn_call( sym, bitcode::NUM_ROUND_F64[IntWidth::I64].to_string(), @@ -784,6 +855,13 @@ trait Backend<'a> { arg_layouts, ret_layout, ), + LowLevel::StrJoinWith => self.build_fn_call( + sym, + bitcode::STR_JOIN_WITH.to_string(), + args, + arg_layouts, + ret_layout, + ), LowLevel::StrSplit => self.build_fn_call( sym, bitcode::STR_SPLIT.to_string(), @@ -805,6 +883,13 @@ trait Backend<'a> { arg_layouts, ret_layout, ), + LowLevel::StrAppendScalar => self.build_fn_call( + sym, + bitcode::STR_APPEND_SCALAR.to_string(), + args, + arg_layouts, + ret_layout, + ), LowLevel::StrEndsWith => self.build_fn_call( sym, bitcode::STR_ENDS_WITH.to_string(), @@ -819,6 +904,122 @@ trait Backend<'a> { arg_layouts, ret_layout, ), + LowLevel::StrSubstringUnsafe => self.build_fn_call( + sym, + bitcode::STR_SUBSTRING_UNSAFE.to_string(), + args, + arg_layouts, + ret_layout, + ), + LowLevel::StrToUtf8 => self.build_fn_call( + sym, + bitcode::STR_TO_UTF8.to_string(), + args, + arg_layouts, + ret_layout, + ), + LowLevel::StrCountUtf8Bytes => self.build_fn_call( + sym, + bitcode::STR_COUNT_UTF8_BYTES.to_string(), + args, + arg_layouts, + ret_layout, + ), + LowLevel::StrFromUtf8Range => self.build_fn_call( + sym, + bitcode::STR_FROM_UTF8_RANGE.to_string(), + args, + arg_layouts, + ret_layout, + ), + // LowLevel::StrToUtf8 => self.build_fn_call( + // sym, + // bitcode::STR_TO_UTF8.to_string(), + // args, + // arg_layouts, + // ret_layout, + // ), + LowLevel::StrRepeat => self.build_fn_call( + sym, + bitcode::STR_REPEAT.to_string(), + args, + arg_layouts, + ret_layout, + ), + LowLevel::StrTrim => self.build_fn_call( + sym, + bitcode::STR_TRIM.to_string(), + args, + arg_layouts, + ret_layout, + ), + LowLevel::StrTrimLeft => self.build_fn_call( + sym, + bitcode::STR_TRIM_LEFT.to_string(), + args, + arg_layouts, + ret_layout, + ), + LowLevel::StrTrimRight => self.build_fn_call( + sym, + bitcode::STR_TRIM_RIGHT.to_string(), + args, + arg_layouts, + ret_layout, + ), + LowLevel::StrReserve => self.build_fn_call( + sym, + bitcode::STR_RESERVE.to_string(), + args, + arg_layouts, + ret_layout, + ), + LowLevel::StrWithCapacity => self.build_fn_call( + sym, + bitcode::STR_WITH_CAPACITY.to_string(), + args, + arg_layouts, + ret_layout, + ), + LowLevel::StrToScalars => self.build_fn_call( + sym, + bitcode::STR_TO_SCALARS.to_string(), + args, + arg_layouts, + ret_layout, + ), + LowLevel::StrGetUnsafe => self.build_fn_call( + sym, + bitcode::STR_GET_UNSAFE.to_string(), + args, + arg_layouts, + ret_layout, + ), + LowLevel::StrGetScalarUnsafe => self.build_fn_call( + sym, + bitcode::STR_GET_SCALAR_UNSAFE.to_string(), + args, + arg_layouts, + ret_layout, + ), + LowLevel::StrToNum => { + let number_layout = match self.interner().get(*ret_layout) { + Layout::Struct { field_layouts, .. } => field_layouts[0], // TODO: why is it sometimes a struct? + _ => unreachable!(), + }; + + // match on the return layout to figure out which zig builtin we need + let intrinsic = match self.interner().get(number_layout) { + Layout::Builtin(Builtin::Int(int_width)) => &bitcode::STR_TO_INT[int_width], + Layout::Builtin(Builtin::Float(float_width)) => { + &bitcode::STR_TO_FLOAT[float_width] + } + Layout::Builtin(Builtin::Decimal) => bitcode::DEC_FROM_STR, + _ => unreachable!(), + }; + + self.build_fn_call(sym, intrinsic.to_string(), args, arg_layouts, ret_layout) + } LowLevel::PtrCast => { debug_assert_eq!( 1, @@ -885,13 +1086,6 @@ trait Backend<'a> { self.load_literal_symbols(args); self.build_fn_call(sym, fn_name, args, arg_layouts, ret_layout) } - Symbol::NUM_ADD_CHECKED => { - let layout_id = LayoutIds::default().get(func_sym, ret_layout); - let fn_name = self.symbol_to_string(func_sym, layout_id); - // Now that the arguments are needed, load them if they are literals. - self.load_literal_symbols(args); - self.build_fn_call(sym, fn_name, args, arg_layouts, ret_layout) - } Symbol::BOOL_TRUE => { let bool_layout = Layout::BOOL; self.load_literal(&Symbol::DEV_TMP, &bool_layout, &Literal::Bool(true)); @@ -904,7 +1098,24 @@ trait Backend<'a> { self.return_symbol(&Symbol::DEV_TMP, &bool_layout); self.free_symbol(&Symbol::DEV_TMP) } - _ => todo!("the function, {:?}", func_sym), + Symbol::STR_IS_VALID_SCALAR => { + // just call the function + let layout_id = LayoutIds::default().get(func_sym, ret_layout); + let fn_name = self.symbol_to_string(func_sym, layout_id); + // Now that the arguments are needed, load them if they are literals. + self.load_literal_symbols(args); + self.build_fn_call(sym, fn_name, args, arg_layouts, ret_layout) + } + other => { + eprintln!("maybe {other:?} should have a custom implementation?"); + + // just call the function + let layout_id = LayoutIds::default().get(func_sym, ret_layout); + let fn_name = self.symbol_to_string(func_sym, layout_id); + // Now that the arguments are needed, load them if they are literals. + self.load_literal_symbols(args); + self.build_fn_call(sym, fn_name, args, arg_layouts, ret_layout) + } } } @@ -935,6 +1146,16 @@ trait Backend<'a> { return_layout: &InLayout<'a>, ); + /// build_num_sub_checked stores the sum of src1 and src2 into dst. + fn build_num_sub_checked( + &mut self, + dst: &Symbol, + src1: &Symbol, + src2: &Symbol, + num_layout: &InLayout<'a>, + return_layout: &InLayout<'a>, + ); + /// build_num_mul stores `src1 * src2` into dst. fn build_num_mul(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &InLayout<'a>); @@ -1016,6 +1237,9 @@ trait Backend<'a> { /// build_neq stores the result of `src1 != src2` into dst. fn build_neq(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, arg_layout: &InLayout<'a>); + /// build_not stores the result of `!src` into dst. + fn build_not(&mut self, dst: &Symbol, src: &Symbol, arg_layout: &InLayout<'a>); + /// build_num_lt stores the result of `src1 < src2` into dst. fn build_num_lt( &mut self, @@ -1061,6 +1285,9 @@ trait Backend<'a> { arg_layout: &InLayout<'a>, ); + /// build_sqrt stores the result of `sqrt(src)` into dst. + fn build_num_sqrt(&mut self, dst: Symbol, src: Symbol, float_width: FloatWidth); + /// build_list_len returns the length of a list. fn build_list_len(&mut self, dst: &Symbol, list: &Symbol); diff --git a/crates/compiler/gen_llvm/Cargo.toml b/crates/compiler/gen_llvm/Cargo.toml index af3bf91a16..031c418bfc 100644 --- a/crates/compiler/gen_llvm/Cargo.toml +++ b/crates/compiler/gen_llvm/Cargo.toml @@ -1,24 +1,26 @@ [package] name = "roc_gen_llvm" description = "The LLVM backend for the Roc compiler" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" + +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true [dependencies] -roc_alias_analysis = { path = "../alias_analysis" } -roc_collections = { path = "../collections" } -roc_module = { path = "../module" } -roc_builtins = { path = "../builtins" } -roc_error_macros = { path = "../../error_macros" } -roc_mono = { path = "../mono" } -roc_target = { path = "../roc_target" } -roc_std = { path = "../../roc_std" } -roc_debug_flags = { path = "../debug_flags" } -roc_region = { path = "../region" } morphic_lib = { path = "../../vendor/morphic_lib" } +roc_alias_analysis = { path = "../alias_analysis" } +roc_bitcode_bc = { path = "../builtins/bitcode/bc" } +roc_builtins = { path = "../builtins" } +roc_collections = { path = "../collections" } +roc_debug_flags = { path = "../debug_flags" } +roc_error_macros = { path = "../../error_macros" } +roc_module = { path = "../module" } +roc_mono = { path = "../mono" } +roc_region = { path = "../region" } +roc_std = { path = "../../roc_std" } +roc_target = { path = "../roc_target" } bumpalo.workspace = true +inkwell.workspace = true target-lexicon.workspace = true -inkwell.workspace = true diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index 2fbabc4255..66cfaebb6b 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -39,8 +39,8 @@ use roc_debug_flags::dbg_do; use roc_debug_flags::ROC_PRINT_LLVM_FN_VERIFICATION; use roc_module::symbol::{Interns, ModuleId, Symbol}; use roc_mono::ir::{ - BranchInfo, CallType, CrashTag, EntryPoint, JoinPointId, ListLiteralElement, ModifyRc, - OptLevel, ProcLayout, SingleEntryPoint, + BranchInfo, CallType, CrashTag, EntryPoint, HostExposedLambdaSet, JoinPointId, + ListLiteralElement, ModifyRc, OptLevel, ProcLayout, SingleEntryPoint, }; use roc_mono::layout::{ Builtin, InLayout, LambdaName, LambdaSet, Layout, LayoutIds, LayoutInterner, Niche, @@ -3977,7 +3977,8 @@ fn expose_function_to_host_help_c_abi_v2<'a, 'ctx, 'env>( // In C, this is modelled as a function returning void ( ¶ms[..], - ¶m_types[..param_types.len().saturating_sub(1)], + // ¶m_types[..param_types.len().saturating_sub(1)], + ¶m_types[..], ) } _ => (¶ms[..], ¶m_types[..]), @@ -4938,26 +4939,24 @@ fn expose_alias_to_host<'a, 'ctx, 'env>( mod_solutions: &'a ModSolutions, proc_name: LambdaName, alias_symbol: Symbol, - exposed_function_symbol: Symbol, - top_level: ProcLayout<'a>, - layout: RawFunctionLayout<'a>, + hels: &HostExposedLambdaSet<'a>, ) { let ident_string = proc_name.name().as_str(&env.interns); let fn_name: String = format!("{}_1", ident_string); - match layout { + match hels.raw_function_layout { RawFunctionLayout::Function(arguments, closure, result) => { // define closure size and return value size, e.g. // // * roc__mainForHost_1_Update_size() -> i64 // * roc__mainForHost_1_Update_result_size() -> i64 - let it = top_level.arguments.iter().copied(); + let it = hels.proc_layout.arguments.iter().copied(); let bytes = roc_alias_analysis::func_name_bytes_help( - exposed_function_symbol, + hels.symbol, it, Niche::NONE, - top_level.result, + hels.proc_layout.result, ); let func_name = FuncName(&bytes); let func_solutions = mod_solutions.func_solutions(func_name).unwrap(); @@ -4973,17 +4972,17 @@ fn expose_alias_to_host<'a, 'ctx, 'env>( function_value_by_func_spec( env, *func_spec, - exposed_function_symbol, - top_level.arguments, + hels.symbol, + hels.proc_layout.arguments, Niche::NONE, - top_level.result, + hels.proc_layout.result, ) } None => { // morphic did not generate a specialization for this function, // therefore it must actually be unused. // An example is our closure callers - panic!("morphic did not specialize {:?}", exposed_function_symbol); + panic!("morphic did not specialize {:?}", hels.symbol); } }; @@ -5237,16 +5236,14 @@ pub fn build_proc<'a, 'ctx, 'env>( /* no host, or exposing types is not supported */ } Binary | BinaryDev => { - for (alias_name, (generated_function, top_level, layout)) in aliases.iter() { + for (alias_name, hels) in aliases.iter() { expose_alias_to_host( env, layout_interner, mod_solutions, proc.name, *alias_name, - *generated_function, - *top_level, - *layout, + hels, ) } } diff --git a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs index c3afaa5ffa..4a1d09cc27 100644 --- a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs +++ b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs @@ -848,9 +848,24 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( _ => unreachable!(), } } - NumAbs | NumNeg | NumRound | NumSqrtUnchecked | NumLogUnchecked | NumSin | NumCos - | NumCeiling | NumFloor | NumToFrac | NumIsFinite | NumAtan | NumAcos | NumAsin - | NumToIntChecked => { + NumAbs + | NumNeg + | NumRound + | NumSqrtUnchecked + | NumLogUnchecked + | NumSin + | NumCos + | NumCeiling + | NumFloor + | NumToFrac + | NumIsFinite + | NumAtan + | NumAcos + | NumAsin + | NumToIntChecked + | NumCountLeadingZeroBits + | NumCountTrailingZeroBits + | NumCountOneBits => { arguments_with_layouts!((arg, arg_layout)); match layout_interner.get(arg_layout) { @@ -914,6 +929,28 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>( bitcode::NUM_BYTES_TO_U32, ) } + NumBytesToU64 => { + arguments!(list, position); + + call_list_bitcode_fn( + env, + &[list.into_struct_value()], + &[position], + BitcodeReturns::Basic, + bitcode::NUM_BYTES_TO_U64, + ) + } + NumBytesToU128 => { + arguments!(list, position); + + call_list_bitcode_fn( + env, + &[list.into_struct_value()], + &[position], + BitcodeReturns::Basic, + bitcode::NUM_BYTES_TO_U128, + ) + } NumCompare => { arguments_with_layouts!((lhs_arg, lhs_layout), (rhs_arg, rhs_layout)); @@ -2045,6 +2082,19 @@ fn build_int_unary_op<'a, 'ctx, 'env>( complex_bitcast_check_size(env, result, return_type.into(), "cast_bitpacked") } } + NumCountLeadingZeroBits => call_bitcode_fn( + env, + &[arg.into()], + &bitcode::NUM_COUNT_LEADING_ZERO_BITS[arg_width], + ), + NumCountTrailingZeroBits => call_bitcode_fn( + env, + &[arg.into()], + &bitcode::NUM_COUNT_TRAILING_ZERO_BITS[arg_width], + ), + NumCountOneBits => { + call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_COUNT_ONE_BITS[arg_width]) + } _ => { unreachable!("Unrecognized int unary operation: {:?}", op); } diff --git a/crates/compiler/gen_llvm/src/llvm/refcounting.rs b/crates/compiler/gen_llvm/src/llvm/refcounting.rs index 000adb85cb..a68f7a12e9 100644 --- a/crates/compiler/gen_llvm/src/llvm/refcounting.rs +++ b/crates/compiler/gen_llvm/src/llvm/refcounting.rs @@ -1345,11 +1345,16 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>( union_layout, UnionLayout::NullableUnwrapped { .. } | UnionLayout::NonNullableUnwrapped { .. } ) { - debug_assert_eq!(cases.len(), 1); + debug_assert!(cases.len() <= 1, "{cases:?}"); - // in this case, don't switch, because the `else` branch below would try to read the (nonexistent) tag id - let (_, only_branch) = cases.pop().unwrap(); - env.builder.build_unconditional_branch(only_branch); + if cases.is_empty() { + // The only other layout doesn't need refcounting. Pass through. + builder.build_return(None); + } else { + // in this case, don't switch, because the `else` branch below would try to read the (nonexistent) tag id + let (_, only_branch) = cases.pop().unwrap(); + env.builder.build_unconditional_branch(only_branch); + } } else { let default_block = env.context.append_basic_block(parent, "switch_default"); @@ -1372,6 +1377,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>( } } +#[derive(Debug)] struct UnionLayoutTags<'a> { nullable_id: Option, tags: &'a [&'a [InLayout<'a>]], diff --git a/crates/compiler/gen_wasm/Cargo.toml b/crates/compiler/gen_wasm/Cargo.toml index b96de60b50..a25ccf0e23 100644 --- a/crates/compiler/gen_wasm/Cargo.toml +++ b/crates/compiler/gen_wasm/Cargo.toml @@ -1,19 +1,20 @@ [package] name = "roc_gen_wasm" -version = "0.0.1" -edition = "2021" -authors = ["The Roc Contributors"] -license = "UPL-1.0" description = "Provides the WASM backend to generate Roc binaries." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] roc_builtins = { path = "../builtins" } roc_collections = { path = "../collections" } +roc_error_macros = { path = "../../error_macros" } roc_module = { path = "../module" } roc_mono = { path = "../mono" } -roc_target = { path = "../roc_target" } roc_std = { path = "../../roc_std" } -roc_error_macros = { path = "../../error_macros" } +roc_target = { path = "../roc_target" } roc_wasm_module = { path = "../../wasm_module" } bitvec.workspace = true diff --git a/crates/compiler/gen_wasm/src/low_level.rs b/crates/compiler/gen_wasm/src/low_level.rs index 5b3a099edd..130d842d5b 100644 --- a/crates/compiler/gen_wasm/src/low_level.rs +++ b/crates/compiler/gen_wasm/src/low_level.rs @@ -1489,6 +1489,40 @@ impl<'a> LowLevelCall<'a> { } _ => panic_ret_type(), }, + + NumCountLeadingZeroBits => match backend + .layout_interner + .get(backend.storage.symbol_layouts[&self.arguments[0]]) + { + Layout::Builtin(Builtin::Int(width)) => { + self.load_args_and_call_zig( + backend, + &bitcode::NUM_COUNT_LEADING_ZERO_BITS[width], + ); + } + _ => panic_ret_type(), + }, + NumCountTrailingZeroBits => match backend + .layout_interner + .get(backend.storage.symbol_layouts[&self.arguments[0]]) + { + Layout::Builtin(Builtin::Int(width)) => { + self.load_args_and_call_zig( + backend, + &bitcode::NUM_COUNT_TRAILING_ZERO_BITS[width], + ); + } + _ => panic_ret_type(), + }, + NumCountOneBits => match backend + .layout_interner + .get(backend.storage.symbol_layouts[&self.arguments[0]]) + { + Layout::Builtin(Builtin::Int(width)) => { + self.load_args_and_call_zig(backend, &bitcode::NUM_COUNT_ONE_BITS[width]); + } + _ => panic_ret_type(), + }, NumRound => { self.load_args(backend); let arg_type = CodeGenNumType::for_symbol(backend, self.arguments[0]); @@ -1577,6 +1611,8 @@ impl<'a> LowLevelCall<'a> { }, NumBytesToU16 => self.load_args_and_call_zig(backend, bitcode::NUM_BYTES_TO_U16), NumBytesToU32 => self.load_args_and_call_zig(backend, bitcode::NUM_BYTES_TO_U32), + NumBytesToU64 => self.load_args_and_call_zig(backend, bitcode::NUM_BYTES_TO_U64), + NumBytesToU128 => self.load_args_and_call_zig(backend, bitcode::NUM_BYTES_TO_U128), NumBitwiseAnd => { self.load_args(backend); match CodeGenNumType::from(self.ret_layout) { diff --git a/crates/compiler/ident/Cargo.toml b/crates/compiler/ident/Cargo.toml index febd0b050c..0c53fa90a9 100644 --- a/crates/compiler/ident/Cargo.toml +++ b/crates/compiler/ident/Cargo.toml @@ -1,7 +1,8 @@ [package] name = "roc_ident" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Implements data structures used for efficiently representing small strings, like identifiers." + +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true diff --git a/crates/compiler/late_solve/Cargo.toml b/crates/compiler/late_solve/Cargo.toml index f4b11fa9c7..cd9af7f6cf 100644 --- a/crates/compiler/late_solve/Cargo.toml +++ b/crates/compiler/late_solve/Cargo.toml @@ -1,19 +1,20 @@ [package] name = "roc_late_solve" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Provides type unification and solving primitives from the perspective of the compiler backend." -[dependencies] -roc_types = { path = "../types" } -roc_can = { path = "../can" } -roc_derive = { path = "../derive" } -roc_module = { path = "../module" } -roc_unify = { path = "../unify" } -roc_solve = { path = "../solve" } -roc_collections = { path = "../collections" } -roc_error_macros = { path = "../../error_macros" } +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true -bumpalo.workspace = true +[dependencies] +roc_can = { path = "../can" } +roc_collections = { path = "../collections" } +roc_derive = { path = "../derive" } +roc_error_macros = { path = "../../error_macros" } +roc_module = { path = "../module" } +roc_solve = { path = "../solve" } +roc_types = { path = "../types" } +roc_unify = { path = "../unify" } + +bumpalo.workspace = true diff --git a/crates/compiler/load/Cargo.toml b/crates/compiler/load/Cargo.toml index fa190af36f..537093b6a6 100644 --- a/crates/compiler/load/Cargo.toml +++ b/crates/compiler/load/Cargo.toml @@ -1,30 +1,31 @@ [package] name = "roc_load" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Used to load a .roc file and coordinate the compiler pipeline, including parsing, type checking, and code generation." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] -roc_load_internal = { path = "../load_internal" } -roc_target = { path = "../roc_target" } roc_can = { path = "../can" } -roc_types = { path = "../types" } -roc_module = { path = "../module" } roc_collections = { path = "../collections" } +roc_load_internal = { path = "../load_internal" } +roc_module = { path = "../module" } roc_packaging = { path = "../../packaging" } roc_reporting = { path = "../../reporting" } +roc_target = { path = "../roc_target" } +roc_types = { path = "../types" } bumpalo.workspace = true [build-dependencies] roc_builtins = { path = "../builtins" } +roc_can = { path = "../can" } roc_module = { path = "../module" } roc_packaging = { path = "../../packaging" } roc_reporting = { path = "../../reporting" } roc_target = { path = "../roc_target" } -roc_can = { path = "../can" } bumpalo.workspace = true diff --git a/crates/compiler/load_internal/Cargo.toml b/crates/compiler/load_internal/Cargo.toml index a52d997f93..e53090ac0b 100644 --- a/crates/compiler/load_internal/Cargo.toml +++ b/crates/compiler/load_internal/Cargo.toml @@ -1,45 +1,46 @@ [package] name = "roc_load_internal" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "The internal implementation of roc_load, separate from roc_load to support caching." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] -roc_collections = { path = "../collections" } -roc_error_macros = { path = "../../error_macros" } -roc_region = { path = "../region" } -roc_module = { path = "../module" } -roc_types = { path = "../types" } -roc_can = { path = "../can" } -roc_constrain = { path = "../constrain" } -roc_derive_key = { path = "../derive_key" } -roc_derive = { path = "../derive" } roc_builtins = { path = "../builtins" } -roc_problem = { path = "../problem" } -roc_unify = { path = "../unify" } +roc_can = { path = "../can" } +roc_collections = { path = "../collections" } +roc_constrain = { path = "../constrain" } +roc_debug_flags = { path = "../debug_flags" } +roc_derive = { path = "../derive" } +roc_derive_key = { path = "../derive_key" } +roc_error_macros = { path = "../../error_macros" } +roc_late_solve = { path = "../late_solve" } +roc_module = { path = "../module" } +roc_mono = { path = "../mono" } +roc_packaging = { path = "../../packaging" } roc_parse = { path = "../parse" } +roc_problem = { path = "../problem" } +roc_region = { path = "../region" } +roc_reporting = { path = "../../reporting" } roc_solve = { path = "../solve" } roc_solve_problem = { path = "../solve_problem" } -roc_late_solve = { path = "../late_solve" } -roc_mono = { path = "../mono" } roc_target = { path = "../roc_target" } roc_tracing = { path = "../../tracing" } -roc_packaging = { path = "../../packaging" } -roc_reporting = { path = "../../reporting" } -roc_debug_flags = { path = "../debug_flags" } +roc_types = { path = "../types" } +roc_unify = { path = "../unify" } ven_pretty = { path = "../../vendor/pretty" } bumpalo.workspace = true -parking_lot.workspace = true crossbeam.workspace = true +parking_lot.workspace = true tempfile.workspace = true [dev-dependencies] roc_test_utils = { path = "../../test_utils" } -pretty_assertions.workspace = true indoc.workspace = true maplit.workspace = true +pretty_assertions.workspace = true diff --git a/crates/compiler/module/Cargo.toml b/crates/compiler/module/Cargo.toml index 938ad44b83..6be6b4e716 100644 --- a/crates/compiler/module/Cargo.toml +++ b/crates/compiler/module/Cargo.toml @@ -1,20 +1,22 @@ [package] name = "roc_module" -version = "0.0.1" -authors = ["The Roc Contributors"] -edition = "2021" -license = "UPL-1.0" description = "Implements data structures used for efficiently representing unique modules and identifiers in Roc programs." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] -roc_region = { path = "../region" } -roc_ident = { path = "../ident" } roc_collections = { path = "../collections" } -roc_error_macros = {path = "../../error_macros"} +roc_error_macros = { path = "../../error_macros" } +roc_ident = { path = "../ident" } +roc_region = { path = "../region" } + bumpalo.workspace = true -static_assertions.workspace = true snafu.workspace = true +static_assertions.workspace = true [features] -default = [] debug-symbols = [] +default = [] diff --git a/crates/compiler/module/src/low_level.rs b/crates/compiler/module/src/low_level.rs index 4f3c343bc7..1a7d870f60 100644 --- a/crates/compiler/module/src/low_level.rs +++ b/crates/compiler/module/src/low_level.rs @@ -90,6 +90,8 @@ pub enum LowLevel { NumAsin, NumBytesToU16, NumBytesToU32, + NumBytesToU64, + NumBytesToU128, NumBitwiseAnd, NumBitwiseXor, NumBitwiseOr, @@ -101,6 +103,9 @@ pub enum LowLevel { NumToIntChecked, NumToFloatChecked, NumToStr, + NumCountLeadingZeroBits, + NumCountTrailingZeroBits, + NumCountOneBits, Eq, NotEq, And, @@ -305,6 +310,8 @@ map_symbol_to_lowlevel! { NumAsin <= NUM_ASIN, NumBytesToU16 <= NUM_BYTES_TO_U16_LOWLEVEL, NumBytesToU32 <= NUM_BYTES_TO_U32_LOWLEVEL, + NumBytesToU64 <= NUM_BYTES_TO_U64_LOWLEVEL, + NumBytesToU128 <= NUM_BYTES_TO_U128_LOWLEVEL, NumBitwiseAnd <= NUM_BITWISE_AND, NumBitwiseXor <= NUM_BITWISE_XOR, NumBitwiseOr <= NUM_BITWISE_OR, @@ -312,6 +319,9 @@ map_symbol_to_lowlevel! { NumShiftRightBy <= NUM_SHIFT_RIGHT, NumShiftRightZfBy <= NUM_SHIFT_RIGHT_ZERO_FILL, NumToStr <= NUM_TO_STR, + NumCountLeadingZeroBits <= NUM_COUNT_LEADING_ZERO_BITS, + NumCountTrailingZeroBits <= NUM_COUNT_TRAILING_ZERO_BITS, + NumCountOneBits <= NUM_COUNT_ONE_BITS, Eq <= BOOL_STRUCTURAL_EQ, NotEq <= BOOL_STRUCTURAL_NOT_EQ, And <= BOOL_AND, diff --git a/crates/compiler/module/src/symbol.rs b/crates/compiler/module/src/symbol.rs index 4ab92ec50c..34096ee30b 100644 --- a/crates/compiler/module/src/symbol.rs +++ b/crates/compiler/module/src/symbol.rs @@ -1189,63 +1189,70 @@ define_builtins! { 88 NUM_DEC: "Dec" exposed_type=true // the Num.Dectype alias 89 NUM_BYTES_TO_U16: "bytesToU16" 90 NUM_BYTES_TO_U32: "bytesToU32" - 91 NUM_CAST_TO_NAT: "#castToNat" - 92 NUM_DIV_CEIL: "divCeil" - 93 NUM_DIV_CEIL_CHECKED: "divCeilChecked" - 94 NUM_TO_STR: "toStr" - 95 NUM_MIN_I8: "minI8" - 96 NUM_MAX_I8: "maxI8" - 97 NUM_MIN_U8: "minU8" - 98 NUM_MAX_U8: "maxU8" - 99 NUM_MIN_I16: "minI16" - 100 NUM_MAX_I16: "maxI16" - 101 NUM_MIN_U16: "minU16" - 102 NUM_MAX_U16: "maxU16" - 103 NUM_MIN_I32: "minI32" - 104 NUM_MAX_I32: "maxI32" - 105 NUM_MIN_U32: "minU32" - 106 NUM_MAX_U32: "maxU32" - 107 NUM_MIN_I64: "minI64" - 108 NUM_MAX_I64: "maxI64" - 109 NUM_MIN_U64: "minU64" - 110 NUM_MAX_U64: "maxU64" - 111 NUM_MIN_I128: "minI128" - 112 NUM_MAX_I128: "maxI128" - 113 NUM_MIN_U128: "minU128" - 114 NUM_MAX_U128: "maxU128" - 115 NUM_TO_I8: "toI8" - 116 NUM_TO_I8_CHECKED: "toI8Checked" - 117 NUM_TO_I16: "toI16" - 118 NUM_TO_I16_CHECKED: "toI16Checked" - 119 NUM_TO_I32: "toI32" - 120 NUM_TO_I32_CHECKED: "toI32Checked" - 121 NUM_TO_I64: "toI64" - 122 NUM_TO_I64_CHECKED: "toI64Checked" - 123 NUM_TO_I128: "toI128" - 124 NUM_TO_I128_CHECKED: "toI128Checked" - 125 NUM_TO_U8: "toU8" - 126 NUM_TO_U8_CHECKED: "toU8Checked" - 127 NUM_TO_U16: "toU16" - 128 NUM_TO_U16_CHECKED: "toU16Checked" - 129 NUM_TO_U32: "toU32" - 130 NUM_TO_U32_CHECKED: "toU32Checked" - 131 NUM_TO_U64: "toU64" - 132 NUM_TO_U64_CHECKED: "toU64Checked" - 133 NUM_TO_U128: "toU128" - 134 NUM_TO_U128_CHECKED: "toU128Checked" - 135 NUM_TO_NAT: "toNat" - 136 NUM_TO_NAT_CHECKED: "toNatChecked" - 137 NUM_TO_F32: "toF32" - 138 NUM_TO_F32_CHECKED: "toF32Checked" - 139 NUM_TO_F64: "toF64" - 140 NUM_TO_F64_CHECKED: "toF64Checked" - 141 NUM_MAX_F64: "maxF64" - 142 NUM_MIN_F64: "minF64" - 143 NUM_ADD_CHECKED_LOWLEVEL: "addCheckedLowlevel" - 144 NUM_SUB_CHECKED_LOWLEVEL: "subCheckedLowlevel" - 145 NUM_MUL_CHECKED_LOWLEVEL: "mulCheckedLowlevel" - 146 NUM_BYTES_TO_U16_LOWLEVEL: "bytesToU16Lowlevel" - 147 NUM_BYTES_TO_U32_LOWLEVEL: "bytesToU32Lowlevel" + 91 NUM_BYTES_TO_U64: "bytesToU64" + 92 NUM_BYTES_TO_U128: "bytesToU128" + 93 NUM_CAST_TO_NAT: "#castToNat" + 94 NUM_DIV_CEIL: "divCeil" + 95 NUM_DIV_CEIL_CHECKED: "divCeilChecked" + 96 NUM_TO_STR: "toStr" + 97 NUM_MIN_I8: "minI8" + 98 NUM_MAX_I8: "maxI8" + 99 NUM_MIN_U8: "minU8" + 100 NUM_MAX_U8: "maxU8" + 101 NUM_MIN_I16: "minI16" + 102 NUM_MAX_I16: "maxI16" + 103 NUM_MIN_U16: "minU16" + 104 NUM_MAX_U16: "maxU16" + 105 NUM_MIN_I32: "minI32" + 106 NUM_MAX_I32: "maxI32" + 107 NUM_MIN_U32: "minU32" + 108 NUM_MAX_U32: "maxU32" + 109 NUM_MIN_I64: "minI64" + 110 NUM_MAX_I64: "maxI64" + 111 NUM_MIN_U64: "minU64" + 112 NUM_MAX_U64: "maxU64" + 113 NUM_MIN_I128: "minI128" + 114 NUM_MAX_I128: "maxI128" + 115 NUM_MIN_U128: "minU128" + 116 NUM_MAX_U128: "maxU128" + 117 NUM_TO_I8: "toI8" + 118 NUM_TO_I8_CHECKED: "toI8Checked" + 119 NUM_TO_I16: "toI16" + 120 NUM_TO_I16_CHECKED: "toI16Checked" + 121 NUM_TO_I32: "toI32" + 122 NUM_TO_I32_CHECKED: "toI32Checked" + 123 NUM_TO_I64: "toI64" + 124 NUM_TO_I64_CHECKED: "toI64Checked" + 125 NUM_TO_I128: "toI128" + 126 NUM_TO_I128_CHECKED: "toI128Checked" + 127 NUM_TO_U8: "toU8" + 128 NUM_TO_U8_CHECKED: "toU8Checked" + 129 NUM_TO_U16: "toU16" + 130 NUM_TO_U16_CHECKED: "toU16Checked" + 131 NUM_TO_U32: "toU32" + 132 NUM_TO_U32_CHECKED: "toU32Checked" + 133 NUM_TO_U64: "toU64" + 134 NUM_TO_U64_CHECKED: "toU64Checked" + 135 NUM_TO_U128: "toU128" + 136 NUM_TO_U128_CHECKED: "toU128Checked" + 137 NUM_TO_NAT: "toNat" + 138 NUM_TO_NAT_CHECKED: "toNatChecked" + 139 NUM_TO_F32: "toF32" + 140 NUM_TO_F32_CHECKED: "toF32Checked" + 141 NUM_TO_F64: "toF64" + 142 NUM_TO_F64_CHECKED: "toF64Checked" + 143 NUM_MAX_F64: "maxF64" + 144 NUM_MIN_F64: "minF64" + 145 NUM_ADD_CHECKED_LOWLEVEL: "addCheckedLowlevel" + 146 NUM_SUB_CHECKED_LOWLEVEL: "subCheckedLowlevel" + 147 NUM_MUL_CHECKED_LOWLEVEL: "mulCheckedLowlevel" + 148 NUM_BYTES_TO_U16_LOWLEVEL: "bytesToU16Lowlevel" + 149 NUM_BYTES_TO_U32_LOWLEVEL: "bytesToU32Lowlevel" + 150 NUM_BYTES_TO_U64_LOWLEVEL: "bytesToU64Lowlevel" + 151 NUM_BYTES_TO_U128_LOWLEVEL: "bytesToU128Lowlevel" + 152 NUM_COUNT_LEADING_ZERO_BITS: "countLeadingZeroBits" + 153 NUM_COUNT_TRAILING_ZERO_BITS: "countTrailingZeroBits" + 154 NUM_COUNT_ONE_BITS: "countOneBits" } 4 BOOL: "Bool" => { 0 BOOL_BOOL: "Bool" exposed_type=true // the Bool.Bool type alias @@ -1319,6 +1326,7 @@ define_builtins! { 53 STR_WITH_CAPACITY: "withCapacity" 54 STR_WITH_PREFIX: "withPrefix" 55 STR_GRAPHEMES: "graphemes" + 56 STR_IS_VALID_SCALAR: "isValidScalar" } 6 LIST: "List" => { 0 LIST_LIST: "List" exposed_apply_type=true // the List.List type alias @@ -1401,6 +1409,7 @@ define_builtins! { 77 LIST_COUNT_IF: "countIf" 78 LIST_WALK_FROM: "walkFrom" 79 LIST_WALK_FROM_UNTIL: "walkFromUntil" + 80 LIST_ITER_HELP: "iterHelp" } 7 RESULT: "Result" => { 0 RESULT_RESULT: "Result" exposed_type=true // the Result.Result type alias diff --git a/crates/compiler/mono/Cargo.toml b/crates/compiler/mono/Cargo.toml index 73ce78d7a0..44887a5b8f 100644 --- a/crates/compiler/mono/Cargo.toml +++ b/crates/compiler/mono/Cargo.toml @@ -1,32 +1,33 @@ [package] name = "roc_mono" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Roc's main intermediate representation (IR), which is responsible for monomorphization, defunctionalization, inserting ref-count instructions, and transforming a Roc program into a form that is easy to consume by a backend." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] -roc_collections = { path = "../collections" } -roc_exhaustive = { path = "../exhaustive" } -roc_region = { path = "../region" } -roc_module = { path = "../module" } -roc_types = { path = "../types" } -roc_can = { path = "../can" } -roc_derive_key = { path = "../derive_key" } -roc_derive = { path = "../derive" } -roc_late_solve = { path = "../late_solve" } -roc_std = { path = "../../roc_std" } -roc_problem = { path = "../problem" } roc_builtins = { path = "../builtins" } +roc_can = { path = "../can" } +roc_collections = { path = "../collections" } +roc_debug_flags = { path = "../debug_flags" } +roc_derive = { path = "../derive" } +roc_derive_key = { path = "../derive_key" } +roc_error_macros = { path = "../../error_macros" } +roc_exhaustive = { path = "../exhaustive" } +roc_late_solve = { path = "../late_solve" } +roc_module = { path = "../module" } +roc_problem = { path = "../problem" } +roc_region = { path = "../region" } +roc_std = { path = "../../roc_std" } roc_target = { path = "../roc_target" } -roc_error_macros = {path="../../error_macros"} -roc_debug_flags = {path="../debug_flags"} roc_tracing = { path = "../../tracing" } +roc_types = { path = "../types" } ven_pretty = { path = "../../vendor/pretty" } +bitvec.workspace = true bumpalo.workspace = true hashbrown.workspace = true -static_assertions.workspace = true -bitvec.workspace = true parking_lot.workspace = true +static_assertions.workspace = true diff --git a/crates/compiler/mono/src/borrow.rs b/crates/compiler/mono/src/borrow.rs index 3d31172173..44f67491a4 100644 --- a/crates/compiler/mono/src/borrow.rs +++ b/crates/compiler/mono/src/borrow.rs @@ -100,8 +100,14 @@ pub fn infer_borrow<'a>( // host-exposed functions must always own their arguments. let is_host_exposed = host_exposed_procs.contains(&key.0); - let param_offset = param_map.get_param_offset(key.0, key.1); - env.collect_proc(&mut param_map, proc, param_offset, is_host_exposed); + let param_offset = param_map.get_param_offset(interner, key.0, key.1); + env.collect_proc( + interner, + &mut param_map, + proc, + param_offset, + is_host_exposed, + ); } if !env.modified { @@ -167,6 +173,7 @@ impl<'a> DeclarationToIndex<'a> { fn get_param_offset( &self, + interner: &STLayoutInterner<'a>, needle_symbol: Symbol, needle_layout: ProcLayout<'a>, ) -> ParamOffset { @@ -181,12 +188,14 @@ impl<'a> DeclarationToIndex<'a> { .elements .iter() .filter_map(|(Declaration { symbol, layout }, _)| { - (*symbol == needle_symbol).then_some(layout) + (*symbol == needle_symbol) + .then_some(layout) + .map(|l| l.dbg_deep(interner)) }) .collect::>(); unreachable!( "symbol/layout {:?} {:#?} combo must be in DeclarationToIndex\nHowever {} similar layouts were found:\n{:#?}", - needle_symbol, needle_layout, similar.len(), similar + needle_symbol, needle_layout.dbg_deep(interner), similar.len(), similar, ) } } @@ -206,13 +215,24 @@ pub struct ParamMap<'a> { } impl<'a> ParamMap<'a> { - pub fn get_param_offset(&self, symbol: Symbol, layout: ProcLayout<'a>) -> ParamOffset { - self.declaration_to_index.get_param_offset(symbol, layout) + pub fn get_param_offset( + &self, + interner: &STLayoutInterner<'a>, + symbol: Symbol, + layout: ProcLayout<'a>, + ) -> ParamOffset { + self.declaration_to_index + .get_param_offset(interner, symbol, layout) } - pub fn get_symbol(&self, symbol: Symbol, layout: ProcLayout<'a>) -> Option<&[Param<'a>]> { + pub fn get_symbol( + &self, + interner: &STLayoutInterner<'a>, + symbol: Symbol, + layout: ProcLayout<'a>, + ) -> Option<&[Param<'a>]> { // let index: usize = self.declaration_to_index[&(symbol, layout)].into(); - let index: usize = self.get_param_offset(symbol, layout).into(); + let index: usize = self.get_param_offset(interner, symbol, layout).into(); self.declarations.get(index..index + layout.arguments.len()) } @@ -292,7 +312,7 @@ impl<'a> ParamMap<'a> { return; } - let index: usize = self.get_param_offset(key.0, key.1).into(); + let index: usize = self.get_param_offset(interner, key.0, key.1).into(); for (i, param) in Self::init_borrow_args(arena, interner, proc.args) .iter() @@ -312,7 +332,7 @@ impl<'a> ParamMap<'a> { proc: &Proc<'a>, key: (Symbol, ProcLayout<'a>), ) { - let index: usize = self.get_param_offset(key.0, key.1).into(); + let index: usize = self.get_param_offset(interner, key.0, key.1).into(); for (i, param) in Self::init_borrow_args_always_owned(arena, proc.args) .iter() @@ -534,7 +554,13 @@ impl<'a> BorrowInfState<'a> { /// /// and determines whether z and which of the symbols used in e /// must be taken as owned parameters - fn collect_call(&mut self, param_map: &mut ParamMap<'a>, z: Symbol, e: &crate::ir::Call<'a>) { + fn collect_call( + &mut self, + interner: &STLayoutInterner<'a>, + param_map: &mut ParamMap<'a>, + z: Symbol, + e: &crate::ir::Call<'a>, + ) { use crate::ir::CallType::*; let crate::ir::Call { @@ -553,7 +579,7 @@ impl<'a> BorrowInfState<'a> { // get the borrow signature of the applied function let ps = param_map - .get_symbol(name.name(), top_level) + .get_symbol(interner, name.name(), top_level) .expect("function is defined"); // the return value will be owned @@ -595,11 +621,14 @@ impl<'a> BorrowInfState<'a> { niche: passed_function.name.niche(), }; - let function_ps = - match param_map.get_symbol(passed_function.name.name(), closure_layout) { - Some(function_ps) => function_ps, - None => unreachable!(), - }; + let function_ps = match param_map.get_symbol( + interner, + passed_function.name.name(), + closure_layout, + ) { + Some(function_ps) => function_ps, + None => unreachable!(), + }; match op { ListMap { xs } => { @@ -671,7 +700,13 @@ impl<'a> BorrowInfState<'a> { } } - fn collect_expr(&mut self, param_map: &mut ParamMap<'a>, z: Symbol, e: &Expr<'a>) { + fn collect_expr( + &mut self, + interner: &STLayoutInterner<'a>, + param_map: &mut ParamMap<'a>, + z: Symbol, + e: &Expr<'a>, + ) { use Expr::*; match e { @@ -724,7 +759,7 @@ impl<'a> BorrowInfState<'a> { self.own_var(z); } - Call(call) => self.collect_call(param_map, z, call), + Call(call) => self.collect_call(interner, param_map, z, call), Literal(_) | RuntimeErrorFunction(_) => {} @@ -757,6 +792,7 @@ impl<'a> BorrowInfState<'a> { #[allow(clippy::many_single_char_names)] fn preserve_tail_call( &mut self, + interner: &STLayoutInterner<'a>, param_map: &mut ParamMap<'a>, x: Symbol, v: &Expr<'a>, @@ -782,7 +818,7 @@ impl<'a> BorrowInfState<'a> { if self.current_proc == g.name() && x == *z { // anonymous functions (for which the ps may not be known) // can never be tail-recursive, so this is fine - if let Some(ps) = param_map.get_symbol(g.name(), top_level) { + if let Some(ps) = param_map.get_symbol(interner, g.name(), top_level) { self.own_params_using_args(ys, ps) } } @@ -801,7 +837,12 @@ impl<'a> BorrowInfState<'a> { } } - fn collect_stmt(&mut self, param_map: &mut ParamMap<'a>, stmt: &Stmt<'a>) { + fn collect_stmt( + &mut self, + interner: &STLayoutInterner<'a>, + param_map: &mut ParamMap<'a>, + stmt: &Stmt<'a>, + ) { use Stmt::*; match stmt { @@ -813,11 +854,11 @@ impl<'a> BorrowInfState<'a> { } => { let old = self.param_set.clone(); self.update_param_set(ys); - self.collect_stmt(param_map, v); + self.collect_stmt(interner, param_map, v); self.param_set = old; self.update_param_map_join_point(param_map, *j); - self.collect_stmt(param_map, b); + self.collect_stmt(interner, param_map, b); } Let(x, v, _, mut b) => { @@ -830,17 +871,17 @@ impl<'a> BorrowInfState<'a> { stack.push((*symbol, expr)); } - self.collect_stmt(param_map, b); + self.collect_stmt(interner, param_map, b); let mut it = stack.into_iter().rev(); // collect the final expr, and see if we need to preserve a tail call let (x, v) = it.next().unwrap(); - self.collect_expr(param_map, x, v); - self.preserve_tail_call(param_map, x, v, b); + self.collect_expr(interner, param_map, x, v); + self.preserve_tail_call(interner, param_map, x, v, b); for (x, v) in it { - self.collect_expr(param_map, x, v); + self.collect_expr(interner, param_map, x, v); } } @@ -859,21 +900,21 @@ impl<'a> BorrowInfState<'a> { .. } => { for (_, _, b) in branches.iter() { - self.collect_stmt(param_map, b); + self.collect_stmt(interner, param_map, b); } - self.collect_stmt(param_map, default_branch.1); + self.collect_stmt(interner, param_map, default_branch.1); } Dbg { remainder, .. } => { - self.collect_stmt(param_map, remainder); + self.collect_stmt(interner, param_map, remainder); } Expect { remainder, .. } => { - self.collect_stmt(param_map, remainder); + self.collect_stmt(interner, param_map, remainder); } ExpectFx { remainder, .. } => { - self.collect_stmt(param_map, remainder); + self.collect_stmt(interner, param_map, remainder); } Refcounting(_, _) => unreachable!("these have not been introduced yet"), @@ -891,6 +932,7 @@ impl<'a> BorrowInfState<'a> { fn collect_proc( &mut self, + interner: &STLayoutInterner<'a>, param_map: &mut ParamMap<'a>, proc: &Proc<'a>, param_offset: ParamOffset, @@ -912,7 +954,7 @@ impl<'a> BorrowInfState<'a> { owned_entry.extend(params.iter().map(|p| p.symbol)); } - self.collect_stmt(param_map, &proc.body); + self.collect_stmt(interner, param_map, &proc.body); self.update_param_map_declaration(param_map, param_offset, proc.args.len()); self.param_set = old; @@ -984,13 +1026,33 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] { | NumPow | NumPowInt | NumBitwiseAnd | NumBitwiseXor | NumBitwiseOr | NumShiftLeftBy | NumShiftRightBy | NumShiftRightZfBy => arena.alloc_slice_copy(&[irrelevant, irrelevant]), - NumToStr | NumAbs | NumNeg | NumSin | NumCos | NumSqrtUnchecked | NumLogUnchecked - | NumRound | NumCeiling | NumFloor | NumToFrac | Not | NumIsFinite | NumAtan | NumAcos - | NumAsin | NumIntCast | NumToIntChecked | NumToFloatCast | NumToFloatChecked => { - arena.alloc_slice_copy(&[irrelevant]) - } + NumToStr + | NumAbs + | NumNeg + | NumSin + | NumCos + | NumSqrtUnchecked + | NumLogUnchecked + | NumRound + | NumCeiling + | NumFloor + | NumToFrac + | Not + | NumIsFinite + | NumAtan + | NumAcos + | NumAsin + | NumIntCast + | NumToIntChecked + | NumToFloatCast + | NumToFloatChecked + | NumCountLeadingZeroBits + | NumCountTrailingZeroBits + | NumCountOneBits => arena.alloc_slice_copy(&[irrelevant]), NumBytesToU16 => arena.alloc_slice_copy(&[borrowed, irrelevant]), NumBytesToU32 => arena.alloc_slice_copy(&[borrowed, irrelevant]), + NumBytesToU64 => arena.alloc_slice_copy(&[borrowed, irrelevant]), + NumBytesToU128 => arena.alloc_slice_copy(&[borrowed, irrelevant]), StrStartsWith | StrEndsWith => arena.alloc_slice_copy(&[borrowed, borrowed]), StrStartsWithScalar => arena.alloc_slice_copy(&[borrowed, irrelevant]), StrFromUtf8Range => arena.alloc_slice_copy(&[owned, irrelevant, irrelevant]), diff --git a/crates/compiler/mono/src/inc_dec.rs b/crates/compiler/mono/src/inc_dec.rs index eab6ec8acf..56b543f612 100644 --- a/crates/compiler/mono/src/inc_dec.rs +++ b/crates/compiler/mono/src/inc_dec.rs @@ -605,7 +605,7 @@ impl<'a, 'i> Context<'a, 'i> { // get the borrow signature let ps = self .param_map - .get_symbol(name.name(), top_level) + .get_symbol(self.layout_interner, name.name(), top_level) .expect("function is defined"); let v = Expr::Call(crate::ir::Call { @@ -653,10 +653,11 @@ impl<'a, 'i> Context<'a, 'i> { niche: passed_function.name.niche(), }; - let function_ps = match self - .param_map - .get_symbol(passed_function.name.name(), function_layout) - { + let function_ps = match self.param_map.get_symbol( + self.layout_interner, + passed_function.name.name(), + function_layout, + ) { Some(function_ps) => function_ps, None => unreachable!(), }; @@ -671,14 +672,14 @@ impl<'a, 'i> Context<'a, 'i> { match ownership { DataOwnedFunctionOwns | DataBorrowedFunctionOwns => { // elements have been consumed, must still consume the list itself - let rest = self.arena.alloc($stmt); + let rest = self.arena.alloc(stmt); let rc = Stmt::Refcounting(ModifyRc::DecRef(argument), rest); stmt = self.arena.alloc(rc); } DataOwnedFunctionBorrows => { // must consume list and elements - let rest = self.arena.alloc($stmt); + let rest = self.arena.alloc(stmt); let rc = Stmt::Refcounting(ModifyRc::Dec(argument), rest); stmt = self.arena.alloc(rc); @@ -1510,19 +1511,28 @@ pub fn visit_procs<'a, 'i>( }; for (key, proc) in procs.iter_mut() { - visit_proc(arena, &mut codegen, param_map, &ctx, proc, key.1); + visit_proc( + arena, + layout_interner, + &mut codegen, + param_map, + &ctx, + proc, + key.1, + ); } } fn visit_proc<'a, 'i>( arena: &'a Bump, + interner: &STLayoutInterner<'a>, codegen: &mut CodegenTools<'i>, param_map: &'a ParamMap<'a>, ctx: &Context<'a, 'i>, proc: &mut Proc<'a>, layout: ProcLayout<'a>, ) { - let params = match param_map.get_symbol(proc.name.name(), layout) { + let params = match param_map.get_symbol(interner, proc.name.name(), layout) { Some(slice) => slice, None => Vec::from_iter_in( proc.args.iter().cloned().map(|(layout, symbol)| Param { diff --git a/crates/compiler/mono/src/ir.rs b/crates/compiler/mono/src/ir.rs index a55373ba33..dd52be6970 100644 --- a/crates/compiler/mono/src/ir.rs +++ b/crates/compiler/mono/src/ir.rs @@ -305,12 +305,21 @@ pub struct Proc<'a> { pub host_exposed_layouts: HostExposedLayouts<'a>, } +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct HostExposedLambdaSet<'a> { + pub id: LambdaSetId, + /// Symbol of the exposed function + pub symbol: Symbol, + pub proc_layout: ProcLayout<'a>, + pub raw_function_layout: RawFunctionLayout<'a>, +} + #[derive(Clone, Debug, PartialEq, Eq)] pub enum HostExposedLayouts<'a> { NotHostExposed, HostExposed { rigids: BumpMap>, - aliases: BumpMap, RawFunctionLayout<'a>)>, + aliases: BumpMap>, }, } @@ -1177,7 +1186,6 @@ impl<'a> Procs<'a> { name, layout_cache, annotation, - &[], partial_proc_id, ) { Ok((proc, layout)) => { @@ -1270,7 +1278,6 @@ impl<'a> Procs<'a> { proc_name, layout_cache, fn_var, - Default::default(), partial_proc_id, ) { Ok((proc, raw_layout)) => { @@ -2310,15 +2317,6 @@ impl<'a> Stmt<'a> { String::from_utf8(w).unwrap() } - pub fn is_terminal(&self) -> bool { - use Stmt::*; - - matches!( - self, - Switch { .. } | Ret(_) | Jump(_, _) // TODO for Switch; is this the reason Lean only looks at the outermost `when`? - ) - } - pub fn if_then_else( arena: &'a Bump, condition_symbol: Symbol, @@ -2911,7 +2909,7 @@ fn specialize_suspended<'a>( } }; - match specialize_variable(env, procs, name, layout_cache, var, &[], partial_proc) { + match specialize_variable(env, procs, name, layout_cache, var, partial_proc) { Ok((proc, raw_layout)) => { let proc_layout = ProcLayout::from_raw_named(env.arena, name, raw_layout); procs @@ -3057,24 +3055,131 @@ fn specialize_external_help<'a>( } }; - let specialization_result = specialize_variable( - env, - procs, - name, - layout_cache, - variable, - host_exposed_aliases, - partial_proc_id, - ); + let specialization_result = + specialize_variable(env, procs, name, layout_cache, variable, partial_proc_id); match specialization_result { - Ok((proc, layout)) => { + Ok((mut proc, layout)) => { let top_level = ProcLayout::from_raw_named(env.arena, name, layout); if procs.is_module_thunk(name.name()) { debug_assert!(top_level.arguments.is_empty()); } + if !host_exposed_aliases.is_empty() { + // layouts that are (transitively) used in the type of `mainForHost`. + let mut host_exposed_layouts: Vec<_> = top_level + .arguments + .iter() + .copied() + .chain([top_level.result]) + .collect_in(env.arena); + + // it is very likely we see the same types across functions, or in multiple arguments + host_exposed_layouts.sort(); + host_exposed_layouts.dedup(); + + // TODO: In the future, we will generate glue procs here + for in_layout in host_exposed_layouts { + let layout = layout_cache.interner.get(in_layout); + + let all_glue_procs = generate_glue_procs( + env.home, + env.ident_ids, + env.arena, + &mut layout_cache.interner, + env.arena.alloc(layout), + ); + + // for now, getters are not processed here + let GlueProcs { + getters: _, + extern_names, + } = all_glue_procs; + + let mut aliases = BumpMap::default(); + + for (id, mut raw_function_layout) in extern_names { + let symbol = env.unique_symbol(); + let lambda_name = LambdaName::no_niche(symbol); + + if false { + raw_function_layout = match raw_function_layout { + RawFunctionLayout::Function(a, mut lambda_set, _) => { + lambda_set.ret = in_layout; + RawFunctionLayout::Function(a, lambda_set, in_layout) + } + RawFunctionLayout::ZeroArgumentThunk(x) => { + RawFunctionLayout::ZeroArgumentThunk(x) + } + }; + } + + let (key, (top_level, proc)) = generate_host_exposed_function( + env, + procs, + layout_cache, + lambda_name, + raw_function_layout, + ); + + procs + .specialized + .insert_specialized(symbol, top_level, proc); + + let hels = HostExposedLambdaSet { + id, + symbol, + proc_layout: top_level, + raw_function_layout, + }; + + aliases.insert(key, hels); + } + + // pre-glue: generate named callers for as-exposed aliases + for (alias_name, variable) in host_exposed_aliases { + let raw_function_layout = layout_cache + .raw_from_var(env.arena, *variable, env.subs) + .unwrap(); + + let symbol = env.unique_symbol(); + let lambda_name = LambdaName::no_niche(symbol); + + let (proc_name, (proc_layout, proc)) = generate_host_exposed_function( + env, + procs, + layout_cache, + lambda_name, + raw_function_layout, + ); + + procs + .specialized + .insert_specialized(proc_name, proc_layout, proc); + + let hels = HostExposedLambdaSet { + id: LambdaSetId::default(), + symbol: proc_name, + proc_layout, + raw_function_layout, + }; + + aliases.insert(*alias_name, hels); + } + + match &mut proc.host_exposed_layouts { + HostExposedLayouts::HostExposed { aliases: old, .. } => old.extend(aliases), + hep @ HostExposedLayouts::NotHostExposed => { + *hep = HostExposedLayouts::HostExposed { + aliases, + rigids: Default::default(), + }; + } + } + } + } + procs .specialized .insert_specialized(name.name(), top_level, proc); @@ -3199,6 +3304,119 @@ fn rollback_typestate( } } +fn generate_host_exposed_function<'a>( + env: &mut Env<'a, '_>, + procs: &mut Procs<'a>, + layout_cache: &mut LayoutCache<'a>, + lambda_name: LambdaName<'a>, + layout: RawFunctionLayout<'a>, +) -> (Symbol, (ProcLayout<'a>, Proc<'a>)) { + let function_name = lambda_name.name(); + + match layout { + RawFunctionLayout::Function(_, lambda_set, _) => { + let (proc, top_level) = generate_host_exposed_lambda_set( + env, + procs, + layout_cache, + function_name, + lambda_set, + ); + + (function_name, (top_level, proc)) + } + RawFunctionLayout::ZeroArgumentThunk(result) => { + let assigned = env.unique_symbol(); + let hole = env.arena.alloc(Stmt::Ret(assigned)); + let forced = force_thunk(env, function_name, result, assigned, hole); + + let lambda_name = LambdaName::no_niche(function_name); + let proc = Proc { + name: lambda_name, + args: &[], + body: forced, + closure_data_layout: None, + ret_layout: result, + is_self_recursive: SelfRecursive::NotSelfRecursive, + must_own_arguments: false, + host_exposed_layouts: HostExposedLayouts::NotHostExposed, + }; + + let top_level = ProcLayout::from_raw_named(env.arena, lambda_name, layout); + + (function_name, (top_level, proc)) + } + } +} + +fn generate_host_exposed_lambda_set<'a>( + env: &mut Env<'a, '_>, + procs: &mut Procs<'a>, + layout_cache: &mut LayoutCache<'a>, + name: Symbol, + lambda_set: LambdaSet<'a>, +) -> (Proc<'a>, ProcLayout<'a>) { + let assigned = env.unique_symbol(); + + let argument_layouts = *lambda_set.args; + let return_layout = lambda_set.ret; + + let mut argument_symbols = Vec::with_capacity_in(argument_layouts.len(), env.arena); + let mut proc_arguments = Vec::with_capacity_in(argument_layouts.len() + 1, env.arena); + let mut top_level_arguments = Vec::with_capacity_in(argument_layouts.len() + 1, env.arena); + + for layout in *lambda_set.args { + let symbol = env.unique_symbol(); + + proc_arguments.push((*layout, symbol)); + + argument_symbols.push(symbol); + top_level_arguments.push(*layout); + } + + // the proc needs to take an extra closure argument + let lambda_set_layout = lambda_set.full_layout; + proc_arguments.push((lambda_set_layout, Symbol::ARG_CLOSURE)); + + // this should also be reflected in the TopLevel signature + top_level_arguments.push(lambda_set_layout); + + let hole = env.arena.alloc(Stmt::Ret(assigned)); + + let body = match_on_lambda_set( + env, + layout_cache, + procs, + lambda_set, + Symbol::ARG_CLOSURE, + argument_symbols.into_bump_slice(), + argument_layouts, + return_layout, + assigned, + hole, + ); + + let proc = Proc { + name: LambdaName::no_niche(name), + args: proc_arguments.into_bump_slice(), + body, + closure_data_layout: None, + ret_layout: return_layout, + is_self_recursive: SelfRecursive::NotSelfRecursive, + must_own_arguments: false, + host_exposed_layouts: HostExposedLayouts::NotHostExposed, + }; + + let top_level = ProcLayout::new( + env.arena, + top_level_arguments.into_bump_slice(), + Niche::NONE, + return_layout, + ); + + (proc, top_level) +} + /// Specialize a single proc. /// /// The caller should snapshot and rollback the type state before and after calling this function, @@ -3209,7 +3427,6 @@ fn specialize_proc_help<'a>( lambda_name: LambdaName<'a>, layout_cache: &mut LayoutCache<'a>, fn_var: Variable, - host_exposed_variables: &[(Symbol, Variable)], partial_proc_id: PartialProcId, ) -> Result, LayoutProblem> { let partial_proc = procs.partial_procs.get_id(partial_proc_id); @@ -3250,121 +3467,8 @@ fn specialize_proc_help<'a>( let body = partial_proc.body.clone(); let body_var = partial_proc.body_var; - // determine the layout of aliases/rigids exposed to the host - let host_exposed_layouts = if host_exposed_variables.is_empty() { - HostExposedLayouts::NotHostExposed - } else { - let mut aliases = BumpMap::new_in(env.arena); - - for (symbol, variable) in host_exposed_variables { - let layout = layout_cache - .raw_from_var(env.arena, *variable, env.subs) - .unwrap(); - - let name = env.unique_symbol(); - - match layout { - RawFunctionLayout::Function(argument_layouts, lambda_set, return_layout) => { - let assigned = env.unique_symbol(); - - let mut argument_symbols = - Vec::with_capacity_in(argument_layouts.len(), env.arena); - let mut proc_arguments = - Vec::with_capacity_in(argument_layouts.len() + 1, env.arena); - let mut top_level_arguments = - Vec::with_capacity_in(argument_layouts.len() + 1, env.arena); - - for layout in argument_layouts { - let symbol = env.unique_symbol(); - - proc_arguments.push((*layout, symbol)); - - argument_symbols.push(symbol); - top_level_arguments.push(*layout); - } - - // the proc needs to take an extra closure argument - let lambda_set_layout = lambda_set.full_layout; - proc_arguments.push((lambda_set_layout, Symbol::ARG_CLOSURE)); - - // this should also be reflected in the TopLevel signature - top_level_arguments.push(lambda_set_layout); - - let hole = env.arena.alloc(Stmt::Ret(assigned)); - - let body = match_on_lambda_set( - env, - layout_cache, - procs, - lambda_set, - Symbol::ARG_CLOSURE, - argument_symbols.into_bump_slice(), - argument_layouts, - return_layout, - assigned, - hole, - ); - - let proc = Proc { - name: LambdaName::no_niche(name), - args: proc_arguments.into_bump_slice(), - body, - closure_data_layout: None, - ret_layout: return_layout, - is_self_recursive: SelfRecursive::NotSelfRecursive, - must_own_arguments: false, - host_exposed_layouts: HostExposedLayouts::NotHostExposed, - }; - - let top_level = ProcLayout::new( - env.arena, - top_level_arguments.into_bump_slice(), - Niche::NONE, - return_layout, - ); - - procs.specialized.insert_specialized(name, top_level, proc); - - aliases.insert(*symbol, (name, top_level, layout)); - } - RawFunctionLayout::ZeroArgumentThunk(result) => { - let assigned = env.unique_symbol(); - let hole = env.arena.alloc(Stmt::Ret(assigned)); - let forced = force_thunk(env, lambda_name.name(), result, assigned, hole); - - let lambda_name = LambdaName::no_niche(name); - let proc = Proc { - name: lambda_name, - args: &[], - body: forced, - closure_data_layout: None, - ret_layout: result, - is_self_recursive: SelfRecursive::NotSelfRecursive, - must_own_arguments: false, - host_exposed_layouts: HostExposedLayouts::NotHostExposed, - }; - - let top_level = ProcLayout::from_raw_named(env.arena, lambda_name, layout); - - procs.specialized.insert_specialized(name, top_level, proc); - - aliases.insert( - *symbol, - ( - name, - ProcLayout::new(env.arena, &[], Niche::NONE, result), - layout, - ), - ); - } - } - } - - HostExposedLayouts::HostExposed { - rigids: BumpMap::new_in(env.arena), - aliases, - } - }; + // host-exposed functions are tagged on later + let host_exposed_layouts = HostExposedLayouts::NotHostExposed; let mut specialized_body = from_can(env, body_var, body, procs, layout_cache); @@ -3811,7 +3915,6 @@ fn specialize_variable<'a>( proc_name: LambdaName<'a>, layout_cache: &mut LayoutCache<'a>, fn_var: Variable, - host_exposed_variables: &[(Symbol, Variable)], partial_proc_id: PartialProcId, ) -> Result, SpecializeFailure<'a>> { let snapshot = snapshot_typestate(env.subs, procs, layout_cache); @@ -3841,15 +3944,8 @@ fn specialize_variable<'a>( procs.push_active_specialization(proc_name.name()); roc_tracing::debug!(?proc_name, ?fn_var, fn_content = ?roc_types::subs::SubsFmtContent(env.subs.get_content_without_compacting(fn_var), env.subs), "specialization start"); - let specialized = specialize_proc_help( - env, - procs, - proc_name, - layout_cache, - fn_var, - host_exposed_variables, - partial_proc_id, - ); + let specialized = + specialize_proc_help(env, procs, proc_name, layout_cache, fn_var, partial_proc_id); roc_tracing::debug!( ?proc_name, @@ -3933,6 +4029,33 @@ impl<'a> ProcLayout<'a> { } } } + + pub fn dbg_deep<'r, I: LayoutInterner<'a>>(&self, interner: &'r I) -> DbgProcLayout<'a, 'r, I> { + DbgProcLayout { + layout: *self, + interner, + } + } +} + +pub struct DbgProcLayout<'a, 'r, I: LayoutInterner<'a>> { + layout: ProcLayout<'a>, + interner: &'r I, +} + +impl<'a, 'r, I: LayoutInterner<'a>> std::fmt::Debug for DbgProcLayout<'a, 'r, I> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let ProcLayout { + arguments, + result, + niche, + } = self.layout; + f.debug_struct("ProcLayout") + .field("arguments", &self.interner.dbg_deep_iter(arguments)) + .field("result", &self.interner.dbg_deep(result)) + .field("niche", &niche.dbg_deep(self.interner)) + .finish() + } } fn specialize_naked_symbol<'a>( @@ -4266,93 +4389,20 @@ pub fn with_hole<'a>( Err(_) => return runtime_error(env, "Can't create tuple with improper layout"), }; - let mut elem_symbols = Vec::with_capacity_in(elems.len(), env.arena); - let mut can_elems = Vec::with_capacity_in(elems.len(), env.arena); - - #[allow(clippy::enum_variant_names)] - enum Field { - // TODO: rename this since it can handle unspecialized expressions now too - FunctionOrUnspecialized(Symbol, Variable), - ValueSymbol, - Field(Variable, Loc), - } - // Hacky way to let us remove the owned elements from the vector, possibly out-of-order. let mut elems = Vec::from_iter_in(elems.into_iter().map(Some), env.arena); + let take_elem_expr = move |index: usize| elems[index].take(); - for (index, variable, _) in sorted_elems.into_iter() { - // TODO how should function pointers be handled here? - use ReuseSymbol::*; - let (var, loc_expr) = elems[index].take().unwrap(); - match can_reuse_symbol(env, procs, &loc_expr.value, var) { - Imported(symbol) | LocalFunction(symbol) | UnspecializedExpr(symbol) => { - elem_symbols.push(symbol); - can_elems.push(Field::FunctionOrUnspecialized(symbol, variable)); - } - Value(symbol) => { - let reusable = procs.get_or_insert_symbol_specialization( - env, - layout_cache, - symbol, - var, - ); - elem_symbols.push(reusable); - can_elems.push(Field::ValueSymbol); - } - NotASymbol => { - elem_symbols.push(env.unique_symbol()); - can_elems.push(Field::Field(var, *loc_expr)); - } - } - } - - // creating a record from the var will unpack it if it's just a single field. - let layout = match layout_cache.from_var(env.arena, tuple_var, env.subs) { - Ok(layout) => layout, - Err(_) => return runtime_error(env, "Can't create record with improper layout"), - }; - - let elem_symbols = elem_symbols.into_bump_slice(); - - let mut stmt = if let [only_field] = elem_symbols { - let mut hole = hole.clone(); - substitute_in_exprs(env.arena, &mut hole, assigned, *only_field); - hole - } else { - Stmt::Let(assigned, Expr::Struct(elem_symbols), layout, hole) - }; - - for (opt_field, symbol) in can_elems.into_iter().rev().zip(elem_symbols.iter().rev()) { - match opt_field { - Field::ValueSymbol => { - // this symbol is already defined; nothing to do - } - Field::FunctionOrUnspecialized(symbol, variable) => { - stmt = specialize_symbol( - env, - procs, - layout_cache, - Some(variable), - symbol, - env.arena.alloc(stmt), - symbol, - ); - } - Field::Field(var, loc_expr) => { - stmt = with_hole( - env, - loc_expr.value, - var, - procs, - layout_cache, - *symbol, - env.arena.alloc(stmt), - ); - } - } - } - - stmt + compile_struct_like( + env, + procs, + layout_cache, + sorted_elems, + take_elem_expr, + tuple_var, + hole, + assigned, + ) } Record { @@ -4374,100 +4424,19 @@ pub fn with_hole<'a>( Err(_) => return runtime_error(env, "Can't create record with improper layout"), }; - let mut field_symbols = Vec::with_capacity_in(fields.len(), env.arena); - let mut can_fields = Vec::with_capacity_in(fields.len(), env.arena); + let take_field_expr = + move |field: Lowercase| fields.remove(&field).map(|f| (f.var, f.loc_expr)); - #[allow(clippy::enum_variant_names)] - enum Field { - // TODO: rename this since it can handle unspecialized expressions now too - FunctionOrUnspecialized(Symbol, Variable), - ValueSymbol, - Field(roc_can::expr::Field), - } - - for (label, variable, _) in sorted_fields.into_iter() { - // TODO how should function pointers be handled here? - use ReuseSymbol::*; - match fields.remove(&label) { - Some(field) => { - match can_reuse_symbol(env, procs, &field.loc_expr.value, field.var) { - Imported(symbol) - | LocalFunction(symbol) - | UnspecializedExpr(symbol) => { - field_symbols.push(symbol); - can_fields.push(Field::FunctionOrUnspecialized(symbol, variable)); - } - Value(symbol) => { - let reusable = procs.get_or_insert_symbol_specialization( - env, - layout_cache, - symbol, - field.var, - ); - field_symbols.push(reusable); - can_fields.push(Field::ValueSymbol); - } - NotASymbol => { - field_symbols.push(env.unique_symbol()); - can_fields.push(Field::Field(field)); - } - } - } - None => { - // this field was optional, but not given - continue; - } - } - } - - // creating a record from the var will unpack it if it's just a single field. - let layout = match layout_cache.from_var(env.arena, record_var, env.subs) { - Ok(layout) => layout, - Err(_) => return runtime_error(env, "Can't create record with improper layout"), - }; - - let field_symbols = field_symbols.into_bump_slice(); - - let mut stmt = if let [only_field] = field_symbols { - let mut hole = hole.clone(); - substitute_in_exprs(env.arena, &mut hole, assigned, *only_field); - hole - } else { - Stmt::Let(assigned, Expr::Struct(field_symbols), layout, hole) - }; - - for (opt_field, symbol) in can_fields.into_iter().rev().zip(field_symbols.iter().rev()) - { - match opt_field { - Field::ValueSymbol => { - // this symbol is already defined; nothing to do - } - Field::FunctionOrUnspecialized(symbol, variable) => { - stmt = specialize_symbol( - env, - procs, - layout_cache, - Some(variable), - symbol, - env.arena.alloc(stmt), - symbol, - ); - } - Field::Field(field) => { - stmt = with_hole( - env, - field.loc_expr.value, - field.var, - procs, - layout_cache, - *symbol, - env.arena.alloc(stmt), - ); - } - } - } - - stmt + compile_struct_like( + env, + procs, + layout_cache, + sorted_fields, + take_field_expr, + record_var, + hole, + assigned, + ) } EmptyRecord => let_empty_struct(assigned, hole), @@ -4787,49 +4756,18 @@ pub fn with_hole<'a>( } } - let record_symbol = possible_reuse_symbol_or_specialize( + compile_struct_like_access( env, procs, layout_cache, - &loc_expr.value, - record_var, - ); - - let mut stmt = match field_layouts.as_slice() { - [_] => { - let mut hole = hole.clone(); - substitute_in_exprs(env.arena, &mut hole, assigned, record_symbol); - - hole - } - _ => { - let expr = Expr::StructAtIndex { - index: index.expect("field not in its own type") as u64, - field_layouts: field_layouts.into_bump_slice(), - structure: record_symbol, - }; - - let layout = layout_cache - .from_var(env.arena, field_var, env.subs) - .unwrap_or_else(|err| { - panic!("TODO turn fn_var into a RuntimeError {:?}", err) - }); - - Stmt::Let(assigned, expr, layout, hole) - } - }; - - stmt = assign_to_symbol( - env, - procs, - layout_cache, - record_var, + field_layouts, + index.expect("field not in its own type") as _, *loc_expr, - record_symbol, - stmt, - ); - - stmt + record_var, + hole, + assigned, + field_var, + ) } RecordAccessor(accessor_data) => { @@ -4907,61 +4845,30 @@ pub fn with_hole<'a>( Ok(fields) => fields, Err(_) => return runtime_error(env, "Can't access tuple with improper layout"), }; + let mut field_layouts = Vec::with_capacity_in(sorted_elems.len(), env.arena); let mut final_index = None; - let mut elem_layouts = Vec::with_capacity_in(sorted_elems.len(), env.arena); for (current, (index, _, elem_layout)) in sorted_elems.into_iter().enumerate() { - elem_layouts.push(elem_layout); + field_layouts.push(elem_layout); if index == accessed_index { final_index = Some(current); } } - let tuple_symbol = possible_reuse_symbol_or_specialize( + compile_struct_like_access( env, procs, layout_cache, - &loc_expr.value, - tuple_var, - ); - - let mut stmt = match elem_layouts.as_slice() { - [_] => { - let mut hole = hole.clone(); - substitute_in_exprs(env.arena, &mut hole, assigned, tuple_symbol); - - hole - } - _ => { - let expr = Expr::StructAtIndex { - index: final_index.expect("field not in its own type") as u64, - field_layouts: elem_layouts.into_bump_slice(), - structure: tuple_symbol, - }; - - let layout = layout_cache - .from_var(env.arena, elem_var, env.subs) - .unwrap_or_else(|err| { - panic!("TODO turn fn_var into a RuntimeError {:?}", err) - }); - - Stmt::Let(assigned, expr, layout, hole) - } - }; - - stmt = assign_to_symbol( - env, - procs, - layout_cache, - tuple_var, + field_layouts, + final_index.expect("elem not in its own type") as u64, *loc_expr, - tuple_symbol, - stmt, - ); - - stmt + tuple_var, + hole, + assigned, + elem_var, + ) } OpaqueWrapFunction(wrap_fn_data) => { @@ -5719,6 +5626,162 @@ pub fn with_hole<'a>( } } +/// Compiles an access into a tuple or record. +fn compile_struct_like_access<'a>( + env: &mut Env<'a, '_>, + procs: &mut Procs<'a>, + layout_cache: &mut LayoutCache<'a>, + field_layouts: Vec<'a, InLayout<'a>>, + index: u64, + loc_expr: Loc, + struct_like_var: Variable, + hole: &'a Stmt<'a>, + assigned: Symbol, + elem_var: Variable, +) -> Stmt<'a> { + let struct_symbol = possible_reuse_symbol_or_specialize( + env, + procs, + layout_cache, + &loc_expr.value, + struct_like_var, + ); + + let mut stmt = match field_layouts.as_slice() { + [_] => { + let mut hole = hole.clone(); + substitute_in_exprs(env.arena, &mut hole, assigned, struct_symbol); + + hole + } + _ => { + let expr = Expr::StructAtIndex { + index, + field_layouts: field_layouts.into_bump_slice(), + structure: struct_symbol, + }; + + let layout = layout_cache + .from_var(env.arena, elem_var, env.subs) + .unwrap_or_else(|err| panic!("TODO turn fn_var into a RuntimeError {:?}", err)); + + Stmt::Let(assigned, expr, layout, hole) + } + }; + + stmt = assign_to_symbol( + env, + procs, + layout_cache, + struct_like_var, + loc_expr, + struct_symbol, + stmt, + ); + + stmt +} + +/// Compiles a record or a tuple. +// TODO: UnusedLayout is because `sort_record_fields` currently returns a three-tuple, but is, in +// fact, unneeded for the compilation. +fn compile_struct_like<'a, L, UnusedLayout>( + env: &mut Env<'a, '_>, + procs: &mut Procs<'a>, + layout_cache: &mut LayoutCache<'a>, + sorted_elems: Vec<(L, Variable, UnusedLayout)>, + mut take_elem_expr: impl FnMut(L) -> Option<(Variable, Box>)>, + struct_like_var: Variable, + hole: &'a Stmt<'a>, + assigned: Symbol, +) -> Stmt<'a> { + let mut elem_symbols = Vec::with_capacity_in(sorted_elems.len(), env.arena); + let mut can_elems = Vec::with_capacity_in(sorted_elems.len(), env.arena); + + #[allow(clippy::enum_variant_names)] + enum Field { + // TODO: rename this since it can handle unspecialized expressions now too + FunctionOrUnspecialized(Symbol, Variable), + ValueSymbol, + Field(Variable, Loc), + } + + for (index, variable, _) in sorted_elems.into_iter() { + // TODO how should function pointers be handled here? + use ReuseSymbol::*; + match take_elem_expr(index) { + Some((var, loc_expr)) => match can_reuse_symbol(env, procs, &loc_expr.value, var) { + Imported(symbol) | LocalFunction(symbol) | UnspecializedExpr(symbol) => { + elem_symbols.push(symbol); + can_elems.push(Field::FunctionOrUnspecialized(symbol, variable)); + } + Value(symbol) => { + let reusable = + procs.get_or_insert_symbol_specialization(env, layout_cache, symbol, var); + elem_symbols.push(reusable); + can_elems.push(Field::ValueSymbol); + } + NotASymbol => { + elem_symbols.push(env.unique_symbol()); + can_elems.push(Field::Field(var, *loc_expr)); + } + }, + None => { + // this field was optional, but not given + continue; + } + } + } + + // creating a record from the var will unpack it if it's just a single field. + let layout = match layout_cache.from_var(env.arena, struct_like_var, env.subs) { + Ok(layout) => layout, + Err(_) => return runtime_error(env, "Can't create record with improper layout"), + }; + + let elem_symbols = elem_symbols.into_bump_slice(); + + let mut stmt = if let [only_field] = elem_symbols { + let mut hole = hole.clone(); + substitute_in_exprs(env.arena, &mut hole, assigned, *only_field); + hole + } else { + Stmt::Let(assigned, Expr::Struct(elem_symbols), layout, hole) + }; + + for (opt_field, symbol) in can_elems.into_iter().rev().zip(elem_symbols.iter().rev()) { + match opt_field { + Field::ValueSymbol => { + // this symbol is already defined; nothing to do + } + Field::FunctionOrUnspecialized(symbol, variable) => { + stmt = specialize_symbol( + env, + procs, + layout_cache, + Some(variable), + symbol, + env.arena.alloc(stmt), + symbol, + ); + } + Field::Field(var, loc_expr) => { + stmt = with_hole( + env, + loc_expr.value, + var, + procs, + layout_cache, + *symbol, + env.arena.alloc(stmt), + ); + } + } + } + + stmt +} + #[inline(always)] fn late_resolve_ability_specialization<'a>( env: &mut Env<'a, '_>, @@ -9020,7 +9083,6 @@ fn call_by_name_help<'a>( proc_name, layout_cache, fn_var, - &[], partial_proc, ) { Ok((proc, layout)) => { @@ -9168,7 +9230,6 @@ fn call_by_name_module_thunk<'a>( LambdaName::no_niche(proc_name), layout_cache, fn_var, - &[], partial_proc, ) { Ok((proc, raw_layout)) => { @@ -10779,7 +10840,20 @@ fn union_lambda_set_to_switch<'a>( return empty_lambda_set_error(env); } - let join_point_id = JoinPointId(env.unique_symbol()); + let (opt_join, branch_assigned, branch_hole) = match hole { + Stmt::Ret(_) => { + // No need to jump to a joinpoint, inline the return in each statement as-is. + // This makes further analyses, like TCO, easier as well. + (None, assigned, hole) + } + _ => { + let join_point_id = JoinPointId(env.unique_symbol()); + let assigned = env.unique_symbol(); + let hole = Stmt::Jump(join_point_id, env.arena.alloc([assigned])); + + (Some(join_point_id), assigned, &*env.arena.alloc(hole)) + } + }; let mut branches = Vec::with_capacity_in(lambda_set.len(), env.arena); @@ -10795,12 +10869,13 @@ fn union_lambda_set_to_switch<'a>( let stmt = union_lambda_set_branch( env, - join_point_id, lambda_name, closure_info, argument_symbols, argument_layouts, return_layout, + branch_assigned, + branch_hole, ); branches.push((i as u64, BranchInfo::None, stmt)); } @@ -10819,34 +10894,36 @@ fn union_lambda_set_to_switch<'a>( ret_layout: return_layout, }; - let param = Param { - symbol: assigned, - layout: return_layout, - ownership: Ownership::Owned, - }; + match opt_join { + None => switch, + Some(join_point_id) => { + let param = Param { + symbol: assigned, + layout: return_layout, + ownership: Ownership::Owned, + }; - Stmt::Join { - id: join_point_id, - parameters: &*env.arena.alloc([param]), - body: hole, - remainder: env.arena.alloc(switch), + Stmt::Join { + id: join_point_id, + parameters: &*env.arena.alloc([param]), + body: hole, + remainder: env.arena.alloc(switch), + } + } } } #[allow(clippy::too_many_arguments)] fn union_lambda_set_branch<'a>( env: &mut Env<'a, '_>, - join_point_id: JoinPointId, lambda_name: LambdaName<'a>, closure_info: ClosureInfo<'a>, argument_symbols_slice: &'a [Symbol], argument_layouts_slice: &'a [InLayout<'a>], return_layout: InLayout<'a>, + assigned: Symbol, + hole: &'a Stmt<'a>, ) -> Stmt<'a> { - let result_symbol = env.unique_symbol(); - - let hole = Stmt::Jump(join_point_id, env.arena.alloc([result_symbol])); - union_lambda_set_branch_help( env, lambda_name, @@ -10854,7 +10931,7 @@ fn union_lambda_set_branch<'a>( argument_symbols_slice, argument_layouts_slice, return_layout, - result_symbol, + assigned, env.arena.alloc(hole), ) } @@ -10940,18 +11017,32 @@ fn enum_lambda_set_to_switch<'a>( ) -> Stmt<'a> { debug_assert_ne!(lambda_set.len(), 0); - let join_point_id = JoinPointId(env.unique_symbol()); + let (opt_join, branch_assigned, branch_hole) = match hole { + Stmt::Ret(_) => { + // No need to jump to a joinpoint, inline the return in each statement as-is. + // This makes further analyses, like TCO, easier as well. + (None, assigned, hole) + } + _ => { + let join_point_id = JoinPointId(env.unique_symbol()); + let assigned = env.unique_symbol(); + let hole = Stmt::Jump(join_point_id, env.arena.alloc([assigned])); + + (Some(join_point_id), assigned, &*env.arena.alloc(hole)) + } + }; let mut branches = Vec::with_capacity_in(lambda_set.len(), env.arena); for (i, lambda_name) in lambda_set.into_iter().enumerate() { let stmt = enum_lambda_set_branch( env, - join_point_id, lambda_name, argument_symbols, argument_layouts, return_layout, + branch_assigned, + branch_hole, ); branches.push((i as u64, BranchInfo::None, stmt)); } @@ -10970,17 +11061,22 @@ fn enum_lambda_set_to_switch<'a>( ret_layout: return_layout, }; - let param = Param { - symbol: assigned, - layout: return_layout, - ownership: Ownership::Owned, - }; + match opt_join { + None => switch, + Some(join_point_id) => { + let param = Param { + symbol: assigned, + layout: return_layout, + ownership: Ownership::Owned, + }; - Stmt::Join { - id: join_point_id, - parameters: &*env.arena.alloc([param]), - body: hole, - remainder: env.arena.alloc(switch), + Stmt::Join { + id: join_point_id, + parameters: &*env.arena.alloc([param]), + body: hole, + remainder: env.arena.alloc(switch), + } + } } } @@ -10988,18 +11084,13 @@ fn enum_lambda_set_to_switch<'a>( #[allow(clippy::too_many_arguments)] fn enum_lambda_set_branch<'a>( env: &mut Env<'a, '_>, - join_point_id: JoinPointId, lambda_name: LambdaName<'a>, argument_symbols: &'a [Symbol], argument_layouts: &'a [InLayout<'a>], return_layout: InLayout<'a>, + assigned: Symbol, + hole: &'a Stmt<'a>, ) -> Stmt<'a> { - let result_symbol = env.unique_symbol(); - - let hole = Stmt::Jump(join_point_id, env.arena.alloc([result_symbol])); - - let assigned = result_symbol; - let call = self::Call { call_type: CallType::ByName { name: lambda_name, @@ -11009,7 +11100,7 @@ fn enum_lambda_set_branch<'a>( }, arguments: argument_symbols, }; - build_call(env, call, assigned, return_layout, env.arena.alloc(hole)) + build_call(env, call, assigned, return_layout, hole) } #[allow(clippy::too_many_arguments)] @@ -11086,3 +11177,343 @@ where remainder: env.arena.alloc(switch), } } + +pub struct GlueLayouts<'a> { + pub getters: std::vec::Vec<(Symbol, ProcLayout<'a>)>, +} + +type GlueProcId = u16; + +pub struct GlueProc<'a> { + pub name: Symbol, + pub proc_layout: ProcLayout<'a>, + pub proc: Proc<'a>, +} + +pub struct GlueProcs<'a> { + pub getters: Vec<'a, (Layout<'a>, Vec<'a, GlueProc<'a>>)>, + pub extern_names: Vec<'a, (LambdaSetId, RawFunctionLayout<'a>)>, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct LambdaSetId(pub u32); + +impl LambdaSetId { + #[must_use] + pub fn next(self) -> Self { + debug_assert!(self.0 < u32::MAX); + Self(self.0 + 1) + } + + pub const fn invalid() -> Self { + Self(u32::MAX) + } +} + +pub fn generate_glue_procs<'a, 'i, I>( + home: ModuleId, + ident_ids: &mut IdentIds, + arena: &'a Bump, + layout_interner: &'i mut I, + layout: &'a Layout<'a>, +) -> GlueProcs<'a> +where + I: LayoutInterner<'a>, +{ + let mut answer = GlueProcs { + getters: Vec::new_in(arena), + extern_names: Vec::new_in(arena), + }; + + let mut lambda_set_id = LambdaSetId(0); + + let mut stack: Vec<'a, Layout<'a>> = Vec::from_iter_in([*layout], arena); + let mut next_unique_id = 0; + + macro_rules! handle_struct_field_layouts { + ($field_layouts: expr) => {{ + if $field_layouts.iter().any(|l| { + layout_interner + .get(*l) + .has_varying_stack_size(layout_interner, arena) + }) { + let procs = generate_glue_procs_for_struct_fields( + layout_interner, + home, + &mut next_unique_id, + ident_ids, + arena, + layout, + $field_layouts, + ); + + answer.getters.push((*layout, procs)); + } + + for in_layout in $field_layouts.iter().rev() { + stack.push(layout_interner.get(*in_layout)); + } + }}; + } + + macro_rules! handle_tag_field_layouts { + ($tag_id:expr, $union_layout:expr, $field_layouts: expr) => {{ + if $field_layouts.iter().any(|l| { + layout_interner + .get(*l) + .has_varying_stack_size(layout_interner, arena) + }) { + let procs = generate_glue_procs_for_tag_fields( + layout_interner, + home, + &mut next_unique_id, + ident_ids, + arena, + $tag_id, + layout, + $union_layout, + $field_layouts, + ); + + answer.getters.push((*layout, procs)); + } + + for in_layout in $field_layouts.iter().rev() { + stack.push(layout_interner.get(*in_layout)); + } + }}; + } + + while let Some(layout) = stack.pop() { + match layout { + Layout::Builtin(builtin) => match builtin { + Builtin::Int(_) + | Builtin::Float(_) + | Builtin::Bool + | Builtin::Decimal + | Builtin::Str => { /* do nothing */ } + Builtin::List(element) => stack.push(layout_interner.get(element)), + }, + Layout::Struct { field_layouts, .. } => { + handle_struct_field_layouts!(field_layouts); + } + Layout::Boxed(boxed) => { + stack.push(layout_interner.get(boxed)); + } + Layout::Union(union_layout) => match union_layout { + UnionLayout::NonRecursive(tags) => { + for in_layout in tags.iter().flat_map(|e| e.iter()) { + stack.push(layout_interner.get(*in_layout)); + } + } + UnionLayout::Recursive(tags) => { + for in_layout in tags.iter().flat_map(|e| e.iter()) { + stack.push(layout_interner.get(*in_layout)); + } + } + UnionLayout::NonNullableUnwrapped(field_layouts) => { + handle_tag_field_layouts!(0, union_layout, field_layouts); + } + UnionLayout::NullableWrapped { + other_tags, + nullable_id, + } => { + let tag_ids = + (0..nullable_id).chain(nullable_id + 1..other_tags.len() as u16 + 1); + for (i, field_layouts) in tag_ids.zip(other_tags) { + handle_tag_field_layouts!(i, union_layout, *field_layouts); + } + } + UnionLayout::NullableUnwrapped { other_fields, .. } => { + for in_layout in other_fields.iter().rev() { + stack.push(layout_interner.get(*in_layout)); + } + } + }, + Layout::LambdaSet(lambda_set) => { + let raw_function_layout = + RawFunctionLayout::Function(lambda_set.args, lambda_set, lambda_set.ret); + + let key = (lambda_set_id, raw_function_layout); + answer.extern_names.push(key); + + // this id is used, increment for the next one + lambda_set_id = lambda_set_id.next(); + + stack.push(layout_interner.get(lambda_set.runtime_representation())); + } + Layout::RecursivePointer(_) => { + /* do nothing, we've already generated for this type through the Union(_) */ + } + } + } + + answer +} + +fn generate_glue_procs_for_struct_fields<'a, 'i, I>( + layout_interner: &'i mut I, + home: ModuleId, + next_unique_id: &mut GlueProcId, + ident_ids: &mut IdentIds, + arena: &'a Bump, + unboxed_struct_layout: &'a Layout<'a>, + field_layouts: &'a [InLayout<'a>], +) -> Vec<'a, GlueProc<'a>> +where + I: LayoutInterner<'a>, +{ + let interned_unboxed_struct_layout = layout_interner.insert(*unboxed_struct_layout); + let boxed_struct_layout = Layout::Boxed(interned_unboxed_struct_layout); + let boxed_struct_layout = layout_interner.insert(boxed_struct_layout); + let mut answer = bumpalo::collections::Vec::with_capacity_in(field_layouts.len(), arena); + + for (index, field) in field_layouts.iter().enumerate() { + let proc_layout = ProcLayout { + arguments: arena.alloc([boxed_struct_layout]), + result: *field, + niche: Niche::NONE, + }; + + let symbol = unique_glue_symbol(arena, next_unique_id, home, ident_ids); + + let argument = Symbol::new(home, ident_ids.gen_unique()); + let unboxed = Symbol::new(home, ident_ids.gen_unique()); + let result = Symbol::new(home, ident_ids.gen_unique()); + + home.register_debug_idents(ident_ids); + + let ret_stmt = arena.alloc(Stmt::Ret(result)); + + let field_get_expr = Expr::StructAtIndex { + index: index as u64, + field_layouts, + structure: unboxed, + }; + + let field_get_stmt = Stmt::Let(result, field_get_expr, *field, ret_stmt); + + let unbox_expr = Expr::ExprUnbox { symbol: argument }; + + let unbox_stmt = Stmt::Let( + unboxed, + unbox_expr, + interned_unboxed_struct_layout, + arena.alloc(field_get_stmt), + ); + + let proc = Proc { + name: LambdaName::no_niche(symbol), + args: arena.alloc([(boxed_struct_layout, argument)]), + body: unbox_stmt, + closure_data_layout: None, + ret_layout: *field, + is_self_recursive: SelfRecursive::NotSelfRecursive, + must_own_arguments: false, + host_exposed_layouts: HostExposedLayouts::NotHostExposed, + }; + + answer.push(GlueProc { + name: symbol, + proc_layout, + proc, + }); + } + + answer +} + +fn unique_glue_symbol( + arena: &Bump, + next_unique_id: &mut GlueProcId, + home: ModuleId, + ident_ids: &mut IdentIds, +) -> Symbol { + let unique_id = *next_unique_id; + + *next_unique_id = unique_id + 1; + + // then name of the platform `main.roc` is the empty string + let module_name = ""; + + // Turn unique_id into a Symbol without doing a heap allocation. + use std::fmt::Write; + let mut string = bumpalo::collections::String::with_capacity_in(32, arena); + + let _result = write!(&mut string, "roc__getter_{}_{}", module_name, unique_id); + debug_assert_eq!(_result, Ok(())); // This should never fail, but doesn't hurt to debug-check! + + let ident_id = ident_ids.get_or_insert(string.into_bump_str()); + + Symbol::new(home, ident_id) +} + +#[allow(clippy::too_many_arguments)] +fn generate_glue_procs_for_tag_fields<'a, 'i, I>( + layout_interner: &'i mut I, + home: ModuleId, + next_unique_id: &mut GlueProcId, + ident_ids: &mut IdentIds, + arena: &'a Bump, + tag_id: TagIdIntType, + unboxed_struct_layout: &'a Layout<'a>, + union_layout: UnionLayout<'a>, + field_layouts: &'a [InLayout<'a>], +) -> Vec<'a, GlueProc<'a>> +where + I: LayoutInterner<'a>, +{ + let interned = layout_interner.insert(*unboxed_struct_layout); + let boxed_struct_layout = Layout::Boxed(interned); + let boxed_struct_layout = layout_interner.insert(boxed_struct_layout); + let mut answer = bumpalo::collections::Vec::with_capacity_in(field_layouts.len(), arena); + + for (index, field) in field_layouts.iter().enumerate() { + let proc_layout = ProcLayout { + arguments: arena.alloc([boxed_struct_layout]), + result: *field, + niche: Niche::NONE, + }; + let symbol = unique_glue_symbol(arena, next_unique_id, home, ident_ids); + + let argument = Symbol::new(home, ident_ids.gen_unique()); + let unboxed = Symbol::new(home, ident_ids.gen_unique()); + let result = Symbol::new(home, ident_ids.gen_unique()); + + home.register_debug_idents(ident_ids); + + let ret_stmt = arena.alloc(Stmt::Ret(result)); + + let field_get_expr = Expr::UnionAtIndex { + structure: unboxed, + tag_id, + union_layout, + index: index as u64, + }; + + let field_get_stmt = Stmt::Let(result, field_get_expr, *field, ret_stmt); + + let unbox_expr = Expr::ExprUnbox { symbol: argument }; + + let unbox_stmt = Stmt::Let(unboxed, unbox_expr, interned, arena.alloc(field_get_stmt)); + + let proc = Proc { + name: LambdaName::no_niche(symbol), + args: arena.alloc([(boxed_struct_layout, argument)]), + body: unbox_stmt, + closure_data_layout: None, + ret_layout: *field, + is_self_recursive: SelfRecursive::NotSelfRecursive, + must_own_arguments: false, + host_exposed_layouts: HostExposedLayouts::NotHostExposed, + }; + + answer.push(GlueProc { + name: symbol, + proc_layout, + proc, + }); + } + + answer +} diff --git a/crates/compiler/mono/src/layout.rs b/crates/compiler/mono/src/layout.rs index 428052f956..159bd58c31 100644 --- a/crates/compiler/mono/src/layout.rs +++ b/crates/compiler/mono/src/layout.rs @@ -1313,6 +1313,14 @@ impl<'a> Niche<'a> { ]), } } + + pub fn dbg_deep<'r, I: LayoutInterner<'a>>( + &'r self, + interner: &'r I, + ) -> crate::layout::intern::dbg::DbgFields<'a, 'r, I> { + let NichePriv::Captures(caps) = &self.0; + interner.dbg_deep_iter(caps) + } } #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] @@ -2717,6 +2725,60 @@ impl<'a> Layout<'a> { } } + pub fn has_varying_stack_size(self, interner: &I, arena: &bumpalo::Bump) -> bool + where + I: LayoutInterner<'a>, + { + let mut stack: Vec = bumpalo::collections::Vec::new_in(arena); + + stack.push(self); + + while let Some(layout) = stack.pop() { + match layout { + Layout::Builtin(builtin) => match builtin { + Builtin::Int(_) + | Builtin::Float(_) + | Builtin::Bool + | Builtin::Decimal + | Builtin::Str + // If there's any layer of indirection (behind a pointer), then it doesn't vary! + | Builtin::List(_) => { /* do nothing */ } + }, + // If there's any layer of indirection (behind a pointer), then it doesn't vary! + Layout::Struct { field_layouts, .. } => { + stack.extend(field_layouts.iter().map(|interned| interner.get(*interned))) + } + Layout::Union(tag_union) => match tag_union { + UnionLayout::NonRecursive(tags) | UnionLayout::Recursive(tags) => { + for tag in tags { + stack.extend(tag.iter().map(|interned| interner.get(*interned))); + } + } + UnionLayout::NonNullableUnwrapped(fields) => { + stack.extend(fields.iter().map(|interned| interner.get(*interned))); + } + UnionLayout::NullableWrapped { other_tags, .. } => { + for tag in other_tags { + stack.extend(tag.iter().map(|interned| interner.get(*interned))); + } + } + UnionLayout::NullableUnwrapped { other_fields, .. } => { + stack.extend(other_fields.iter().map(|interned| interner.get(*interned))); + } + }, + Layout::LambdaSet(_) => return true, + Layout::Boxed(_) => { + // If there's any layer of indirection (behind a pointer), then it doesn't vary! + } + Layout::RecursivePointer(_) => { + /* do nothing, we've already generated for this type through the Union(_) */ + } + } + } + + false + } + /// Used to build a `Layout::Struct` where the field name order is irrelevant. pub fn struct_no_name_order(field_layouts: &'a [InLayout]) -> Self { if field_layouts.is_empty() { diff --git a/crates/compiler/mono/src/layout/intern.rs b/crates/compiler/mono/src/layout/intern.rs index 8687f010e9..158a47dd74 100644 --- a/crates/compiler/mono/src/layout/intern.rs +++ b/crates/compiler/mono/src/layout/intern.rs @@ -365,6 +365,10 @@ pub trait LayoutInterner<'a>: Sized { fn dbg_deep<'r>(&'r self, layout: InLayout<'a>) -> dbg::Dbg<'a, 'r, Self> { dbg::Dbg(self, layout) } + + fn dbg_deep_iter<'r>(&'r self, layouts: &'a [InLayout<'a>]) -> dbg::DbgFields<'a, 'r, Self> { + dbg::DbgFields(self, layouts) + } } /// An interned layout. @@ -1274,7 +1278,7 @@ mod equiv { } } -mod dbg { +pub mod dbg { use roc_module::symbol::Symbol; use crate::layout::{Builtin, LambdaSet, Layout, UnionLayout}; @@ -1311,7 +1315,7 @@ mod dbg { } } - struct DbgFields<'a, 'r, I: LayoutInterner<'a>>(&'r I, &'a [InLayout<'a>]); + pub struct DbgFields<'a, 'r, I: LayoutInterner<'a>>(pub &'r I, pub &'a [InLayout<'a>]); impl<'a, 'r, I: LayoutInterner<'a>> std::fmt::Debug for DbgFields<'a, 'r, I> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { diff --git a/crates/compiler/mono/src/lib.rs b/crates/compiler/mono/src/lib.rs index ea50d61bfe..d82c7a228a 100644 --- a/crates/compiler/mono/src/lib.rs +++ b/crates/compiler/mono/src/lib.rs @@ -6,6 +6,8 @@ #![warn(clippy::dbg_macro)] // See github.com/roc-lang/roc/issues/800 for discussion of the large_enum_variant check. #![allow(clippy::large_enum_variant, clippy::upper_case_acronyms)] +// Not a useful lint for us +#![allow(clippy::too_many_arguments)] pub mod borrow; pub mod code_gen_help; diff --git a/crates/compiler/mono/src/low_level.rs b/crates/compiler/mono/src/low_level.rs index ddad554c81..d346838e88 100644 --- a/crates/compiler/mono/src/low_level.rs +++ b/crates/compiler/mono/src/low_level.rs @@ -120,6 +120,8 @@ enum FirstOrder { NumShiftRightBy, NumBytesToU16, NumBytesToU32, + NumBytesToU64, + NumBytesToU128, NumShiftRightZfBy, NumIntCast, NumFloatCast, diff --git a/crates/compiler/parse/Cargo.toml b/crates/compiler/parse/Cargo.toml index 82b666b846..dbb2ca21c1 100644 --- a/crates/compiler/parse/Cargo.toml +++ b/crates/compiler/parse/Cargo.toml @@ -1,32 +1,31 @@ [package] name = "roc_parse" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Implements the Roc parser, which transforms a textual representation of a Roc program to an AST." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [features] "parse_debug_trace" = [] [dependencies] roc_collections = { path = "../collections" } -roc_region = { path = "../region" } roc_module = { path = "../module" } +roc_region = { path = "../region" } bumpalo.workspace = true encode_unicode.workspace = true [dev-dependencies] -roc_test_utils = { path = "../../test_utils" } -proptest = "1.0.0" - criterion.workspace = true -pretty_assertions.workspace = true indoc.workspace = true +pretty_assertions.workspace = true +proptest.workspace = true quickcheck.workspace = true quickcheck_macros.workspace = true [[bench]] -name = "bench_parse" harness = false +name = "bench_parse" diff --git a/crates/compiler/parse/src/blankspace.rs b/crates/compiler/parse/src/blankspace.rs index 3f9cc06d3d..b0dbb7bb35 100644 --- a/crates/compiler/parse/src/blankspace.rs +++ b/crates/compiler/parse/src/blankspace.rs @@ -1,5 +1,6 @@ use crate::ast::CommentOrNewline; use crate::ast::Spaceable; +use crate::parser::Progress; use crate::parser::SpaceProblem; use crate::parser::{self, and, backtrackable, BadInputError, Parser, Progress::*}; use crate::state::State; @@ -7,6 +8,7 @@ use bumpalo::collections::vec::Vec; use bumpalo::Bump; use roc_region::all::Loc; use roc_region::all::Position; +use roc_region::all::Region; pub fn space0_around_ee<'a, P, S, E>( parser: P, @@ -386,98 +388,132 @@ pub fn spaces<'a, E>() -> impl Parser<'a, &'a [CommentOrNewline<'a>], E> where E: 'a + SpaceProblem, { - move |arena, mut state: State<'a>, _min_indent: u32| { + move |arena, state: State<'a>, _min_indent: u32| { let mut newlines = Vec::new_in(arena); - let mut progress = NoProgress; - loop { - let whitespace = fast_eat_whitespace(state.bytes()); - if whitespace > 0 { - state.advance_mut(whitespace); - progress = MadeProgress; - } - match state.bytes().first() { - Some(b'#') => { - state.advance_mut(1); - - let is_doc_comment = state.bytes().first() == Some(&b'#') - && (state.bytes().get(1) == Some(&b' ') - || state.bytes().get(1) == Some(&b'\n') - || begins_with_crlf(&state.bytes()[1..]) - || Option::is_none(&state.bytes().get(1))); - - if is_doc_comment { - state.advance_mut(1); - if state.bytes().first() == Some(&b' ') { - state.advance_mut(1); - } - } - - let len = fast_eat_until_control_character(state.bytes()); - - // We already checked that the string is valid UTF-8 - debug_assert!(std::str::from_utf8(&state.bytes()[..len]).is_ok()); - let text = unsafe { std::str::from_utf8_unchecked(&state.bytes()[..len]) }; - - let comment = if is_doc_comment { - CommentOrNewline::DocComment(text) - } else { - CommentOrNewline::LineComment(text) - }; - newlines.push(comment); - state.advance_mut(len); - - if begins_with_crlf(state.bytes()) { - state.advance_mut(1); - state = state.advance_newline(); - } else if state.bytes().first() == Some(&b'\n') { - state = state.advance_newline(); - } - - progress = MadeProgress; - } - Some(b'\r') => { - if state.bytes().get(1) == Some(&b'\n') { - newlines.push(CommentOrNewline::Newline); - state.advance_mut(1); - state = state.advance_newline(); - progress = MadeProgress; - } else { - return Err(( - progress, - E::space_problem( - BadInputError::HasMisplacedCarriageReturn, - state.pos(), - ), - )); - } - } - Some(b'\n') => { - newlines.push(CommentOrNewline::Newline); - state = state.advance_newline(); - progress = MadeProgress; - } - Some(b'\t') => { - return Err(( - progress, - E::space_problem(BadInputError::HasTab, state.pos()), - )); - } - Some(x) if *x < b' ' => { - return Err(( - progress, - E::space_problem(BadInputError::HasAsciiControl, state.pos()), - )); - } - _ => { - if !newlines.is_empty() { - state = state.mark_current_indent(); - } - break; - } - } + match consume_spaces(state, |_, space, _| newlines.push(space)) { + Ok((progress, state)) => Ok((progress, newlines.into_bump_slice(), state)), + Err((progress, err)) => Err((progress, err)), } - - Ok((progress, newlines.into_bump_slice(), state)) } } + +pub fn loc_spaces<'a, E>() -> impl Parser<'a, &'a [Loc>], E> +where + E: 'a + SpaceProblem, +{ + move |arena, state: State<'a>, _min_indent: u32| { + let mut newlines = Vec::new_in(arena); + + match consume_spaces(state, |start, space, end| { + newlines.push(Loc::at(Region::between(start, end), space)) + }) { + Ok((progress, state)) => Ok((progress, newlines.into_bump_slice(), state)), + Err((progress, err)) => Err((progress, err)), + } + } +} + +fn consume_spaces<'a, E, F>( + mut state: State<'a>, + mut on_space: F, +) -> Result<(Progress, State<'a>), (Progress, E)> +where + E: 'a + SpaceProblem, + F: FnMut(Position, CommentOrNewline<'a>, Position), +{ + let mut progress = NoProgress; + let mut found_newline = false; + loop { + let whitespace = fast_eat_whitespace(state.bytes()); + if whitespace > 0 { + state.advance_mut(whitespace); + progress = MadeProgress; + } + + let start = state.pos(); + + match state.bytes().first() { + Some(b'#') => { + state.advance_mut(1); + + let is_doc_comment = state.bytes().first() == Some(&b'#') + && (state.bytes().get(1) == Some(&b' ') + || state.bytes().get(1) == Some(&b'\n') + || begins_with_crlf(&state.bytes()[1..]) + || Option::is_none(&state.bytes().get(1))); + + if is_doc_comment { + state.advance_mut(1); + if state.bytes().first() == Some(&b' ') { + state.advance_mut(1); + } + } + + let len = fast_eat_until_control_character(state.bytes()); + + // We already checked that the string is valid UTF-8 + debug_assert!(std::str::from_utf8(&state.bytes()[..len]).is_ok()); + let text = unsafe { std::str::from_utf8_unchecked(&state.bytes()[..len]) }; + + let comment = if is_doc_comment { + CommentOrNewline::DocComment(text) + } else { + CommentOrNewline::LineComment(text) + }; + state.advance_mut(len); + on_space(start, comment, state.pos()); + found_newline = true; + + if begins_with_crlf(state.bytes()) { + state.advance_mut(1); + state = state.advance_newline(); + } else if state.bytes().first() == Some(&b'\n') { + state = state.advance_newline(); + } + + progress = MadeProgress; + } + Some(b'\r') => { + if state.bytes().get(1) == Some(&b'\n') { + state.advance_mut(1); + state = state.advance_newline(); + on_space(start, CommentOrNewline::Newline, state.pos()); + found_newline = true; + progress = MadeProgress; + } else { + return Err(( + progress, + E::space_problem(BadInputError::HasMisplacedCarriageReturn, state.pos()), + )); + } + } + Some(b'\n') => { + state = state.advance_newline(); + on_space(start, CommentOrNewline::Newline, state.pos()); + found_newline = true; + progress = MadeProgress; + } + Some(b'\t') => { + return Err(( + progress, + E::space_problem(BadInputError::HasTab, state.pos()), + )); + } + Some(x) if *x < b' ' => { + return Err(( + progress, + E::space_problem(BadInputError::HasAsciiControl, state.pos()), + )); + } + _ => { + if found_newline { + state = state.mark_current_indent(); + } + break; + } + } + } + + Ok((progress, state)) +} diff --git a/crates/compiler/parse/src/expr.rs b/crates/compiler/parse/src/expr.rs index 79c1d7fcd7..9dce58ddbb 100644 --- a/crates/compiler/parse/src/expr.rs +++ b/crates/compiler/parse/src/expr.rs @@ -1,6 +1,6 @@ use crate::ast::{ AssignedField, Collection, CommentOrNewline, Defs, Expr, ExtractSpaces, Has, HasAbilities, - Pattern, Spaceable, TypeAnnotation, TypeDef, TypeHeader, ValueDef, + Pattern, Spaceable, Spaces, TypeAnnotation, TypeDef, TypeHeader, ValueDef, }; use crate::blankspace::{ space0_after_e, space0_around_e_no_after_indent_check, space0_around_ee, space0_before_e, @@ -1085,6 +1085,29 @@ enum AliasOrOpaque { Opaque, } +fn extract_tag_and_spaces<'a>(arena: &'a Bump, expr: Expr<'a>) -> Option> { + let mut expr = expr.extract_spaces(); + + loop { + match &expr.item { + Expr::ParensAround(inner_expr) => { + let inner_expr = inner_expr.extract_spaces(); + expr.item = inner_expr.item; + expr.before = merge_spaces(arena, expr.before, inner_expr.before); + expr.after = merge_spaces(arena, inner_expr.after, expr.after); + } + Expr::Tag(tag) => { + return Some(Spaces { + before: expr.before, + item: tag, + after: expr.after, + }); + } + _ => return None, + } + } +} + #[allow(clippy::too_many_arguments)] fn finish_parsing_alias_or_opaque<'a>( min_indent: u32, @@ -1105,120 +1128,113 @@ fn finish_parsing_alias_or_opaque<'a>( let mut defs = Defs::default(); - let state = match &expr.value.extract_spaces().item { - Expr::ParensAround(Expr::SpaceBefore(Expr::Tag(name), _)) - | Expr::ParensAround(Expr::SpaceAfter(Expr::Tag(name), _)) - | Expr::ParensAround(Expr::Tag(name)) - | Expr::Tag(name) => { - let mut type_arguments = Vec::with_capacity_in(arguments.len(), arena); + let state = if let Some(tag) = extract_tag_and_spaces(arena, expr.value) { + let name = tag.item; + let mut type_arguments = Vec::with_capacity_in(arguments.len(), arena); - for argument in arguments { - match expr_to_pattern_help(arena, &argument.value) { - Ok(good) => { - type_arguments.push(Loc::at(argument.region, good)); - } - Err(()) => { - return Err(( - MadeProgress, - EExpr::Pattern( - arena.alloc(EPattern::NotAPattern(state.pos())), - state.pos(), - ), - )); - } + for argument in arguments { + match expr_to_pattern_help(arena, &argument.value) { + Ok(good) => { + type_arguments.push(Loc::at(argument.region, good)); } - } - - match kind { - AliasOrOpaque::Alias => { - let (_, signature, state) = - alias_signature_with_space_before().parse(arena, state, min_indent)?; - - let def_region = Region::span_across(&expr.region, &signature.region); - - let header = TypeHeader { - name: Loc::at(expr.region, name), - vars: type_arguments.into_bump_slice(), - }; - - let def = TypeDef::Alias { - header, - ann: signature, - }; - - defs.push_type_def(def, def_region, &[], &[]); - - state - } - - AliasOrOpaque::Opaque => { - let (_, (signature, derived), state) = - opaque_signature_with_space_before().parse(arena, state, indented_more)?; - - let def_region = Region::span_across(&expr.region, &signature.region); - - let header = TypeHeader { - name: Loc::at(expr.region, name), - vars: type_arguments.into_bump_slice(), - }; - - let def = TypeDef::Opaque { - header, - typ: signature, - derived, - }; - - defs.push_type_def(def, def_region, &[], &[]); - - state + Err(()) => { + return Err(( + MadeProgress, + EExpr::Pattern( + arena.alloc(EPattern::NotAPattern(state.pos())), + state.pos(), + ), + )); } } } - _ => { - let call = to_call(arena, arguments, expr); + match kind { + AliasOrOpaque::Alias => { + let (_, signature, state) = + alias_signature_with_space_before().parse(arena, state, min_indent)?; - match expr_to_pattern_help(arena, &call.value) { - Ok(good) => { - let parser = specialize( - EExpr::Type, - space0_before_e( - set_min_indent(indented_more, type_annotation::located(false)), - EType::TIndentStart, - ), - ); + let def_region = Region::span_across(&expr.region, &signature.region); - match parser.parse(arena, state.clone(), min_indent) { - Err((_, fail)) => return Err((MadeProgress, fail)), - Ok((_, mut ann_type, state)) => { - // put the spaces from after the operator in front of the call - if !spaces_after_operator.is_empty() { - ann_type = arena - .alloc(ann_type.value) - .with_spaces_before(spaces_after_operator, ann_type.region); - } + let header = TypeHeader { + name: Loc::at(expr.region, name), + vars: type_arguments.into_bump_slice(), + }; - let def_region = Region::span_across(&call.region, &ann_type.region); + let def = TypeDef::Alias { + header, + ann: signature, + }; - let value_def = - ValueDef::Annotation(Loc::at(expr_region, good), ann_type); + defs.push_type_def(def, def_region, &[], &[]); - defs.push_value_def(value_def, def_region, &[], &[]); + state + } - state + AliasOrOpaque::Opaque => { + let (_, (signature, derived), state) = + opaque_signature_with_space_before().parse(arena, state, indented_more)?; + + let def_region = Region::span_across(&expr.region, &signature.region); + + let header = TypeHeader { + name: Loc::at(expr.region, name), + vars: type_arguments.into_bump_slice(), + }; + + let def = TypeDef::Opaque { + header, + typ: signature, + derived, + }; + + defs.push_type_def(def, def_region, &[], &[]); + + state + } + } + } else { + let call = to_call(arena, arguments, expr); + + match expr_to_pattern_help(arena, &call.value) { + Ok(good) => { + let parser = specialize( + EExpr::Type, + space0_before_e( + set_min_indent(indented_more, type_annotation::located(false)), + EType::TIndentStart, + ), + ); + + match parser.parse(arena, state.clone(), min_indent) { + Err((_, fail)) => return Err((MadeProgress, fail)), + Ok((_, mut ann_type, state)) => { + // put the spaces from after the operator in front of the call + if !spaces_after_operator.is_empty() { + ann_type = arena + .alloc(ann_type.value) + .with_spaces_before(spaces_after_operator, ann_type.region); } + + let def_region = Region::span_across(&call.region, &ann_type.region); + + let value_def = ValueDef::Annotation(Loc::at(expr_region, good), ann_type); + + defs.push_value_def(value_def, def_region, &[], &[]); + + state } } - Err(_) => { - // this `:`/`:=` likely occurred inline; treat it as an invalid operator - let op = match kind { - AliasOrOpaque::Alias => ":", - AliasOrOpaque::Opaque => ":=", - }; - let fail = EExpr::BadOperator(op, loc_op.region.start()); + } + Err(_) => { + // this `:`/`:=` likely occurred inline; treat it as an invalid operator + let op = match kind { + AliasOrOpaque::Alias => ":", + AliasOrOpaque::Opaque => ":=", + }; + let fail = EExpr::BadOperator(op, loc_op.region.start()); - return Err((MadeProgress, fail)); - } + return Err((MadeProgress, fail)); } } }; diff --git a/crates/compiler/parse/src/highlight.rs b/crates/compiler/parse/src/highlight.rs new file mode 100644 index 0000000000..2b561d1446 --- /dev/null +++ b/crates/compiler/parse/src/highlight.rs @@ -0,0 +1,661 @@ +use encode_unicode::CharExt; +use std::collections::HashSet; + +use bumpalo::Bump; +use roc_region::all::{Loc, Region}; + +use crate::{ + ast::CommentOrNewline, + blankspace::loc_spaces, + keyword::KEYWORDS, + number_literal::positive_number_literal, + parser::{EExpr, ParseResult, Parser}, + state::State, + string_literal::{parse_str_like_literal, StrLikeLiteral}, +}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum Token { + LineComment, + DocComment, + Error, + SingleQuote, + String, + UnicodeEscape, + EscapedChar, + Interpolated, + Keyword, + UpperIdent, + LowerIdent, + Number, + QuestionMark, + Percent, + Caret, + Other, + Minus, + Bang, + BangEquals, + Plus, + Colon, + ColonEquals, + Bar, + DoubleBar, + And, + DoubleAnd, + Equals, + DoubleEquals, + GreaterThan, + GreaterThanEquals, + LessThan, + LessThanEquals, + Comma, + Backslash, + Slash, + DoubleSlash, + Pizza, + Brace, + Bracket, + AtSign, + Paren, + Arrow, + Pipe, + Backpass, + Decimal, + Multiply, + Underscore, +} + +pub fn highlight(text: &str) -> Vec> { + let mut tokens = Vec::new(); + let state = State::new(text.as_bytes()); + + let arena = Bump::new(); + + let header_keywords = HEADER_KEYWORDS.iter().copied().collect::>(); + let body_keywords = KEYWORDS.iter().copied().collect::>(); + + if let Ok((_prog, _, new_state)) = crate::module::header().parse(&arena, state.clone(), 0) { + let inner_state = + State::new(text[..state.bytes().len() - new_state.bytes().len()].as_bytes()); + highlight_inner(&arena, inner_state, &mut tokens, &header_keywords); + highlight_inner(&arena, new_state, &mut tokens, &body_keywords); + } else { + highlight_inner(&arena, state, &mut tokens, &body_keywords); + } + + tokens +} + +fn highlight_inner<'a>( + arena: &'a Bump, + mut state: State<'a>, + tokens: &mut Vec>, + keywords: &HashSet<&str>, +) { + loop { + let start = state.pos(); + if let Ok((b, _width)) = char::from_utf8_slice_start(state.bytes()) { + match b { + ' ' | '\n' | '\t' | '\r' | '#' => { + let res: ParseResult<'a, _, EExpr<'a>> = + loc_spaces().parse(arena, state.clone(), 0); + if let Ok((_, spaces, new_state)) = res { + state = new_state; + for space in spaces { + let token = match space.value { + CommentOrNewline::Newline => { + continue; + } + CommentOrNewline::LineComment(_) => Token::LineComment, + CommentOrNewline::DocComment(_) => Token::DocComment, + }; + tokens.push(Loc::at(space.region, token)); + } + } else { + fast_forward_to(&mut state, tokens, start, |c| c == b'\n'); + } + } + '"' | '\'' => { + if let Ok((_, item, new_state)) = + parse_str_like_literal().parse(arena, state.clone(), 0) + { + state = new_state; + match item { + StrLikeLiteral::SingleQuote(_) => { + tokens.push(Loc::at( + Region::between(start, state.pos()), + Token::SingleQuote, + )); + } + StrLikeLiteral::Str(_) => { + tokens.push(Loc::at( + Region::between(start, state.pos()), + Token::String, + )); + } + } + } else { + fast_forward_to(&mut state, tokens, start, |c| c == b'\n'); + } + } + c if c.is_alphabetic() => { + let buffer = state.bytes(); + let mut chomped = 0; + + let is_upper = c.is_uppercase(); + + while let Ok((ch, width)) = char::from_utf8_slice_start(&buffer[chomped..]) { + if ch.is_alphabetic() || ch.is_ascii_digit() { + chomped += width; + } else { + // we're done + break; + } + } + + let ident = std::str::from_utf8(&buffer[..chomped]).unwrap(); + state.advance_mut(chomped); + + if keywords.contains(ident) { + tokens.push(Loc::at(Region::between(start, state.pos()), Token::Keyword)); + } else { + tokens.push(Loc::at( + Region::between(start, state.pos()), + if is_upper { + Token::UpperIdent + } else { + Token::LowerIdent + }, + )); + } + } + '.' => { + state.advance_mut(1); + tokens.push(Loc::at(Region::between(start, state.pos()), Token::Decimal)); + } + '0'..='9' => { + if let Ok((_, _item, new_state)) = + positive_number_literal().parse(arena, state.clone(), 0) + { + state = new_state; + tokens.push(Loc::at(Region::between(start, state.pos()), Token::Number)); + } else { + fast_forward_to(&mut state, tokens, start, |b| !b.is_ascii_digit()); + } + } + ':' => { + state.advance_mut(1); + let tok = if state.bytes().first() == Some(&b'=') { + state.advance_mut(1); + Token::ColonEquals + } else { + Token::Colon + }; + tokens.push(Loc::at(Region::between(start, state.pos()), tok)); + } + '|' => { + state.advance_mut(1); + let tok = if state.bytes().first() == Some(&b'>') { + state.advance_mut(1); + Token::Pizza + } else if state.bytes().first() == Some(&b'|') { + state.advance_mut(1); + Token::DoubleBar + } else { + Token::Bar + }; + tokens.push(Loc::at(Region::between(start, state.pos()), tok)); + } + '&' => { + state.advance_mut(1); + let tok = if state.bytes().first() == Some(&b'&') { + state.advance_mut(1); + Token::DoubleAnd + } else { + Token::And + }; + tokens.push(Loc::at(Region::between(start, state.pos()), tok)); + } + '-' => { + state.advance_mut(1); + let tok = if state.bytes().first() == Some(&b'>') { + state.advance_mut(1); + Token::Arrow + } else { + Token::Minus + }; + tokens.push(Loc::at(Region::between(start, state.pos()), tok)); + } + '+' => { + state.advance_mut(1); + tokens.push(Loc::at(Region::between(start, state.pos()), Token::Plus)); + } + '=' => { + state.advance_mut(1); + let tok = if state.bytes().first() == Some(&b'=') { + state.advance_mut(1); + Token::DoubleEquals + } else { + Token::Equals + }; + tokens.push(Loc::at(Region::between(start, state.pos()), tok)); + } + '>' => { + state.advance_mut(1); + let tok = if state.bytes().first() == Some(&b'=') { + state.advance_mut(1); + Token::GreaterThanEquals + } else { + Token::GreaterThan + }; + tokens.push(Loc::at(Region::between(start, state.pos()), tok)); + } + '<' => { + state.advance_mut(1); + let tok = if state.bytes().first() == Some(&b'=') { + state.advance_mut(1); + Token::LessThanEquals + } else if state.bytes().first() == Some(&b'-') { + state.advance_mut(1); + Token::Backpass + } else { + Token::LessThan + }; + tokens.push(Loc::at(Region::between(start, state.pos()), tok)); + } + '!' => { + state.advance_mut(1); + let tok = if state.bytes().first() == Some(&b'=') { + state.advance_mut(1); + Token::BangEquals + } else { + Token::Bang + }; + tokens.push(Loc::at(Region::between(start, state.pos()), tok)); + } + ',' => { + state.advance_mut(1); + tokens.push(Loc::at(Region::between(start, state.pos()), Token::Comma)); + } + '_' => { + state.advance_mut(1); + tokens.push(Loc::at( + Region::between(start, state.pos()), + Token::Underscore, + )); + } + '?' => { + state.advance_mut(1); + tokens.push(Loc::at( + Region::between(start, state.pos()), + Token::QuestionMark, + )); + } + '%' => { + state.advance_mut(1); + tokens.push(Loc::at(Region::between(start, state.pos()), Token::Percent)); + } + '*' => { + state.advance_mut(1); + tokens.push(Loc::at( + Region::between(start, state.pos()), + Token::Multiply, + )); + } + '^' => { + state.advance_mut(1); + tokens.push(Loc::at(Region::between(start, state.pos()), Token::Caret)); + } + '\\' => { + state.advance_mut(1); + tokens.push(Loc::at( + Region::between(start, state.pos()), + Token::Backslash, + )); + } + '/' => { + state.advance_mut(1); + let tok = if state.bytes().first() == Some(&b'/') { + state.advance_mut(1); + Token::DoubleSlash + } else { + Token::Slash + }; + tokens.push(Loc::at(Region::between(start, state.pos()), tok)); + } + '@' => { + state.advance_mut(1); + tokens.push(Loc::at(Region::between(start, state.pos()), Token::AtSign)); + } + '{' | '}' => { + state.advance_mut(1); + tokens.push(Loc::at(Region::between(start, state.pos()), Token::Brace)); + } + '[' | ']' => { + state.advance_mut(1); + tokens.push(Loc::at(Region::between(start, state.pos()), Token::Bracket)); + } + '(' | ')' => { + state.advance_mut(1); + tokens.push(Loc::at(Region::between(start, state.pos()), Token::Paren)); + } + _ => { + state.advance_mut(1); + tokens.push(Loc::at(Region::between(start, state.pos()), Token::Other)); + } + } + } else { + break; + } + } +} + +fn fast_forward_to( + state: &mut State, + tokens: &mut Vec>, + start: roc_region::all::Position, + end: impl Fn(u8) -> bool, +) { + while let Some(b) = state.bytes().first() { + if end(*b) { + break; + } + state.advance_mut(1); + } + tokens.push(Loc::at(Region::between(start, state.pos()), Token::Error)); +} + +pub const HEADER_KEYWORDS: [&str; 14] = [ + "interface", + "app", + "package", + "platform", + "hosted", + "exposes", + "imports", + "with", + "generates", + "package", + "packages", + "requires", + "provides", + "to", +]; + +#[cfg(test)] +mod tests { + use roc_region::all::Position; + + use super::*; + + #[test] + fn test_highlight_comments() { + let text = "# a\n#b\n#c"; + let tokens = highlight(text); + assert_eq!( + tokens, + vec![ + Loc::at( + Region::between(Position::new(0), Position::new(3)), + Token::LineComment + ), + Loc::at( + Region::between(Position::new(4), Position::new(6)), + Token::LineComment + ), + Loc::at( + Region::between(Position::new(7), Position::new(9)), + Token::LineComment + ), + ] + ); + } + + #[test] + fn test_highlight_doc_comments() { + let text = "## a\n##b\n##c"; + let tokens = highlight(text); + assert_eq!( + tokens, + vec![ + Loc::at( + Region::between(Position::new(0), Position::new(4)), + Token::DocComment + ), + // the next two are line comments because there's not a space at the beginning + Loc::at( + Region::between(Position::new(5), Position::new(8)), + Token::LineComment + ), + Loc::at( + Region::between(Position::new(9), Position::new(12)), + Token::LineComment + ), + ] + ); + } + + #[test] + fn test_highlight_strings() { + let text = r#""a""#; + let tokens = highlight(text); + assert_eq!( + tokens, + vec![Loc::at( + Region::between(Position::new(0), Position::new(3)), + Token::String + )] + ); + } + + #[test] + fn test_highlight_single_quotes() { + let text = r#"'a'"#; + let tokens = highlight(text); + assert_eq!( + tokens, + vec![Loc::at( + Region::between(Position::new(0), Position::new(3)), + Token::SingleQuote + )] + ); + } + + #[test] + fn test_highlight_header() { + let text = r#"app "test-app" provides [] to "./blah""#; + let tokens = highlight(text); + assert_eq!( + tokens, + vec![ + Loc::at( + Region::between(Position::new(0), Position::new(3)), + Token::Keyword + ), + Loc::at( + Region::between(Position::new(4), Position::new(14)), + Token::String + ), + Loc::at( + Region::between(Position::new(15), Position::new(23)), + Token::Keyword + ), + Loc::at( + Region::between(Position::new(24), Position::new(25)), + Token::Bracket + ), + Loc::at( + Region::between(Position::new(25), Position::new(26)), + Token::Bracket + ), + Loc::at( + Region::between(Position::new(27), Position::new(29)), + Token::Keyword + ), + Loc::at( + Region::between(Position::new(30), Position::new(38)), + Token::String + ), + ] + ); + } + + #[test] + fn test_highlight_numbers() { + let text = "123.0 123 123. 123.0e10 123e10 123e-10 0x123"; + let tokens = highlight(text); + assert_eq!( + tokens, + vec![ + Loc::at( + Region::between(Position::new(0), Position::new(5)), + Token::Number + ), + Loc::at( + Region::between(Position::new(6), Position::new(9)), + Token::Number + ), + Loc::at( + Region::between(Position::new(10), Position::new(14)), + Token::Number + ), + Loc::at( + Region::between(Position::new(15), Position::new(23)), + Token::Number + ), + Loc::at( + Region::between(Position::new(24), Position::new(30)), + Token::Number + ), + Loc::at( + Region::between(Position::new(31), Position::new(38)), + Token::Number + ), + Loc::at( + Region::between(Position::new(39), Position::new(44)), + Token::Number + ), + ] + ); + } + + #[test] + fn test_combine_tokens() { + let text = "-> := <- |> || >= <= =="; + let actual = highlight(text); + + let expected = vec![ + Loc::at( + Region::between(Position::new(0), Position::new(2)), + Token::Arrow, + ), + Loc::at( + Region::between(Position::new(3), Position::new(5)), + Token::ColonEquals, + ), + Loc::at( + Region::between(Position::new(6), Position::new(8)), + Token::Backpass, + ), + Loc::at( + Region::between(Position::new(9), Position::new(11)), + Token::Pizza, + ), + Loc::at( + Region::between(Position::new(12), Position::new(14)), + Token::DoubleBar, + ), + Loc::at( + Region::between(Position::new(15), Position::new(17)), + Token::GreaterThanEquals, + ), + Loc::at( + Region::between(Position::new(18), Position::new(20)), + Token::LessThanEquals, + ), + Loc::at( + Region::between(Position::new(21), Position::new(23)), + Token::DoubleEquals, + ), + ]; + + assert_eq!(actual, expected); + } + + #[test] + fn test_highlight_pattern_matching() { + let text = "Green | Yellow -> \"not red\""; + let tokens = highlight(text); + assert_eq!( + tokens, + vec![ + Loc::at( + Region::between(Position::new(0), Position::new(5)), + Token::UpperIdent + ), + Loc::at( + Region::between(Position::new(6), Position::new(7)), + Token::Bar + ), + Loc::at( + Region::between(Position::new(8), Position::new(14)), + Token::UpperIdent + ), + Loc::at( + Region::between(Position::new(15), Position::new(17)), + Token::Arrow + ), + Loc::at( + Region::between(Position::new(18), Position::new(27)), + Token::String + ), + ] + ) + } + + #[test] + fn test_highlight_question_mark() { + let text = "title? Str"; + let tokens = highlight(text); + assert_eq!( + tokens, + vec![ + Loc::at( + Region::between(Position::new(0), Position::new(5)), + Token::LowerIdent + ), + Loc::at( + Region::between(Position::new(5), Position::new(6)), + Token::QuestionMark + ), + Loc::at( + Region::between(Position::new(7), Position::new(10)), + Token::UpperIdent + ), + ] + ) + } + + #[test] + fn test_highlight_slash() { + let text = "first / second"; + let tokens = highlight(text); + assert_eq!( + tokens, + vec![ + Loc::at( + Region::between(Position::new(0), Position::new(5)), + Token::LowerIdent + ), + Loc::at( + Region::between(Position::new(6), Position::new(7)), + Token::Slash + ), + Loc::at( + Region::between(Position::new(8), Position::new(14)), + Token::LowerIdent + ), + ] + ) + } +} diff --git a/crates/compiler/parse/src/lib.rs b/crates/compiler/parse/src/lib.rs index dbdfe30ff4..41deda54f6 100644 --- a/crates/compiler/parse/src/lib.rs +++ b/crates/compiler/parse/src/lib.rs @@ -10,6 +10,7 @@ pub mod ast; pub mod blankspace; pub mod expr; pub mod header; +pub mod highlight; pub mod ident; pub mod keyword; pub mod module; diff --git a/crates/compiler/problem/Cargo.toml b/crates/compiler/problem/Cargo.toml index cd1cd8770b..d6b0d7cf4e 100644 --- a/crates/compiler/problem/Cargo.toml +++ b/crates/compiler/problem/Cargo.toml @@ -1,14 +1,15 @@ [package] name = "roc_problem" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Provides types to describe problems that can occur when compiling Roc code." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] roc_collections = { path = "../collections" } -roc_region = { path = "../region" } roc_module = { path = "../module" } -roc_types = { path = "../types" } roc_parse = { path = "../parse" } +roc_region = { path = "../region" } +roc_types = { path = "../types" } diff --git a/crates/compiler/region/Cargo.toml b/crates/compiler/region/Cargo.toml index b67e5a44c2..bc82774e74 100644 --- a/crates/compiler/region/Cargo.toml +++ b/crates/compiler/region/Cargo.toml @@ -1,10 +1,11 @@ [package] name = "roc_region" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Data structures for storing source-code-location information, used heavily for contextual error messages." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] -static_assertions = "1.1.0" +static_assertions.workspace = true diff --git a/crates/compiler/region/src/all.rs b/crates/compiler/region/src/all.rs index 457810cdf9..fb83fe2b37 100644 --- a/crates/compiler/region/src/all.rs +++ b/crates/compiler/region/src/all.rs @@ -129,6 +129,10 @@ impl Position { offset: self.offset - count as u32, } } + + pub fn byte_offset(&self) -> usize { + self.offset as usize + } } impl Debug for Position { @@ -322,6 +326,10 @@ impl Loc { value: transform(self.value), } } + + pub fn byte_range(&self) -> std::ops::Range { + self.region.start.byte_offset()..self.region.end.byte_offset() + } } impl fmt::Debug for Loc diff --git a/crates/compiler/roc_target/Cargo.toml b/crates/compiler/roc_target/Cargo.toml index 76325d052b..e75e309667 100644 --- a/crates/compiler/roc_target/Cargo.toml +++ b/crates/compiler/roc_target/Cargo.toml @@ -1,12 +1,13 @@ [package] name = "roc_target" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Provides types and helpers for compiler targets such as default_x86_64." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] -target-lexicon = "0.12.3" -strum = "0.24.0" -strum_macros = "0.24" +strum.workspace = true +strum_macros.workspace = true +target-lexicon.workspace = true diff --git a/crates/compiler/roc_target/src/lib.rs b/crates/compiler/roc_target/src/lib.rs index f7c3d0426d..a98b40116a 100644 --- a/crates/compiler/roc_target/src/lib.rs +++ b/crates/compiler/roc_target/src/lib.rs @@ -150,3 +150,57 @@ impl From for Architecture { } } } + +pub const WASM_TARGET_STR: &str = "wasm32"; +pub const LINUX_X86_64_TARGET_STR: &str = "linux-x86_64"; +pub const LINUX_ARM64_TARGET_STR: &str = "linux-arm64"; +pub const MACOS_ARM64_TARGET_STR: &str = "macos-arm64"; +pub const MACOS_X86_64_TARGET_STR: &str = "macos-x86_64"; +pub const WINDOWS_X86_64_TARGET_STR: &str = "windows-x86_64"; +pub const WINDOWS_X86_32_TARGET_STR: &str = "windows-x86_32"; +pub const WIDNOWS_ARM64_TARGET_STR: &str = "windows-arm64"; + +pub fn get_target_triple_str(target: &target_lexicon::Triple) -> Option<&'static str> { + match target { + target_lexicon::Triple { + architecture: target_lexicon::Architecture::Wasm32, + .. + } => Some(WASM_TARGET_STR), + target_lexicon::Triple { + operating_system: target_lexicon::OperatingSystem::Linux, + architecture: target_lexicon::Architecture::X86_64, + .. + } => Some(LINUX_X86_64_TARGET_STR), + target_lexicon::Triple { + operating_system: target_lexicon::OperatingSystem::Linux, + architecture: target_lexicon::Architecture::Aarch64(_), + .. + } => Some(LINUX_ARM64_TARGET_STR), + target_lexicon::Triple { + operating_system: target_lexicon::OperatingSystem::Darwin, + architecture: target_lexicon::Architecture::Aarch64(_), + .. + } => Some(MACOS_ARM64_TARGET_STR), + target_lexicon::Triple { + operating_system: target_lexicon::OperatingSystem::Darwin, + architecture: target_lexicon::Architecture::X86_64, + .. + } => Some(MACOS_X86_64_TARGET_STR), + target_lexicon::Triple { + operating_system: target_lexicon::OperatingSystem::Windows, + architecture: target_lexicon::Architecture::X86_64, + .. + } => Some(WINDOWS_X86_64_TARGET_STR), + target_lexicon::Triple { + operating_system: target_lexicon::OperatingSystem::Windows, + architecture: target_lexicon::Architecture::X86_32(_), + .. + } => Some(WINDOWS_X86_32_TARGET_STR), + target_lexicon::Triple { + operating_system: target_lexicon::OperatingSystem::Windows, + architecture: target_lexicon::Architecture::Aarch64(_), + .. + } => Some(WIDNOWS_ARM64_TARGET_STR), + _ => None, + } +} diff --git a/crates/compiler/serialize/Cargo.toml b/crates/compiler/serialize/Cargo.toml index 221013e628..9431277b53 100644 --- a/crates/compiler/serialize/Cargo.toml +++ b/crates/compiler/serialize/Cargo.toml @@ -1,10 +1,11 @@ [package] name = "roc_serialize" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Provides helpers for serializing and deserializing to/from bytes." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] roc_collections = { path = "../collections" } diff --git a/crates/compiler/solve/Cargo.toml b/crates/compiler/solve/Cargo.toml index 4d1627030b..852b0eac7b 100644 --- a/crates/compiler/solve/Cargo.toml +++ b/crates/compiler/solve/Cargo.toml @@ -1,44 +1,45 @@ [package] name = "roc_solve" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "The entry point of Roc's type inference system. Implements type inference and specialization of abilities." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] +roc_can = { path = "../can" } roc_collections = { path = "../collections" } +roc_debug_flags = { path = "../debug_flags" } +roc_derive = { path = "../derive" } +roc_derive_key = { path = "../derive_key" } roc_error_macros = { path = "../../error_macros" } roc_exhaustive = { path = "../exhaustive" } -roc_packaging = { path = "../../packaging" } -roc_region = { path = "../region" } roc_module = { path = "../module" } -roc_types = { path = "../types" } -roc_can = { path = "../can" } -roc_derive_key = { path = "../derive_key" } -roc_derive = { path = "../derive" } +roc_packaging = { path = "../../packaging" } roc_problem = { path = "../problem" } +roc_region = { path = "../region" } roc_solve_problem = { path = "../solve_problem" } +roc_types = { path = "../types" } roc_unify = { path = "../unify" } -roc_debug_flags = { path = "../debug_flags" } arrayvec.workspace = true bumpalo.workspace = true [dev-dependencies] -roc_load = { path = "../load" } roc_builtins = { path = "../builtins" } -roc_problem = { path = "../problem" } +roc_derive = { path = "../derive", features = ["debug-derived-symbols"] } +roc_load = { path = "../load" } roc_parse = { path = "../parse" } +roc_problem = { path = "../problem" } +roc_reporting = { path = "../../reporting" } roc_solve = { path = "../solve" } roc_target = { path = "../roc_target" } -roc_reporting = { path = "../../reporting" } -roc_derive = { path = "../derive", features = ["debug-derived-symbols"] } -pretty_assertions.workspace = true -indoc.workspace = true -tempfile.workspace = true bumpalo.workspace = true -regex.workspace = true -lazy_static.workspace = true +indoc.workspace = true insta.workspace = true +lazy_static.workspace = true +pretty_assertions.workspace = true +regex.workspace = true +tempfile.workspace = true diff --git a/crates/compiler/solve_problem/Cargo.toml b/crates/compiler/solve_problem/Cargo.toml index 73148f7c72..0c33244b60 100644 --- a/crates/compiler/solve_problem/Cargo.toml +++ b/crates/compiler/solve_problem/Cargo.toml @@ -1,16 +1,17 @@ [package] name = "roc_solve_problem" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Provides types to describe problems that can occur during solving." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] -roc_collections = { path = "../collections" } -roc_region = { path = "../region" } -roc_module = { path = "../module" } -roc_types = { path = "../types" } roc_can = { path = "../can" } -roc_problem = { path = "../problem" } +roc_collections = { path = "../collections" } roc_exhaustive = { path = "../exhaustive" } +roc_module = { path = "../module" } +roc_problem = { path = "../problem" } +roc_region = { path = "../region" } +roc_types = { path = "../types" } diff --git a/crates/compiler/str/Cargo.toml b/crates/compiler/str/Cargo.toml deleted file mode 100644 index 688048376a..0000000000 --- a/crates/compiler/str/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -name = "roc_str" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" -description = "Provides a Roc Str with reference-counting so that it may be mutated in-place." - -[dependencies] -roc_collections = { path = "../collections" } -roc_region = { path = "../region" } -roc_module = { path = "../module" } -roc_types = { path = "../types" } -roc_can = { path = "../can" } -roc_unify = { path = "../unify" } -roc_problem = { path = "../problem" } -bumpalo = { version = "3.6.1", features = ["collections"] } - -[dev-dependencies] -roc_constrain = { path = "../constrain" } -roc_builtins = { path = "../builtins" } -roc_parse = { path = "../parse" } -roc_solve = { path = "../solve" } -pretty_assertions = "0.5.1" -indoc = "0.3.3" -quickcheck = "0.8" -quickcheck_macros = "0.8" diff --git a/crates/compiler/str/README.md b/crates/compiler/str/README.md deleted file mode 100644 index 276278bb58..0000000000 --- a/crates/compiler/str/README.md +++ /dev/null @@ -1,209 +0,0 @@ -# `Str` - -This is the in-memory representation for `Str`. To explain how `Str` is laid out in memory, it's helpful to start with how `List` is laid out. - -## Empty list - -An empty `List Str` is essentially this Rust type with all 0s in memory: - -```rust -struct List { - pointer: *Str, // pointers are the same size as `usize` - length: usize -} -``` - -On a 64-bit system, this `struct` would take up 16B in memory. On a 32-bit system, it would take up 8B. - -Here's what the fields mean: - -- `pointer` is the memory address of the heap-allocated memory containing the `Bool` elements. For an empty list, the pointer is null (that is, 0). -- `length` is the number of `Bool` elements in the list. For an empty list, this is also 0. - -## Nonempty list - -Now let's say we define a `List Str` with two elements in it, like so: `["foo", "bar"]`. - -First we'd have the `struct` above, with both `length` and `capacity` set to 2. Then, we'd have some memory allocated on the heap, and `pointer` would store that memory's address. - -Here's how that heap memory would be laid out on a 64-bit system. It's a total of 48 bytes. - -```text -|------16B------|------16B------|---8B---|---8B---| - string #1 string #2 refcount unused -``` - -Just like how `List` is a `struct` that takes up `2 * usize` bytes in memory, `Str` takes up the same amount of memory - namely, 16B on a 64-bit system. That's why each of the two strings take up 16B of this heap-allocated memory. (Those structs may also point to other heap memory, but they could also be empty strings! Either way we just store the structs in the list, which take up 16B.) - -We'll get to what the refcount is for shortly, but first let's talk about the memory layout. The refcount is a `usize` integer, so 8B on our 64-bit system. Why is there 8B of unused memory after it? - -This is because of memory alignment. Whenever a system loads some memory from a memory address, it's much more efficient if the address is a multiple of the number of bytes it wants to get. So if we want to load a 16B string struct, we want its address to be a multiple of 16. - -When we're allocating memory on the heap, the way we specify what alignment we want is to say how big each element is, and how many of them we want. In this case, we say we want 16B elements, and we want 3 of them. Then we use the first 16B slot to store the 8B refcount, and the 8B after it are unused. - -This is memory-inefficient, but it's the price we pay for having all the 16B strings stored in addresses that are multiples of 16. It'd be worse for performance if we tried to pack everything tightly, so we accept the memory inefficiency as a cost of achieving better overall execution speed. - -> Note: if we happened to have 8B elements instead of 16B elements, the alignment would be 8 anyway and we'd have no unused memory. - -## Reference counting - -Let's go back to the refcount - short for "reference count." - -The refcount is a `usize` integer which counts how many times this `List` has been shared. For example, if we named this list `myList` and then wrote `[myList, myList, myList]` then we'd increment that refcount 3 times because `myList` is now being shared three more times. - -If we were to later call `List.pop` on that list, and the result was an in-place mutation that removed one of the `myList` entries, we'd decrement the refcount. If we did that again and again until the refcount got all the way down to 0, meaning nothing is using it anymore, then we'd deallocate these 48B of heap memory because nobody is using them anymore. - -In some cases, the compiler can detect that no reference counting is necessary. In that scenario, it doesn't bother allocating extra space for the refcount; instead, it inserts an instruction to allocate the memory at the appropriate place, another to free it later, and that's it. - -## Pointing to the first element - -The fact that the reference count may or may not be present could creat a tricky situation for some `List` operations. - -For example, should `List.get 0` return the first 16B of the heap-allocated bytes, or the second 16B? If there's a reference count in the first 16B, it should return the second 16B. If there's no refcount, it should return the first 16B. - -To solve this, the pointer in the List struct *always* points to the first element in the list. That means to access the reference count, it does negative pointer arithmetic to get the address at 16B *preceding* the memory address it has stored in its pointer field. - -## Growing lists - -If uniqueness typing tells us that a list is Unique, we know two things about it: - -1. It doesn't need a refcount, because nothing else ever references it. -2. It can be mutated in-place. - -One of the in-place mutations that can happen to a list is that its length can increase. For example, if I call `List.append list1 list2`, and `list1` is unique, then we'll attempt to append `list2`'s contents in-place into `list1`. - -Calling `List.append` on a Shared list results in allocating a new chunk of heap memory large enough to hold both lists (with a fresh refcount, since nothing is referencing the new memory yet), then copying the contents of both lists into the new memory, and finally decrementing the refcount of the old memory. - -Calling `List.append` on a Unique list can potentially be done in-place instead. - -First, `List.append` repurposes the `usize` slot normally used to store refcount, and stores a `capacity` counter in there instead of a refcount. (After all, unique lists don't need to be refcounted.) A list's capacity refers to how many elements the list *can* hold given the memory it has allocated to it, which is always guaranteed to be at least as many as its length. - -When calling `List.append list1 list2` on a unique `list1`, first we'll check to see if `list1.capacity <= list1.length + list2.length`. If it is, then we can copy in the new values without needing to allocate more memory for `list1`. - -If there is not enough capacity to fit both lists, then we can try to call [`realloc`](https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/realloc?view=vs-2019) to hopefully extend the size of our allocated memory. If `realloc` succeeds (meaning there happened to be enough free memory right after our current allocation), then we update `capacity` to reflect the new amount of space, and move on. - -> **Note:** The reason we store capacity right after the last element in the list is because of how memory cache lines work. Whenever we need to access `capacity`, it's because we're about to increase the length of the list, which means that we will most certainly be writing to the memory location right after its last element. That in turn means that we'll need to have that memory location in cache, which in turn means that looking up the `capacity` there is guaranteed not to cause a cache miss. (It's possible that writing the new capacity value to a later address could cause a cache miss, but this strategy minimizes the chance of that happening.) An alternate design would be where we store the capacity right before the first element in the list. In that design we wouldn't have to re-write the capacity value at the end of the list every time we grew it, but we'd be much more likely to incur more cache misses that way - because we're working at the end of the list, not at the beginning. Cache misses are many times more expensive than an extra write to a memory address that's in cache already, not to mention the potential extra load instruction to add the length to the memory address of the first element (instead of subtracting 1 from that address), so we optimize for minimizing the highly expensive cache misses by always paying a tiny additional cost when increasing the length of the list, as well as a potential even tinier cost (zero, if the length already happens to be in a register) when looking up its capacity or refcount. - -If `realloc` fails, then we have to fall back on the same "allocate new memory and copy everything" strategy that we do with shared lists. - -When you have a way to anticipate that a list will want to grow incrementally to a certain size, you can avoid such extra allocations by using `List.reserve` to guarantee more capacity up front. (`List.reserve` works like Rust's [`Vec::reserve`](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.reserve).) - -> **Note:** Calling `List.reserve 0 myList` will have no effect on a Unique list, but on a Shared list it will clone `myList` and return a Unique one. If you want to do a bunch of in-place mutations on a list, but it's currently Shared, calling `List.reserve 0` on it to get a Unique clone could actually be an effective performance optimization! - -## Capacity and alignment - -Some lists may end up beginning with excess capacity due to memory alignment requirements. Since the refcount is `usize`, all lists need a minimum of that alignment. For example, on a 64-bit system, a `List Bool` has an alignment of 8B even though bools can fit in 1B. - -This means the list `[True, True, False]` would have a memory layout like this): - -```text -|--------------8B--------------|--1B--|--1B--|--1B--|-----5B-----| - either refcount or capacity bool1 bool2 bool3 unused -``` - -As such, if this list is Unique, it would start out with a length of 3 and a capacity of 8. - -Since each bool value is a byte, it's okay for them to be packed side-by-side even though the overall alignment of the list elements is 8. This is fine because each of their individual memory addresses will end up being a multiple of their size in bytes. - -Note that unlike in the `List Str` example before, there wouldn't be any unused memory between the refcount (or capacity, depending on whether the list was shared or unique) and the first element in the list. That will always be the case when the size of the refcount is no bigger than the alignment of the list's elements. - -## Distinguishing between refcount and capacity in the host - -If I'm a platform author, and I receive a `List` from the application, it's important that I be able to tell whether I'm dealing with a refcount or a capacity. (The uniqueness type information will have been erased by this time, because some applications will return a Unique list while others return a Shared list, so I need to be able to tell using runtime information only which is which.) This way, I can know to either increment the refcount, or to feel free to mutate it in-place using the capacity value. - -We use a very simple system to distinguish the two: if the high bit in that `usize` value is 0, then it's capacity. If it's 1, then it's a refcount. - -This has a couple of implications: - -- `capacity` actually has a maximum of `isize::MAX`, not `usize::MAX` - because if its high bit flips to 1, then now suddenly it's considered a refcount by the host. As it happens, capacity's maximum value is naturally `isize::MAX` anyway, so there's no downside here. -- `refcount` actually begins at `isize::MIN` and increments towards 0, rather than beginning at 0 and incrementing towards a larger number. When a decrement instruction is executed and the refcount is `isize::MIN`, it gets freed instead. Since all refcounts do is count up and down, and they only ever compare the refcount to a fixed constant, there's no real performance cost to comparing to `isize::MIN` instead of to 0. So this has no significant downside either. - -Using this representation, hosts can trivially distinguish any list they receive as being either refcounted or having a capacity value, without any runtime cost in either the refcounted case or the capacity case. - -### Saturated reference count - -What happens if the reference count overflows? As in, we try to reference the same list more than `isize` times? - -In this situation, the reference count becomes unreliable. Suppose we try to increment it 3 more times after it's already been incremented `isize` times, and since we can't store any further numbers without flipping the high bit from 1 to 0 (meaning it will become a capacity value instead of a refcount), we leave it at -1. If we later decrement it `isize` times, we'll be down to `isize::MIN` and will free the memory, even though 3 things are still referencing that memory! - -This would be a total disaster, so what we do instead is that we decide to leak the memory. Once the reference count hits -1, we neither increment nor decrement it ever again, which in turn means we will never free it. So -1 is a special reference count meaning "this memory has become unreclaimable, and must never be freed." - -This has the downside of being potentially wasteful of the program's memory, but it's less detrimental to user experience than a crash, and it doesn't impact correctness at all. - -## Summary of Lists - -Lists are a `2 * usize` struct which contains a length and a pointer. - -That pointer is a memory address (null in the case of an empty list) which points to the first element in a sequential array of memory. - -If that pointer is shared in multiple places, then there will be a `usize` reference count stored right before the first element of the list. There may be unused memory after the refcount if `usize` is smaller than the alignment of one of the list's elements. - -Refcounts get incremented each time a list gets shared somewhere, and decremented each time that shared value is no longer referenced by anything else (for example, by going out of scope). Once there are no more references, the list's heap memory can be safely freed. If a reference count gets all the way up to `usize`, then it will never be decremented again and the memory will never be freed. - -Whenever a list grows, it will grow in-place if it's Unique and there is enough capacity. (Capacity is stored where a refcount would be in a Shared list.) If there isn't enough capacity - even after trying `realloc` - or if the list is Shared, then instead new heap memory will be allocated, all the necessary elements will get copied into it, and the original list's refcount will be decremented. - -## Strings - -Strings have several things in common with lists: - -- They are a `2 * usize` struct, sometimes with a non-null pointer to some heap memory -- They have a length and a capacity, and they can grow in basically the same way -- They are reference counted in basically the same way - -However, they also have two things going on that lists do not: - -- The Small String Optimization -- Literals stored in read-only memory - -## The Small String Optimization - -In practice, a lot of strings are pretty small. For example, the string `"Richard Feldman"` can be stored in 15 UTF-8 bytes. If we stored that string the same way we store a list, then on a 64-bit system we'd need a 16B struct, which would include a pointer to 24B of heap memory (including the refcount/capacity and one unused byte for alignment). - -That's a total of 48B to store 15B of data, when we could have fit the whole string into the original 16B we needed for the struct, with one byte left over. - -The Small String Optimization is where we store strings directly in the struct, assuming they can fit in there. We reserve one of those bytes to indicate whether this is a Small String or a larger one that actually uses a pointer. - -## String Memory Layout - -How do we tell small strings apart from nonsmall strings? - -We make use of the fact that lengths (for both strings *and* lists) are `usize` values which have a maximum value of `isize::MAX` rather than `usize::MAX`. This is because `List.get` compiles down to an array access operation, and LLVM uses `isize` indices for those because they do signed arithmetic on the pointer in case the caller wants to add a negative number to the address. (We don't want to, as it happens, but that's what the low-level API supports, so we are bound by its limitations.) - -Since the string's length is a `usize` value with a maximum of `isize::MAX`, we can be sure that its most significant bit will always be 0, not 1. (If it were a 1, that would be a negative `isize`!) We can use this fact to use that spare bit as a flag indicating whether the string is small: if that bit is a 1, it's a small string; otherwise, it's a nonsmall string. - -This makes calculating the length of the string a multi-step process: - -1. Get the length field out of the struct. -2. Look at its highest bit. If that bit is 0, return the length as-is. -3. If the bit is 1, then this is a small string, and its length is packed into the highest byte of the `usize` length field we're currently examining. Take that byte and bit shift it by 1 (to drop the `1` flag we used to indicate this is a small string), cast the resulting byte to `usize`, and that's our length. (Actually we bit shift by 4, not 1, because we only need 4 bits to store a length of 0-16, and the leftover 3 bits can potentially be useful in the future.) - -Using this strategy with a [conditional move instruction](https://stackoverflow.com/questions/14131096/why-is-a-conditional-move-not-vulnerable-for-branch-prediction-failure), we can always get the length of a `Str` in 2-3 cheap instructions on a single `usize` value, without any chance of a branch misprediction. - -Thus, the layout of a small string on a 64-bit big-endian architecture would be: - -```text -|-----------usize length field----------|-----------usize pointer field---------| -|-1B-|-1B-|-1B-|-1B-|-1B-|-1B-|-1B-|-1B-|-1B-|-1B-|-1B-|-1B-|-1B-|-1B-|-1B-|-1B-| - len 'R' 'i' 'c' 'h' 'a' 'r' 'd' ' ' 'F' 'e' 'l' 'd' 'm' 'a' 'n' -``` - -The `len` value here would be the number 15, plus a 1 (to flag that this is a small string) that would always get bit-shifted away. The capacity of a small Unique string is always equal to `2 * usize`, because that's how much you can fit without promoting to a nonsmall string. - -## Endianness - -The preceding memory layout example works on a big-endian architecture, but most CPUs are little-endian. That means the high bit where we want to store the flag (the 0 or 1 -that would make an `isize` either negative or positive) will actually be the `usize`'s last byte rather than its first byte. - -That means we'd have to move swap the order of the struct's length and pointer fields. Here's how the string `"Roc string"` would be stored on a little-endian system: - -```text -|-----------usize pointer field---------|-----------usize length field----------| -|-1B-|-1B-|-1B-|-1B-|-1B-|-1B-|-1B-|-1B-|-1B-|-1B-|-1B-|-1B-|-1B-|-1B-|-1B-|-1B-| - 'R' 'o' 'c' ' ' 's' 't' 'r' 'i' 'n' 'g' 0 0 0 0 0 len -``` - -Here, `len` would have the same format as before (including the extra 1 in the same position, which we'd bit shift away) except that it'd store a length of 10 instead of 15. - -Notice that the leftover bytes are stored as zeroes. This is handy because it means we can convert small Roc strings into C strings (which are 0-terminated) for free as long as they have at least one unused byte. Also notice that `usize pointer field` and `usize length field` have been swapped compared to the preceding example! - -## Storing string literals in read-only memory diff --git a/crates/compiler/str/src/lib.rs b/crates/compiler/str/src/lib.rs deleted file mode 100644 index 17f19c0fe0..0000000000 --- a/crates/compiler/str/src/lib.rs +++ /dev/null @@ -1,71 +0,0 @@ -//! Provides `Roc` styled collection [reference counting](https://en.wikipedia.org/wiki/Reference_counting). -//! This means the collection may or may not be safe to mutate in-place, may or -//! may not be reference counted, and may or may not need to be freed when no -//! longer in use. Whether each of these is true for a given collection can be -//! determined by inspecting that collection at runtime. -#![crate_type = "lib"] -#![no_std] - -/// Str does Roc-style collection reference counting, which means the collection -/// may or may not be safe to mutate in-place, may or may not be reference counted, -/// and may or may not need to be freed when no longer in use. Whether each of -/// these is true for a given collection can be determined by inspecting -/// that collection at runtime. -/// -/// Details: -/// -/// 1. If the collection is empty, it does not allocate on the heap. -/// 2. If it is nonempty, its pointer points to the first element of a "backing array" on the heap. -/// 3. There is an extra `isize` right before that backing array (still on the heap) which stores the -/// "flexible reference count" ("flexcount" for short). -/// 4. The flexcount can refer to one of three things, depending on whether it is positive, -/// negative, or zero. -/// 5. If the flexcount is positive, then it's a capacity. The capacity refers to the number of -/// collection elements in the backing array. This collection can be mutated in-place, until it -/// runs out of capacity. At that point, it will need a new backing array. Once it goes out of -/// scope, the backing array should be freed by the system allocator - but free() must be passed -/// a pointer to the flexcount slot, not to element 0 (because the flexcount slot is where the -/// original allocation began). Capacity will always be at least 1, because otherwise we would -/// not have allocated on the heap in the first place. -/// 6. If the flexcount is 0, then this collection resides in readonly memory. That means it cannot -/// be mutated in-place (and attempting to do so will segfault), and it must not be attempted to -/// be freed. It exists in memory forever! -/// 7. If the flexcount is negative, then it is a reference count. Treat the collection as immutable, just like -/// if the flexcount were 0, except free it when there are no more references to it. Instead of the reference count -/// starting at 0 or 1 and incrementing when new references are added, this refcount starts with all bits being 1 (so, isize::MIN) and -/// increments towards 0 when new references are added. When a reference is removed, if all bits are 1, then it should be freed. If so many new references are added that it gets incremented all the way from isize::MAX to 0, then, as is best practice when running out of reference counts, it will leak. (Leaking memory is typically less bad than crashing, and this should essentially never happen.) This happens automatically because when the flexcount is 0, it's assumed that the collection is in readonly memory and should not be freed - which is nice because it means there is no extra conditional required to implement this edge case. -/// 8. If a collection has a refcount of isize::MIN (meaning nothing else references it), it may or may not be safe to convert it to a capacity, -/// depending on whether it contains other refcounted collections. For example, a Str -/// is a collection of all bytes, so if it has a refcount of all 1 bits, it can be safely -/// converted to a capacity (the initial capacity should be equal to the collection's length), -/// after which point it can be safely mutated in-place. However, a refcounted List of Lists with a refcount of isize::MIN will not be safe to convert to a capacity, unless the inner Lists also happen to have refcounts of isize::MIN. This is because mutate-in-place operations like removing an element from a list do not check for refcounts in the elements they remove, which means removing an element from the newly mutable-in-place list would cause memory leaks in its refcounted contents. (They'd have been removed, but their reference counts would not have been adjusted accordingly.) -/// -/// Note that because of these runtime conditionals, modifying and freeing Roc collections are both -/// cheaper operations in generated Roc code than in host code. Since the Roc compiler knows -/// statically whether a collection is refcounted, unique, or readonly, it does not bother with -/// these checks at runtime. A host, however, cannot have that information statically (since it may be different -/// for different applications), and so must check at runtime instead. -struct Str { - bytes: [16, u8]; -} - -#[no_mangle] -pub fn empty_() -> Str { - Str { - bytes : [0; 16] - } -} - -#[no_mangle] -pub fn len_(string: Str) -> usize { - let disc = discriminant(str); - - if disc == 0 { - // It's a - } -} - -#[inline(always)] -fn discriminant(string: &Str) -> u8 { - // cast the first 8 bytes to be u64, return its lsbyte -} diff --git a/crates/compiler/test_derive/Cargo.toml b/crates/compiler/test_derive/Cargo.toml index 35ed004fa0..2c5f5e14a3 100644 --- a/crates/compiler/test_derive/Cargo.toml +++ b/crates/compiler/test_derive/Cargo.toml @@ -1,35 +1,34 @@ [package] name = "test_derive" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Tests Roc's auto-derivers." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [[test]] name = "test_derive" path = "src/tests.rs" [dev-dependencies] -roc_collections = { path = "../collections" } -roc_module = { path = "../module" } roc_builtins = { path = "../builtins" } -roc_load_internal = { path = "../load_internal" } roc_can = { path = "../can" } -roc_derive_key = { path = "../derive_key" } +roc_collections = { path = "../collections" } +roc_constrain = { path = "../constrain" } +roc_debug_flags = { path = "../debug_flags" } roc_derive = { path = "../derive", features = ["debug-derived-symbols", "open-extension-vars"] } +roc_derive_key = { path = "../derive_key" } +roc_load_internal = { path = "../load_internal" } +roc_module = { path = "../module" } +roc_packaging = { path = "../../packaging" } +roc_region = { path = "../region" } +roc_reporting = { path = "../../reporting" } +roc_solve = { path = "../solve" } roc_target = { path = "../roc_target" } roc_types = { path = "../types" } -roc_packaging = { path = "../../packaging" } -roc_reporting = { path = "../../reporting" } -roc_constrain = { path = "../constrain" } -roc_region = { path = "../region" } -roc_solve = { path = "../solve" } -roc_debug_flags = { path = "../debug_flags" } ven_pretty = { path = "../../vendor/pretty" } bumpalo.workspace = true -indoc.workspace = true -pretty_assertions.workspace = true insta.workspace = true diff --git a/crates/compiler/test_gen/Cargo.toml b/crates/compiler/test_gen/Cargo.toml index 6e9731a157..a5f5173ac3 100644 --- a/crates/compiler/test_gen/Cargo.toml +++ b/crates/compiler/test_gen/Cargo.toml @@ -1,67 +1,73 @@ [package] name = "test_gen" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Contains all of Roc's code generation tests." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [[test]] name = "test_gen" path = "src/tests.rs" [build-dependencies] -roc_builtins = { path = "../builtins" } -roc_utils = { path = "../../utils" } +roc_bitcode = { path = "../builtins/bitcode" } +roc_command_utils = { path = "../../utils/command" } wasi_libc_sys = { path = "../../wasi-libc-sys" } + tempfile.workspace = true [dev-dependencies] -roc_gen_llvm = { path = "../gen_llvm" } -roc_gen_dev = { path = "../gen_dev" } -roc_gen_wasm = { path = "../gen_wasm" } -roc_collections = { path = "../collections" } -roc_region = { path = "../region" } -roc_module = { path = "../module" } -roc_problem = { path = "../problem" } -roc_types = { path = "../types" } +roc_bitcode = { path = "../builtins/bitcode" } +roc_build = { path = "../build", features = ["target-aarch64", "target-x86_64", "target-wasm32"] } roc_builtins = { path = "../builtins" } +roc_can = { path = "../can" } +roc_collections = { path = "../collections" } +roc_command_utils = { path = "../../utils/command" } roc_constrain = { path = "../constrain" } -roc_unify = { path = "../unify" } -roc_utils = { path = "../../utils" } -roc_solve = { path = "../solve" } +roc_debug_flags = { path = "../debug_flags" } +roc_error_macros = { path = "../../error_macros" } +roc_gen_dev = { path = "../gen_dev" } +roc_gen_llvm = { path = "../gen_llvm" } +roc_gen_wasm = { path = "../gen_wasm" } +roc_load = { path = "../load" } +roc_module = { path = "../module" } roc_mono = { path = "../mono" } roc_packaging = { path = "../../packaging" } -roc_reporting = { path = "../../reporting" } -roc_load = { path = "../load" } -roc_can = { path = "../can" } roc_parse = { path = "../parse" } -roc_build = { path = "../build", features = ["target-aarch64", "target-x86_64", "target-wasm32"] } +roc_problem = { path = "../problem" } +roc_region = { path = "../region" } +roc_reporting = { path = "../../reporting" } +roc_solve = { path = "../solve" } +roc_std = { path = "../../roc_std" } roc_target = { path = "../roc_target" } -roc_error_macros = { path = "../../error_macros" } -roc_std = { path = "../../roc_std" } -roc_debug_flags = {path="../debug_flags"} -roc_wasm_module = {path="../../wasm_module"} -roc_wasm_interp = {path="../../wasm_interp"} +roc_types = { path = "../types" } +roc_unify = { path = "../unify" } +roc_wasm_interp = { path = "../../wasm_interp" } +roc_wasm_module = { path = "../../wasm_module" } bumpalo.workspace = true +criterion.workspace = true +indoc.workspace = true +inkwell.workspace = true +lazy_static.workspace = true libc.workspace = true libloading.workspace = true -criterion.workspace = true -tempfile.workspace = true -indoc.workspace = true -lazy_static.workspace = true -inkwell.workspace = true target-lexicon.workspace = true +tempfile.workspace = true [features] default = ["gen-llvm"] -gen-llvm = [] gen-dev = [] -gen-wasm = [] +gen-llvm = [] gen-llvm-wasm = ["gen-llvm"] +gen-wasm = [] [[bench]] name = "list_map" harness = false + +[package.metadata.cargo-udeps.ignore] +development = ["roc_wasm_interp"] \ No newline at end of file diff --git a/crates/compiler/test_gen/build.rs b/crates/compiler/test_gen/build.rs index ad87fb0747..a9abb28f13 100644 --- a/crates/compiler/test_gen/build.rs +++ b/crates/compiler/test_gen/build.rs @@ -1,5 +1,4 @@ -use roc_builtins::bitcode; -use roc_utils::zig; +use roc_command_utils::zig; use std::env; use std::fs; use std::path::Path; @@ -100,8 +99,8 @@ fn build_wasm_test_host() { let mut outfile = PathBuf::from(&out_dir).join(PLATFORM_FILENAME); outfile.set_extension("wasm"); - let builtins_host_tempfile = - bitcode::host_wasm_tempfile().expect("failed to write host builtins object to tempfile"); + let builtins_host_tempfile = roc_bitcode::host_wasm_tempfile() + .expect("failed to write host builtins object to tempfile"); run_zig(&[ "wasm-ld", diff --git a/crates/compiler/test_gen/src/gen_abilities.rs b/crates/compiler/test_gen/src/gen_abilities.rs index 996bfb61ef..498293824e 100644 --- a/crates/compiler/test_gen/src/gen_abilities.rs +++ b/crates/compiler/test_gen/src/gen_abilities.rs @@ -787,6 +787,59 @@ fn encode_derived_record_with_many_types() { ) } +#[test] +#[cfg(all(any(feature = "gen-llvm", feature = "gen-wasm")))] +fn encode_derived_generic_record_with_different_field_types() { + assert_evals_to!( + indoc!( + r#" + app "test" + imports [Encode, Json] + provides [main] to "./platform" + + Q a b := {a: a, b: b} has [Encoding] + + q = @Q {a: 10u32, b: "fieldb"} + + main = + result = Str.fromUtf8 (Encode.toBytes q Json.toUtf8) + when result is + Ok s -> s + _ -> "" + "# + ), + RocStr::from(r#"{"a":10,"b":"fieldb"}"#), + RocStr + ) +} + +#[test] +#[cfg(all(any(feature = "gen-llvm", feature = "gen-wasm")))] +fn encode_derived_generic_tag_with_different_field_types() { + assert_evals_to!( + indoc!( + r#" + app "test" + imports [Encode, Json] + provides [main] to "./platform" + + Q a b := [A a, B b] has [Encoding] + + q : Q Str U32 + q = @Q (B 67) + + main = + result = Str.fromUtf8 (Encode.toBytes q Json.toUtf8) + when result is + Ok s -> s + _ -> "" + "# + ), + RocStr::from(r#"{"B":[67]}"#), + RocStr + ) +} + #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] fn decode_use_stdlib() { diff --git a/crates/compiler/test_gen/src/gen_compare.rs b/crates/compiler/test_gen/src/gen_compare.rs index 78f2b4dbe2..7e2f31dc93 100644 --- a/crates/compiler/test_gen/src/gen_compare.rs +++ b/crates/compiler/test_gen/src/gen_compare.rs @@ -27,7 +27,7 @@ fn eq_i64() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn neq_i64() { assert_evals_to!( indoc!( @@ -61,7 +61,7 @@ fn eq_u64() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn neq_u64() { assert_evals_to!( indoc!( @@ -78,7 +78,7 @@ fn neq_u64() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn eq_bool_tag() { assert_evals_to!( indoc!( @@ -95,7 +95,7 @@ fn eq_bool_tag() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn neq_bool_tag() { assert_evals_to!( indoc!( @@ -111,6 +111,52 @@ fn neq_bool_tag() { ); } +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] +fn bool_logic() { + assert_evals_to!( + indoc!( + r#" + bool1 = Bool.true + bool2 = Bool.false + bool3 = !bool1 + + (bool1 && bool2) || bool2 && bool3 + "# + ), + false, + bool + ); +} + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] +fn and_bool() { + assert_evals_to!("Bool.true && Bool.true", true, bool); + assert_evals_to!("Bool.true && Bool.false", false, bool); + assert_evals_to!("Bool.false && Bool.true", false, bool); + assert_evals_to!("Bool.false && Bool.false", false, bool); +} + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] +fn or_bool() { + assert_evals_to!("Bool.true || Bool.true", true, bool); + assert_evals_to!("Bool.true || Bool.false", true, bool); + assert_evals_to!("Bool.false || Bool.true", true, bool); + assert_evals_to!("Bool.false || Bool.false", false, bool); +} + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] +fn not_bool() { + assert_evals_to!("!Bool.true", false, bool); + assert_evals_to!("!Bool.false", true, bool); + + assert_evals_to!("!(!Bool.true)", true, bool); + assert_evals_to!("!(!Bool.false)", false, bool); +} + #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] fn empty_record() { @@ -152,7 +198,7 @@ fn unit() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn newtype() { assert_evals_to!("Identity 42 == Identity 42", true, bool); assert_evals_to!("Identity 42 != Identity 42", false, bool); diff --git a/crates/compiler/test_gen/src/gen_list.rs b/crates/compiler/test_gen/src/gen_list.rs index bdbdd19153..87dbca3565 100644 --- a/crates/compiler/test_gen/src/gen_list.rs +++ b/crates/compiler/test_gen/src/gen_list.rs @@ -1859,13 +1859,11 @@ fn first_int_list() { assert_evals_to!( indoc!( r#" - when List.first [12, 9, 6, 3] is - Ok val -> val - Err _ -> -1 + List.first [12, 9, 6, 3] "# ), - 12, - i64 + RocResult::ok(12), + RocResult ); } @@ -1889,45 +1887,42 @@ fn first_wildcard_empty_list() { assert_evals_to!( indoc!( r#" - when List.first [] is - Ok _ -> 5 - Err _ -> -1 + List.last [] |> Result.map (\_ -> 0i64) "# ), - -1, - i64 + RocResult::err(()), + RocResult ); } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn first_empty_list() { assert_evals_to!( indoc!( r#" - when List.first [] is - Ok val -> val - Err _ -> -1 + list : List I64 + list = [] + + List.first list "# ), - -1, - i64 + RocResult::err(()), + RocResult ); } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn last_int_list() { assert_evals_to!( indoc!( r#" - when List.last [12, 9, 6, 3] is - Ok val -> val - Err _ -> -1 + List.last [12, 9, 6, 3] "# ), - 3, - i64 + RocResult::ok(3), + RocResult ); } @@ -1937,13 +1932,11 @@ fn last_wildcard_empty_list() { assert_evals_to!( indoc!( r#" - when List.last [] is - Ok _ -> 5 - Err _ -> -1 + List.last [] |> Result.map (\_ -> 0i64) "# ), - -1, - i64 + RocResult::err(()), + RocResult ); } @@ -1953,13 +1946,14 @@ fn last_empty_list() { assert_evals_to!( indoc!( r#" - when List.last [] is - Ok val -> val - Err _ -> -1 + list : List I64 + list = [] + + List.last list "# ), - -1, - i64 + RocResult::err(()), + RocResult ); } @@ -1969,29 +1963,32 @@ fn get_empty_list() { assert_evals_to!( indoc!( r#" - when List.get [] 0 is - Ok val -> val - Err _ -> -1 + list : List I64 + list = [] + + List.get list 0 "# ), - -1, - i64 + RocResult::err(()), + RocResult ); } #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] fn get_wildcard_empty_list() { + // NOTE: by default, the return type is `Result [] [NotFound]`, which is actually represented + // as just `[NotFound]`. Casting that to `RocResult<(), ()>` is invalid! But accepting any `()` + // would make the test pointless. Therefore, we must explicitly change the type on the roc side assert_evals_to!( indoc!( r#" - when List.get [] 0 is - Ok _ -> 5 - Err _ -> -1 + List.get [] 0 + |> Result.map (\_ -> {}) "# ), - -1, - i64 + RocResult::err(()), + RocResult<(), ()> ); } @@ -2010,39 +2007,35 @@ fn get_str_list_ok() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn get_int_list_ok() { assert_evals_to!( indoc!( r#" - when List.get [12, 9, 6] 1 is - Ok val -> val - Err _ -> -1 + List.get [12, 9, 6] 1 "# ), - 9, - i64 + RocResult::ok(9), + RocResult ); } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn get_int_list_oob() { assert_evals_to!( indoc!( r#" - when List.get [12, 9, 6] 1000 is - Ok val -> val - Err _ -> -1 + List.get [12, 9, 6] 1000 "# ), - -1, - i64 + RocResult::err(()), + RocResult ); } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn replace_unique_int_list() { assert_evals_to!( indoc!( @@ -2057,7 +2050,7 @@ fn replace_unique_int_list() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn replace_unique_int_list_out_of_bounds() { assert_evals_to!( indoc!( @@ -2072,7 +2065,7 @@ fn replace_unique_int_list_out_of_bounds() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn replace_unique_int_list_get_old_value() { assert_evals_to!( indoc!( @@ -2087,7 +2080,7 @@ fn replace_unique_int_list_get_old_value() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn replace_unique_get_large_value() { assert_evals_to!( indoc!( @@ -2138,13 +2131,11 @@ fn get_set_unique_int_list_i64() { assert_evals_to!( indoc!( r#" - when List.get (List.set [12, 9, 7, 3] 1 42) 1 is - Ok val -> val - Err _ -> -1 + List.get (List.set [12, 9, 7, 3] 1 42) 1 "# ), - 42, - i64 + RocResult::ok(42), + RocResult ); } @@ -2154,13 +2145,11 @@ fn get_set_unique_int_list_i8() { assert_evals_to!( indoc!( r#" - when List.get (List.set [12, 9, 7, 3] 1 42i8) 1 is - Ok val -> val - Err _ -> -1i8 + List.get (List.set [12, 9, 7, 3] 1 42i8) 1 "# ), - 42, - i8 + RocResult::ok(42), + RocResult ); } @@ -2175,7 +2164,7 @@ fn set_unique_int_list() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn set_unique_list_oob() { assert_evals_to!( "List.set [3, 17, 4.1] 1337 9.25", @@ -2240,20 +2229,18 @@ fn set_shared_list_oob() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn get_unique_int_list() { assert_evals_to!( indoc!( r#" unique = [2, 4] - when List.get unique 1 is - Ok num -> num - Err _ -> -1 + List.get unique 1 "# ), - 4, - i64 + RocResult::ok(4), + RocResult ); } @@ -2275,7 +2262,7 @@ fn gen_wrap_len() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn gen_wrap_first() { assert_evals_to!( indoc!( @@ -2292,7 +2279,7 @@ fn gen_wrap_first() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn gen_duplicate() { assert_evals_to!( indoc!( @@ -2605,7 +2592,7 @@ fn list_literal_increment_decrement() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn list_pass_to_function() { assert_evals_to!( indoc!( @@ -2625,7 +2612,7 @@ fn list_pass_to_function() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn list_pass_to_set() { assert_evals_to!( indoc!( @@ -2713,24 +2700,22 @@ fn list_min() { assert_evals_to!( indoc!( r#" - when List.min [] is - Ok val -> val - Err _ -> -1 - "# + List.min [] + |> Result.map (\_ -> {}) + "# ), - -1, - i64 + RocResult::err(()), + RocResult<(), ()> ); + assert_evals_to!( indoc!( r#" - when List.min [3, 1, 2] is - Ok val -> val - Err _ -> -1 - "# + List.min [3, 1, 2] + "# ), - 1, - i64 + RocResult::ok(1), + RocResult ); } @@ -2740,24 +2725,22 @@ fn list_max() { assert_evals_to!( indoc!( r#" - when List.max [] is - Ok val -> val - Err _ -> -1 - "# + List.max [] + |> Result.map (\_ -> {}) + "# ), - -1, - i64 + RocResult::err(()), + RocResult<(), ()> ); + assert_evals_to!( indoc!( r#" - when List.max [3, 1, 2] is - Ok val -> val - Err _ -> -1 - "# + List.max [3, 1, 2] + "# ), - 3, - i64 + RocResult::ok(3), + RocResult ); } @@ -3440,7 +3423,7 @@ fn with_capacity() { r#" l : List U64 l = List.withCapacity 10 - + l "# ), @@ -3713,6 +3696,24 @@ fn list_walk_from_even_prefix_sum() { ); } +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +// TODO: update how roc decides whether or not to print `User crashed` or `Roc failed` such that this prints `Roc failed ...`` +#[should_panic( + expected = r#"User crash with message: "List.range: failed to generate enough elements to fill the range before overflowing the numeric type"# +)] +fn list_range_length_overflow() { + assert_evals_to!( + indoc!( + r#" + List.range {start: At 255u8, end: Length 2} + "# + ), + RocList::::default(), + RocList:: + ); +} + #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] mod pattern_match { #[cfg(feature = "gen-llvm")] diff --git a/crates/compiler/test_gen/src/gen_num.rs b/crates/compiler/test_gen/src/gen_num.rs index afdd1b0118..2e9276c86f 100644 --- a/crates/compiler/test_gen/src/gen_num.rs +++ b/crates/compiler/test_gen/src/gen_num.rs @@ -19,11 +19,11 @@ fn nat_alias() { assert_evals_to!( indoc!( r#" - i : Num.Nat - i = 1 + i : Num.Nat + i = 1 - i - "# + i + "# ), 1, usize @@ -31,16 +31,16 @@ fn nat_alias() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn i128_signed_int_alias() { assert_evals_to!( indoc!( r#" - i : I128 - i = 128 + i : I128 + i = 128 - i - "# + i + "# ), 128, i128 @@ -71,11 +71,11 @@ fn i32_signed_int_alias() { assert_evals_to!( indoc!( r#" - i : I32 - i = 32 + i : I32 + i = 32 - i - "# + i + "# ), 32, i32 @@ -115,7 +115,7 @@ fn i8_signed_int_alias() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))] fn i128_hex_int_alias() { assert_evals_to!( indoc!( @@ -196,7 +196,7 @@ fn i8_hex_int_alias() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))] fn u128_signed_int_alias() { assert_evals_to!( indoc!( @@ -277,7 +277,7 @@ fn u8_signed_int_alias() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))] fn u128_hex_int_alias() { assert_evals_to!( indoc!( @@ -418,7 +418,7 @@ fn character_literal_new_line() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))] fn dec_float_alias() { assert_evals_to!( indoc!( @@ -451,7 +451,7 @@ fn f64_float_alias() { ); } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))] fn f32_float_alias() { assert_evals_to!( indoc!( @@ -468,112 +468,51 @@ fn f32_float_alias() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] -fn f64_sqrt() { - assert_evals_to!( - indoc!( - r#" - when Num.sqrtChecked 100 is - Ok val -> val - Err _ -> -1 - "# - ), - 10.0, - f64 - ); +#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))] +fn f64_sqrt_100() { + assert_evals_to!("Num.sqrt 100", 10.0, f64); +} + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))] +fn f64_sqrt_checked_0() { + assert_evals_to!("Num.sqrt 0", 0.0, f64); } #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] -fn f64_log() { - assert_evals_to!( - indoc!( - r#" - Num.log 7.38905609893 - "# - ), - 1.999999999999912, - f64 - ); -} - -#[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] -fn f64_log_checked_one() { - assert_evals_to!( - indoc!( - r#" - when Num.logChecked 1 is - Ok val -> val - Err _ -> -1 - "# - ), - 0.0, - f64 - ); -} - -#[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] -fn f64_sqrt_zero() { - assert_evals_to!( - indoc!( - r#" - when Num.sqrtChecked 0 is - Ok val -> val - Err _ -> -1 - "# - ), - 0.0, - f64 - ); +fn f64_sqrt_checked_positive() { + assert_evals_to!("Num.sqrtChecked 100", RocResult::ok(10.0), RocResult); } #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] fn f64_sqrt_checked_negative() { - assert_evals_to!( - indoc!( - r#" - when Num.sqrtChecked -1 is - Err _ -> 42 - Ok val -> val - "# - ), - 42.0, - f64 - ); + assert_evals_to!("Num.sqrtChecked -1f64", RocResult::err(()), RocResult); +} + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))] +fn f64_log() { + assert_evals_to!("Num.log 7.38905609893", 1.999999999999912, f64); +} + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +fn f64_log_checked_one() { + assert_evals_to!("Num.logChecked 1", RocResult::ok(0.0), RocResult); } #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] fn f64_log_checked_zero() { - assert_evals_to!( - indoc!( - r#" - when Num.logChecked 0 is - Err _ -> 42 - Ok val -> val - "# - ), - 42.0, - f64 - ); + assert_evals_to!("Num.logChecked 0", RocResult::err(()), RocResult); } #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] fn f64_log_negative() { - assert_evals_to!( - indoc!( - r#" - Num.log -1 - "# - ), - true, - f64, - |f: f64| f.is_nan() - ); + assert_evals_to!("Num.log -1", true, f64, |f: f64| f.is_nan()); } #[test] @@ -890,16 +829,20 @@ fn gen_int_neq() { #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] -fn gen_int_less_than() { - assert_evals_to!( - indoc!( - r#" - 4 < 5 - "# - ), - true, - bool - ); +fn int_less_than() { + assert_evals_to!("4 < 5", true, bool); +} + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] +fn float_less_than() { + assert_evals_to!("4.0 < 5.0", true, bool); +} + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] +fn float_greater_than() { + assert_evals_to!("5.0 > 4.0", true, bool); } #[test] @@ -2863,6 +2806,74 @@ fn bytes_to_u32_subtly_out_of_bounds() { ); } +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +fn bytes_to_u64_clearly_out_of_bounds() { + assert_evals_to!( + indoc!( + r#" + bytes = Str.toUtf8 "hello" + when Num.bytesToU64 bytes 234 is + Ok v -> v + Err OutOfBounds -> 1 + "# + ), + 1, + u64 + ); +} + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +fn bytes_to_u64_subtly_out_of_bounds() { + assert_evals_to!( + indoc!( + r#" + bytes = Str.toUtf8 "hello world" + when Num.bytesToU64 bytes 4 is + Ok v -> v + Err OutOfBounds -> 1 + "# + ), + 1, + u64 + ); +} + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +fn bytes_to_u128_clearly_out_of_bounds() { + assert_evals_to!( + indoc!( + r#" + bytes = Str.toUtf8 "hello" + when Num.bytesToU128 bytes 234 is + Ok v -> v + Err OutOfBounds -> 1 + "# + ), + 1, + u128 + ); +} + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +fn bytes_to_u128_subtly_out_of_bounds() { + assert_evals_to!( + indoc!( + r#" + bytes = Str.toUtf8 "hello world!!!!!!" + when Num.bytesToU128 bytes 2 is + Ok v -> v + Err OutOfBounds -> 1 + "# + ), + 1, + u128 + ); +} + #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] fn bytes_to_u16_max_u8s() { @@ -2959,6 +2970,102 @@ fn bytes_to_u32_random_u8s() { ); } +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +fn bytes_to_u64_min_u8s() { + assert_evals_to!( + indoc!( + r#" + when Num.bytesToU64 [0, 0, 0, 0, 0, 0, 0, 0] 0 is + Ok v -> v + Err OutOfBounds -> 1 + "# + ), + 0, + u64 + ); +} + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +fn bytes_to_u64_max_u8s() { + assert_evals_to!( + indoc!( + r#" + when Num.bytesToU64 [255, 255, 255, 255, 255, 255, 255, 255] 0 is + Ok v -> v + Err OutOfBounds -> 1 + "# + ), + 18_446_744_073_709_551_615, + u64 + ); +} + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +fn bytes_to_u64_random_u8s() { + assert_evals_to!( + indoc!( + r#" + when Num.bytesToU64 [252, 124, 128, 121, 1, 32, 177, 211] 0 is + Ok v -> v + Err OutOfBounds -> 1 + "# + ), + 15_254_008_603_586_100_476, + u64 + ); +} + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +fn bytes_to_u128_min_u8s() { + assert_evals_to!( + indoc!( + r#" + when Num.bytesToU128 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 0 is + Ok v -> v + Err OutOfBounds -> 1 + "# + ), + 0, + u128 + ); +} + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +fn bytes_to_u128_max_u8s() { + assert_evals_to!( + indoc!( + r#" + when Num.bytesToU128 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255] 0 is + Ok v -> v + Err OutOfBounds -> 1 + "# + ), + 340_282_366_920_938_463_463_374_607_431_768_211_455, + u128 + ); +} + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +fn bytes_to_u128_random_u8s() { + assert_evals_to!( + indoc!( + r#" + when Num.bytesToU128 [252, 124, 128, 121, 1, 32, 177, 211, 3, 57, 203, 122, 95, 164, 23, 145] 0 is + Ok v -> v + Err OutOfBounds -> 1 + "# + ), + 192_860_816_096_412_392_720_639_456_393_488_792_828, + u128 + ); +} + #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] fn when_on_i32() { @@ -3864,3 +3971,30 @@ fn condition_polymorphic_num_becomes_float() { f32 ); } + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +fn num_count_leading_zero_bits() { + assert_evals_to!(r#"Num.countLeadingZeroBits 0b0010_1000u8"#, 2, usize); + assert_evals_to!(r#"Num.countLeadingZeroBits 0b0010_1000u16"#, 10, usize); + assert_evals_to!(r#"Num.countLeadingZeroBits 0b0010_1000u32"#, 26, usize); + assert_evals_to!(r#"Num.countLeadingZeroBits 0b0010_1000u64"#, 58, usize); +} + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +fn num_count_trailing_zero_bits() { + assert_evals_to!(r#"Num.countTrailingZeroBits 0b0010_1000u8"#, 3, usize); + assert_evals_to!(r#"Num.countTrailingZeroBits 0b0010_0000u16"#, 5, usize); + assert_evals_to!(r#"Num.countTrailingZeroBits 0u32"#, 32, usize); + assert_evals_to!(r#"Num.countTrailingZeroBits 0b0010_1111u64"#, 0, usize); +} + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +fn num_count_one_bits() { + assert_evals_to!(r#"Num.countOneBits 0b0010_1000u8"#, 2, usize); + assert_evals_to!(r#"Num.countOneBits 0b0010_0000u16"#, 1, usize); + assert_evals_to!(r#"Num.countOneBits 0u32"#, 0, usize); + assert_evals_to!(r#"Num.countOneBits 0b0010_1111u64"#, 5, usize); +} diff --git a/crates/compiler/test_gen/src/gen_primitives.rs b/crates/compiler/test_gen/src/gen_primitives.rs index 51c9ed01a2..3c07349438 100644 --- a/crates/compiler/test_gen/src/gen_primitives.rs +++ b/crates/compiler/test_gen/src/gen_primitives.rs @@ -3307,10 +3307,46 @@ fn box_str() { #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] -fn box_and_unbox_num() { +fn box_and_unbox_u64() { assert_evals_to!("Box.unbox (Box.box (123u64))", 123, u64) } +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] +fn box_and_unbox_u32() { + assert_evals_to!("Box.unbox (Box.box (123u32))", 123, u32) +} + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] +fn box_and_unbox_u16() { + assert_evals_to!("Box.unbox (Box.box (123u16))", 123, u16) +} + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] +fn box_and_unbox_u8() { + assert_evals_to!("Box.unbox (Box.box (123u8))", 123, u8) +} + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] +fn box_and_unbox_bool() { + assert_evals_to!("Box.unbox (Box.box (Bool.true))", true, bool) +} + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] +fn box_and_unbox_f64() { + assert_evals_to!("Box.unbox (Box.box (123.0f64))", 123.0, f64) +} + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] +fn box_and_unbox_f32() { + assert_evals_to!("Box.unbox (Box.box (123.0f32))", 123.0, f32) +} + #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] fn box_and_unbox_record() { diff --git a/crates/compiler/test_gen/src/gen_records.rs b/crates/compiler/test_gen/src/gen_records.rs index 9f1106e4a9..33f63a6d43 100644 --- a/crates/compiler/test_gen/src/gen_records.rs +++ b/crates/compiler/test_gen/src/gen_records.rs @@ -360,7 +360,7 @@ fn i64_record1_literal() { // ); // } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn bool_literal() { assert_evals_to!( indoc!( @@ -1111,3 +1111,22 @@ fn toplevel_accessor_fn_thunk() { u8 ) } + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +fn pass_record_of_u8s() { + assert_evals_to!( + indoc!( + r#" + app "test" provides [main] to "./platform" + + ra = \_ -> 1u8 + + main = + ra { a: 1u8, b: 0u8 } + "# + ), + true, + bool + ) +} diff --git a/crates/compiler/test_gen/src/gen_result.rs b/crates/compiler/test_gen/src/gen_result.rs index 53cc8aaf76..9729fbe9ce 100644 --- a/crates/compiler/test_gen/src/gen_result.rs +++ b/crates/compiler/test_gen/src/gen_result.rs @@ -227,7 +227,7 @@ fn is_err() { #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] -fn roc_result_ok() { +fn roc_result_ok_i64() { assert_evals_to!( indoc!( r#" @@ -242,6 +242,26 @@ fn roc_result_ok() { ); } +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +fn roc_result_ok_f64() { + // NOTE: the dev backend does not currently use float registers when returning a more + // complex type, but the rust side does expect it to. Hence this test fails with gen-dev + + assert_evals_to!( + indoc!( + r#" + result : Result F64 {} + result = Ok 42.0 + + result + "# + ), + RocResult::ok(42.0), + RocResult + ); +} + #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn roc_result_err() { diff --git a/crates/compiler/test_gen/src/gen_str.rs b/crates/compiler/test_gen/src/gen_str.rs index f540e62c61..4b4b61f41a 100644 --- a/crates/compiler/test_gen/src/gen_str.rs +++ b/crates/compiler/test_gen/src/gen_str.rs @@ -16,7 +16,7 @@ use indoc::indoc; use roc_std::{RocList, RocResult, RocStr}; #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_split_empty_delimiter() { assert_evals_to!( indoc!( @@ -46,7 +46,7 @@ fn str_split_empty_delimiter() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_split_bigger_delimiter_small_str() { assert_evals_to!( indoc!( @@ -110,7 +110,7 @@ fn str_split_small_str_bigger_delimiter() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_split_big_str_small_delimiter() { assert_evals_to!( indoc!( @@ -154,7 +154,7 @@ fn str_split_small_str_small_delimiter() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_split_bigger_delimiter_big_strs() { assert_evals_to!( indoc!( @@ -198,7 +198,7 @@ fn str_split_minimal_example() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_split_small_str_big_delimiter() { assert_evals_to!( indoc!( @@ -227,7 +227,7 @@ fn str_split_small_str_big_delimiter() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_split_small_str_20_char_delimiter() { assert_evals_to!( indoc!( @@ -243,7 +243,7 @@ fn str_split_small_str_20_char_delimiter() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_concat_big_to_big() { assert_evals_to!( indoc!( @@ -402,7 +402,7 @@ fn small_str_concat_empty_second_arg() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn small_str_concat_small_to_big() { assert_evals_to!( r#"Str.concat "abc" " this is longer than 15 chars""#, @@ -530,7 +530,7 @@ fn str_count_graphemes_three_js() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_count_graphemes_big_str() { assert_evals_to!( r#"Str.countGraphemes "6🤔å🤔e¥🤔çppkd🙃1jdal🦯asdfa∆ltråø˚waia8918.,🏅jjc""#, @@ -540,7 +540,7 @@ fn str_count_graphemes_big_str() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_starts_with_same_big_str() { assert_evals_to!( r#"Str.startsWith "123456789123456789" "123456789123456789""#, @@ -550,7 +550,7 @@ fn str_starts_with_same_big_str() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_starts_with_different_big_str() { assert_evals_to!( r#"Str.startsWith "12345678912345678910" "123456789123456789""#, @@ -560,24 +560,24 @@ fn str_starts_with_different_big_str() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_starts_with_same_small_str() { assert_evals_to!(r#"Str.startsWith "1234" "1234""#, true, bool); } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_starts_with_different_small_str() { assert_evals_to!(r#"Str.startsWith "1234" "12""#, true, bool); } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_starts_with_false_small_str() { assert_evals_to!(r#"Str.startsWith "1234" "23""#, false, bool); } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_from_utf8_pass_single_ascii() { assert_evals_to!( indoc!( @@ -593,7 +593,7 @@ fn str_from_utf8_pass_single_ascii() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_from_utf8_pass_many_ascii() { assert_evals_to!( indoc!( @@ -609,7 +609,7 @@ fn str_from_utf8_pass_many_ascii() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_from_utf8_pass_single_unicode() { assert_evals_to!( indoc!( @@ -625,7 +625,7 @@ fn str_from_utf8_pass_single_unicode() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_from_utf8_pass_many_unicode() { assert_evals_to!( indoc!( @@ -641,7 +641,7 @@ fn str_from_utf8_pass_many_unicode() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_from_utf8_pass_single_grapheme() { assert_evals_to!( indoc!( @@ -657,7 +657,7 @@ fn str_from_utf8_pass_single_grapheme() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_from_utf8_pass_many_grapheme() { assert_evals_to!( indoc!( @@ -673,7 +673,7 @@ fn str_from_utf8_pass_many_grapheme() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_from_utf8_pass_all() { assert_evals_to!( indoc!( @@ -689,7 +689,7 @@ fn str_from_utf8_pass_all() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_from_utf8_fail_invalid_start_byte() { assert_evals_to!( indoc!( @@ -709,7 +709,7 @@ fn str_from_utf8_fail_invalid_start_byte() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_from_utf8_fail_unexpected_end_of_sequence() { assert_evals_to!( indoc!( @@ -729,7 +729,7 @@ fn str_from_utf8_fail_unexpected_end_of_sequence() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_from_utf8_fail_expected_continuation() { assert_evals_to!( indoc!( @@ -749,7 +749,7 @@ fn str_from_utf8_fail_expected_continuation() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_from_utf8_fail_overlong_encoding() { assert_evals_to!( indoc!( @@ -769,7 +769,7 @@ fn str_from_utf8_fail_overlong_encoding() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_from_utf8_fail_codepoint_too_large() { assert_evals_to!( indoc!( @@ -789,7 +789,7 @@ fn str_from_utf8_fail_codepoint_too_large() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_from_utf8_fail_surrogate_half() { assert_evals_to!( indoc!( @@ -809,7 +809,7 @@ fn str_from_utf8_fail_surrogate_half() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_equality() { assert_evals_to!(r#""a" == "a""#, true, bool); assert_evals_to!( @@ -865,7 +865,7 @@ fn nested_recursive_literal() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_join_comma_small() { assert_evals_to!( r#"Str.joinWith ["1", "2"] ", " "#, @@ -875,7 +875,7 @@ fn str_join_comma_small() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_join_comma_big() { assert_evals_to!( r#"Str.joinWith ["10000000", "2000000", "30000000"] ", " "#, @@ -885,13 +885,13 @@ fn str_join_comma_big() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_join_comma_single() { assert_evals_to!(r#"Str.joinWith ["1"] ", " "#, RocStr::from("1"), RocStr); } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_to_utf8() { assert_evals_to!( r#"Str.toUtf8 "hello""#, @@ -909,7 +909,7 @@ fn str_to_utf8() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_from_utf8_range() { assert_evals_to!( indoc!( @@ -926,7 +926,7 @@ fn str_from_utf8_range() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_from_utf8_range_slice() { assert_evals_to!( indoc!( @@ -943,7 +943,7 @@ fn str_from_utf8_range_slice() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_from_utf8_range_slice_not_end() { assert_evals_to!( indoc!( @@ -960,7 +960,7 @@ fn str_from_utf8_range_slice_not_end() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_from_utf8_range_order_does_not_matter() { assert_evals_to!( indoc!( @@ -977,7 +977,7 @@ fn str_from_utf8_range_order_does_not_matter() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_from_utf8_range_out_of_bounds_start_value() { assert_evals_to!( indoc!( @@ -995,7 +995,7 @@ fn str_from_utf8_range_out_of_bounds_start_value() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_from_utf8_range_count_too_high() { assert_evals_to!( indoc!( @@ -1013,7 +1013,7 @@ fn str_from_utf8_range_count_too_high() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_from_utf8_range_count_too_high_for_start() { assert_evals_to!( indoc!( @@ -1031,7 +1031,7 @@ fn str_from_utf8_range_count_too_high_for_start() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_repeat_small_stays_small() { assert_evals_to!( indoc!(r#"Str.repeat "Roc" 3"#), @@ -1041,7 +1041,7 @@ fn str_repeat_small_stays_small() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_repeat_small_becomes_big() { assert_evals_to!( indoc!(r#"Str.repeat "less than 23 characters" 2"#), @@ -1051,7 +1051,7 @@ fn str_repeat_small_becomes_big() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_repeat_big() { assert_evals_to!( indoc!(r#"Str.repeat "more than 23 characters now" 2"#), @@ -1061,27 +1061,26 @@ fn str_repeat_big() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_repeat_empty_string() { let a = indoc!(r#"Str.repeat "" 3"#); - let b = RocStr::from(""); - assert_evals_to!(a, b, RocStr); + assert_evals_to!(a, RocStr::from(""), RocStr); } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_repeat_zero_times() { assert_evals_to!(indoc!(r#"Str.repeat "Roc" 0"#), RocStr::from(""), RocStr); } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_trim_empty_string() { assert_evals_to!(indoc!(r#"Str.trim """#), RocStr::from(""), RocStr); } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_trim_null_byte() { assert_evals_to!( indoc!(r#"Str.trim (Str.reserve "\u(0000)" 40)"#), @@ -1091,13 +1090,13 @@ fn str_trim_null_byte() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_trim_small_blank_string() { assert_evals_to!(indoc!(r#"Str.trim " ""#), RocStr::from(""), RocStr); } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_trim_small_to_small() { assert_evals_to!( indoc!(r#"Str.trim " hello world ""#), @@ -1107,7 +1106,7 @@ fn str_trim_small_to_small() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_trim_large_to_large_unique() { assert_evals_to!( indoc!(r#"Str.trim (Str.concat " " "hello world from a large string ")"#), @@ -1117,7 +1116,7 @@ fn str_trim_large_to_large_unique() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_trim_large_to_small_unique() { assert_evals_to!( indoc!(r#"Str.trim (Str.concat " " "hello world ")"#), @@ -1184,13 +1183,13 @@ fn str_trim_small_to_small_shared() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_trim_left_small_blank_string() { assert_evals_to!(indoc!(r#"Str.trimLeft " ""#), RocStr::from(""), RocStr); } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_trim_left_small_to_small() { assert_evals_to!( indoc!(r#"Str.trimLeft " hello world ""#), @@ -1200,7 +1199,7 @@ fn str_trim_left_small_to_small() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_trim_left_large_to_large_unique() { assert_evals_to!( indoc!(r#"Str.trimLeft (Str.concat " " "hello world from a large string ")"#), @@ -1210,7 +1209,7 @@ fn str_trim_left_large_to_large_unique() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_trim_left_large_to_small_unique() { assert_evals_to!( indoc!(r#"Str.trimLeft (Str.concat " " "hello world ")"#), @@ -1277,13 +1276,13 @@ fn str_trim_left_small_to_small_shared() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_trim_right_small_blank_string() { assert_evals_to!(indoc!(r#"Str.trimRight " ""#), RocStr::from(""), RocStr); } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_trim_right_small_to_small() { assert_evals_to!( indoc!(r#"Str.trimRight " hello world ""#), @@ -1293,7 +1292,7 @@ fn str_trim_right_small_to_small() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_trim_right_large_to_large_unique() { assert_evals_to!( indoc!(r#"Str.trimRight (Str.concat " hello world from a large string" " ")"#), @@ -1303,7 +1302,7 @@ fn str_trim_right_large_to_large_unique() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_trim_right_large_to_small_unique() { assert_evals_to!( indoc!(r#"Str.trimRight (Str.concat " hello world" " ")"#), @@ -1370,9 +1369,17 @@ fn str_trim_right_small_to_small_shared() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_to_nat() { - assert_evals_to!(r#"Str.toNat "1" |> Result.withDefault 0"#, 1, usize); + assert_evals_to!( + indoc!( + r#" + Str.toNat "1" + "# + ), + RocResult::ok(1), + RocResult + ); } #[test] @@ -1381,14 +1388,11 @@ fn str_to_i128() { assert_evals_to!( indoc!( r#" - when Str.toI128 "1" is - Ok n -> n - Err _ -> 0 - - "# + Str.toI128 "1" + "# ), - 1, - i128 + RocResult::ok(1), + RocResult ); } @@ -1398,41 +1402,39 @@ fn str_to_u128() { assert_evals_to!( indoc!( r#" - when Str.toU128 "1" is - Ok n -> n - Err _ -> 0 - - "# + Str.toU128 "1" + "# ), - 1, - u128 + RocResult::ok(1), + RocResult ); } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_to_i64() { assert_evals_to!( indoc!( r#" - when Str.toI64 "1" is - Ok n -> n - Err _ -> 0 - - "# + Str.toI64 "1" + "# ), - 1, - i64 + RocResult::ok(1), + RocResult ); } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_to_u64() { assert_evals_to!( - r#"Str.toU64 "1""#, - RocResult::ok(1u64), - RocResult + indoc!( + r#" + Str.toU64 "1" + "# + ), + RocResult::ok(1), + RocResult ); } @@ -1442,14 +1444,11 @@ fn str_to_i32() { assert_evals_to!( indoc!( r#" - when Str.toI32 "1" is - Ok n -> n - Err _ -> 0 - - "# + Str.toI32 "1" + "# ), - 1, - i32 + RocResult::ok(1), + RocResult ); } @@ -1457,9 +1456,13 @@ fn str_to_i32() { #[cfg(any(feature = "gen-llvm"))] fn str_to_u32() { assert_evals_to!( - r#"Str.toU32 "1""#, - RocResult::ok(1u32), - RocResult + indoc!( + r#" + Str.toU32 "1" + "# + ), + RocResult::ok(1), + RocResult ); } @@ -1469,14 +1472,11 @@ fn str_to_i16() { assert_evals_to!( indoc!( r#" - when Str.toI16 "1" is - Ok n -> n - Err _ -> 0 - - "# + Str.toI16 "1" + "# ), - 1, - i16 + RocResult::ok(1), + RocResult ); } @@ -1486,14 +1486,11 @@ fn str_to_u16() { assert_evals_to!( indoc!( r#" - when Str.toU16 "1" is - Ok n -> n - Err _ -> 0 - - "# + Str.toU16 "1" + "# ), - 1, - u16 + RocResult::ok(1), + RocResult ); } @@ -1503,14 +1500,11 @@ fn str_to_i8() { assert_evals_to!( indoc!( r#" - when Str.toI8 "1" is - Ok n -> n - Err _ -> 0 - - "# + Str.toI8 "1" + "# ), - 1, - i8 + RocResult::ok(1), + RocResult ); } @@ -1520,14 +1514,11 @@ fn str_to_u8() { assert_evals_to!( indoc!( r#" - when Str.toU8 "1" is - Ok n -> n - Err _ -> 0 - - "# + Str.toU8 "1" + "# ), - 1, - u8 + RocResult::ok(1), + RocResult ); } @@ -1585,7 +1576,7 @@ fn str_to_dec() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn issue_2811() { assert_evals_to!( indoc!( @@ -1601,7 +1592,7 @@ fn issue_2811() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn to_scalar_1_byte() { assert_evals_to!( indoc!( @@ -1625,7 +1616,7 @@ fn to_scalar_1_byte() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn to_scalar_2_byte() { assert_evals_to!( indoc!( @@ -1649,7 +1640,7 @@ fn to_scalar_2_byte() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn to_scalar_3_byte() { assert_evals_to!( indoc!( @@ -1673,7 +1664,7 @@ fn to_scalar_3_byte() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn to_scalar_4_byte() { // from https://design215.com/toolbox/utf8-4byte-characters.php assert_evals_to!( @@ -1698,7 +1689,7 @@ fn to_scalar_4_byte() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_split_first_one_char() { assert_evals_to!( indoc!( @@ -1714,7 +1705,7 @@ fn str_split_first_one_char() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_split_first_multiple_chars() { assert_evals_to!( indoc!( @@ -1728,7 +1719,7 @@ fn str_split_first_multiple_chars() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_split_first_entire_input() { assert_evals_to!( indoc!( @@ -1742,7 +1733,7 @@ fn str_split_first_entire_input() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_split_first_not_found() { assert_evals_to!( indoc!( @@ -1756,7 +1747,7 @@ fn str_split_first_not_found() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_split_last_one_char() { assert_evals_to!( indoc!( @@ -1770,7 +1761,7 @@ fn str_split_last_one_char() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_split_last_multiple_chars() { assert_evals_to!( indoc!( @@ -1784,7 +1775,7 @@ fn str_split_last_multiple_chars() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_split_last_entire_input() { assert_evals_to!( indoc!( @@ -1798,12 +1789,12 @@ fn str_split_last_entire_input() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_split_last_not_found() { assert_evals_to!( indoc!( r#" - Str.splitFirst "foo" "bar" + Str.splitLast "foo" "bar" "# ), RocResult::err(()), @@ -1812,7 +1803,7 @@ fn str_split_last_not_found() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_split_overlapping_substring_1() { assert_evals_to!( r#"Str.split "aaa" "aa""#, @@ -1822,7 +1813,7 @@ fn str_split_overlapping_substring_1() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_split_overlapping_substring_2() { assert_evals_to!( r#"Str.split "aaaa" "aa""#, @@ -1832,7 +1823,7 @@ fn str_split_overlapping_substring_2() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_walk_utf8_with_index() { #[cfg(not(feature = "gen-llvm-wasm"))] assert_evals_to!( @@ -1872,7 +1863,7 @@ fn str_append_scalar() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] fn str_walk_scalars() { assert_evals_to!( indoc!( @@ -1951,7 +1942,7 @@ fn when_on_strings() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn with_capacity() { assert_evals_to!( indoc!( @@ -1965,7 +1956,7 @@ fn with_capacity() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn with_capacity_concat() { assert_evals_to!( indoc!( @@ -1979,7 +1970,7 @@ fn with_capacity_concat() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn str_with_prefix() { assert_evals_to!( indoc!( @@ -2003,7 +1994,7 @@ fn str_with_prefix() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn destructure_pattern_assigned_from_thunk_opaque() { assert_evals_to!( indoc!( @@ -2025,7 +2016,7 @@ fn destructure_pattern_assigned_from_thunk_opaque() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn destructure_pattern_assigned_from_thunk_tag() { assert_evals_to!( indoc!( diff --git a/crates/compiler/test_gen/src/gen_tags.rs b/crates/compiler/test_gen/src/gen_tags.rs index 7f2b297180..18b8c22915 100644 --- a/crates/compiler/test_gen/src/gen_tags.rs +++ b/crates/compiler/test_gen/src/gen_tags.rs @@ -2196,3 +2196,42 @@ fn nullable_wrapped_with_nullable_not_last_index() { RocStr ); } + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +fn refcount_nullable_unwrapped_needing_no_refcount_issue_5027() { + assert_evals_to!( + indoc!( + r#" + app "test" provides [main] to "./platform" + + Effect : {} -> Str + + after = \effect, buildNext -> + \{} -> + when buildNext (effect {}) is + thunk -> thunk {} + + line : Effect + line = \{} -> "done" + + await : Effect, (Str -> Effect) -> Effect + await = \fx, cont -> + after + fx + cont + + succeed : {} -> Effect + succeed = \{} -> (\{} -> "success") + + test = + await line \s -> + if s == "done" then succeed {} else test + + main = test {} + "# + ), + RocStr::from("success"), + RocStr + ); +} diff --git a/crates/compiler/test_gen/src/helpers/dev.rs b/crates/compiler/test_gen/src/helpers/dev.rs index 3c40d4269a..43b775f362 100644 --- a/crates/compiler/test_gen/src/helpers/dev.rs +++ b/crates/compiler/test_gen/src/helpers/dev.rs @@ -208,7 +208,7 @@ pub fn helper( std::fs::write(&app_o_file, module_out).expect("failed to write object to file"); let builtins_host_tempfile = - bitcode::host_tempfile().expect("failed to write host builtins object to tempfile"); + roc_bitcode::host_tempfile().expect("failed to write host builtins object to tempfile"); if false { std::fs::copy(&app_o_file, "/tmp/app.o").unwrap(); diff --git a/crates/compiler/test_gen/src/helpers/llvm.rs b/crates/compiler/test_gen/src/helpers/llvm.rs index 5ba252242f..0a6197abbc 100644 --- a/crates/compiler/test_gen/src/helpers/llvm.rs +++ b/crates/compiler/test_gen/src/helpers/llvm.rs @@ -5,6 +5,7 @@ use inkwell::module::Module; use libloading::Library; use roc_build::link::llvm_module_to_dylib; use roc_collections::all::MutSet; +use roc_command_utils::zig; use roc_gen_llvm::llvm::externs::add_default_roc_externs; use roc_gen_llvm::{llvm::build::LlvmBackendMode, run_roc::RocCallResult}; use roc_load::{EntryPoint, ExecutionMode, LoadConfig, LoadMonomorphizedError, Threading}; @@ -12,7 +13,6 @@ use roc_mono::ir::{CrashTag, OptLevel, SingleEntryPoint}; use roc_packaging::cache::RocCacheDir; use roc_region::all::LineInfo; use roc_reporting::report::{RenderTarget, DEFAULT_PALETTE}; -use roc_utils::zig; use target_lexicon::Triple; #[cfg(feature = "gen-llvm-wasm")] diff --git a/crates/compiler/test_mono/Cargo.toml b/crates/compiler/test_mono/Cargo.toml index 85766f29db..05de03ab18 100644 --- a/crates/compiler/test_mono/Cargo.toml +++ b/crates/compiler/test_mono/Cargo.toml @@ -1,25 +1,26 @@ [package] name = "test_mono" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Tests Roc's generation of the mono intermediate representation." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [[test]] name = "test_mono" path = "src/tests.rs" [dev-dependencies] -roc_collections = { path = "../collections" } -roc_module = { path = "../module", features = ["debug-symbols"] } roc_builtins = { path = "../builtins" } -roc_load = { path = "../load" } roc_can = { path = "../can" } +roc_collections = { path = "../collections" } +roc_load = { path = "../load" } +roc_module = { path = "../module", features = ["debug-symbols"] } roc_mono = { path = "../mono" } -roc_target = { path = "../roc_target" } roc_packaging = { path = "../../packaging" } roc_reporting = { path = "../../reporting" } +roc_target = { path = "../roc_target" } roc_tracing = { path = "../../tracing" } test_mono_macros = { path = "../test_mono_macros" } diff --git a/crates/compiler/test_mono/generated/anonymous_closure_in_polymorphic_expression_issue_4717.txt b/crates/compiler/test_mono/generated/anonymous_closure_in_polymorphic_expression_issue_4717.txt index 4538c4e459..155e5c2879 100644 --- a/crates/compiler/test_mono/generated/anonymous_closure_in_polymorphic_expression_issue_4717.txt +++ b/crates/compiler/test_mono/generated/anonymous_closure_in_polymorphic_expression_issue_4717.txt @@ -3,97 +3,97 @@ procedure Bool.11 (#Attr.2, #Attr.3): ret Bool.24; procedure List.26 (List.152, List.153, List.154): - let List.493 : [C U64, C U64] = CallByName List.90 List.152 List.153 List.154; - let List.496 : U8 = 1i64; - let List.497 : U8 = GetTagId List.493; - let List.498 : Int1 = lowlevel Eq List.496 List.497; - if List.498 then - let List.155 : U64 = UnionAtIndex (Id 1) (Index 0) List.493; + let List.508 : [C U64, C U64] = CallByName List.91 List.152 List.153 List.154; + let List.511 : U8 = 1i64; + let List.512 : U8 = GetTagId List.508; + let List.513 : Int1 = lowlevel Eq List.511 List.512; + if List.513 then + let List.155 : U64 = UnionAtIndex (Id 1) (Index 0) List.508; ret List.155; else - let List.156 : U64 = UnionAtIndex (Id 0) (Index 0) List.493; + let List.156 : U64 = UnionAtIndex (Id 0) (Index 0) List.508; ret List.156; -procedure List.29 (List.294, List.295): - let List.492 : U64 = CallByName List.6 List.294; - let List.296 : U64 = CallByName Num.77 List.492 List.295; - let List.478 : List U8 = CallByName List.43 List.294 List.296; - ret List.478; +procedure List.29 (List.297, List.298): + let List.507 : U64 = CallByName List.6 List.297; + let List.299 : U64 = CallByName Num.77 List.507 List.298; + let List.493 : List U8 = CallByName List.43 List.297 List.299; + ret List.493; -procedure List.43 (List.292, List.293): - let List.490 : U64 = CallByName List.6 List.292; - let List.489 : U64 = CallByName Num.77 List.490 List.293; - let List.480 : {U64, U64} = Struct {List.293, List.489}; - let List.479 : List U8 = CallByName List.49 List.292 List.480; - ret List.479; +procedure List.43 (List.295, List.296): + let List.505 : U64 = CallByName List.6 List.295; + let List.504 : U64 = CallByName Num.77 List.505 List.296; + let List.495 : {U64, U64} = Struct {List.296, List.504}; + let List.494 : List U8 = CallByName List.49 List.295 List.495; + ret List.494; -procedure List.49 (List.366, List.367): - let List.487 : U64 = StructAtIndex 0 List.367; - let List.488 : U64 = 0i64; - let List.485 : Int1 = CallByName Bool.11 List.487 List.488; - if List.485 then - dec List.366; - let List.486 : List U8 = Array []; - ret List.486; +procedure List.49 (List.369, List.370): + let List.502 : U64 = StructAtIndex 0 List.370; + let List.503 : U64 = 0i64; + let List.500 : Int1 = CallByName Bool.11 List.502 List.503; + if List.500 then + dec List.369; + let List.501 : List U8 = Array []; + ret List.501; else - let List.482 : U64 = StructAtIndex 1 List.367; - let List.483 : U64 = StructAtIndex 0 List.367; - let List.481 : List U8 = CallByName List.72 List.366 List.482 List.483; - ret List.481; + let List.497 : U64 = StructAtIndex 1 List.370; + let List.498 : U64 = StructAtIndex 0 List.370; + let List.496 : List U8 = CallByName List.72 List.369 List.497 List.498; + ret List.496; procedure List.6 (#Attr.2): - let List.491 : U64 = lowlevel ListLen #Attr.2; - ret List.491; + let List.506 : U64 = lowlevel ListLen #Attr.2; + ret List.506; procedure List.66 (#Attr.2, #Attr.3): - let List.514 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.514; + let List.529 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.529; procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.484 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.484; - -procedure List.90 (List.426, List.427, List.428): - let List.500 : U64 = 0i64; - let List.501 : U64 = CallByName List.6 List.426; - let List.499 : [C U64, C U64] = CallByName List.91 List.426 List.427 List.428 List.500 List.501; + let List.499 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; ret List.499; -procedure List.91 (List.528, List.529, List.530, List.531, List.532): - joinpoint List.502 List.429 List.430 List.431 List.432 List.433: - let List.504 : Int1 = CallByName Num.22 List.432 List.433; - if List.504 then - let List.513 : U8 = CallByName List.66 List.429 List.432; - let List.505 : [C U64, C U64] = CallByName Test.4 List.430 List.513; - let List.510 : U8 = 1i64; - let List.511 : U8 = GetTagId List.505; - let List.512 : Int1 = lowlevel Eq List.510 List.511; - if List.512 then - let List.434 : U64 = UnionAtIndex (Id 1) (Index 0) List.505; - let List.508 : U64 = 1i64; - let List.507 : U64 = CallByName Num.19 List.432 List.508; - jump List.502 List.429 List.434 List.431 List.507 List.433; +procedure List.80 (List.543, List.544, List.545, List.546, List.547): + joinpoint List.517 List.432 List.433 List.434 List.435 List.436: + let List.519 : Int1 = CallByName Num.22 List.435 List.436; + if List.519 then + let List.528 : U8 = CallByName List.66 List.432 List.435; + let List.520 : [C U64, C U64] = CallByName Test.4 List.433 List.528; + let List.525 : U8 = 1i64; + let List.526 : U8 = GetTagId List.520; + let List.527 : Int1 = lowlevel Eq List.525 List.526; + if List.527 then + let List.437 : U64 = UnionAtIndex (Id 1) (Index 0) List.520; + let List.523 : U64 = 1i64; + let List.522 : U64 = CallByName Num.19 List.435 List.523; + jump List.517 List.432 List.437 List.434 List.522 List.436; else - let List.435 : U64 = UnionAtIndex (Id 0) (Index 0) List.505; - let List.509 : [C U64, C U64] = TagId(0) List.435; - ret List.509; + let List.438 : U64 = UnionAtIndex (Id 0) (Index 0) List.520; + let List.524 : [C U64, C U64] = TagId(0) List.438; + ret List.524; else - let List.503 : [C U64, C U64] = TagId(1) List.430; - ret List.503; + let List.518 : [C U64, C U64] = TagId(1) List.433; + ret List.518; in - jump List.502 List.528 List.529 List.530 List.531 List.532; + jump List.517 List.543 List.544 List.545 List.546 List.547; + +procedure List.91 (List.429, List.430, List.431): + let List.515 : U64 = 0i64; + let List.516 : U64 = CallByName List.6 List.429; + let List.514 : [C U64, C U64] = CallByName List.80 List.429 List.430 List.431 List.515 List.516; + ret List.514; procedure Num.19 (#Attr.2, #Attr.3): - let Num.258 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.258; + let Num.277 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.277; procedure Num.22 (#Attr.2, #Attr.3): - let Num.259 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; - ret Num.259; + let Num.278 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.278; procedure Num.77 (#Attr.2, #Attr.3): - let Num.257 : U64 = lowlevel NumSubSaturated #Attr.2 #Attr.3; - ret Num.257; + let Num.276 : U64 = lowlevel NumSubSaturated #Attr.2 #Attr.3; + ret Num.276; procedure Test.1 (Test.2): let Test.13 : U64 = 0i64; diff --git a/crates/compiler/test_mono/generated/call_function_in_empty_list.txt b/crates/compiler/test_mono/generated/call_function_in_empty_list.txt index cab62b26c7..bad512ffe1 100644 --- a/crates/compiler/test_mono/generated/call_function_in_empty_list.txt +++ b/crates/compiler/test_mono/generated/call_function_in_empty_list.txt @@ -1,7 +1,7 @@ procedure List.5 (#Attr.2, #Attr.3): - let List.478 : List {} = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.2 #Attr.3; + let List.493 : List {} = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.2 #Attr.3; decref #Attr.2; - ret List.478; + ret List.493; procedure Test.2 (Test.3): let Test.7 : {} = Struct {}; diff --git a/crates/compiler/test_mono/generated/call_function_in_empty_list_unbound.txt b/crates/compiler/test_mono/generated/call_function_in_empty_list_unbound.txt index 7a0e9bcf29..75bf5156de 100644 --- a/crates/compiler/test_mono/generated/call_function_in_empty_list_unbound.txt +++ b/crates/compiler/test_mono/generated/call_function_in_empty_list_unbound.txt @@ -1,7 +1,7 @@ procedure List.5 (#Attr.2, #Attr.3): - let List.478 : List [] = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.2 #Attr.3; + let List.493 : List [] = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.2 #Attr.3; decref #Attr.2; - ret List.478; + ret List.493; procedure Test.2 (Test.3): let Test.7 : {} = Struct {}; diff --git a/crates/compiler/test_mono/generated/choose_correct_recursion_var_under_record.txt b/crates/compiler/test_mono/generated/choose_correct_recursion_var_under_record.txt index b66fa51420..7a970d296a 100644 --- a/crates/compiler/test_mono/generated/choose_correct_recursion_var_under_record.txt +++ b/crates/compiler/test_mono/generated/choose_correct_recursion_var_under_record.txt @@ -3,50 +3,50 @@ procedure Bool.1 (): ret Bool.24; procedure List.2 (List.95, List.96): - let List.492 : U64 = CallByName List.6 List.95; - let List.488 : Int1 = CallByName Num.22 List.96 List.492; - if List.488 then - let List.490 : Str = CallByName List.66 List.95 List.96; - let List.489 : [C {}, C Str] = TagId(1) List.490; - ret List.489; + let List.507 : U64 = CallByName List.6 List.95; + let List.503 : Int1 = CallByName Num.22 List.96 List.507; + if List.503 then + let List.505 : Str = CallByName List.66 List.95 List.96; + let List.504 : [C {}, C Str] = TagId(1) List.505; + ret List.504; else - let List.487 : {} = Struct {}; - let List.486 : [C {}, C Str] = TagId(0) List.487; - ret List.486; + let List.502 : {} = Struct {}; + let List.501 : [C {}, C Str] = TagId(0) List.502; + ret List.501; procedure List.5 (#Attr.2, #Attr.3): - let List.494 : List Str = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.10 #Attr.3; - ret List.494; + let List.509 : List Str = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.10 #Attr.3; + ret List.509; procedure List.6 (#Attr.2): - let List.493 : U64 = lowlevel ListLen #Attr.2; - ret List.493; + let List.508 : U64 = lowlevel ListLen #Attr.2; + ret List.508; procedure List.66 (#Attr.2, #Attr.3): - let List.491 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.491; + let List.506 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.506; -procedure List.9 (List.283): - let List.485 : U64 = 0i64; - let List.478 : [C {}, C Str] = CallByName List.2 List.283 List.485; - let List.482 : U8 = 1i64; - let List.483 : U8 = GetTagId List.478; - let List.484 : Int1 = lowlevel Eq List.482 List.483; - if List.484 then - let List.284 : Str = UnionAtIndex (Id 1) (Index 0) List.478; - inc List.284; - dec List.478; - let List.479 : [C {}, C Str] = TagId(1) List.284; - ret List.479; +procedure List.9 (List.286): + let List.500 : U64 = 0i64; + let List.493 : [C {}, C Str] = CallByName List.2 List.286 List.500; + let List.497 : U8 = 1i64; + let List.498 : U8 = GetTagId List.493; + let List.499 : Int1 = lowlevel Eq List.497 List.498; + if List.499 then + let List.287 : Str = UnionAtIndex (Id 1) (Index 0) List.493; + inc List.287; + dec List.493; + let List.494 : [C {}, C Str] = TagId(1) List.287; + ret List.494; else - dec List.478; - let List.481 : {} = Struct {}; - let List.480 : [C {}, C Str] = TagId(0) List.481; - ret List.480; + dec List.493; + let List.496 : {} = Struct {}; + let List.495 : [C {}, C Str] = TagId(0) List.496; + ret List.495; procedure Num.22 (#Attr.2, #Attr.3): - let Num.256 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.275; procedure Result.5 (Result.12, Result.13): let Result.39 : U8 = 1i64; diff --git a/crates/compiler/test_mono/generated/choose_i128_layout.txt b/crates/compiler/test_mono/generated/choose_i128_layout.txt index 811ac35b19..b14d4d43fb 100644 --- a/crates/compiler/test_mono/generated/choose_i128_layout.txt +++ b/crates/compiler/test_mono/generated/choose_i128_layout.txt @@ -1,6 +1,6 @@ procedure Num.19 (#Attr.2, #Attr.3): - let Num.257 : I128 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.257; + let Num.276 : I128 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.276; procedure Test.0 (): let Test.6 : I128 = 18446744073709551616i64; diff --git a/crates/compiler/test_mono/generated/choose_u128_layout.txt b/crates/compiler/test_mono/generated/choose_u128_layout.txt index acf76c6677..4754f21bcd 100644 --- a/crates/compiler/test_mono/generated/choose_u128_layout.txt +++ b/crates/compiler/test_mono/generated/choose_u128_layout.txt @@ -1,6 +1,6 @@ procedure Num.19 (#Attr.2, #Attr.3): - let Num.256 : U128 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : U128 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.275; procedure Test.0 (): let Test.2 : U128 = 170141183460469231731687303715884105728u128; diff --git a/crates/compiler/test_mono/generated/choose_u64_layout.txt b/crates/compiler/test_mono/generated/choose_u64_layout.txt index 7a88a19504..21383cc40e 100644 --- a/crates/compiler/test_mono/generated/choose_u64_layout.txt +++ b/crates/compiler/test_mono/generated/choose_u64_layout.txt @@ -1,6 +1,6 @@ procedure Num.19 (#Attr.2, #Attr.3): - let Num.256 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.275; procedure Test.0 (): let Test.2 : U64 = 9999999999999999999i64; diff --git a/crates/compiler/test_mono/generated/closure_in_list.txt b/crates/compiler/test_mono/generated/closure_in_list.txt index c2300aec72..4caccac8fc 100644 --- a/crates/compiler/test_mono/generated/closure_in_list.txt +++ b/crates/compiler/test_mono/generated/closure_in_list.txt @@ -1,6 +1,6 @@ procedure List.6 (#Attr.2): - let List.478 : U64 = lowlevel ListLen #Attr.2; - ret List.478; + let List.493 : U64 = lowlevel ListLen #Attr.2; + ret List.493; procedure Test.1 (Test.5): let Test.2 : I64 = 41i64; diff --git a/crates/compiler/test_mono/generated/dict.txt b/crates/compiler/test_mono/generated/dict.txt index d1c66212c0..7311a98d3e 100644 --- a/crates/compiler/test_mono/generated/dict.txt +++ b/crates/compiler/test_mono/generated/dict.txt @@ -20,66 +20,66 @@ procedure Dict.4 (Dict.497): ret Dict.85; procedure List.11 (List.114, List.115): - let List.479 : List I8 = CallByName List.68 List.115; - let List.478 : List I8 = CallByName List.80 List.114 List.115 List.479; - ret List.478; + let List.494 : List I8 = CallByName List.68 List.115; + let List.493 : List I8 = CallByName List.81 List.114 List.115 List.494; + ret List.493; procedure List.11 (List.114, List.115): - let List.491 : List U64 = CallByName List.68 List.115; - let List.490 : List U64 = CallByName List.80 List.114 List.115 List.491; - ret List.490; + let List.506 : List U64 = CallByName List.68 List.115; + let List.505 : List U64 = CallByName List.81 List.114 List.115 List.506; + ret List.505; procedure List.68 (#Attr.2): - let List.489 : List I8 = lowlevel ListWithCapacity #Attr.2; - ret List.489; + let List.504 : List I8 = lowlevel ListWithCapacity #Attr.2; + ret List.504; procedure List.68 (#Attr.2): - let List.501 : List U64 = lowlevel ListWithCapacity #Attr.2; + let List.516 : List U64 = lowlevel ListWithCapacity #Attr.2; + ret List.516; + +procedure List.71 (#Attr.2, #Attr.3): + let List.501 : List I8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; ret List.501; procedure List.71 (#Attr.2, #Attr.3): - let List.486 : List I8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.486; + let List.513 : List U64 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.513; -procedure List.71 (#Attr.2, #Attr.3): - let List.498 : List U64 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.498; - -procedure List.80 (List.502, List.503, List.504): - joinpoint List.480 List.116 List.117 List.118: - let List.488 : U64 = 0i64; - let List.482 : Int1 = CallByName Num.24 List.117 List.488; - if List.482 then - let List.487 : U64 = 1i64; - let List.484 : U64 = CallByName Num.20 List.117 List.487; - let List.485 : List I8 = CallByName List.71 List.118 List.116; - jump List.480 List.116 List.484 List.485; +procedure List.81 (List.517, List.518, List.519): + joinpoint List.495 List.116 List.117 List.118: + let List.503 : U64 = 0i64; + let List.497 : Int1 = CallByName Num.24 List.117 List.503; + if List.497 then + let List.502 : U64 = 1i64; + let List.499 : U64 = CallByName Num.20 List.117 List.502; + let List.500 : List I8 = CallByName List.71 List.118 List.116; + jump List.495 List.116 List.499 List.500; else ret List.118; in - jump List.480 List.502 List.503 List.504; + jump List.495 List.517 List.518 List.519; -procedure List.80 (List.510, List.511, List.512): - joinpoint List.492 List.116 List.117 List.118: - let List.500 : U64 = 0i64; - let List.494 : Int1 = CallByName Num.24 List.117 List.500; - if List.494 then - let List.499 : U64 = 1i64; - let List.496 : U64 = CallByName Num.20 List.117 List.499; - let List.497 : List U64 = CallByName List.71 List.118 List.116; - jump List.492 List.116 List.496 List.497; +procedure List.81 (List.525, List.526, List.527): + joinpoint List.507 List.116 List.117 List.118: + let List.515 : U64 = 0i64; + let List.509 : Int1 = CallByName Num.24 List.117 List.515; + if List.509 then + let List.514 : U64 = 1i64; + let List.511 : U64 = CallByName Num.20 List.117 List.514; + let List.512 : List U64 = CallByName List.71 List.118 List.116; + jump List.507 List.116 List.511 List.512; else ret List.118; in - jump List.492 List.510 List.511 List.512; + jump List.507 List.525 List.526 List.527; procedure Num.20 (#Attr.2, #Attr.3): - let Num.257 : U64 = lowlevel NumSub #Attr.2 #Attr.3; - ret Num.257; + let Num.276 : U64 = lowlevel NumSub #Attr.2 #Attr.3; + ret Num.276; procedure Num.24 (#Attr.2, #Attr.3): - let Num.259 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; - ret Num.259; + let Num.278 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; + ret Num.278; procedure Test.0 (): let Test.3 : {} = Struct {}; diff --git a/crates/compiler/test_mono/generated/empty_list_of_function_type.txt b/crates/compiler/test_mono/generated/empty_list_of_function_type.txt index f1465173fb..0559214cf3 100644 --- a/crates/compiler/test_mono/generated/empty_list_of_function_type.txt +++ b/crates/compiler/test_mono/generated/empty_list_of_function_type.txt @@ -3,28 +3,28 @@ procedure Bool.1 (): ret Bool.23; procedure List.2 (List.95, List.96): - let List.484 : U64 = CallByName List.6 List.95; - let List.480 : Int1 = CallByName Num.22 List.96 List.484; - if List.480 then - let List.482 : {} = CallByName List.66 List.95 List.96; - let List.481 : [C {}, C {}] = TagId(1) List.482; - ret List.481; + let List.499 : U64 = CallByName List.6 List.95; + let List.495 : Int1 = CallByName Num.22 List.96 List.499; + if List.495 then + let List.497 : {} = CallByName List.66 List.95 List.96; + let List.496 : [C {}, C {}] = TagId(1) List.497; + ret List.496; else - let List.479 : {} = Struct {}; - let List.478 : [C {}, C {}] = TagId(0) List.479; - ret List.478; + let List.494 : {} = Struct {}; + let List.493 : [C {}, C {}] = TagId(0) List.494; + ret List.493; procedure List.6 (#Attr.2): - let List.485 : U64 = lowlevel ListLen #Attr.2; - ret List.485; + let List.500 : U64 = lowlevel ListLen #Attr.2; + ret List.500; procedure List.66 (#Attr.2, #Attr.3): - let List.483 : {} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.483; + let List.498 : {} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.498; procedure Num.22 (#Attr.2, #Attr.3): - let Num.256 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.275; procedure Test.2 (Test.5): let Test.17 : Str = "bar"; diff --git a/crates/compiler/test_mono/generated/encode.txt b/crates/compiler/test_mono/generated/encode.txt index eae2acc8ad..76e645ff06 100644 --- a/crates/compiler/test_mono/generated/encode.txt +++ b/crates/compiler/test_mono/generated/encode.txt @@ -1,16 +1,16 @@ procedure List.4 (List.106, List.107): - let List.481 : U64 = 1i64; - let List.479 : List U8 = CallByName List.70 List.106 List.481; - let List.478 : List U8 = CallByName List.71 List.479 List.107; - ret List.478; + let List.496 : U64 = 1i64; + let List.494 : List U8 = CallByName List.70 List.106 List.496; + let List.493 : List U8 = CallByName List.71 List.494 List.107; + ret List.493; procedure List.70 (#Attr.2, #Attr.3): - let List.482 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.482; + let List.497 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.497; procedure List.71 (#Attr.2, #Attr.3): - let List.480 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.480; + let List.495 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.495; procedure Test.23 (Test.24, Test.35, Test.22): let Test.37 : List U8 = CallByName List.4 Test.24 Test.22; diff --git a/crates/compiler/test_mono/generated/encode_derived_nested_record_string.txt b/crates/compiler/test_mono/generated/encode_derived_nested_record_string.txt index 0c7233dd44..a0bca139eb 100644 --- a/crates/compiler/test_mono/generated/encode_derived_nested_record_string.txt +++ b/crates/compiler/test_mono/generated/encode_derived_nested_record_string.txt @@ -44,7 +44,7 @@ procedure Encode.23 (Encode.94, Encode.102, Encode.96): ret Encode.106; procedure Encode.23 (Encode.94, Encode.102, Encode.96): - let Encode.113 : List U8 = CallByName Json.112 Encode.94 Encode.96 Encode.102; + let Encode.113 : List U8 = CallByName Json.115 Encode.94 Encode.96 Encode.102; ret Encode.113; procedure Encode.23 (Encode.94, Encode.102, Encode.96): @@ -52,11 +52,11 @@ procedure Encode.23 (Encode.94, Encode.102, Encode.96): ret Encode.115; procedure Encode.23 (Encode.94, Encode.102, Encode.96): - let Encode.125 : List U8 = CallByName Json.112 Encode.94 Encode.96 Encode.102; + let Encode.125 : List U8 = CallByName Json.115 Encode.94 Encode.96 Encode.102; ret Encode.125; procedure Encode.23 (Encode.94, Encode.102, Encode.96): - let Encode.128 : List U8 = CallByName Json.96 Encode.94 Encode.96 Encode.102; + let Encode.128 : List U8 = CallByName Json.99 Encode.94 Encode.96 Encode.102; ret Encode.128; procedure Encode.25 (Encode.100, Encode.101): @@ -66,257 +66,257 @@ procedure Encode.25 (Encode.100, Encode.101): ret Encode.103; procedure Json.1 (): - let Json.396 : {} = Struct {}; - ret Json.396; + let Json.425 : {} = Struct {}; + ret Json.425; -procedure Json.112 (Json.113, Json.399, Json.111): - let Json.432 : I64 = 123i64; - let Json.431 : U8 = CallByName Num.125 Json.432; - let Json.115 : List U8 = CallByName List.4 Json.113 Json.431; - let Json.430 : U64 = CallByName List.6 Json.111; - let Json.407 : {List U8, U64} = Struct {Json.115, Json.430}; - let Json.408 : {} = Struct {}; - let Json.406 : {List U8, U64} = CallByName List.18 Json.111 Json.407 Json.408; - dec Json.111; - let Json.117 : List U8 = StructAtIndex 0 Json.406; - inc Json.117; - dec Json.406; - let Json.405 : I64 = 125i64; - let Json.404 : U8 = CallByName Num.125 Json.405; - let Json.403 : List U8 = CallByName List.4 Json.117 Json.404; - ret Json.403; +procedure Json.115 (Json.116, Json.428, Json.114): + let Json.461 : I64 = 123i64; + let Json.460 : U8 = CallByName Num.127 Json.461; + let Json.118 : List U8 = CallByName List.4 Json.116 Json.460; + let Json.459 : U64 = CallByName List.6 Json.114; + let Json.436 : {List U8, U64} = Struct {Json.118, Json.459}; + let Json.437 : {} = Struct {}; + let Json.435 : {List U8, U64} = CallByName List.18 Json.114 Json.436 Json.437; + dec Json.114; + let Json.120 : List U8 = StructAtIndex 0 Json.435; + inc Json.120; + dec Json.435; + let Json.434 : I64 = 125i64; + let Json.433 : U8 = CallByName Num.127 Json.434; + let Json.432 : List U8 = CallByName List.4 Json.120 Json.433; + ret Json.432; -procedure Json.112 (Json.113, Json.399, Json.111): - let Json.472 : I64 = 123i64; - let Json.471 : U8 = CallByName Num.125 Json.472; - let Json.115 : List U8 = CallByName List.4 Json.113 Json.471; - let Json.470 : U64 = CallByName List.6 Json.111; - let Json.447 : {List U8, U64} = Struct {Json.115, Json.470}; +procedure Json.115 (Json.116, Json.428, Json.114): + let Json.501 : I64 = 123i64; + let Json.500 : U8 = CallByName Num.127 Json.501; + let Json.118 : List U8 = CallByName List.4 Json.116 Json.500; + let Json.499 : U64 = CallByName List.6 Json.114; + let Json.476 : {List U8, U64} = Struct {Json.118, Json.499}; + let Json.477 : {} = Struct {}; + let Json.475 : {List U8, U64} = CallByName List.18 Json.114 Json.476 Json.477; + dec Json.114; + let Json.120 : List U8 = StructAtIndex 0 Json.475; + inc Json.120; + dec Json.475; + let Json.474 : I64 = 125i64; + let Json.473 : U8 = CallByName Num.127 Json.474; + let Json.472 : List U8 = CallByName List.4 Json.120 Json.473; + ret Json.472; + +procedure Json.117 (Json.430, Json.431): + let Json.123 : Str = StructAtIndex 0 Json.431; + inc Json.123; + let Json.124 : Str = StructAtIndex 1 Json.431; + inc Json.124; + dec Json.431; + let Json.121 : List U8 = StructAtIndex 0 Json.430; + inc Json.121; + let Json.122 : U64 = StructAtIndex 1 Json.430; + dec Json.430; + let Json.458 : I64 = 34i64; + let Json.457 : U8 = CallByName Num.127 Json.458; + let Json.455 : List U8 = CallByName List.4 Json.121 Json.457; + let Json.456 : List U8 = CallByName Str.12 Json.123; + let Json.452 : List U8 = CallByName List.8 Json.455 Json.456; + let Json.454 : I64 = 34i64; + let Json.453 : U8 = CallByName Num.127 Json.454; + let Json.449 : List U8 = CallByName List.4 Json.452 Json.453; + let Json.451 : I64 = 58i64; + let Json.450 : U8 = CallByName Num.127 Json.451; + let Json.447 : List U8 = CallByName List.4 Json.449 Json.450; let Json.448 : {} = Struct {}; - let Json.446 : {List U8, U64} = CallByName List.18 Json.111 Json.447 Json.448; - dec Json.111; - let Json.117 : List U8 = StructAtIndex 0 Json.446; - inc Json.117; - dec Json.446; - let Json.445 : I64 = 125i64; - let Json.444 : U8 = CallByName Num.125 Json.445; - let Json.443 : List U8 = CallByName List.4 Json.117 Json.444; - ret Json.443; - -procedure Json.114 (Json.401, Json.402): - let Json.120 : Str = StructAtIndex 0 Json.402; - inc Json.120; - let Json.121 : Str = StructAtIndex 1 Json.402; - inc Json.121; - dec Json.402; - let Json.118 : List U8 = StructAtIndex 0 Json.401; - inc Json.118; - let Json.119 : U64 = StructAtIndex 1 Json.401; - dec Json.401; - let Json.429 : I64 = 34i64; - let Json.428 : U8 = CallByName Num.125 Json.429; - let Json.426 : List U8 = CallByName List.4 Json.118 Json.428; - let Json.427 : List U8 = CallByName Str.12 Json.120; - let Json.423 : List U8 = CallByName List.8 Json.426 Json.427; - let Json.425 : I64 = 34i64; - let Json.424 : U8 = CallByName Num.125 Json.425; - let Json.420 : List U8 = CallByName List.4 Json.423 Json.424; - let Json.422 : I64 = 58i64; - let Json.421 : U8 = CallByName Num.125 Json.422; - let Json.418 : List U8 = CallByName List.4 Json.420 Json.421; - let Json.419 : {} = Struct {}; - let Json.122 : List U8 = CallByName Encode.23 Json.418 Json.121 Json.419; - joinpoint Json.413 Json.123: - let Json.411 : U64 = 1i64; - let Json.410 : U64 = CallByName Num.20 Json.119 Json.411; - let Json.409 : {List U8, U64} = Struct {Json.123, Json.410}; - ret Json.409; + let Json.125 : List U8 = CallByName Encode.23 Json.447 Json.124 Json.448; + joinpoint Json.442 Json.126: + let Json.440 : U64 = 1i64; + let Json.439 : U64 = CallByName Num.20 Json.122 Json.440; + let Json.438 : {List U8, U64} = Struct {Json.126, Json.439}; + ret Json.438; in - let Json.417 : U64 = 1i64; - let Json.414 : Int1 = CallByName Num.24 Json.119 Json.417; - if Json.414 then - let Json.416 : I64 = 44i64; - let Json.415 : U8 = CallByName Num.125 Json.416; - let Json.412 : List U8 = CallByName List.4 Json.122 Json.415; - jump Json.413 Json.412; + let Json.446 : U64 = 1i64; + let Json.443 : Int1 = CallByName Num.24 Json.122 Json.446; + if Json.443 then + let Json.445 : I64 = 44i64; + let Json.444 : U8 = CallByName Num.127 Json.445; + let Json.441 : List U8 = CallByName List.4 Json.125 Json.444; + jump Json.442 Json.441; else - jump Json.413 Json.122; + jump Json.442 Json.125; -procedure Json.114 (Json.401, Json.402): - let Json.120 : Str = StructAtIndex 0 Json.402; - inc Json.120; - let Json.121 : Str = StructAtIndex 1 Json.402; +procedure Json.117 (Json.430, Json.431): + let Json.123 : Str = StructAtIndex 0 Json.431; + inc Json.123; + let Json.124 : Str = StructAtIndex 1 Json.431; + inc Json.124; + dec Json.431; + let Json.121 : List U8 = StructAtIndex 0 Json.430; inc Json.121; - dec Json.402; - let Json.118 : List U8 = StructAtIndex 0 Json.401; - inc Json.118; - let Json.119 : U64 = StructAtIndex 1 Json.401; - dec Json.401; - let Json.469 : I64 = 34i64; - let Json.468 : U8 = CallByName Num.125 Json.469; - let Json.466 : List U8 = CallByName List.4 Json.118 Json.468; - let Json.467 : List U8 = CallByName Str.12 Json.120; - let Json.463 : List U8 = CallByName List.8 Json.466 Json.467; - let Json.465 : I64 = 34i64; - let Json.464 : U8 = CallByName Num.125 Json.465; - let Json.460 : List U8 = CallByName List.4 Json.463 Json.464; - let Json.462 : I64 = 58i64; - let Json.461 : U8 = CallByName Num.125 Json.462; - let Json.458 : List U8 = CallByName List.4 Json.460 Json.461; - let Json.459 : {} = Struct {}; - let Json.122 : List U8 = CallByName Encode.23 Json.458 Json.121 Json.459; - joinpoint Json.453 Json.123: - let Json.451 : U64 = 1i64; - let Json.450 : U64 = CallByName Num.20 Json.119 Json.451; - let Json.449 : {List U8, U64} = Struct {Json.123, Json.450}; - ret Json.449; + let Json.122 : U64 = StructAtIndex 1 Json.430; + dec Json.430; + let Json.498 : I64 = 34i64; + let Json.497 : U8 = CallByName Num.127 Json.498; + let Json.495 : List U8 = CallByName List.4 Json.121 Json.497; + let Json.496 : List U8 = CallByName Str.12 Json.123; + let Json.492 : List U8 = CallByName List.8 Json.495 Json.496; + let Json.494 : I64 = 34i64; + let Json.493 : U8 = CallByName Num.127 Json.494; + let Json.489 : List U8 = CallByName List.4 Json.492 Json.493; + let Json.491 : I64 = 58i64; + let Json.490 : U8 = CallByName Num.127 Json.491; + let Json.487 : List U8 = CallByName List.4 Json.489 Json.490; + let Json.488 : {} = Struct {}; + let Json.125 : List U8 = CallByName Encode.23 Json.487 Json.124 Json.488; + joinpoint Json.482 Json.126: + let Json.480 : U64 = 1i64; + let Json.479 : U64 = CallByName Num.20 Json.122 Json.480; + let Json.478 : {List U8, U64} = Struct {Json.126, Json.479}; + ret Json.478; in - let Json.457 : U64 = 1i64; - let Json.454 : Int1 = CallByName Num.24 Json.119 Json.457; - if Json.454 then - let Json.456 : I64 = 44i64; - let Json.455 : U8 = CallByName Num.125 Json.456; - let Json.452 : List U8 = CallByName List.4 Json.122 Json.455; - jump Json.453 Json.452; + let Json.486 : U64 = 1i64; + let Json.483 : Int1 = CallByName Num.24 Json.122 Json.486; + if Json.483 then + let Json.485 : I64 = 44i64; + let Json.484 : U8 = CallByName Num.127 Json.485; + let Json.481 : List U8 = CallByName List.4 Json.125 Json.484; + jump Json.482 Json.481; else - jump Json.453 Json.122; + jump Json.482 Json.125; -procedure Json.18 (Json.95): - let Json.473 : Str = CallByName Encode.22 Json.95; - ret Json.473; +procedure Json.18 (Json.98): + let Json.502 : Str = CallByName Encode.22 Json.98; + ret Json.502; -procedure Json.20 (Json.111): - let Json.397 : List {Str, Str} = CallByName Encode.22 Json.111; - ret Json.397; +procedure Json.20 (Json.114): + let Json.426 : List {Str, Str} = CallByName Encode.22 Json.114; + ret Json.426; -procedure Json.20 (Json.111): - let Json.439 : List {Str, Str} = CallByName Encode.22 Json.111; - ret Json.439; +procedure Json.20 (Json.114): + let Json.468 : List {Str, Str} = CallByName Encode.22 Json.114; + ret Json.468; -procedure Json.96 (Json.97, Json.475, Json.95): - let Json.484 : I64 = 34i64; - let Json.483 : U8 = CallByName Num.125 Json.484; - let Json.481 : List U8 = CallByName List.4 Json.97 Json.483; - let Json.482 : List U8 = CallByName Str.12 Json.95; - let Json.478 : List U8 = CallByName List.8 Json.481 Json.482; - let Json.480 : I64 = 34i64; - let Json.479 : U8 = CallByName Num.125 Json.480; - let Json.477 : List U8 = CallByName List.4 Json.478 Json.479; - ret Json.477; +procedure Json.99 (Json.100, Json.504, Json.98): + let Json.513 : I64 = 34i64; + let Json.512 : U8 = CallByName Num.127 Json.513; + let Json.510 : List U8 = CallByName List.4 Json.100 Json.512; + let Json.511 : List U8 = CallByName Str.12 Json.98; + let Json.507 : List U8 = CallByName List.8 Json.510 Json.511; + let Json.509 : I64 = 34i64; + let Json.508 : U8 = CallByName Num.127 Json.509; + let Json.506 : List U8 = CallByName List.4 Json.507 Json.508; + ret Json.506; procedure List.138 (List.139, List.140, List.137): - let List.519 : {List U8, U64} = CallByName Json.114 List.139 List.140; - ret List.519; + let List.534 : {List U8, U64} = CallByName Json.117 List.139 List.140; + ret List.534; procedure List.138 (List.139, List.140, List.137): - let List.592 : {List U8, U64} = CallByName Json.114 List.139 List.140; - ret List.592; + let List.607 : {List U8, U64} = CallByName Json.117 List.139 List.140; + ret List.607; procedure List.18 (List.135, List.136, List.137): - let List.500 : {List U8, U64} = CallByName List.90 List.135 List.136 List.137; - ret List.500; + let List.515 : {List U8, U64} = CallByName List.91 List.135 List.136 List.137; + ret List.515; procedure List.18 (List.135, List.136, List.137): - let List.573 : {List U8, U64} = CallByName List.90 List.135 List.136 List.137; - ret List.573; + let List.588 : {List U8, U64} = CallByName List.91 List.135 List.136 List.137; + ret List.588; procedure List.4 (List.106, List.107): - let List.572 : U64 = 1i64; - let List.571 : List U8 = CallByName List.70 List.106 List.572; - let List.570 : List U8 = CallByName List.71 List.571 List.107; - ret List.570; + let List.587 : U64 = 1i64; + let List.586 : List U8 = CallByName List.70 List.106 List.587; + let List.585 : List U8 = CallByName List.71 List.586 List.107; + ret List.585; procedure List.6 (#Attr.2): - let List.478 : U64 = lowlevel ListLen #Attr.2; - ret List.478; + let List.493 : U64 = lowlevel ListLen #Attr.2; + ret List.493; procedure List.6 (#Attr.2): - let List.521 : U64 = lowlevel ListLen #Attr.2; - ret List.521; + let List.536 : U64 = lowlevel ListLen #Attr.2; + ret List.536; procedure List.6 (#Attr.2): - let List.595 : U64 = lowlevel ListLen #Attr.2; - ret List.595; + let List.610 : U64 = lowlevel ListLen #Attr.2; + ret List.610; procedure List.66 (#Attr.2, #Attr.3): - let List.516 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.516; + let List.531 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.531; procedure List.66 (#Attr.2, #Attr.3): - let List.589 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.589; + let List.604 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.604; procedure List.70 (#Attr.2, #Attr.3): - let List.551 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.551; + let List.566 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.566; procedure List.71 (#Attr.2, #Attr.3): - let List.549 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.549; + let List.564 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.564; procedure List.8 (#Attr.2, #Attr.3): - let List.594 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.594; + let List.609 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.609; -procedure List.90 (List.426, List.427, List.428): - let List.504 : U64 = 0i64; - let List.505 : U64 = CallByName List.6 List.426; - let List.503 : {List U8, U64} = CallByName List.91 List.426 List.427 List.428 List.504 List.505; - ret List.503; - -procedure List.90 (List.426, List.427, List.428): - let List.577 : U64 = 0i64; - let List.578 : U64 = CallByName List.6 List.426; - let List.576 : {List U8, U64} = CallByName List.91 List.426 List.427 List.428 List.577 List.578; - ret List.576; - -procedure List.91 (List.531, List.532, List.533, List.534, List.535): - joinpoint List.506 List.429 List.430 List.431 List.432 List.433: - let List.508 : Int1 = CallByName Num.22 List.432 List.433; - if List.508 then - let List.515 : {Str, Str} = CallByName List.66 List.429 List.432; - let List.509 : {List U8, U64} = CallByName List.138 List.430 List.515 List.431; - let List.512 : U64 = 1i64; - let List.511 : U64 = CallByName Num.19 List.432 List.512; - jump List.506 List.429 List.509 List.431 List.511 List.433; +procedure List.80 (List.546, List.547, List.548, List.549, List.550): + joinpoint List.521 List.432 List.433 List.434 List.435 List.436: + let List.523 : Int1 = CallByName Num.22 List.435 List.436; + if List.523 then + let List.530 : {Str, Str} = CallByName List.66 List.432 List.435; + let List.524 : {List U8, U64} = CallByName List.138 List.433 List.530 List.434; + let List.527 : U64 = 1i64; + let List.526 : U64 = CallByName Num.19 List.435 List.527; + jump List.521 List.432 List.524 List.434 List.526 List.436; else - ret List.430; + ret List.433; in - jump List.506 List.531 List.532 List.533 List.534 List.535; + jump List.521 List.546 List.547 List.548 List.549 List.550; -procedure List.91 (List.605, List.606, List.607, List.608, List.609): - joinpoint List.579 List.429 List.430 List.431 List.432 List.433: - let List.581 : Int1 = CallByName Num.22 List.432 List.433; - if List.581 then - let List.588 : {Str, Str} = CallByName List.66 List.429 List.432; - let List.582 : {List U8, U64} = CallByName List.138 List.430 List.588 List.431; - let List.585 : U64 = 1i64; - let List.584 : U64 = CallByName Num.19 List.432 List.585; - jump List.579 List.429 List.582 List.431 List.584 List.433; +procedure List.80 (List.620, List.621, List.622, List.623, List.624): + joinpoint List.594 List.432 List.433 List.434 List.435 List.436: + let List.596 : Int1 = CallByName Num.22 List.435 List.436; + if List.596 then + let List.603 : {Str, Str} = CallByName List.66 List.432 List.435; + let List.597 : {List U8, U64} = CallByName List.138 List.433 List.603 List.434; + let List.600 : U64 = 1i64; + let List.599 : U64 = CallByName Num.19 List.435 List.600; + jump List.594 List.432 List.597 List.434 List.599 List.436; else - ret List.430; + ret List.433; in - jump List.579 List.605 List.606 List.607 List.608 List.609; + jump List.594 List.620 List.621 List.622 List.623 List.624; -procedure Num.125 (#Attr.2): - let Num.282 : U8 = lowlevel NumIntCast #Attr.2; - ret Num.282; +procedure List.91 (List.429, List.430, List.431): + let List.519 : U64 = 0i64; + let List.520 : U64 = CallByName List.6 List.429; + let List.518 : {List U8, U64} = CallByName List.80 List.429 List.430 List.431 List.519 List.520; + ret List.518; + +procedure List.91 (List.429, List.430, List.431): + let List.592 : U64 = 0i64; + let List.593 : U64 = CallByName List.6 List.429; + let List.591 : {List U8, U64} = CallByName List.80 List.429 List.430 List.431 List.592 List.593; + ret List.591; + +procedure Num.127 (#Attr.2): + let Num.301 : U8 = lowlevel NumIntCast #Attr.2; + ret Num.301; procedure Num.19 (#Attr.2, #Attr.3): - let Num.285 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.285; + let Num.304 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.304; procedure Num.20 (#Attr.2, #Attr.3): - let Num.283 : U64 = lowlevel NumSub #Attr.2 #Attr.3; - ret Num.283; + let Num.302 : U64 = lowlevel NumSub #Attr.2 #Attr.3; + ret Num.302; procedure Num.22 (#Attr.2, #Attr.3): - let Num.286 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; - ret Num.286; + let Num.305 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.305; procedure Num.24 (#Attr.2, #Attr.3): - let Num.284 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; - ret Num.284; + let Num.303 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; + ret Num.303; procedure Str.12 (#Attr.2): let Str.282 : List U8 = lowlevel StrToUtf8 #Attr.2; diff --git a/crates/compiler/test_mono/generated/encode_derived_record_one_field_string.txt b/crates/compiler/test_mono/generated/encode_derived_record_one_field_string.txt index 02d3f30240..efb2d76329 100644 --- a/crates/compiler/test_mono/generated/encode_derived_record_one_field_string.txt +++ b/crates/compiler/test_mono/generated/encode_derived_record_one_field_string.txt @@ -25,11 +25,11 @@ procedure Encode.23 (Encode.94, Encode.102, Encode.96): ret Encode.106; procedure Encode.23 (Encode.94, Encode.102, Encode.96): - let Encode.113 : List U8 = CallByName Json.112 Encode.94 Encode.96 Encode.102; + let Encode.113 : List U8 = CallByName Json.115 Encode.94 Encode.96 Encode.102; ret Encode.113; procedure Encode.23 (Encode.94, Encode.102, Encode.96): - let Encode.116 : List U8 = CallByName Json.96 Encode.94 Encode.96 Encode.102; + let Encode.116 : List U8 = CallByName Json.99 Encode.94 Encode.96 Encode.102; ret Encode.116; procedure Encode.25 (Encode.100, Encode.101): @@ -39,161 +39,161 @@ procedure Encode.25 (Encode.100, Encode.101): ret Encode.103; procedure Json.1 (): - let Json.396 : {} = Struct {}; - ret Json.396; + let Json.425 : {} = Struct {}; + ret Json.425; -procedure Json.112 (Json.113, Json.399, Json.111): - let Json.432 : I64 = 123i64; - let Json.431 : U8 = CallByName Num.125 Json.432; - let Json.115 : List U8 = CallByName List.4 Json.113 Json.431; - let Json.430 : U64 = CallByName List.6 Json.111; - let Json.407 : {List U8, U64} = Struct {Json.115, Json.430}; - let Json.408 : {} = Struct {}; - let Json.406 : {List U8, U64} = CallByName List.18 Json.111 Json.407 Json.408; - dec Json.111; - let Json.117 : List U8 = StructAtIndex 0 Json.406; - inc Json.117; - dec Json.406; - let Json.405 : I64 = 125i64; - let Json.404 : U8 = CallByName Num.125 Json.405; - let Json.403 : List U8 = CallByName List.4 Json.117 Json.404; - ret Json.403; - -procedure Json.114 (Json.401, Json.402): - let Json.120 : Str = StructAtIndex 0 Json.402; +procedure Json.115 (Json.116, Json.428, Json.114): + let Json.461 : I64 = 123i64; + let Json.460 : U8 = CallByName Num.127 Json.461; + let Json.118 : List U8 = CallByName List.4 Json.116 Json.460; + let Json.459 : U64 = CallByName List.6 Json.114; + let Json.436 : {List U8, U64} = Struct {Json.118, Json.459}; + let Json.437 : {} = Struct {}; + let Json.435 : {List U8, U64} = CallByName List.18 Json.114 Json.436 Json.437; + dec Json.114; + let Json.120 : List U8 = StructAtIndex 0 Json.435; inc Json.120; - let Json.121 : Str = StructAtIndex 1 Json.402; + dec Json.435; + let Json.434 : I64 = 125i64; + let Json.433 : U8 = CallByName Num.127 Json.434; + let Json.432 : List U8 = CallByName List.4 Json.120 Json.433; + ret Json.432; + +procedure Json.117 (Json.430, Json.431): + let Json.123 : Str = StructAtIndex 0 Json.431; + inc Json.123; + let Json.124 : Str = StructAtIndex 1 Json.431; + inc Json.124; + dec Json.431; + let Json.121 : List U8 = StructAtIndex 0 Json.430; inc Json.121; - dec Json.402; - let Json.118 : List U8 = StructAtIndex 0 Json.401; - inc Json.118; - let Json.119 : U64 = StructAtIndex 1 Json.401; - dec Json.401; - let Json.429 : I64 = 34i64; - let Json.428 : U8 = CallByName Num.125 Json.429; - let Json.426 : List U8 = CallByName List.4 Json.118 Json.428; - let Json.427 : List U8 = CallByName Str.12 Json.120; - let Json.423 : List U8 = CallByName List.8 Json.426 Json.427; - let Json.425 : I64 = 34i64; - let Json.424 : U8 = CallByName Num.125 Json.425; - let Json.420 : List U8 = CallByName List.4 Json.423 Json.424; - let Json.422 : I64 = 58i64; - let Json.421 : U8 = CallByName Num.125 Json.422; - let Json.418 : List U8 = CallByName List.4 Json.420 Json.421; - let Json.419 : {} = Struct {}; - let Json.122 : List U8 = CallByName Encode.23 Json.418 Json.121 Json.419; - joinpoint Json.413 Json.123: - let Json.411 : U64 = 1i64; - let Json.410 : U64 = CallByName Num.20 Json.119 Json.411; - let Json.409 : {List U8, U64} = Struct {Json.123, Json.410}; - ret Json.409; + let Json.122 : U64 = StructAtIndex 1 Json.430; + dec Json.430; + let Json.458 : I64 = 34i64; + let Json.457 : U8 = CallByName Num.127 Json.458; + let Json.455 : List U8 = CallByName List.4 Json.121 Json.457; + let Json.456 : List U8 = CallByName Str.12 Json.123; + let Json.452 : List U8 = CallByName List.8 Json.455 Json.456; + let Json.454 : I64 = 34i64; + let Json.453 : U8 = CallByName Num.127 Json.454; + let Json.449 : List U8 = CallByName List.4 Json.452 Json.453; + let Json.451 : I64 = 58i64; + let Json.450 : U8 = CallByName Num.127 Json.451; + let Json.447 : List U8 = CallByName List.4 Json.449 Json.450; + let Json.448 : {} = Struct {}; + let Json.125 : List U8 = CallByName Encode.23 Json.447 Json.124 Json.448; + joinpoint Json.442 Json.126: + let Json.440 : U64 = 1i64; + let Json.439 : U64 = CallByName Num.20 Json.122 Json.440; + let Json.438 : {List U8, U64} = Struct {Json.126, Json.439}; + ret Json.438; in - let Json.417 : U64 = 1i64; - let Json.414 : Int1 = CallByName Num.24 Json.119 Json.417; - if Json.414 then - let Json.416 : I64 = 44i64; - let Json.415 : U8 = CallByName Num.125 Json.416; - let Json.412 : List U8 = CallByName List.4 Json.122 Json.415; - jump Json.413 Json.412; + let Json.446 : U64 = 1i64; + let Json.443 : Int1 = CallByName Num.24 Json.122 Json.446; + if Json.443 then + let Json.445 : I64 = 44i64; + let Json.444 : U8 = CallByName Num.127 Json.445; + let Json.441 : List U8 = CallByName List.4 Json.125 Json.444; + jump Json.442 Json.441; else - jump Json.413 Json.122; + jump Json.442 Json.125; -procedure Json.18 (Json.95): - let Json.433 : Str = CallByName Encode.22 Json.95; - ret Json.433; +procedure Json.18 (Json.98): + let Json.462 : Str = CallByName Encode.22 Json.98; + ret Json.462; -procedure Json.20 (Json.111): - let Json.397 : List {Str, Str} = CallByName Encode.22 Json.111; - ret Json.397; +procedure Json.20 (Json.114): + let Json.426 : List {Str, Str} = CallByName Encode.22 Json.114; + ret Json.426; -procedure Json.96 (Json.97, Json.435, Json.95): - let Json.444 : I64 = 34i64; - let Json.443 : U8 = CallByName Num.125 Json.444; - let Json.441 : List U8 = CallByName List.4 Json.97 Json.443; - let Json.442 : List U8 = CallByName Str.12 Json.95; - let Json.438 : List U8 = CallByName List.8 Json.441 Json.442; - let Json.440 : I64 = 34i64; - let Json.439 : U8 = CallByName Num.125 Json.440; - let Json.437 : List U8 = CallByName List.4 Json.438 Json.439; - ret Json.437; +procedure Json.99 (Json.100, Json.464, Json.98): + let Json.473 : I64 = 34i64; + let Json.472 : U8 = CallByName Num.127 Json.473; + let Json.470 : List U8 = CallByName List.4 Json.100 Json.472; + let Json.471 : List U8 = CallByName Str.12 Json.98; + let Json.467 : List U8 = CallByName List.8 Json.470 Json.471; + let Json.469 : I64 = 34i64; + let Json.468 : U8 = CallByName Num.127 Json.469; + let Json.466 : List U8 = CallByName List.4 Json.467 Json.468; + ret Json.466; procedure List.138 (List.139, List.140, List.137): - let List.525 : {List U8, U64} = CallByName Json.114 List.139 List.140; - ret List.525; + let List.540 : {List U8, U64} = CallByName Json.117 List.139 List.140; + ret List.540; procedure List.18 (List.135, List.136, List.137): - let List.506 : {List U8, U64} = CallByName List.90 List.135 List.136 List.137; - ret List.506; + let List.521 : {List U8, U64} = CallByName List.91 List.135 List.136 List.137; + ret List.521; procedure List.4 (List.106, List.107): - let List.505 : U64 = 1i64; - let List.504 : List U8 = CallByName List.70 List.106 List.505; - let List.503 : List U8 = CallByName List.71 List.504 List.107; - ret List.503; + let List.520 : U64 = 1i64; + let List.519 : List U8 = CallByName List.70 List.106 List.520; + let List.518 : List U8 = CallByName List.71 List.519 List.107; + ret List.518; procedure List.6 (#Attr.2): - let List.478 : U64 = lowlevel ListLen #Attr.2; - ret List.478; + let List.493 : U64 = lowlevel ListLen #Attr.2; + ret List.493; procedure List.6 (#Attr.2): - let List.528 : U64 = lowlevel ListLen #Attr.2; - ret List.528; + let List.543 : U64 = lowlevel ListLen #Attr.2; + ret List.543; procedure List.66 (#Attr.2, #Attr.3): - let List.522 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.522; + let List.537 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.537; procedure List.70 (#Attr.2, #Attr.3): - let List.484 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.484; + let List.499 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.499; procedure List.71 (#Attr.2, #Attr.3): - let List.482 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.482; + let List.497 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.497; procedure List.8 (#Attr.2, #Attr.3): - let List.527 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.527; + let List.542 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.542; -procedure List.90 (List.426, List.427, List.428): - let List.510 : U64 = 0i64; - let List.511 : U64 = CallByName List.6 List.426; - let List.509 : {List U8, U64} = CallByName List.91 List.426 List.427 List.428 List.510 List.511; - ret List.509; - -procedure List.91 (List.538, List.539, List.540, List.541, List.542): - joinpoint List.512 List.429 List.430 List.431 List.432 List.433: - let List.514 : Int1 = CallByName Num.22 List.432 List.433; - if List.514 then - let List.521 : {Str, Str} = CallByName List.66 List.429 List.432; - let List.515 : {List U8, U64} = CallByName List.138 List.430 List.521 List.431; - let List.518 : U64 = 1i64; - let List.517 : U64 = CallByName Num.19 List.432 List.518; - jump List.512 List.429 List.515 List.431 List.517 List.433; +procedure List.80 (List.553, List.554, List.555, List.556, List.557): + joinpoint List.527 List.432 List.433 List.434 List.435 List.436: + let List.529 : Int1 = CallByName Num.22 List.435 List.436; + if List.529 then + let List.536 : {Str, Str} = CallByName List.66 List.432 List.435; + let List.530 : {List U8, U64} = CallByName List.138 List.433 List.536 List.434; + let List.533 : U64 = 1i64; + let List.532 : U64 = CallByName Num.19 List.435 List.533; + jump List.527 List.432 List.530 List.434 List.532 List.436; else - ret List.430; + ret List.433; in - jump List.512 List.538 List.539 List.540 List.541 List.542; + jump List.527 List.553 List.554 List.555 List.556 List.557; -procedure Num.125 (#Attr.2): - let Num.263 : U8 = lowlevel NumIntCast #Attr.2; - ret Num.263; +procedure List.91 (List.429, List.430, List.431): + let List.525 : U64 = 0i64; + let List.526 : U64 = CallByName List.6 List.429; + let List.524 : {List U8, U64} = CallByName List.80 List.429 List.430 List.431 List.525 List.526; + ret List.524; + +procedure Num.127 (#Attr.2): + let Num.282 : U8 = lowlevel NumIntCast #Attr.2; + ret Num.282; procedure Num.19 (#Attr.2, #Attr.3): - let Num.266 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.266; + let Num.285 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.285; procedure Num.20 (#Attr.2, #Attr.3): - let Num.264 : U64 = lowlevel NumSub #Attr.2 #Attr.3; - ret Num.264; + let Num.283 : U64 = lowlevel NumSub #Attr.2 #Attr.3; + ret Num.283; procedure Num.22 (#Attr.2, #Attr.3): - let Num.267 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; - ret Num.267; + let Num.286 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.286; procedure Num.24 (#Attr.2, #Attr.3): - let Num.265 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; - ret Num.265; + let Num.284 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; + ret Num.284; procedure Str.12 (#Attr.2): let Str.280 : List U8 = lowlevel StrToUtf8 #Attr.2; diff --git a/crates/compiler/test_mono/generated/encode_derived_record_two_field_strings.txt b/crates/compiler/test_mono/generated/encode_derived_record_two_field_strings.txt index 829fbcd5a2..05b09ec108 100644 --- a/crates/compiler/test_mono/generated/encode_derived_record_two_field_strings.txt +++ b/crates/compiler/test_mono/generated/encode_derived_record_two_field_strings.txt @@ -33,11 +33,11 @@ procedure Encode.23 (Encode.94, Encode.102, Encode.96): ret Encode.106; procedure Encode.23 (Encode.94, Encode.102, Encode.96): - let Encode.113 : List U8 = CallByName Json.112 Encode.94 Encode.96 Encode.102; + let Encode.113 : List U8 = CallByName Json.115 Encode.94 Encode.96 Encode.102; ret Encode.113; procedure Encode.23 (Encode.94, Encode.102, Encode.96): - let Encode.117 : List U8 = CallByName Json.96 Encode.94 Encode.96 Encode.102; + let Encode.117 : List U8 = CallByName Json.99 Encode.94 Encode.96 Encode.102; ret Encode.117; procedure Encode.25 (Encode.100, Encode.101): @@ -47,161 +47,161 @@ procedure Encode.25 (Encode.100, Encode.101): ret Encode.103; procedure Json.1 (): - let Json.396 : {} = Struct {}; - ret Json.396; + let Json.425 : {} = Struct {}; + ret Json.425; -procedure Json.112 (Json.113, Json.399, Json.111): - let Json.432 : I64 = 123i64; - let Json.431 : U8 = CallByName Num.125 Json.432; - let Json.115 : List U8 = CallByName List.4 Json.113 Json.431; - let Json.430 : U64 = CallByName List.6 Json.111; - let Json.407 : {List U8, U64} = Struct {Json.115, Json.430}; - let Json.408 : {} = Struct {}; - let Json.406 : {List U8, U64} = CallByName List.18 Json.111 Json.407 Json.408; - dec Json.111; - let Json.117 : List U8 = StructAtIndex 0 Json.406; - inc Json.117; - dec Json.406; - let Json.405 : I64 = 125i64; - let Json.404 : U8 = CallByName Num.125 Json.405; - let Json.403 : List U8 = CallByName List.4 Json.117 Json.404; - ret Json.403; - -procedure Json.114 (Json.401, Json.402): - let Json.120 : Str = StructAtIndex 0 Json.402; +procedure Json.115 (Json.116, Json.428, Json.114): + let Json.461 : I64 = 123i64; + let Json.460 : U8 = CallByName Num.127 Json.461; + let Json.118 : List U8 = CallByName List.4 Json.116 Json.460; + let Json.459 : U64 = CallByName List.6 Json.114; + let Json.436 : {List U8, U64} = Struct {Json.118, Json.459}; + let Json.437 : {} = Struct {}; + let Json.435 : {List U8, U64} = CallByName List.18 Json.114 Json.436 Json.437; + dec Json.114; + let Json.120 : List U8 = StructAtIndex 0 Json.435; inc Json.120; - let Json.121 : Str = StructAtIndex 1 Json.402; + dec Json.435; + let Json.434 : I64 = 125i64; + let Json.433 : U8 = CallByName Num.127 Json.434; + let Json.432 : List U8 = CallByName List.4 Json.120 Json.433; + ret Json.432; + +procedure Json.117 (Json.430, Json.431): + let Json.123 : Str = StructAtIndex 0 Json.431; + inc Json.123; + let Json.124 : Str = StructAtIndex 1 Json.431; + inc Json.124; + dec Json.431; + let Json.121 : List U8 = StructAtIndex 0 Json.430; inc Json.121; - dec Json.402; - let Json.118 : List U8 = StructAtIndex 0 Json.401; - inc Json.118; - let Json.119 : U64 = StructAtIndex 1 Json.401; - dec Json.401; - let Json.429 : I64 = 34i64; - let Json.428 : U8 = CallByName Num.125 Json.429; - let Json.426 : List U8 = CallByName List.4 Json.118 Json.428; - let Json.427 : List U8 = CallByName Str.12 Json.120; - let Json.423 : List U8 = CallByName List.8 Json.426 Json.427; - let Json.425 : I64 = 34i64; - let Json.424 : U8 = CallByName Num.125 Json.425; - let Json.420 : List U8 = CallByName List.4 Json.423 Json.424; - let Json.422 : I64 = 58i64; - let Json.421 : U8 = CallByName Num.125 Json.422; - let Json.418 : List U8 = CallByName List.4 Json.420 Json.421; - let Json.419 : {} = Struct {}; - let Json.122 : List U8 = CallByName Encode.23 Json.418 Json.121 Json.419; - joinpoint Json.413 Json.123: - let Json.411 : U64 = 1i64; - let Json.410 : U64 = CallByName Num.20 Json.119 Json.411; - let Json.409 : {List U8, U64} = Struct {Json.123, Json.410}; - ret Json.409; + let Json.122 : U64 = StructAtIndex 1 Json.430; + dec Json.430; + let Json.458 : I64 = 34i64; + let Json.457 : U8 = CallByName Num.127 Json.458; + let Json.455 : List U8 = CallByName List.4 Json.121 Json.457; + let Json.456 : List U8 = CallByName Str.12 Json.123; + let Json.452 : List U8 = CallByName List.8 Json.455 Json.456; + let Json.454 : I64 = 34i64; + let Json.453 : U8 = CallByName Num.127 Json.454; + let Json.449 : List U8 = CallByName List.4 Json.452 Json.453; + let Json.451 : I64 = 58i64; + let Json.450 : U8 = CallByName Num.127 Json.451; + let Json.447 : List U8 = CallByName List.4 Json.449 Json.450; + let Json.448 : {} = Struct {}; + let Json.125 : List U8 = CallByName Encode.23 Json.447 Json.124 Json.448; + joinpoint Json.442 Json.126: + let Json.440 : U64 = 1i64; + let Json.439 : U64 = CallByName Num.20 Json.122 Json.440; + let Json.438 : {List U8, U64} = Struct {Json.126, Json.439}; + ret Json.438; in - let Json.417 : U64 = 1i64; - let Json.414 : Int1 = CallByName Num.24 Json.119 Json.417; - if Json.414 then - let Json.416 : I64 = 44i64; - let Json.415 : U8 = CallByName Num.125 Json.416; - let Json.412 : List U8 = CallByName List.4 Json.122 Json.415; - jump Json.413 Json.412; + let Json.446 : U64 = 1i64; + let Json.443 : Int1 = CallByName Num.24 Json.122 Json.446; + if Json.443 then + let Json.445 : I64 = 44i64; + let Json.444 : U8 = CallByName Num.127 Json.445; + let Json.441 : List U8 = CallByName List.4 Json.125 Json.444; + jump Json.442 Json.441; else - jump Json.413 Json.122; + jump Json.442 Json.125; -procedure Json.18 (Json.95): - let Json.445 : Str = CallByName Encode.22 Json.95; - ret Json.445; +procedure Json.18 (Json.98): + let Json.474 : Str = CallByName Encode.22 Json.98; + ret Json.474; -procedure Json.20 (Json.111): - let Json.397 : List {Str, Str} = CallByName Encode.22 Json.111; - ret Json.397; +procedure Json.20 (Json.114): + let Json.426 : List {Str, Str} = CallByName Encode.22 Json.114; + ret Json.426; -procedure Json.96 (Json.97, Json.435, Json.95): - let Json.444 : I64 = 34i64; - let Json.443 : U8 = CallByName Num.125 Json.444; - let Json.441 : List U8 = CallByName List.4 Json.97 Json.443; - let Json.442 : List U8 = CallByName Str.12 Json.95; - let Json.438 : List U8 = CallByName List.8 Json.441 Json.442; - let Json.440 : I64 = 34i64; - let Json.439 : U8 = CallByName Num.125 Json.440; - let Json.437 : List U8 = CallByName List.4 Json.438 Json.439; - ret Json.437; +procedure Json.99 (Json.100, Json.464, Json.98): + let Json.473 : I64 = 34i64; + let Json.472 : U8 = CallByName Num.127 Json.473; + let Json.470 : List U8 = CallByName List.4 Json.100 Json.472; + let Json.471 : List U8 = CallByName Str.12 Json.98; + let Json.467 : List U8 = CallByName List.8 Json.470 Json.471; + let Json.469 : I64 = 34i64; + let Json.468 : U8 = CallByName Num.127 Json.469; + let Json.466 : List U8 = CallByName List.4 Json.467 Json.468; + ret Json.466; procedure List.138 (List.139, List.140, List.137): - let List.525 : {List U8, U64} = CallByName Json.114 List.139 List.140; - ret List.525; + let List.540 : {List U8, U64} = CallByName Json.117 List.139 List.140; + ret List.540; procedure List.18 (List.135, List.136, List.137): - let List.506 : {List U8, U64} = CallByName List.90 List.135 List.136 List.137; - ret List.506; + let List.521 : {List U8, U64} = CallByName List.91 List.135 List.136 List.137; + ret List.521; procedure List.4 (List.106, List.107): - let List.505 : U64 = 1i64; - let List.504 : List U8 = CallByName List.70 List.106 List.505; - let List.503 : List U8 = CallByName List.71 List.504 List.107; - ret List.503; + let List.520 : U64 = 1i64; + let List.519 : List U8 = CallByName List.70 List.106 List.520; + let List.518 : List U8 = CallByName List.71 List.519 List.107; + ret List.518; procedure List.6 (#Attr.2): - let List.478 : U64 = lowlevel ListLen #Attr.2; - ret List.478; + let List.493 : U64 = lowlevel ListLen #Attr.2; + ret List.493; procedure List.6 (#Attr.2): - let List.528 : U64 = lowlevel ListLen #Attr.2; - ret List.528; + let List.543 : U64 = lowlevel ListLen #Attr.2; + ret List.543; procedure List.66 (#Attr.2, #Attr.3): - let List.522 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.522; + let List.537 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.537; procedure List.70 (#Attr.2, #Attr.3): - let List.484 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.484; + let List.499 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.499; procedure List.71 (#Attr.2, #Attr.3): - let List.482 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.482; + let List.497 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.497; procedure List.8 (#Attr.2, #Attr.3): - let List.527 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.527; + let List.542 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.542; -procedure List.90 (List.426, List.427, List.428): - let List.510 : U64 = 0i64; - let List.511 : U64 = CallByName List.6 List.426; - let List.509 : {List U8, U64} = CallByName List.91 List.426 List.427 List.428 List.510 List.511; - ret List.509; - -procedure List.91 (List.538, List.539, List.540, List.541, List.542): - joinpoint List.512 List.429 List.430 List.431 List.432 List.433: - let List.514 : Int1 = CallByName Num.22 List.432 List.433; - if List.514 then - let List.521 : {Str, Str} = CallByName List.66 List.429 List.432; - let List.515 : {List U8, U64} = CallByName List.138 List.430 List.521 List.431; - let List.518 : U64 = 1i64; - let List.517 : U64 = CallByName Num.19 List.432 List.518; - jump List.512 List.429 List.515 List.431 List.517 List.433; +procedure List.80 (List.553, List.554, List.555, List.556, List.557): + joinpoint List.527 List.432 List.433 List.434 List.435 List.436: + let List.529 : Int1 = CallByName Num.22 List.435 List.436; + if List.529 then + let List.536 : {Str, Str} = CallByName List.66 List.432 List.435; + let List.530 : {List U8, U64} = CallByName List.138 List.433 List.536 List.434; + let List.533 : U64 = 1i64; + let List.532 : U64 = CallByName Num.19 List.435 List.533; + jump List.527 List.432 List.530 List.434 List.532 List.436; else - ret List.430; + ret List.433; in - jump List.512 List.538 List.539 List.540 List.541 List.542; + jump List.527 List.553 List.554 List.555 List.556 List.557; -procedure Num.125 (#Attr.2): - let Num.263 : U8 = lowlevel NumIntCast #Attr.2; - ret Num.263; +procedure List.91 (List.429, List.430, List.431): + let List.525 : U64 = 0i64; + let List.526 : U64 = CallByName List.6 List.429; + let List.524 : {List U8, U64} = CallByName List.80 List.429 List.430 List.431 List.525 List.526; + ret List.524; + +procedure Num.127 (#Attr.2): + let Num.282 : U8 = lowlevel NumIntCast #Attr.2; + ret Num.282; procedure Num.19 (#Attr.2, #Attr.3): - let Num.266 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.266; + let Num.285 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.285; procedure Num.20 (#Attr.2, #Attr.3): - let Num.264 : U64 = lowlevel NumSub #Attr.2 #Attr.3; - ret Num.264; + let Num.283 : U64 = lowlevel NumSub #Attr.2 #Attr.3; + ret Num.283; procedure Num.22 (#Attr.2, #Attr.3): - let Num.267 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; - ret Num.267; + let Num.286 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.286; procedure Num.24 (#Attr.2, #Attr.3): - let Num.265 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; - ret Num.265; + let Num.284 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; + ret Num.284; procedure Str.12 (#Attr.2): let Str.280 : List U8 = lowlevel StrToUtf8 #Attr.2; diff --git a/crates/compiler/test_mono/generated/encode_derived_string.txt b/crates/compiler/test_mono/generated/encode_derived_string.txt index 7195cf4c87..8712d76eb1 100644 --- a/crates/compiler/test_mono/generated/encode_derived_string.txt +++ b/crates/compiler/test_mono/generated/encode_derived_string.txt @@ -2,7 +2,7 @@ procedure Encode.22 (Encode.93): ret Encode.93; procedure Encode.23 (Encode.94, Encode.102, Encode.96): - let Encode.106 : List U8 = CallByName Json.96 Encode.94 Encode.96 Encode.102; + let Encode.106 : List U8 = CallByName Json.99 Encode.94 Encode.96 Encode.102; ret Encode.106; procedure Encode.25 (Encode.100, Encode.101): @@ -12,49 +12,49 @@ procedure Encode.25 (Encode.100, Encode.101): ret Encode.103; procedure Json.1 (): - let Json.396 : {} = Struct {}; - ret Json.396; + let Json.425 : {} = Struct {}; + ret Json.425; -procedure Json.18 (Json.95): - let Json.397 : Str = CallByName Encode.22 Json.95; - ret Json.397; +procedure Json.18 (Json.98): + let Json.426 : Str = CallByName Encode.22 Json.98; + ret Json.426; -procedure Json.96 (Json.97, Json.399, Json.95): - let Json.408 : I64 = 34i64; - let Json.407 : U8 = CallByName Num.125 Json.408; - let Json.405 : List U8 = CallByName List.4 Json.97 Json.407; - let Json.406 : List U8 = CallByName Str.12 Json.95; - let Json.402 : List U8 = CallByName List.8 Json.405 Json.406; - let Json.404 : I64 = 34i64; - let Json.403 : U8 = CallByName Num.125 Json.404; - let Json.401 : List U8 = CallByName List.4 Json.402 Json.403; - ret Json.401; +procedure Json.99 (Json.100, Json.428, Json.98): + let Json.437 : I64 = 34i64; + let Json.436 : U8 = CallByName Num.127 Json.437; + let Json.434 : List U8 = CallByName List.4 Json.100 Json.436; + let Json.435 : List U8 = CallByName Str.12 Json.98; + let Json.431 : List U8 = CallByName List.8 Json.434 Json.435; + let Json.433 : I64 = 34i64; + let Json.432 : U8 = CallByName Num.127 Json.433; + let Json.430 : List U8 = CallByName List.4 Json.431 Json.432; + ret Json.430; procedure List.4 (List.106, List.107): - let List.487 : U64 = 1i64; - let List.486 : List U8 = CallByName List.70 List.106 List.487; - let List.485 : List U8 = CallByName List.71 List.486 List.107; - ret List.485; + let List.502 : U64 = 1i64; + let List.501 : List U8 = CallByName List.70 List.106 List.502; + let List.500 : List U8 = CallByName List.71 List.501 List.107; + ret List.500; procedure List.6 (#Attr.2): - let List.478 : U64 = lowlevel ListLen #Attr.2; - ret List.478; + let List.493 : U64 = lowlevel ListLen #Attr.2; + ret List.493; procedure List.70 (#Attr.2, #Attr.3): - let List.484 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.484; + let List.499 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.499; procedure List.71 (#Attr.2, #Attr.3): - let List.482 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.482; + let List.497 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.497; procedure List.8 (#Attr.2, #Attr.3): - let List.488 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.488; + let List.503 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.503; -procedure Num.125 (#Attr.2): - let Num.257 : U8 = lowlevel NumIntCast #Attr.2; - ret Num.257; +procedure Num.127 (#Attr.2): + let Num.276 : U8 = lowlevel NumIntCast #Attr.2; + ret Num.276; procedure Str.12 (#Attr.2): let Str.279 : List U8 = lowlevel StrToUtf8 #Attr.2; diff --git a/crates/compiler/test_mono/generated/encode_derived_tag_one_field_string.txt b/crates/compiler/test_mono/generated/encode_derived_tag_one_field_string.txt index 40580ef311..1cf68601a0 100644 --- a/crates/compiler/test_mono/generated/encode_derived_tag_one_field_string.txt +++ b/crates/compiler/test_mono/generated/encode_derived_tag_one_field_string.txt @@ -27,11 +27,11 @@ procedure Encode.23 (Encode.94, Encode.102, Encode.96): ret Encode.106; procedure Encode.23 (Encode.94, Encode.102, Encode.96): - let Encode.113 : List U8 = CallByName Json.126 Encode.94 Encode.96 Encode.102; + let Encode.113 : List U8 = CallByName Json.129 Encode.94 Encode.96 Encode.102; ret Encode.113; procedure Encode.23 (Encode.94, Encode.102, Encode.96): - let Encode.116 : List U8 = CallByName Json.96 Encode.94 Encode.96 Encode.102; + let Encode.116 : List U8 = CallByName Json.99 Encode.94 Encode.96 Encode.102; ret Encode.116; procedure Encode.25 (Encode.100, Encode.101): @@ -41,168 +41,168 @@ procedure Encode.25 (Encode.100, Encode.101): ret Encode.103; procedure Json.1 (): - let Json.396 : {} = Struct {}; - ret Json.396; + let Json.425 : {} = Struct {}; + ret Json.425; -procedure Json.126 (Json.127, Json.399, #Attr.12): - let Json.125 : List Str = StructAtIndex 1 #Attr.12; - inc Json.125; - let Json.124 : Str = StructAtIndex 0 #Attr.12; - inc Json.124; +procedure Json.129 (Json.130, Json.428, #Attr.12): + let Json.128 : List Str = StructAtIndex 1 #Attr.12; + inc Json.128; + let Json.127 : Str = StructAtIndex 0 #Attr.12; + inc Json.127; dec #Attr.12; - let Json.437 : I64 = 123i64; - let Json.436 : U8 = CallByName Num.125 Json.437; - let Json.433 : List U8 = CallByName List.4 Json.127 Json.436; - let Json.435 : I64 = 34i64; - let Json.434 : U8 = CallByName Num.125 Json.435; - let Json.431 : List U8 = CallByName List.4 Json.433 Json.434; - let Json.432 : List U8 = CallByName Str.12 Json.124; - let Json.428 : List U8 = CallByName List.8 Json.431 Json.432; - let Json.430 : I64 = 34i64; - let Json.429 : U8 = CallByName Num.125 Json.430; - let Json.425 : List U8 = CallByName List.4 Json.428 Json.429; - let Json.427 : I64 = 58i64; - let Json.426 : U8 = CallByName Num.125 Json.427; - let Json.422 : List U8 = CallByName List.4 Json.425 Json.426; - let Json.424 : I64 = 91i64; - let Json.423 : U8 = CallByName Num.125 Json.424; - let Json.129 : List U8 = CallByName List.4 Json.422 Json.423; - let Json.421 : U64 = CallByName List.6 Json.125; - let Json.409 : {List U8, U64} = Struct {Json.129, Json.421}; - let Json.410 : {} = Struct {}; - let Json.408 : {List U8, U64} = CallByName List.18 Json.125 Json.409 Json.410; - dec Json.125; - let Json.131 : List U8 = StructAtIndex 0 Json.408; - inc Json.131; - dec Json.408; - let Json.407 : I64 = 93i64; - let Json.406 : U8 = CallByName Num.125 Json.407; - let Json.403 : List U8 = CallByName List.4 Json.131 Json.406; - let Json.405 : I64 = 125i64; - let Json.404 : U8 = CallByName Num.125 Json.405; - let Json.402 : List U8 = CallByName List.4 Json.403 Json.404; - ret Json.402; + let Json.466 : I64 = 123i64; + let Json.465 : U8 = CallByName Num.127 Json.466; + let Json.462 : List U8 = CallByName List.4 Json.130 Json.465; + let Json.464 : I64 = 34i64; + let Json.463 : U8 = CallByName Num.127 Json.464; + let Json.460 : List U8 = CallByName List.4 Json.462 Json.463; + let Json.461 : List U8 = CallByName Str.12 Json.127; + let Json.457 : List U8 = CallByName List.8 Json.460 Json.461; + let Json.459 : I64 = 34i64; + let Json.458 : U8 = CallByName Num.127 Json.459; + let Json.454 : List U8 = CallByName List.4 Json.457 Json.458; + let Json.456 : I64 = 58i64; + let Json.455 : U8 = CallByName Num.127 Json.456; + let Json.451 : List U8 = CallByName List.4 Json.454 Json.455; + let Json.453 : I64 = 91i64; + let Json.452 : U8 = CallByName Num.127 Json.453; + let Json.132 : List U8 = CallByName List.4 Json.451 Json.452; + let Json.450 : U64 = CallByName List.6 Json.128; + let Json.438 : {List U8, U64} = Struct {Json.132, Json.450}; + let Json.439 : {} = Struct {}; + let Json.437 : {List U8, U64} = CallByName List.18 Json.128 Json.438 Json.439; + dec Json.128; + let Json.134 : List U8 = StructAtIndex 0 Json.437; + inc Json.134; + dec Json.437; + let Json.436 : I64 = 93i64; + let Json.435 : U8 = CallByName Num.127 Json.436; + let Json.432 : List U8 = CallByName List.4 Json.134 Json.435; + let Json.434 : I64 = 125i64; + let Json.433 : U8 = CallByName Num.127 Json.434; + let Json.431 : List U8 = CallByName List.4 Json.432 Json.433; + ret Json.431; -procedure Json.128 (Json.401, Json.134): - let Json.132 : List U8 = StructAtIndex 0 Json.401; - inc Json.132; - let Json.133 : U64 = StructAtIndex 1 Json.401; - dec Json.401; - let Json.420 : {} = Struct {}; - let Json.135 : List U8 = CallByName Encode.23 Json.132 Json.134 Json.420; - joinpoint Json.415 Json.136: - let Json.413 : U64 = 1i64; - let Json.412 : U64 = CallByName Num.20 Json.133 Json.413; - let Json.411 : {List U8, U64} = Struct {Json.136, Json.412}; - ret Json.411; +procedure Json.131 (Json.430, Json.137): + let Json.135 : List U8 = StructAtIndex 0 Json.430; + inc Json.135; + let Json.136 : U64 = StructAtIndex 1 Json.430; + dec Json.430; + let Json.449 : {} = Struct {}; + let Json.138 : List U8 = CallByName Encode.23 Json.135 Json.137 Json.449; + joinpoint Json.444 Json.139: + let Json.442 : U64 = 1i64; + let Json.441 : U64 = CallByName Num.20 Json.136 Json.442; + let Json.440 : {List U8, U64} = Struct {Json.139, Json.441}; + ret Json.440; in - let Json.419 : U64 = 1i64; - let Json.416 : Int1 = CallByName Num.24 Json.133 Json.419; - if Json.416 then - let Json.418 : I64 = 44i64; - let Json.417 : U8 = CallByName Num.125 Json.418; - let Json.414 : List U8 = CallByName List.4 Json.135 Json.417; - jump Json.415 Json.414; + let Json.448 : U64 = 1i64; + let Json.445 : Int1 = CallByName Num.24 Json.136 Json.448; + if Json.445 then + let Json.447 : I64 = 44i64; + let Json.446 : U8 = CallByName Num.127 Json.447; + let Json.443 : List U8 = CallByName List.4 Json.138 Json.446; + jump Json.444 Json.443; else - jump Json.415 Json.135; + jump Json.444 Json.138; -procedure Json.18 (Json.95): - let Json.438 : Str = CallByName Encode.22 Json.95; - ret Json.438; +procedure Json.18 (Json.98): + let Json.467 : Str = CallByName Encode.22 Json.98; + ret Json.467; -procedure Json.21 (Json.124, Json.125): - let Json.398 : {Str, List Str} = Struct {Json.124, Json.125}; - let Json.397 : {Str, List Str} = CallByName Encode.22 Json.398; - ret Json.397; +procedure Json.21 (Json.127, Json.128): + let Json.427 : {Str, List Str} = Struct {Json.127, Json.128}; + let Json.426 : {Str, List Str} = CallByName Encode.22 Json.427; + ret Json.426; -procedure Json.96 (Json.97, Json.440, Json.95): - let Json.449 : I64 = 34i64; - let Json.448 : U8 = CallByName Num.125 Json.449; - let Json.446 : List U8 = CallByName List.4 Json.97 Json.448; - let Json.447 : List U8 = CallByName Str.12 Json.95; - let Json.443 : List U8 = CallByName List.8 Json.446 Json.447; - let Json.445 : I64 = 34i64; - let Json.444 : U8 = CallByName Num.125 Json.445; - let Json.442 : List U8 = CallByName List.4 Json.443 Json.444; - ret Json.442; +procedure Json.99 (Json.100, Json.469, Json.98): + let Json.478 : I64 = 34i64; + let Json.477 : U8 = CallByName Num.127 Json.478; + let Json.475 : List U8 = CallByName List.4 Json.100 Json.477; + let Json.476 : List U8 = CallByName Str.12 Json.98; + let Json.472 : List U8 = CallByName List.8 Json.475 Json.476; + let Json.474 : I64 = 34i64; + let Json.473 : U8 = CallByName Num.127 Json.474; + let Json.471 : List U8 = CallByName List.4 Json.472 Json.473; + ret Json.471; procedure List.138 (List.139, List.140, List.137): - let List.531 : {List U8, U64} = CallByName Json.128 List.139 List.140; - ret List.531; + let List.546 : {List U8, U64} = CallByName Json.131 List.139 List.140; + ret List.546; procedure List.18 (List.135, List.136, List.137): - let List.512 : {List U8, U64} = CallByName List.90 List.135 List.136 List.137; - ret List.512; + let List.527 : {List U8, U64} = CallByName List.91 List.135 List.136 List.137; + ret List.527; procedure List.4 (List.106, List.107): - let List.511 : U64 = 1i64; - let List.510 : List U8 = CallByName List.70 List.106 List.511; - let List.509 : List U8 = CallByName List.71 List.510 List.107; - ret List.509; + let List.526 : U64 = 1i64; + let List.525 : List U8 = CallByName List.70 List.106 List.526; + let List.524 : List U8 = CallByName List.71 List.525 List.107; + ret List.524; procedure List.6 (#Attr.2): - let List.478 : U64 = lowlevel ListLen #Attr.2; - ret List.478; + let List.493 : U64 = lowlevel ListLen #Attr.2; + ret List.493; procedure List.6 (#Attr.2): - let List.532 : U64 = lowlevel ListLen #Attr.2; - ret List.532; + let List.547 : U64 = lowlevel ListLen #Attr.2; + ret List.547; procedure List.66 (#Attr.2, #Attr.3): - let List.528 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.528; + let List.543 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.543; procedure List.70 (#Attr.2, #Attr.3): - let List.484 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.484; + let List.499 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.499; procedure List.71 (#Attr.2, #Attr.3): - let List.482 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.482; + let List.497 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.497; procedure List.8 (#Attr.2, #Attr.3): - let List.534 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.534; + let List.549 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.549; -procedure List.90 (List.426, List.427, List.428): - let List.516 : U64 = 0i64; - let List.517 : U64 = CallByName List.6 List.426; - let List.515 : {List U8, U64} = CallByName List.91 List.426 List.427 List.428 List.516 List.517; - ret List.515; - -procedure List.91 (List.544, List.545, List.546, List.547, List.548): - joinpoint List.518 List.429 List.430 List.431 List.432 List.433: - let List.520 : Int1 = CallByName Num.22 List.432 List.433; - if List.520 then - let List.527 : Str = CallByName List.66 List.429 List.432; - let List.521 : {List U8, U64} = CallByName List.138 List.430 List.527 List.431; - let List.524 : U64 = 1i64; - let List.523 : U64 = CallByName Num.19 List.432 List.524; - jump List.518 List.429 List.521 List.431 List.523 List.433; +procedure List.80 (List.559, List.560, List.561, List.562, List.563): + joinpoint List.533 List.432 List.433 List.434 List.435 List.436: + let List.535 : Int1 = CallByName Num.22 List.435 List.436; + if List.535 then + let List.542 : Str = CallByName List.66 List.432 List.435; + let List.536 : {List U8, U64} = CallByName List.138 List.433 List.542 List.434; + let List.539 : U64 = 1i64; + let List.538 : U64 = CallByName Num.19 List.435 List.539; + jump List.533 List.432 List.536 List.434 List.538 List.436; else - ret List.430; + ret List.433; in - jump List.518 List.544 List.545 List.546 List.547 List.548; + jump List.533 List.559 List.560 List.561 List.562 List.563; -procedure Num.125 (#Attr.2): - let Num.265 : U8 = lowlevel NumIntCast #Attr.2; - ret Num.265; +procedure List.91 (List.429, List.430, List.431): + let List.531 : U64 = 0i64; + let List.532 : U64 = CallByName List.6 List.429; + let List.530 : {List U8, U64} = CallByName List.80 List.429 List.430 List.431 List.531 List.532; + ret List.530; + +procedure Num.127 (#Attr.2): + let Num.284 : U8 = lowlevel NumIntCast #Attr.2; + ret Num.284; procedure Num.19 (#Attr.2, #Attr.3): - let Num.268 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.268; + let Num.287 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.287; procedure Num.20 (#Attr.2, #Attr.3): - let Num.266 : U64 = lowlevel NumSub #Attr.2 #Attr.3; - ret Num.266; + let Num.285 : U64 = lowlevel NumSub #Attr.2 #Attr.3; + ret Num.285; procedure Num.22 (#Attr.2, #Attr.3): - let Num.269 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; - ret Num.269; + let Num.288 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.288; procedure Num.24 (#Attr.2, #Attr.3): - let Num.267 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; - ret Num.267; + let Num.286 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; + ret Num.286; procedure Str.12 (#Attr.2): let Str.280 : List U8 = lowlevel StrToUtf8 #Attr.2; diff --git a/crates/compiler/test_mono/generated/encode_derived_tag_two_payloads_string.txt b/crates/compiler/test_mono/generated/encode_derived_tag_two_payloads_string.txt index 72a865f670..d8701b77ba 100644 --- a/crates/compiler/test_mono/generated/encode_derived_tag_two_payloads_string.txt +++ b/crates/compiler/test_mono/generated/encode_derived_tag_two_payloads_string.txt @@ -33,11 +33,11 @@ procedure Encode.23 (Encode.94, Encode.102, Encode.96): ret Encode.106; procedure Encode.23 (Encode.94, Encode.102, Encode.96): - let Encode.113 : List U8 = CallByName Json.126 Encode.94 Encode.96 Encode.102; + let Encode.113 : List U8 = CallByName Json.129 Encode.94 Encode.96 Encode.102; ret Encode.113; procedure Encode.23 (Encode.94, Encode.102, Encode.96): - let Encode.117 : List U8 = CallByName Json.96 Encode.94 Encode.96 Encode.102; + let Encode.117 : List U8 = CallByName Json.99 Encode.94 Encode.96 Encode.102; ret Encode.117; procedure Encode.25 (Encode.100, Encode.101): @@ -47,168 +47,168 @@ procedure Encode.25 (Encode.100, Encode.101): ret Encode.103; procedure Json.1 (): - let Json.396 : {} = Struct {}; - ret Json.396; + let Json.425 : {} = Struct {}; + ret Json.425; -procedure Json.126 (Json.127, Json.399, #Attr.12): - let Json.125 : List Str = StructAtIndex 1 #Attr.12; - inc Json.125; - let Json.124 : Str = StructAtIndex 0 #Attr.12; - inc Json.124; +procedure Json.129 (Json.130, Json.428, #Attr.12): + let Json.128 : List Str = StructAtIndex 1 #Attr.12; + inc Json.128; + let Json.127 : Str = StructAtIndex 0 #Attr.12; + inc Json.127; dec #Attr.12; - let Json.437 : I64 = 123i64; - let Json.436 : U8 = CallByName Num.125 Json.437; - let Json.433 : List U8 = CallByName List.4 Json.127 Json.436; - let Json.435 : I64 = 34i64; - let Json.434 : U8 = CallByName Num.125 Json.435; - let Json.431 : List U8 = CallByName List.4 Json.433 Json.434; - let Json.432 : List U8 = CallByName Str.12 Json.124; - let Json.428 : List U8 = CallByName List.8 Json.431 Json.432; - let Json.430 : I64 = 34i64; - let Json.429 : U8 = CallByName Num.125 Json.430; - let Json.425 : List U8 = CallByName List.4 Json.428 Json.429; - let Json.427 : I64 = 58i64; - let Json.426 : U8 = CallByName Num.125 Json.427; - let Json.422 : List U8 = CallByName List.4 Json.425 Json.426; - let Json.424 : I64 = 91i64; - let Json.423 : U8 = CallByName Num.125 Json.424; - let Json.129 : List U8 = CallByName List.4 Json.422 Json.423; - let Json.421 : U64 = CallByName List.6 Json.125; - let Json.409 : {List U8, U64} = Struct {Json.129, Json.421}; - let Json.410 : {} = Struct {}; - let Json.408 : {List U8, U64} = CallByName List.18 Json.125 Json.409 Json.410; - dec Json.125; - let Json.131 : List U8 = StructAtIndex 0 Json.408; - inc Json.131; - dec Json.408; - let Json.407 : I64 = 93i64; - let Json.406 : U8 = CallByName Num.125 Json.407; - let Json.403 : List U8 = CallByName List.4 Json.131 Json.406; - let Json.405 : I64 = 125i64; - let Json.404 : U8 = CallByName Num.125 Json.405; - let Json.402 : List U8 = CallByName List.4 Json.403 Json.404; - ret Json.402; + let Json.466 : I64 = 123i64; + let Json.465 : U8 = CallByName Num.127 Json.466; + let Json.462 : List U8 = CallByName List.4 Json.130 Json.465; + let Json.464 : I64 = 34i64; + let Json.463 : U8 = CallByName Num.127 Json.464; + let Json.460 : List U8 = CallByName List.4 Json.462 Json.463; + let Json.461 : List U8 = CallByName Str.12 Json.127; + let Json.457 : List U8 = CallByName List.8 Json.460 Json.461; + let Json.459 : I64 = 34i64; + let Json.458 : U8 = CallByName Num.127 Json.459; + let Json.454 : List U8 = CallByName List.4 Json.457 Json.458; + let Json.456 : I64 = 58i64; + let Json.455 : U8 = CallByName Num.127 Json.456; + let Json.451 : List U8 = CallByName List.4 Json.454 Json.455; + let Json.453 : I64 = 91i64; + let Json.452 : U8 = CallByName Num.127 Json.453; + let Json.132 : List U8 = CallByName List.4 Json.451 Json.452; + let Json.450 : U64 = CallByName List.6 Json.128; + let Json.438 : {List U8, U64} = Struct {Json.132, Json.450}; + let Json.439 : {} = Struct {}; + let Json.437 : {List U8, U64} = CallByName List.18 Json.128 Json.438 Json.439; + dec Json.128; + let Json.134 : List U8 = StructAtIndex 0 Json.437; + inc Json.134; + dec Json.437; + let Json.436 : I64 = 93i64; + let Json.435 : U8 = CallByName Num.127 Json.436; + let Json.432 : List U8 = CallByName List.4 Json.134 Json.435; + let Json.434 : I64 = 125i64; + let Json.433 : U8 = CallByName Num.127 Json.434; + let Json.431 : List U8 = CallByName List.4 Json.432 Json.433; + ret Json.431; -procedure Json.128 (Json.401, Json.134): - let Json.132 : List U8 = StructAtIndex 0 Json.401; - inc Json.132; - let Json.133 : U64 = StructAtIndex 1 Json.401; - dec Json.401; - let Json.420 : {} = Struct {}; - let Json.135 : List U8 = CallByName Encode.23 Json.132 Json.134 Json.420; - joinpoint Json.415 Json.136: - let Json.413 : U64 = 1i64; - let Json.412 : U64 = CallByName Num.20 Json.133 Json.413; - let Json.411 : {List U8, U64} = Struct {Json.136, Json.412}; - ret Json.411; +procedure Json.131 (Json.430, Json.137): + let Json.135 : List U8 = StructAtIndex 0 Json.430; + inc Json.135; + let Json.136 : U64 = StructAtIndex 1 Json.430; + dec Json.430; + let Json.449 : {} = Struct {}; + let Json.138 : List U8 = CallByName Encode.23 Json.135 Json.137 Json.449; + joinpoint Json.444 Json.139: + let Json.442 : U64 = 1i64; + let Json.441 : U64 = CallByName Num.20 Json.136 Json.442; + let Json.440 : {List U8, U64} = Struct {Json.139, Json.441}; + ret Json.440; in - let Json.419 : U64 = 1i64; - let Json.416 : Int1 = CallByName Num.24 Json.133 Json.419; - if Json.416 then - let Json.418 : I64 = 44i64; - let Json.417 : U8 = CallByName Num.125 Json.418; - let Json.414 : List U8 = CallByName List.4 Json.135 Json.417; - jump Json.415 Json.414; + let Json.448 : U64 = 1i64; + let Json.445 : Int1 = CallByName Num.24 Json.136 Json.448; + if Json.445 then + let Json.447 : I64 = 44i64; + let Json.446 : U8 = CallByName Num.127 Json.447; + let Json.443 : List U8 = CallByName List.4 Json.138 Json.446; + jump Json.444 Json.443; else - jump Json.415 Json.135; + jump Json.444 Json.138; -procedure Json.18 (Json.95): - let Json.450 : Str = CallByName Encode.22 Json.95; - ret Json.450; +procedure Json.18 (Json.98): + let Json.479 : Str = CallByName Encode.22 Json.98; + ret Json.479; -procedure Json.21 (Json.124, Json.125): - let Json.398 : {Str, List Str} = Struct {Json.124, Json.125}; - let Json.397 : {Str, List Str} = CallByName Encode.22 Json.398; - ret Json.397; +procedure Json.21 (Json.127, Json.128): + let Json.427 : {Str, List Str} = Struct {Json.127, Json.128}; + let Json.426 : {Str, List Str} = CallByName Encode.22 Json.427; + ret Json.426; -procedure Json.96 (Json.97, Json.440, Json.95): - let Json.449 : I64 = 34i64; - let Json.448 : U8 = CallByName Num.125 Json.449; - let Json.446 : List U8 = CallByName List.4 Json.97 Json.448; - let Json.447 : List U8 = CallByName Str.12 Json.95; - let Json.443 : List U8 = CallByName List.8 Json.446 Json.447; - let Json.445 : I64 = 34i64; - let Json.444 : U8 = CallByName Num.125 Json.445; - let Json.442 : List U8 = CallByName List.4 Json.443 Json.444; - ret Json.442; +procedure Json.99 (Json.100, Json.469, Json.98): + let Json.478 : I64 = 34i64; + let Json.477 : U8 = CallByName Num.127 Json.478; + let Json.475 : List U8 = CallByName List.4 Json.100 Json.477; + let Json.476 : List U8 = CallByName Str.12 Json.98; + let Json.472 : List U8 = CallByName List.8 Json.475 Json.476; + let Json.474 : I64 = 34i64; + let Json.473 : U8 = CallByName Num.127 Json.474; + let Json.471 : List U8 = CallByName List.4 Json.472 Json.473; + ret Json.471; procedure List.138 (List.139, List.140, List.137): - let List.531 : {List U8, U64} = CallByName Json.128 List.139 List.140; - ret List.531; + let List.546 : {List U8, U64} = CallByName Json.131 List.139 List.140; + ret List.546; procedure List.18 (List.135, List.136, List.137): - let List.512 : {List U8, U64} = CallByName List.90 List.135 List.136 List.137; - ret List.512; + let List.527 : {List U8, U64} = CallByName List.91 List.135 List.136 List.137; + ret List.527; procedure List.4 (List.106, List.107): - let List.511 : U64 = 1i64; - let List.510 : List U8 = CallByName List.70 List.106 List.511; - let List.509 : List U8 = CallByName List.71 List.510 List.107; - ret List.509; + let List.526 : U64 = 1i64; + let List.525 : List U8 = CallByName List.70 List.106 List.526; + let List.524 : List U8 = CallByName List.71 List.525 List.107; + ret List.524; procedure List.6 (#Attr.2): - let List.478 : U64 = lowlevel ListLen #Attr.2; - ret List.478; + let List.493 : U64 = lowlevel ListLen #Attr.2; + ret List.493; procedure List.6 (#Attr.2): - let List.532 : U64 = lowlevel ListLen #Attr.2; - ret List.532; + let List.547 : U64 = lowlevel ListLen #Attr.2; + ret List.547; procedure List.66 (#Attr.2, #Attr.3): - let List.528 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.528; + let List.543 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.543; procedure List.70 (#Attr.2, #Attr.3): - let List.484 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.484; + let List.499 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.499; procedure List.71 (#Attr.2, #Attr.3): - let List.482 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.482; + let List.497 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.497; procedure List.8 (#Attr.2, #Attr.3): - let List.534 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.534; + let List.549 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.549; -procedure List.90 (List.426, List.427, List.428): - let List.516 : U64 = 0i64; - let List.517 : U64 = CallByName List.6 List.426; - let List.515 : {List U8, U64} = CallByName List.91 List.426 List.427 List.428 List.516 List.517; - ret List.515; - -procedure List.91 (List.544, List.545, List.546, List.547, List.548): - joinpoint List.518 List.429 List.430 List.431 List.432 List.433: - let List.520 : Int1 = CallByName Num.22 List.432 List.433; - if List.520 then - let List.527 : Str = CallByName List.66 List.429 List.432; - let List.521 : {List U8, U64} = CallByName List.138 List.430 List.527 List.431; - let List.524 : U64 = 1i64; - let List.523 : U64 = CallByName Num.19 List.432 List.524; - jump List.518 List.429 List.521 List.431 List.523 List.433; +procedure List.80 (List.559, List.560, List.561, List.562, List.563): + joinpoint List.533 List.432 List.433 List.434 List.435 List.436: + let List.535 : Int1 = CallByName Num.22 List.435 List.436; + if List.535 then + let List.542 : Str = CallByName List.66 List.432 List.435; + let List.536 : {List U8, U64} = CallByName List.138 List.433 List.542 List.434; + let List.539 : U64 = 1i64; + let List.538 : U64 = CallByName Num.19 List.435 List.539; + jump List.533 List.432 List.536 List.434 List.538 List.436; else - ret List.430; + ret List.433; in - jump List.518 List.544 List.545 List.546 List.547 List.548; + jump List.533 List.559 List.560 List.561 List.562 List.563; -procedure Num.125 (#Attr.2): - let Num.265 : U8 = lowlevel NumIntCast #Attr.2; - ret Num.265; +procedure List.91 (List.429, List.430, List.431): + let List.531 : U64 = 0i64; + let List.532 : U64 = CallByName List.6 List.429; + let List.530 : {List U8, U64} = CallByName List.80 List.429 List.430 List.431 List.531 List.532; + ret List.530; + +procedure Num.127 (#Attr.2): + let Num.284 : U8 = lowlevel NumIntCast #Attr.2; + ret Num.284; procedure Num.19 (#Attr.2, #Attr.3): - let Num.268 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.268; + let Num.287 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.287; procedure Num.20 (#Attr.2, #Attr.3): - let Num.266 : U64 = lowlevel NumSub #Attr.2 #Attr.3; - ret Num.266; + let Num.285 : U64 = lowlevel NumSub #Attr.2 #Attr.3; + ret Num.285; procedure Num.22 (#Attr.2, #Attr.3): - let Num.269 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; - ret Num.269; + let Num.288 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.288; procedure Num.24 (#Attr.2, #Attr.3): - let Num.267 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; - ret Num.267; + let Num.286 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; + ret Num.286; procedure Str.12 (#Attr.2): let Str.280 : List U8 = lowlevel StrToUtf8 #Attr.2; diff --git a/crates/compiler/test_mono/generated/factorial.txt b/crates/compiler/test_mono/generated/factorial.txt index b0319aa20a..e0c96b0c43 100644 --- a/crates/compiler/test_mono/generated/factorial.txt +++ b/crates/compiler/test_mono/generated/factorial.txt @@ -1,10 +1,10 @@ procedure Num.20 (#Attr.2, #Attr.3): - let Num.257 : I64 = lowlevel NumSub #Attr.2 #Attr.3; - ret Num.257; + let Num.276 : I64 = lowlevel NumSub #Attr.2 #Attr.3; + ret Num.276; procedure Num.21 (#Attr.2, #Attr.3): - let Num.256 : I64 = lowlevel NumMul #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : I64 = lowlevel NumMul #Attr.2 #Attr.3; + ret Num.275; procedure Test.1 (Test.15, Test.16): joinpoint Test.7 Test.2 Test.3: diff --git a/crates/compiler/test_mono/generated/function_specialization_information_in_lambda_set_thunk.txt b/crates/compiler/test_mono/generated/function_specialization_information_in_lambda_set_thunk.txt index c6e1133e78..c344eb7f53 100644 --- a/crates/compiler/test_mono/generated/function_specialization_information_in_lambda_set_thunk.txt +++ b/crates/compiler/test_mono/generated/function_specialization_information_in_lambda_set_thunk.txt @@ -1,6 +1,6 @@ procedure Num.19 (#Attr.2, #Attr.3): - let Num.256 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.275; procedure Test.1 (Test.8): let Test.3 : I64 = 10i64; @@ -23,19 +23,19 @@ procedure Test.4 (Test.5, Test.3): jump Test.19 Test.20; default: - let Test.21 : I64 = CallByName Test.7 Test.18; - jump Test.19 Test.21; + let Test.20 : I64 = CallByName Test.7 Test.18; + jump Test.19 Test.20; -procedure Test.6 (Test.22): - let Test.25 : Int1 = true; - let Test.24 : I64 = CallByName Test.2; - let Test.23 : I64 = CallByName Test.4 Test.25 Test.24; - ret Test.23; +procedure Test.6 (Test.21): + let Test.24 : Int1 = true; + let Test.23 : I64 = CallByName Test.2; + let Test.22 : I64 = CallByName Test.4 Test.24 Test.23; + ret Test.22; -procedure Test.7 (Test.26): - let Test.27 : I64 = 10i64; - ret Test.27; +procedure Test.7 (Test.25): + let Test.26 : I64 = 10i64; + ret Test.26; procedure Test.0 (): let Test.11 : Int1 = false; diff --git a/crates/compiler/test_mono/generated/function_specialization_information_in_lambda_set_thunk_independent_defs.txt b/crates/compiler/test_mono/generated/function_specialization_information_in_lambda_set_thunk_independent_defs.txt index 754b2f895a..0c7b8891e0 100644 --- a/crates/compiler/test_mono/generated/function_specialization_information_in_lambda_set_thunk_independent_defs.txt +++ b/crates/compiler/test_mono/generated/function_specialization_information_in_lambda_set_thunk_independent_defs.txt @@ -1,6 +1,6 @@ procedure Num.19 (#Attr.2, #Attr.3): - let Num.257 : U8 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.257; + let Num.276 : U8 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.276; procedure Test.1 (Test.9): let Test.4 : U8 = 10i64; diff --git a/crates/compiler/test_mono/generated/inline_return_joinpoints_in_bool_lambda_set.txt b/crates/compiler/test_mono/generated/inline_return_joinpoints_in_bool_lambda_set.txt new file mode 100644 index 0000000000..fe6e0ec65d --- /dev/null +++ b/crates/compiler/test_mono/generated/inline_return_joinpoints_in_bool_lambda_set.txt @@ -0,0 +1,34 @@ +procedure Bool.1 (): + let Bool.23 : Int1 = false; + ret Bool.23; + +procedure Num.19 (#Attr.2, #Attr.3): + let Num.275 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.275; + +procedure Test.3 (Test.4): + ret Test.4; + +procedure Test.0 (Test.14): + joinpoint Test.5 Test.1: + joinpoint Test.10 Test.2: + let Test.8 : I64 = 1i64; + let Test.7 : I64 = CallByName Num.19 Test.1 Test.8; + switch Test.2: + case 0: + jump Test.5 Test.7; + + default: + let Test.6 : I64 = CallByName Test.3 Test.7; + ret Test.6; + + in + let Test.12 : Int1 = CallByName Bool.1; + if Test.12 then + let Test.9 : Int1 = false; + jump Test.10 Test.9; + else + let Test.9 : Int1 = true; + jump Test.10 Test.9; + in + jump Test.5 Test.14; diff --git a/crates/compiler/test_mono/generated/inline_return_joinpoints_in_enum_lambda_set.txt b/crates/compiler/test_mono/generated/inline_return_joinpoints_in_enum_lambda_set.txt new file mode 100644 index 0000000000..93430cffc9 --- /dev/null +++ b/crates/compiler/test_mono/generated/inline_return_joinpoints_in_enum_lambda_set.txt @@ -0,0 +1,60 @@ +procedure Num.19 (#Attr.2, #Attr.3): + let Num.277 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.277; + +procedure Test.2 (Test.3): + switch Test.3: + case 0: + let Test.16 : U8 = 0u8; + ret Test.16; + + case 1: + let Test.17 : U8 = 1u8; + ret Test.17; + + case 2: + let Test.19 : U8 = 2u8; + ret Test.19; + + default: + let Test.22 : U8 = 3u8; + ret Test.22; + + +procedure Test.4 (Test.5): + ret Test.5; + +procedure Test.6 (Test.7): + let Test.21 : I64 = 1i64; + let Test.20 : I64 = CallByName Num.19 Test.7 Test.21; + ret Test.20; + +procedure Test.8 (Test.9): + let Test.24 : I64 = 2i64; + let Test.23 : I64 = CallByName Num.19 Test.9 Test.24; + ret Test.23; + +procedure Test.0 (Test.30): + joinpoint Test.11 Test.1: + let Test.25 : I64 = 1i64; + let Test.13 : I64 = CallByName Num.19 Test.1 Test.25; + let Test.15 : U8 = 0u8; + let Test.14 : U8 = CallByName Test.2 Test.15; + switch Test.14: + case 0: + jump Test.11 Test.13; + + case 1: + let Test.12 : I64 = CallByName Test.4 Test.13; + ret Test.12; + + case 2: + let Test.12 : I64 = CallByName Test.6 Test.13; + ret Test.12; + + default: + let Test.12 : I64 = CallByName Test.8 Test.13; + ret Test.12; + + in + jump Test.11 Test.30; diff --git a/crates/compiler/test_mono/generated/inline_return_joinpoints_in_union_lambda_set.txt b/crates/compiler/test_mono/generated/inline_return_joinpoints_in_union_lambda_set.txt new file mode 100644 index 0000000000..361c97da60 --- /dev/null +++ b/crates/compiler/test_mono/generated/inline_return_joinpoints_in_union_lambda_set.txt @@ -0,0 +1,36 @@ +procedure Num.19 (#Attr.2, #Attr.3): + let Num.276 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.276; + +procedure Test.2 (Test.3, Test.1): + let Test.17 : Int1 = false; + let Test.18 : Int1 = lowlevel Eq Test.17 Test.3; + if Test.18 then + let Test.13 : [C , C I64] = TagId(0) ; + ret Test.13; + else + let Test.14 : [C , C I64] = TagId(1) Test.1; + ret Test.14; + +procedure Test.4 (Test.5, #Attr.12): + let Test.1 : I64 = UnionAtIndex (Id 1) (Index 0) #Attr.12; + let Test.16 : I64 = CallByName Num.19 Test.5 Test.1; + ret Test.16; + +procedure Test.0 (Test.25): + joinpoint Test.7 Test.1: + let Test.20 : I64 = 1i64; + let Test.9 : I64 = CallByName Num.19 Test.1 Test.20; + let Test.12 : Int1 = false; + let Test.10 : [C , C I64] = CallByName Test.2 Test.12 Test.1; + let Test.11 : U8 = GetTagId Test.10; + switch Test.11: + case 0: + jump Test.7 Test.9; + + default: + let Test.8 : I64 = CallByName Test.4 Test.9 Test.10; + ret Test.8; + + in + jump Test.7 Test.25; diff --git a/crates/compiler/test_mono/generated/ir_int_add.txt b/crates/compiler/test_mono/generated/ir_int_add.txt index 6180e4569c..83bc56e1ab 100644 --- a/crates/compiler/test_mono/generated/ir_int_add.txt +++ b/crates/compiler/test_mono/generated/ir_int_add.txt @@ -1,10 +1,10 @@ procedure List.6 (#Attr.2): - let List.478 : U64 = lowlevel ListLen #Attr.2; - ret List.478; + let List.493 : U64 = lowlevel ListLen #Attr.2; + ret List.493; procedure Num.19 (#Attr.2, #Attr.3): - let Num.258 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.258; + let Num.277 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.277; procedure Test.0 (): let Test.1 : List I64 = Array [1i64, 2i64]; diff --git a/crates/compiler/test_mono/generated/ir_plus.txt b/crates/compiler/test_mono/generated/ir_plus.txt index 2994403a5a..19f312321c 100644 --- a/crates/compiler/test_mono/generated/ir_plus.txt +++ b/crates/compiler/test_mono/generated/ir_plus.txt @@ -1,6 +1,6 @@ procedure Num.19 (#Attr.2, #Attr.3): - let Num.256 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.275; procedure Test.0 (): let Test.2 : I64 = 1i64; diff --git a/crates/compiler/test_mono/generated/ir_round.txt b/crates/compiler/test_mono/generated/ir_round.txt index 0ba65b4515..b385b68115 100644 --- a/crates/compiler/test_mono/generated/ir_round.txt +++ b/crates/compiler/test_mono/generated/ir_round.txt @@ -1,6 +1,6 @@ procedure Num.45 (#Attr.2): - let Num.256 : I64 = lowlevel NumRound #Attr.2; - ret Num.256; + let Num.275 : I64 = lowlevel NumRound #Attr.2; + ret Num.275; procedure Test.0 (): let Test.2 : Float64 = 3.6f64; diff --git a/crates/compiler/test_mono/generated/ir_two_defs.txt b/crates/compiler/test_mono/generated/ir_two_defs.txt index aa2e631fbb..5088e4342b 100644 --- a/crates/compiler/test_mono/generated/ir_two_defs.txt +++ b/crates/compiler/test_mono/generated/ir_two_defs.txt @@ -1,6 +1,6 @@ procedure Num.19 (#Attr.2, #Attr.3): - let Num.256 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.275; procedure Test.0 (): let Test.1 : I64 = 3i64; diff --git a/crates/compiler/test_mono/generated/ir_when_idiv.txt b/crates/compiler/test_mono/generated/ir_when_idiv.txt index 5bd2abf771..1a24b0dd7f 100644 --- a/crates/compiler/test_mono/generated/ir_when_idiv.txt +++ b/crates/compiler/test_mono/generated/ir_when_idiv.txt @@ -1,22 +1,22 @@ procedure Num.30 (#Attr.2): - let Num.263 : I64 = 0i64; - let Num.262 : Int1 = lowlevel Eq #Attr.2 Num.263; - ret Num.262; + let Num.282 : I64 = 0i64; + let Num.281 : Int1 = lowlevel Eq #Attr.2 Num.282; + ret Num.281; procedure Num.39 (#Attr.2, #Attr.3): - let Num.258 : I64 = lowlevel NumDivTruncUnchecked #Attr.2 #Attr.3; - ret Num.258; + let Num.277 : I64 = lowlevel NumDivTruncUnchecked #Attr.2 #Attr.3; + ret Num.277; -procedure Num.40 (Num.228, Num.229): - let Num.259 : Int1 = CallByName Num.30 Num.229; - if Num.259 then - let Num.261 : {} = Struct {}; - let Num.260 : [C {}, C I64] = TagId(0) Num.261; - ret Num.260; +procedure Num.40 (Num.247, Num.248): + let Num.278 : Int1 = CallByName Num.30 Num.248; + if Num.278 then + let Num.280 : {} = Struct {}; + let Num.279 : [C {}, C I64] = TagId(0) Num.280; + ret Num.279; else - let Num.257 : I64 = CallByName Num.39 Num.228 Num.229; - let Num.256 : [C {}, C I64] = TagId(1) Num.257; - ret Num.256; + let Num.276 : I64 = CallByName Num.39 Num.247 Num.248; + let Num.275 : [C {}, C I64] = TagId(1) Num.276; + ret Num.275; procedure Test.0 (): let Test.8 : I64 = 1000i64; diff --git a/crates/compiler/test_mono/generated/ir_when_just.txt b/crates/compiler/test_mono/generated/ir_when_just.txt index 95413986b7..a830281301 100644 --- a/crates/compiler/test_mono/generated/ir_when_just.txt +++ b/crates/compiler/test_mono/generated/ir_when_just.txt @@ -1,6 +1,6 @@ procedure Num.19 (#Attr.2, #Attr.3): - let Num.256 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.275; procedure Test.0 (): let Test.10 : I64 = 41i64; diff --git a/crates/compiler/test_mono/generated/issue_2583_specialize_errors_behind_unified_branches.txt b/crates/compiler/test_mono/generated/issue_2583_specialize_errors_behind_unified_branches.txt index bedc8876e7..0fbbea6c45 100644 --- a/crates/compiler/test_mono/generated/issue_2583_specialize_errors_behind_unified_branches.txt +++ b/crates/compiler/test_mono/generated/issue_2583_specialize_errors_behind_unified_branches.txt @@ -7,43 +7,43 @@ procedure Bool.2 (): ret Bool.23; procedure List.2 (List.95, List.96): - let List.492 : U64 = CallByName List.6 List.95; - let List.488 : Int1 = CallByName Num.22 List.96 List.492; - if List.488 then - let List.490 : I64 = CallByName List.66 List.95 List.96; - let List.489 : [C {}, C I64] = TagId(1) List.490; - ret List.489; + let List.507 : U64 = CallByName List.6 List.95; + let List.503 : Int1 = CallByName Num.22 List.96 List.507; + if List.503 then + let List.505 : I64 = CallByName List.66 List.95 List.96; + let List.504 : [C {}, C I64] = TagId(1) List.505; + ret List.504; else - let List.487 : {} = Struct {}; - let List.486 : [C {}, C I64] = TagId(0) List.487; - ret List.486; + let List.502 : {} = Struct {}; + let List.501 : [C {}, C I64] = TagId(0) List.502; + ret List.501; procedure List.6 (#Attr.2): - let List.493 : U64 = lowlevel ListLen #Attr.2; - ret List.493; + let List.508 : U64 = lowlevel ListLen #Attr.2; + ret List.508; procedure List.66 (#Attr.2, #Attr.3): - let List.491 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.491; + let List.506 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.506; -procedure List.9 (List.283): - let List.485 : U64 = 0i64; - let List.478 : [C {}, C I64] = CallByName List.2 List.283 List.485; - let List.482 : U8 = 1i64; - let List.483 : U8 = GetTagId List.478; - let List.484 : Int1 = lowlevel Eq List.482 List.483; - if List.484 then - let List.284 : I64 = UnionAtIndex (Id 1) (Index 0) List.478; - let List.479 : [C Int1, C I64] = TagId(1) List.284; - ret List.479; +procedure List.9 (List.286): + let List.500 : U64 = 0i64; + let List.493 : [C {}, C I64] = CallByName List.2 List.286 List.500; + let List.497 : U8 = 1i64; + let List.498 : U8 = GetTagId List.493; + let List.499 : Int1 = lowlevel Eq List.497 List.498; + if List.499 then + let List.287 : I64 = UnionAtIndex (Id 1) (Index 0) List.493; + let List.494 : [C Int1, C I64] = TagId(1) List.287; + ret List.494; else - let List.481 : Int1 = true; - let List.480 : [C Int1, C I64] = TagId(0) List.481; - ret List.480; + let List.496 : Int1 = true; + let List.495 : [C Int1, C I64] = TagId(0) List.496; + ret List.495; procedure Num.22 (#Attr.2, #Attr.3): - let Num.256 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.275; procedure Str.27 (Str.96): let Str.265 : [C Int1, C I64] = CallByName Str.69 Str.96; diff --git a/crates/compiler/test_mono/generated/issue_4557.txt b/crates/compiler/test_mono/generated/issue_4557.txt index ba9e7e473b..ac27c966f7 100644 --- a/crates/compiler/test_mono/generated/issue_4557.txt +++ b/crates/compiler/test_mono/generated/issue_4557.txt @@ -8,11 +8,11 @@ procedure Bool.4 (#Attr.2, #Attr.3): procedure Test.1 (Test.2, Test.3): let Test.17 : {Int1, Int1} = Struct {Test.2, Test.3}; - let Test.34 : Int1 = StructAtIndex 0 Test.17; - let Test.33 : Int1 = StructAtIndex 1 Test.17; - let Test.19 : Int1 = CallByName Test.1 Test.33 Test.34; - let Test.27 : {} = Struct {}; - joinpoint Test.28 Test.21: + let Test.32 : Int1 = StructAtIndex 0 Test.17; + let Test.31 : Int1 = StructAtIndex 1 Test.17; + let Test.19 : Int1 = CallByName Test.1 Test.31 Test.32; + let Test.26 : {} = Struct {}; + joinpoint Test.27 Test.21: let Test.23 : {} = Struct {}; joinpoint Test.24 Test.22: let Test.20 : Int1 = CallByName Bool.11 Test.21 Test.22; @@ -21,36 +21,36 @@ procedure Test.1 (Test.2, Test.3): let Test.18 : Int1 = CallByName Bool.4 Test.19 Test.20; ret Test.18; in - switch Test.33: + switch Test.31: case 0: let Test.25 : Str = CallByName Test.9 Test.23; jump Test.24 Test.25; default: - let Test.26 : Str = CallByName Test.11 Test.23; - jump Test.24 Test.26; + let Test.25 : Str = CallByName Test.11 Test.23; + jump Test.24 Test.25; in - switch Test.34: + switch Test.32: case 0: - let Test.29 : Str = CallByName Test.9 Test.27; - jump Test.28 Test.29; + let Test.28 : Str = CallByName Test.9 Test.26; + jump Test.27 Test.28; default: - let Test.30 : Str = CallByName Test.11 Test.27; - jump Test.28 Test.30; + let Test.28 : Str = CallByName Test.11 Test.26; + jump Test.27 Test.28; -procedure Test.11 (Test.36): - let Test.37 : Str = "a"; - ret Test.37; +procedure Test.11 (Test.34): + let Test.35 : Str = "a"; + ret Test.35; -procedure Test.9 (Test.39): - let Test.40 : Str = "a"; - ret Test.40; +procedure Test.9 (Test.37): + let Test.38 : Str = "a"; + ret Test.38; procedure Test.0 (): - let Test.38 : Int1 = false; - let Test.35 : Int1 = true; - let Test.13 : Int1 = CallByName Test.1 Test.38 Test.35; + let Test.36 : Int1 = false; + let Test.33 : Int1 = true; + let Test.13 : Int1 = CallByName Test.1 Test.36 Test.33; ret Test.13; diff --git a/crates/compiler/test_mono/generated/issue_4749.txt b/crates/compiler/test_mono/generated/issue_4749.txt index aabc060876..96c26822bd 100644 --- a/crates/compiler/test_mono/generated/issue_4749.txt +++ b/crates/compiler/test_mono/generated/issue_4749.txt @@ -1,3 +1,7 @@ +procedure Bool.1 (): + let Bool.36 : Int1 = false; + ret Bool.36; + procedure Bool.11 (#Attr.2, #Attr.3): let Bool.23 : Int1 = lowlevel Eq #Attr.2 #Attr.3; dec #Attr.3; @@ -5,30 +9,34 @@ procedure Bool.11 (#Attr.2, #Attr.3): ret Bool.23; procedure Bool.11 (#Attr.2, #Attr.3): - let Bool.31 : Int1 = lowlevel Eq #Attr.2 #Attr.3; - ret Bool.31; + let Bool.39 : Int1 = lowlevel Eq #Attr.2 #Attr.3; + ret Bool.39; procedure Bool.11 (#Attr.2, #Attr.3): - let Bool.38 : Int1 = lowlevel Eq #Attr.2 #Attr.3; - ret Bool.38; + let Bool.46 : Int1 = lowlevel Eq #Attr.2 #Attr.3; + ret Bool.46; procedure Bool.12 (#Attr.2, #Attr.3): - let Bool.30 : Int1 = lowlevel NotEq #Attr.2 #Attr.3; - ret Bool.30; + let Bool.38 : Int1 = lowlevel NotEq #Attr.2 #Attr.3; + ret Bool.38; + +procedure Bool.2 (): + let Bool.35 : Int1 = true; + ret Bool.35; procedure Bool.7 (Bool.19, Bool.20): - let Bool.29 : Int1 = CallByName Bool.12 Bool.19 Bool.20; - ret Bool.29; + let Bool.37 : Int1 = CallByName Bool.12 Bool.19 Bool.20; + ret Bool.37; procedure Decode.23 (Decode.94): ret Decode.94; procedure Decode.24 (Decode.95, Decode.114, Decode.97): - let Decode.127 : {List U8, [C {}, C Str]} = CallByName Json.293 Decode.95 Decode.97; + let Decode.127 : {List U8, [C {}, C Str]} = CallByName Json.300 Decode.95 Decode.97; ret Decode.127; procedure Decode.25 (Decode.98, Decode.99): - let Decode.126 : {} = CallByName Json.41; + let Decode.126 : {} = CallByName Json.42; let Decode.125 : {List U8, [C {}, C Str]} = CallByName Decode.24 Decode.98 Decode.126 Decode.99; ret Decode.125; @@ -62,222 +70,282 @@ procedure Decode.26 (Decode.100, Decode.101): let Decode.116 : [C [C List U8, C ], C Str] = TagId(0) Decode.117; ret Decode.116; -procedure Json.139 (Json.452, Json.453): - joinpoint Json.421 Json.418 Json.138: - let Json.141 : List U8 = StructAtIndex 0 Json.418; - inc Json.141; - let Json.140 : List U8 = StructAtIndex 1 Json.418; - inc Json.140; - dec Json.418; - let Json.422 : [C {}, C U8] = CallByName List.9 Json.141; - let Json.436 : U8 = 1i64; - let Json.437 : U8 = GetTagId Json.422; - let Json.438 : Int1 = lowlevel Eq Json.436 Json.437; - if Json.438 then - let Json.142 : U8 = UnionAtIndex (Id 1) (Index 0) Json.422; - let Json.424 : Int1 = CallByName Json.283 Json.142; - if Json.424 then - let Json.434 : U64 = 1i64; - let Json.430 : {List U8, List U8} = CallByName List.52 Json.141 Json.434; - let Json.431 : {} = Struct {}; - let Json.428 : List U8 = CallByName Json.143 Json.430; - let Json.429 : List U8 = CallByName List.4 Json.140 Json.142; - let Json.426 : {List U8, List U8} = Struct {Json.428, Json.429}; - jump Json.421 Json.426 Json.138; +procedure Json.145 (Json.512, Json.513): + joinpoint Json.450 Json.447 Json.144: + let Json.147 : List U8 = StructAtIndex 0 Json.447; + inc Json.147; + let Json.146 : List U8 = StructAtIndex 1 Json.447; + inc Json.146; + dec Json.447; + joinpoint Json.490: + let Json.487 : {List U8, List U8} = Struct {Json.147, Json.146}; + ret Json.487; + in + let Json.496 : U64 = lowlevel ListLen Json.147; + let Json.497 : U64 = 2i64; + let Json.498 : Int1 = lowlevel NumGte Json.496 Json.497; + if Json.498 then + let Json.489 : U64 = 0i64; + let Json.148 : U8 = lowlevel ListGetUnsafe Json.147 Json.489; + let Json.488 : U64 = 1i64; + let Json.149 : U8 = lowlevel ListGetUnsafe Json.147 Json.488; + let Json.458 : Int1 = CallByName Json.22 Json.148 Json.149; + if Json.458 then + let Json.465 : U64 = 2i64; + let Json.462 : List U8 = CallByName List.29 Json.147 Json.465; + let Json.464 : List U8 = CallByName List.4 Json.146 Json.148; + let Json.463 : List U8 = CallByName List.4 Json.464 Json.149; + let Json.460 : {List U8, List U8} = Struct {Json.462, Json.463}; + jump Json.450 Json.460 Json.144; else - let Json.423 : {List U8, List U8} = Struct {Json.141, Json.140}; - ret Json.423; + let Json.452 : Int1 = CallByName Json.290 Json.148; + if Json.452 then + let Json.456 : List U8 = CallByName List.38 Json.147; + let Json.457 : List U8 = CallByName List.4 Json.146 Json.148; + let Json.454 : {List U8, List U8} = Struct {Json.456, Json.457}; + jump Json.450 Json.454 Json.144; + else + let Json.451 : {List U8, List U8} = Struct {Json.147, Json.146}; + ret Json.451; else - let Json.435 : {List U8, List U8} = Struct {Json.141, Json.140}; - ret Json.435; + let Json.493 : U64 = lowlevel ListLen Json.147; + let Json.494 : U64 = 1i64; + let Json.495 : Int1 = lowlevel NumGte Json.493 Json.494; + if Json.495 then + let Json.492 : U64 = 0i64; + let Json.150 : U8 = lowlevel ListGetUnsafe Json.147 Json.492; + joinpoint Json.485 Json.491: + if Json.491 then + let Json.483 : List U8 = CallByName List.38 Json.147; + let Json.484 : List U8 = CallByName List.4 Json.146 Json.150; + let Json.481 : {List U8, List U8} = Struct {Json.483, Json.484}; + jump Json.450 Json.481 Json.144; + else + jump Json.490; + in + let Json.486 : Int1 = CallByName Json.290 Json.150; + jump Json.485 Json.486; + else + jump Json.490; in - jump Json.421 Json.452 Json.453; - -procedure Json.143 (Json.432): - let Json.433 : List U8 = StructAtIndex 1 Json.432; - inc Json.433; - dec Json.432; - ret Json.433; + jump Json.450 Json.512 Json.513; procedure Json.2 (): - let Json.396 : {} = Struct {}; - ret Json.396; + let Json.425 : {} = Struct {}; + ret Json.425; -procedure Json.22 (Json.137, Json.138): - let Json.440 : List U8 = Array []; - let Json.420 : {List U8, List U8} = Struct {Json.137, Json.440}; - let Json.419 : {List U8, List U8} = CallByName Json.139 Json.420 Json.138; - ret Json.419; - -procedure Json.283 (Json.284): - let Json.442 : U8 = 34i64; - let Json.441 : Int1 = CallByName Bool.7 Json.284 Json.442; - ret Json.441; - -procedure Json.293 (Json.294, Json.399): - let Json.400 : {List U8, [C {}, C Str]} = CallByName Json.40 Json.294; - ret Json.400; - -procedure Json.40 (Json.276): - let Json.446 : U64 = 1i64; - inc Json.276; - let Json.445 : {List U8, List U8} = CallByName List.52 Json.276 Json.446; - let Json.277 : List U8 = StructAtIndex 0 Json.445; - inc Json.277; - let Json.279 : List U8 = StructAtIndex 1 Json.445; - inc Json.279; - dec Json.445; - let Json.444 : U8 = 34i64; - let Json.443 : List U8 = Array [Json.444]; - let Json.404 : Int1 = CallByName Bool.11 Json.277 Json.443; - dec Json.443; - dec Json.277; - if Json.404 then - dec Json.276; - let Json.417 : {} = Struct {}; - let Json.416 : {List U8, List U8} = CallByName Json.22 Json.279 Json.417; - let Json.282 : List U8 = StructAtIndex 0 Json.416; - inc Json.282; - let Json.281 : List U8 = StructAtIndex 1 Json.416; - inc Json.281; - dec Json.416; - let Json.405 : [C {U64, U8}, C Str] = CallByName Str.9 Json.281; - let Json.413 : U8 = 1i64; - let Json.414 : U8 = GetTagId Json.405; - let Json.415 : Int1 = lowlevel Eq Json.413 Json.414; - if Json.415 then - let Json.285 : Str = UnionAtIndex (Id 1) (Index 0) Json.405; - inc Json.285; - dec Json.405; - let Json.409 : U64 = 1i64; - let Json.408 : {List U8, List U8} = CallByName List.52 Json.282 Json.409; - let Json.287 : List U8 = StructAtIndex 1 Json.408; - inc Json.287; - dec Json.408; - let Json.407 : [C {}, C Str] = TagId(1) Json.285; - let Json.406 : {List U8, [C {}, C Str]} = Struct {Json.287, Json.407}; - ret Json.406; - else - dec Json.405; - let Json.412 : {} = Struct {}; - let Json.411 : [C {}, C Str] = TagId(0) Json.412; - let Json.410 : {List U8, [C {}, C Str]} = Struct {Json.282, Json.411}; - ret Json.410; +procedure Json.22 (Json.140, Json.141): + let Json.466 : {U8, U8} = Struct {Json.140, Json.141}; + joinpoint Json.475: + let Json.474 : Int1 = CallByName Bool.1; + ret Json.474; + in + let Json.477 : U8 = StructAtIndex 0 Json.466; + let Json.478 : U8 = 92i64; + let Json.479 : Int1 = lowlevel Eq Json.478 Json.477; + if Json.479 then + let Json.476 : U8 = StructAtIndex 1 Json.466; + switch Json.476: + case 98: + let Json.467 : Int1 = CallByName Bool.2; + ret Json.467; + + case 102: + let Json.468 : Int1 = CallByName Bool.2; + ret Json.468; + + case 110: + let Json.469 : Int1 = CallByName Bool.2; + ret Json.469; + + case 114: + let Json.470 : Int1 = CallByName Bool.2; + ret Json.470; + + case 116: + let Json.471 : Int1 = CallByName Bool.2; + ret Json.471; + + case 34: + let Json.472 : Int1 = CallByName Bool.2; + ret Json.472; + + case 92: + let Json.473 : Int1 = CallByName Bool.2; + ret Json.473; + + default: + jump Json.475; + else - dec Json.279; - let Json.403 : {} = Struct {}; - let Json.402 : [C {}, C Str] = TagId(0) Json.403; - let Json.401 : {List U8, [C {}, C Str]} = Struct {Json.276, Json.402}; - ret Json.401; + jump Json.475; -procedure Json.41 (): - let Json.398 : {} = Struct {}; - let Json.397 : {} = CallByName Decode.23 Json.398; - ret Json.397; +procedure Json.23 (Json.143, Json.144): + let Json.500 : List U8 = Array []; + let Json.449 : {List U8, List U8} = Struct {Json.143, Json.500}; + let Json.448 : {List U8, List U8} = CallByName Json.145 Json.449 Json.144; + ret Json.448; + +procedure Json.290 (Json.291): + let Json.502 : U8 = 34i64; + let Json.501 : Int1 = CallByName Bool.7 Json.291 Json.502; + ret Json.501; + +procedure Json.300 (Json.301, Json.428): + let Json.429 : {List U8, [C {}, C Str]} = CallByName Json.41 Json.301; + ret Json.429; + +procedure Json.41 (Json.283): + let Json.506 : U64 = 1i64; + inc Json.283; + let Json.505 : {List U8, List U8} = CallByName List.52 Json.283 Json.506; + let Json.284 : List U8 = StructAtIndex 0 Json.505; + inc Json.284; + let Json.286 : List U8 = StructAtIndex 1 Json.505; + inc Json.286; + dec Json.505; + let Json.504 : U8 = 34i64; + let Json.503 : List U8 = Array [Json.504]; + let Json.433 : Int1 = CallByName Bool.11 Json.284 Json.503; + dec Json.503; + dec Json.284; + if Json.433 then + dec Json.283; + let Json.446 : {} = Struct {}; + let Json.445 : {List U8, List U8} = CallByName Json.23 Json.286 Json.446; + let Json.289 : List U8 = StructAtIndex 0 Json.445; + inc Json.289; + let Json.288 : List U8 = StructAtIndex 1 Json.445; + inc Json.288; + dec Json.445; + let Json.434 : [C {U64, U8}, C Str] = CallByName Str.9 Json.288; + let Json.442 : U8 = 1i64; + let Json.443 : U8 = GetTagId Json.434; + let Json.444 : Int1 = lowlevel Eq Json.442 Json.443; + if Json.444 then + let Json.292 : Str = UnionAtIndex (Id 1) (Index 0) Json.434; + inc Json.292; + dec Json.434; + let Json.438 : U64 = 1i64; + let Json.437 : {List U8, List U8} = CallByName List.52 Json.289 Json.438; + let Json.294 : List U8 = StructAtIndex 1 Json.437; + inc Json.294; + dec Json.437; + let Json.436 : [C {}, C Str] = TagId(1) Json.292; + let Json.435 : {List U8, [C {}, C Str]} = Struct {Json.294, Json.436}; + ret Json.435; + else + dec Json.434; + let Json.441 : {} = Struct {}; + let Json.440 : [C {}, C Str] = TagId(0) Json.441; + let Json.439 : {List U8, [C {}, C Str]} = Struct {Json.289, Json.440}; + ret Json.439; + else + dec Json.286; + let Json.432 : {} = Struct {}; + let Json.431 : [C {}, C Str] = TagId(0) Json.432; + let Json.430 : {List U8, [C {}, C Str]} = Struct {Json.283, Json.431}; + ret Json.430; + +procedure Json.42 (): + let Json.427 : {} = Struct {}; + let Json.426 : {} = CallByName Decode.23 Json.427; + ret Json.426; procedure List.1 (List.94): - let List.479 : U64 = CallByName List.6 List.94; - let List.480 : U64 = 0i64; - let List.478 : Int1 = CallByName Bool.11 List.479 List.480; - ret List.478; + let List.494 : U64 = CallByName List.6 List.94; + let List.495 : U64 = 0i64; + let List.493 : Int1 = CallByName Bool.11 List.494 List.495; + ret List.493; -procedure List.2 (List.95, List.96): - let List.536 : U64 = CallByName List.6 List.95; - let List.532 : Int1 = CallByName Num.22 List.96 List.536; - if List.532 then - let List.534 : U8 = CallByName List.66 List.95 List.96; - let List.533 : [C {}, C U8] = TagId(1) List.534; - ret List.533; - else - let List.531 : {} = Struct {}; - let List.530 : [C {}, C U8] = TagId(0) List.531; - ret List.530; +procedure List.29 (List.297, List.298): + let List.548 : U64 = CallByName List.6 List.297; + let List.299 : U64 = CallByName Num.77 List.548 List.298; + let List.543 : List U8 = CallByName List.43 List.297 List.299; + ret List.543; + +procedure List.31 (#Attr.2, #Attr.3): + let List.540 : List U8 = lowlevel ListDropAt #Attr.2 #Attr.3; + ret List.540; + +procedure List.38 (List.291): + let List.542 : U64 = 0i64; + let List.541 : List U8 = CallByName List.31 List.291 List.542; + ret List.541; procedure List.4 (List.106, List.107): - let List.520 : U64 = 1i64; - let List.518 : List U8 = CallByName List.70 List.106 List.520; - let List.517 : List U8 = CallByName List.71 List.518 List.107; - ret List.517; - -procedure List.49 (List.366, List.367): - let List.492 : U64 = StructAtIndex 0 List.367; - let List.493 : U64 = 0i64; - let List.490 : Int1 = CallByName Bool.11 List.492 List.493; - if List.490 then - dec List.366; - let List.491 : List U8 = Array []; - ret List.491; - else - let List.487 : U64 = StructAtIndex 1 List.367; - let List.488 : U64 = StructAtIndex 0 List.367; - let List.486 : List U8 = CallByName List.72 List.366 List.487 List.488; - ret List.486; - -procedure List.52 (List.381, List.382): - let List.383 : U64 = CallByName List.6 List.381; - joinpoint List.515 List.384: - let List.513 : U64 = 0i64; - let List.512 : {U64, U64} = Struct {List.384, List.513}; - inc List.381; - let List.385 : List U8 = CallByName List.49 List.381 List.512; - let List.511 : U64 = CallByName Num.20 List.383 List.384; - let List.510 : {U64, U64} = Struct {List.511, List.384}; - let List.386 : List U8 = CallByName List.49 List.381 List.510; - let List.509 : {List U8, List U8} = Struct {List.385, List.386}; - ret List.509; - in - let List.516 : Int1 = CallByName Num.24 List.383 List.382; - if List.516 then - jump List.515 List.382; - else - jump List.515 List.383; - -procedure List.6 (#Attr.2): - let List.556 : U64 = lowlevel ListLen #Attr.2; - ret List.556; - -procedure List.66 (#Attr.2, #Attr.3): - let List.535 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + let List.537 : U64 = 1i64; + let List.536 : List U8 = CallByName List.70 List.106 List.537; + let List.535 : List U8 = CallByName List.71 List.536 List.107; ret List.535; +procedure List.43 (List.295, List.296): + let List.547 : U64 = CallByName List.6 List.295; + let List.546 : U64 = CallByName Num.77 List.547 List.296; + let List.545 : {U64, U64} = Struct {List.296, List.546}; + let List.544 : List U8 = CallByName List.49 List.295 List.545; + ret List.544; + +procedure List.49 (List.369, List.370): + let List.507 : U64 = StructAtIndex 0 List.370; + let List.508 : U64 = 0i64; + let List.505 : Int1 = CallByName Bool.11 List.507 List.508; + if List.505 then + dec List.369; + let List.506 : List U8 = Array []; + ret List.506; + else + let List.502 : U64 = StructAtIndex 1 List.370; + let List.503 : U64 = StructAtIndex 0 List.370; + let List.501 : List U8 = CallByName List.72 List.369 List.502 List.503; + ret List.501; + +procedure List.52 (List.384, List.385): + let List.386 : U64 = CallByName List.6 List.384; + joinpoint List.522 List.387: + let List.520 : U64 = 0i64; + let List.519 : {U64, U64} = Struct {List.387, List.520}; + inc List.384; + let List.388 : List U8 = CallByName List.49 List.384 List.519; + let List.518 : U64 = CallByName Num.20 List.386 List.387; + let List.517 : {U64, U64} = Struct {List.518, List.387}; + let List.389 : List U8 = CallByName List.49 List.384 List.517; + let List.516 : {List U8, List U8} = Struct {List.388, List.389}; + ret List.516; + in + let List.523 : Int1 = CallByName Num.24 List.386 List.385; + if List.523 then + jump List.522 List.385; + else + jump List.522 List.386; + +procedure List.6 (#Attr.2): + let List.570 : U64 = lowlevel ListLen #Attr.2; + ret List.570; + procedure List.70 (#Attr.2, #Attr.3): - let List.521 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.521; + let List.528 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.528; procedure List.71 (#Attr.2, #Attr.3): - let List.519 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.519; + let List.526 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.526; procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.489 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.489; - -procedure List.9 (List.283): - let List.529 : U64 = 0i64; - let List.522 : [C {}, C U8] = CallByName List.2 List.283 List.529; - let List.526 : U8 = 1i64; - let List.527 : U8 = GetTagId List.522; - let List.528 : Int1 = lowlevel Eq List.526 List.527; - if List.528 then - let List.284 : U8 = UnionAtIndex (Id 1) (Index 0) List.522; - let List.523 : [C {}, C U8] = TagId(1) List.284; - ret List.523; - else - let List.525 : {} = Struct {}; - let List.524 : [C {}, C U8] = TagId(0) List.525; - ret List.524; + let List.504 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.504; procedure Num.20 (#Attr.2, #Attr.3): - let Num.258 : U64 = lowlevel NumSub #Attr.2 #Attr.3; - ret Num.258; - -procedure Num.22 (#Attr.2, #Attr.3): - let Num.262 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; - ret Num.262; + let Num.276 : U64 = lowlevel NumSub #Attr.2 #Attr.3; + ret Num.276; procedure Num.24 (#Attr.2, #Attr.3): - let Num.261 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; - ret Num.261; + let Num.278 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; + ret Num.278; + +procedure Num.77 (#Attr.2, #Attr.3): + let Num.280 : U64 = lowlevel NumSubSaturated #Attr.2 #Attr.3; + ret Num.280; procedure Str.48 (#Attr.2, #Attr.3, #Attr.4): let Str.274 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8Range #Attr.2 #Attr.3 #Attr.4; diff --git a/crates/compiler/test_mono/generated/issue_4772_weakened_monomorphic_destructure.txt b/crates/compiler/test_mono/generated/issue_4772_weakened_monomorphic_destructure.txt index 1145a82d45..365ca61197 100644 --- a/crates/compiler/test_mono/generated/issue_4772_weakened_monomorphic_destructure.txt +++ b/crates/compiler/test_mono/generated/issue_4772_weakened_monomorphic_destructure.txt @@ -1,3 +1,7 @@ +procedure Bool.1 (): + let Bool.36 : Int1 = false; + ret Bool.36; + procedure Bool.11 (#Attr.2, #Attr.3): let Bool.23 : Int1 = lowlevel Eq #Attr.2 #Attr.3; dec #Attr.3; @@ -9,243 +13,307 @@ procedure Bool.11 (#Attr.2, #Attr.3): ret Bool.24; procedure Bool.11 (#Attr.2, #Attr.3): - let Bool.31 : Int1 = lowlevel Eq #Attr.2 #Attr.3; - ret Bool.31; + let Bool.39 : Int1 = lowlevel Eq #Attr.2 #Attr.3; + ret Bool.39; procedure Bool.11 (#Attr.2, #Attr.3): - let Bool.38 : Int1 = lowlevel Eq #Attr.2 #Attr.3; - ret Bool.38; + let Bool.46 : Int1 = lowlevel Eq #Attr.2 #Attr.3; + ret Bool.46; procedure Bool.12 (#Attr.2, #Attr.3): - let Bool.30 : Int1 = lowlevel NotEq #Attr.2 #Attr.3; - ret Bool.30; + let Bool.38 : Int1 = lowlevel NotEq #Attr.2 #Attr.3; + ret Bool.38; + +procedure Bool.2 (): + let Bool.35 : Int1 = true; + ret Bool.35; procedure Bool.7 (Bool.19, Bool.20): - let Bool.29 : Int1 = CallByName Bool.12 Bool.19 Bool.20; - ret Bool.29; + let Bool.37 : Int1 = CallByName Bool.12 Bool.19 Bool.20; + ret Bool.37; procedure Decode.23 (Decode.94): ret Decode.94; procedure Decode.24 (Decode.95, Decode.114, Decode.97): - let Decode.117 : {List U8, [C {}, C Str]} = CallByName Json.293 Decode.95 Decode.97; + let Decode.117 : {List U8, [C {}, C Str]} = CallByName Json.300 Decode.95 Decode.97; ret Decode.117; procedure Decode.25 (Decode.98, Decode.99): - let Decode.116 : {} = CallByName Json.41; + let Decode.116 : {} = CallByName Json.42; let Decode.115 : {List U8, [C {}, C Str]} = CallByName Decode.24 Decode.98 Decode.116 Decode.99; ret Decode.115; -procedure Json.139 (Json.452, Json.453): - joinpoint Json.421 Json.418 Json.138: - let Json.141 : List U8 = StructAtIndex 0 Json.418; - inc Json.141; - let Json.140 : List U8 = StructAtIndex 1 Json.418; - inc Json.140; - dec Json.418; - let Json.422 : [C {}, C U8] = CallByName List.9 Json.141; - let Json.436 : U8 = 1i64; - let Json.437 : U8 = GetTagId Json.422; - let Json.438 : Int1 = lowlevel Eq Json.436 Json.437; - if Json.438 then - let Json.142 : U8 = UnionAtIndex (Id 1) (Index 0) Json.422; - let Json.424 : Int1 = CallByName Json.283 Json.142; - if Json.424 then - let Json.434 : U64 = 1i64; - let Json.430 : {List U8, List U8} = CallByName List.52 Json.141 Json.434; - let Json.431 : {} = Struct {}; - let Json.428 : List U8 = CallByName Json.143 Json.430; - let Json.429 : List U8 = CallByName List.4 Json.140 Json.142; - let Json.426 : {List U8, List U8} = Struct {Json.428, Json.429}; - jump Json.421 Json.426 Json.138; +procedure Json.145 (Json.512, Json.513): + joinpoint Json.450 Json.447 Json.144: + let Json.147 : List U8 = StructAtIndex 0 Json.447; + inc Json.147; + let Json.146 : List U8 = StructAtIndex 1 Json.447; + inc Json.146; + dec Json.447; + joinpoint Json.490: + let Json.487 : {List U8, List U8} = Struct {Json.147, Json.146}; + ret Json.487; + in + let Json.496 : U64 = lowlevel ListLen Json.147; + let Json.497 : U64 = 2i64; + let Json.498 : Int1 = lowlevel NumGte Json.496 Json.497; + if Json.498 then + let Json.489 : U64 = 0i64; + let Json.148 : U8 = lowlevel ListGetUnsafe Json.147 Json.489; + let Json.488 : U64 = 1i64; + let Json.149 : U8 = lowlevel ListGetUnsafe Json.147 Json.488; + let Json.458 : Int1 = CallByName Json.22 Json.148 Json.149; + if Json.458 then + let Json.465 : U64 = 2i64; + let Json.462 : List U8 = CallByName List.29 Json.147 Json.465; + let Json.464 : List U8 = CallByName List.4 Json.146 Json.148; + let Json.463 : List U8 = CallByName List.4 Json.464 Json.149; + let Json.460 : {List U8, List U8} = Struct {Json.462, Json.463}; + jump Json.450 Json.460 Json.144; else - let Json.423 : {List U8, List U8} = Struct {Json.141, Json.140}; - ret Json.423; + let Json.452 : Int1 = CallByName Json.290 Json.148; + if Json.452 then + let Json.456 : List U8 = CallByName List.38 Json.147; + let Json.457 : List U8 = CallByName List.4 Json.146 Json.148; + let Json.454 : {List U8, List U8} = Struct {Json.456, Json.457}; + jump Json.450 Json.454 Json.144; + else + let Json.451 : {List U8, List U8} = Struct {Json.147, Json.146}; + ret Json.451; else - let Json.435 : {List U8, List U8} = Struct {Json.141, Json.140}; - ret Json.435; + let Json.493 : U64 = lowlevel ListLen Json.147; + let Json.494 : U64 = 1i64; + let Json.495 : Int1 = lowlevel NumGte Json.493 Json.494; + if Json.495 then + let Json.492 : U64 = 0i64; + let Json.150 : U8 = lowlevel ListGetUnsafe Json.147 Json.492; + joinpoint Json.485 Json.491: + if Json.491 then + let Json.483 : List U8 = CallByName List.38 Json.147; + let Json.484 : List U8 = CallByName List.4 Json.146 Json.150; + let Json.481 : {List U8, List U8} = Struct {Json.483, Json.484}; + jump Json.450 Json.481 Json.144; + else + jump Json.490; + in + let Json.486 : Int1 = CallByName Json.290 Json.150; + jump Json.485 Json.486; + else + jump Json.490; in - jump Json.421 Json.452 Json.453; - -procedure Json.143 (Json.432): - let Json.433 : List U8 = StructAtIndex 1 Json.432; - inc Json.433; - dec Json.432; - ret Json.433; + jump Json.450 Json.512 Json.513; procedure Json.2 (): - let Json.396 : {} = Struct {}; - ret Json.396; + let Json.425 : {} = Struct {}; + ret Json.425; -procedure Json.22 (Json.137, Json.138): - let Json.440 : List U8 = Array []; - let Json.420 : {List U8, List U8} = Struct {Json.137, Json.440}; - let Json.419 : {List U8, List U8} = CallByName Json.139 Json.420 Json.138; - ret Json.419; +procedure Json.22 (Json.140, Json.141): + let Json.466 : {U8, U8} = Struct {Json.140, Json.141}; + joinpoint Json.475: + let Json.474 : Int1 = CallByName Bool.1; + ret Json.474; + in + let Json.477 : U8 = StructAtIndex 0 Json.466; + let Json.478 : U8 = 92i64; + let Json.479 : Int1 = lowlevel Eq Json.478 Json.477; + if Json.479 then + let Json.476 : U8 = StructAtIndex 1 Json.466; + switch Json.476: + case 98: + let Json.467 : Int1 = CallByName Bool.2; + ret Json.467; + + case 102: + let Json.468 : Int1 = CallByName Bool.2; + ret Json.468; + + case 110: + let Json.469 : Int1 = CallByName Bool.2; + ret Json.469; + + case 114: + let Json.470 : Int1 = CallByName Bool.2; + ret Json.470; + + case 116: + let Json.471 : Int1 = CallByName Bool.2; + ret Json.471; + + case 34: + let Json.472 : Int1 = CallByName Bool.2; + ret Json.472; + + case 92: + let Json.473 : Int1 = CallByName Bool.2; + ret Json.473; + + default: + jump Json.475; + + else + jump Json.475; -procedure Json.283 (Json.284): - let Json.442 : U8 = 34i64; - let Json.441 : Int1 = CallByName Bool.7 Json.284 Json.442; - ret Json.441; +procedure Json.23 (Json.143, Json.144): + let Json.500 : List U8 = Array []; + let Json.449 : {List U8, List U8} = Struct {Json.143, Json.500}; + let Json.448 : {List U8, List U8} = CallByName Json.145 Json.449 Json.144; + ret Json.448; -procedure Json.293 (Json.294, Json.399): - let Json.400 : {List U8, [C {}, C Str]} = CallByName Json.40 Json.294; - ret Json.400; +procedure Json.290 (Json.291): + let Json.502 : U8 = 34i64; + let Json.501 : Int1 = CallByName Bool.7 Json.291 Json.502; + ret Json.501; -procedure Json.40 (Json.276): - let Json.446 : U64 = 1i64; - inc Json.276; - let Json.445 : {List U8, List U8} = CallByName List.52 Json.276 Json.446; - let Json.277 : List U8 = StructAtIndex 0 Json.445; - inc Json.277; - let Json.279 : List U8 = StructAtIndex 1 Json.445; - inc Json.279; - dec Json.445; - let Json.444 : U8 = 34i64; - let Json.443 : List U8 = Array [Json.444]; - let Json.404 : Int1 = CallByName Bool.11 Json.277 Json.443; - dec Json.443; - dec Json.277; - if Json.404 then - dec Json.276; - let Json.417 : {} = Struct {}; - let Json.416 : {List U8, List U8} = CallByName Json.22 Json.279 Json.417; - let Json.282 : List U8 = StructAtIndex 0 Json.416; - inc Json.282; - let Json.281 : List U8 = StructAtIndex 1 Json.416; - inc Json.281; - dec Json.416; - let Json.405 : [C {U64, U8}, C Str] = CallByName Str.9 Json.281; - let Json.413 : U8 = 1i64; - let Json.414 : U8 = GetTagId Json.405; - let Json.415 : Int1 = lowlevel Eq Json.413 Json.414; - if Json.415 then - let Json.285 : Str = UnionAtIndex (Id 1) (Index 0) Json.405; - inc Json.285; - dec Json.405; - let Json.409 : U64 = 1i64; - let Json.408 : {List U8, List U8} = CallByName List.52 Json.282 Json.409; - let Json.287 : List U8 = StructAtIndex 1 Json.408; - inc Json.287; - dec Json.408; - let Json.407 : [C {}, C Str] = TagId(1) Json.285; - let Json.406 : {List U8, [C {}, C Str]} = Struct {Json.287, Json.407}; - ret Json.406; +procedure Json.300 (Json.301, Json.428): + let Json.429 : {List U8, [C {}, C Str]} = CallByName Json.41 Json.301; + ret Json.429; + +procedure Json.41 (Json.283): + let Json.506 : U64 = 1i64; + inc Json.283; + let Json.505 : {List U8, List U8} = CallByName List.52 Json.283 Json.506; + let Json.284 : List U8 = StructAtIndex 0 Json.505; + inc Json.284; + let Json.286 : List U8 = StructAtIndex 1 Json.505; + inc Json.286; + dec Json.505; + let Json.504 : U8 = 34i64; + let Json.503 : List U8 = Array [Json.504]; + let Json.433 : Int1 = CallByName Bool.11 Json.284 Json.503; + dec Json.503; + dec Json.284; + if Json.433 then + dec Json.283; + let Json.446 : {} = Struct {}; + let Json.445 : {List U8, List U8} = CallByName Json.23 Json.286 Json.446; + let Json.289 : List U8 = StructAtIndex 0 Json.445; + inc Json.289; + let Json.288 : List U8 = StructAtIndex 1 Json.445; + inc Json.288; + dec Json.445; + let Json.434 : [C {U64, U8}, C Str] = CallByName Str.9 Json.288; + let Json.442 : U8 = 1i64; + let Json.443 : U8 = GetTagId Json.434; + let Json.444 : Int1 = lowlevel Eq Json.442 Json.443; + if Json.444 then + let Json.292 : Str = UnionAtIndex (Id 1) (Index 0) Json.434; + inc Json.292; + dec Json.434; + let Json.438 : U64 = 1i64; + let Json.437 : {List U8, List U8} = CallByName List.52 Json.289 Json.438; + let Json.294 : List U8 = StructAtIndex 1 Json.437; + inc Json.294; + dec Json.437; + let Json.436 : [C {}, C Str] = TagId(1) Json.292; + let Json.435 : {List U8, [C {}, C Str]} = Struct {Json.294, Json.436}; + ret Json.435; else - dec Json.405; - let Json.412 : {} = Struct {}; - let Json.411 : [C {}, C Str] = TagId(0) Json.412; - let Json.410 : {List U8, [C {}, C Str]} = Struct {Json.282, Json.411}; - ret Json.410; + dec Json.434; + let Json.441 : {} = Struct {}; + let Json.440 : [C {}, C Str] = TagId(0) Json.441; + let Json.439 : {List U8, [C {}, C Str]} = Struct {Json.289, Json.440}; + ret Json.439; else - dec Json.279; - let Json.403 : {} = Struct {}; - let Json.402 : [C {}, C Str] = TagId(0) Json.403; - let Json.401 : {List U8, [C {}, C Str]} = Struct {Json.276, Json.402}; - ret Json.401; + dec Json.286; + let Json.432 : {} = Struct {}; + let Json.431 : [C {}, C Str] = TagId(0) Json.432; + let Json.430 : {List U8, [C {}, C Str]} = Struct {Json.283, Json.431}; + ret Json.430; -procedure Json.41 (): - let Json.398 : {} = Struct {}; - let Json.397 : {} = CallByName Decode.23 Json.398; - ret Json.397; +procedure Json.42 (): + let Json.427 : {} = Struct {}; + let Json.426 : {} = CallByName Decode.23 Json.427; + ret Json.426; -procedure List.2 (List.95, List.96): - let List.530 : U64 = CallByName List.6 List.95; - let List.526 : Int1 = CallByName Num.22 List.96 List.530; - if List.526 then - let List.528 : U8 = CallByName List.66 List.95 List.96; - let List.527 : [C {}, C U8] = TagId(1) List.528; - ret List.527; - else - let List.525 : {} = Struct {}; - let List.524 : [C {}, C U8] = TagId(0) List.525; - ret List.524; +procedure List.29 (List.297, List.298): + let List.542 : U64 = CallByName List.6 List.297; + let List.299 : U64 = CallByName Num.77 List.542 List.298; + let List.537 : List U8 = CallByName List.43 List.297 List.299; + ret List.537; + +procedure List.31 (#Attr.2, #Attr.3): + let List.534 : List U8 = lowlevel ListDropAt #Attr.2 #Attr.3; + ret List.534; + +procedure List.38 (List.291): + let List.536 : U64 = 0i64; + let List.535 : List U8 = CallByName List.31 List.291 List.536; + ret List.535; procedure List.4 (List.106, List.107): - let List.514 : U64 = 1i64; - let List.512 : List U8 = CallByName List.70 List.106 List.514; - let List.511 : List U8 = CallByName List.71 List.512 List.107; - ret List.511; - -procedure List.49 (List.366, List.367): - let List.486 : U64 = StructAtIndex 0 List.367; - let List.487 : U64 = 0i64; - let List.484 : Int1 = CallByName Bool.11 List.486 List.487; - if List.484 then - dec List.366; - let List.485 : List U8 = Array []; - ret List.485; - else - let List.481 : U64 = StructAtIndex 1 List.367; - let List.482 : U64 = StructAtIndex 0 List.367; - let List.480 : List U8 = CallByName List.72 List.366 List.481 List.482; - ret List.480; - -procedure List.52 (List.381, List.382): - let List.383 : U64 = CallByName List.6 List.381; - joinpoint List.509 List.384: - let List.507 : U64 = 0i64; - let List.506 : {U64, U64} = Struct {List.384, List.507}; - inc List.381; - let List.385 : List U8 = CallByName List.49 List.381 List.506; - let List.505 : U64 = CallByName Num.20 List.383 List.384; - let List.504 : {U64, U64} = Struct {List.505, List.384}; - let List.386 : List U8 = CallByName List.49 List.381 List.504; - let List.503 : {List U8, List U8} = Struct {List.385, List.386}; - ret List.503; - in - let List.510 : Int1 = CallByName Num.24 List.383 List.382; - if List.510 then - jump List.509 List.382; - else - jump List.509 List.383; - -procedure List.6 (#Attr.2): - let List.550 : U64 = lowlevel ListLen #Attr.2; - ret List.550; - -procedure List.66 (#Attr.2, #Attr.3): - let List.529 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + let List.531 : U64 = 1i64; + let List.530 : List U8 = CallByName List.70 List.106 List.531; + let List.529 : List U8 = CallByName List.71 List.530 List.107; ret List.529; +procedure List.43 (List.295, List.296): + let List.541 : U64 = CallByName List.6 List.295; + let List.540 : U64 = CallByName Num.77 List.541 List.296; + let List.539 : {U64, U64} = Struct {List.296, List.540}; + let List.538 : List U8 = CallByName List.49 List.295 List.539; + ret List.538; + +procedure List.49 (List.369, List.370): + let List.501 : U64 = StructAtIndex 0 List.370; + let List.502 : U64 = 0i64; + let List.499 : Int1 = CallByName Bool.11 List.501 List.502; + if List.499 then + dec List.369; + let List.500 : List U8 = Array []; + ret List.500; + else + let List.496 : U64 = StructAtIndex 1 List.370; + let List.497 : U64 = StructAtIndex 0 List.370; + let List.495 : List U8 = CallByName List.72 List.369 List.496 List.497; + ret List.495; + +procedure List.52 (List.384, List.385): + let List.386 : U64 = CallByName List.6 List.384; + joinpoint List.516 List.387: + let List.514 : U64 = 0i64; + let List.513 : {U64, U64} = Struct {List.387, List.514}; + inc List.384; + let List.388 : List U8 = CallByName List.49 List.384 List.513; + let List.512 : U64 = CallByName Num.20 List.386 List.387; + let List.511 : {U64, U64} = Struct {List.512, List.387}; + let List.389 : List U8 = CallByName List.49 List.384 List.511; + let List.510 : {List U8, List U8} = Struct {List.388, List.389}; + ret List.510; + in + let List.517 : Int1 = CallByName Num.24 List.386 List.385; + if List.517 then + jump List.516 List.385; + else + jump List.516 List.386; + +procedure List.6 (#Attr.2): + let List.564 : U64 = lowlevel ListLen #Attr.2; + ret List.564; + procedure List.70 (#Attr.2, #Attr.3): - let List.515 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.515; + let List.522 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.522; procedure List.71 (#Attr.2, #Attr.3): - let List.513 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.513; + let List.520 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.520; procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.483 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.483; - -procedure List.9 (List.283): - let List.523 : U64 = 0i64; - let List.516 : [C {}, C U8] = CallByName List.2 List.283 List.523; - let List.520 : U8 = 1i64; - let List.521 : U8 = GetTagId List.516; - let List.522 : Int1 = lowlevel Eq List.520 List.521; - if List.522 then - let List.284 : U8 = UnionAtIndex (Id 1) (Index 0) List.516; - let List.517 : [C {}, C U8] = TagId(1) List.284; - ret List.517; - else - let List.519 : {} = Struct {}; - let List.518 : [C {}, C U8] = TagId(0) List.519; - ret List.518; + let List.498 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.498; procedure Num.20 (#Attr.2, #Attr.3): - let Num.258 : U64 = lowlevel NumSub #Attr.2 #Attr.3; - ret Num.258; - -procedure Num.22 (#Attr.2, #Attr.3): - let Num.262 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; - ret Num.262; + let Num.276 : U64 = lowlevel NumSub #Attr.2 #Attr.3; + ret Num.276; procedure Num.24 (#Attr.2, #Attr.3): - let Num.261 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; - ret Num.261; + let Num.278 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; + ret Num.278; + +procedure Num.77 (#Attr.2, #Attr.3): + let Num.280 : U64 = lowlevel NumSubSaturated #Attr.2 #Attr.3; + ret Num.280; procedure Str.12 (#Attr.2): let Str.274 : List U8 = lowlevel StrToUtf8 #Attr.2; diff --git a/crates/compiler/test_mono/generated/lambda_capture_niche_u8_vs_u64.txt b/crates/compiler/test_mono/generated/lambda_capture_niche_u8_vs_u64.txt index 351d5255f1..33ffa57579 100644 --- a/crates/compiler/test_mono/generated/lambda_capture_niche_u8_vs_u64.txt +++ b/crates/compiler/test_mono/generated/lambda_capture_niche_u8_vs_u64.txt @@ -1,54 +1,51 @@ -procedure Num.94 (#Attr.2): - let Num.256 : Str = lowlevel NumToStr #Attr.2; - ret Num.256; +procedure Num.96 (#Attr.2): + let Num.275 : Str = lowlevel NumToStr #Attr.2; + ret Num.275; -procedure Num.94 (#Attr.2): - let Num.257 : Str = lowlevel NumToStr #Attr.2; - ret Num.257; +procedure Num.96 (#Attr.2): + let Num.276 : Str = lowlevel NumToStr #Attr.2; + ret Num.276; procedure Test.1 (Test.4): - let Test.16 : [C U8, C U64] = TagId(1) Test.4; - ret Test.16; + let Test.13 : [C U8, C U64] = TagId(1) Test.4; + ret Test.13; procedure Test.1 (Test.4): - let Test.22 : [C U8, C U64] = TagId(0) Test.4; - ret Test.22; - -procedure Test.5 (Test.17, #Attr.12): - let Test.4 : U64 = UnionAtIndex (Id 1) (Index 0) #Attr.12; - let Test.19 : Str = CallByName Num.94 Test.4; + let Test.19 : [C U8, C U64] = TagId(0) Test.4; ret Test.19; -procedure Test.5 (Test.17, #Attr.12): +procedure Test.5 (Test.14, #Attr.12): + let Test.4 : U64 = UnionAtIndex (Id 1) (Index 0) #Attr.12; + let Test.16 : Str = CallByName Num.96 Test.4; + ret Test.16; + +procedure Test.5 (Test.14, #Attr.12): let Test.4 : U8 = UnionAtIndex (Id 0) (Index 0) #Attr.12; - let Test.25 : Str = CallByName Num.94 Test.4; - ret Test.25; + let Test.22 : Str = CallByName Num.96 Test.4; + ret Test.22; procedure Test.0 (): let Test.2 : Int1 = true; - joinpoint Test.13 Test.3: + joinpoint Test.10 Test.3: let Test.8 : {} = Struct {}; let Test.9 : U8 = GetTagId Test.3; - joinpoint Test.10 Test.7: - ret Test.7; - in switch Test.9: case 0: - let Test.11 : Str = CallByName Test.5 Test.8 Test.3; - jump Test.10 Test.11; + let Test.7 : Str = CallByName Test.5 Test.8 Test.3; + ret Test.7; default: - let Test.12 : Str = CallByName Test.5 Test.8 Test.3; - jump Test.10 Test.12; + let Test.7 : Str = CallByName Test.5 Test.8 Test.3; + ret Test.7; in - let Test.26 : Int1 = true; - let Test.27 : Int1 = lowlevel Eq Test.26 Test.2; - if Test.27 then - let Test.15 : U64 = 123i64; - let Test.14 : [C U8, C U64] = CallByName Test.1 Test.15; - jump Test.13 Test.14; + let Test.23 : Int1 = true; + let Test.24 : Int1 = lowlevel Eq Test.23 Test.2; + if Test.24 then + let Test.12 : U64 = 123i64; + let Test.11 : [C U8, C U64] = CallByName Test.1 Test.12; + jump Test.10 Test.11; else - let Test.21 : U8 = 18i64; - let Test.20 : [C U8, C U64] = CallByName Test.1 Test.21; - jump Test.13 Test.20; + let Test.18 : U8 = 18i64; + let Test.17 : [C U8, C U64] = CallByName Test.1 Test.18; + jump Test.10 Test.17; diff --git a/crates/compiler/test_mono/generated/lambda_capture_niches_have_captured_function_in_closure.txt b/crates/compiler/test_mono/generated/lambda_capture_niches_have_captured_function_in_closure.txt index f4b8c206eb..87fadf120d 100644 --- a/crates/compiler/test_mono/generated/lambda_capture_niches_have_captured_function_in_closure.txt +++ b/crates/compiler/test_mono/generated/lambda_capture_niches_have_captured_function_in_closure.txt @@ -1,83 +1,80 @@ -procedure Test.11 (Test.37): - let Test.38 : Str = ""; - ret Test.38; +procedure Test.11 (Test.34): + let Test.35 : Str = ""; + ret Test.35; -procedure Test.13 (Test.51, Test.12): +procedure Test.13 (Test.48, Test.12): ret Test.12; -procedure Test.15 (Test.39): - let Test.40 : Str = ""; - ret Test.40; +procedure Test.15 (Test.36): + let Test.37 : Str = ""; + ret Test.37; -procedure Test.16 (Test.54): - let Test.56 : Str = "s1"; - ret Test.56; +procedure Test.16 (Test.51): + let Test.53 : Str = "s1"; + ret Test.53; procedure Test.2 (Test.7, Test.8): - let Test.30 : [C {} {}, C {} {}] = TagId(1) Test.7 Test.8; - ret Test.30; + let Test.27 : [C {} {}, C {} {}] = TagId(1) Test.7 Test.8; + ret Test.27; procedure Test.2 (Test.7, Test.8): - let Test.44 : [C {} {}, C {} {}] = TagId(0) Test.7 Test.8; - ret Test.44; + let Test.41 : [C {} {}, C {} {}] = TagId(0) Test.7 Test.8; + ret Test.41; procedure Test.3 (Test.17): - let Test.36 : {} = Struct {}; - ret Test.36; + let Test.33 : {} = Struct {}; + ret Test.33; procedure Test.4 (Test.18): inc Test.18; ret Test.18; -procedure Test.9 (Test.29, #Attr.12): +procedure Test.9 (Test.26, #Attr.12): let Test.8 : {} = UnionAtIndex (Id 0) (Index 1) #Attr.12; let Test.7 : {} = UnionAtIndex (Id 0) (Index 0) #Attr.12; - let Test.49 : {} = Struct {}; - let Test.48 : Str = CallByName Test.16 Test.49; - let Test.45 : Str = CallByName Test.4 Test.48; - dec Test.48; - let Test.47 : {} = Struct {}; - let Test.46 : Str = CallByName Test.13 Test.47 Test.45; - ret Test.46; + let Test.46 : {} = Struct {}; + let Test.45 : Str = CallByName Test.16 Test.46; + let Test.42 : Str = CallByName Test.4 Test.45; + dec Test.45; + let Test.44 : {} = Struct {}; + let Test.43 : Str = CallByName Test.13 Test.44 Test.42; + ret Test.43; -procedure Test.9 (Test.29, #Attr.12): +procedure Test.9 (Test.26, #Attr.12): let Test.8 : {} = UnionAtIndex (Id 1) (Index 1) #Attr.12; let Test.7 : {} = UnionAtIndex (Id 1) (Index 0) #Attr.12; - let Test.35 : {} = Struct {}; - let Test.34 : Str = CallByName Test.15 Test.35; - let Test.31 : {} = CallByName Test.3 Test.34; - dec Test.34; - let Test.33 : {} = Struct {}; - let Test.32 : Str = CallByName Test.11 Test.33; - ret Test.32; + let Test.32 : {} = Struct {}; + let Test.31 : Str = CallByName Test.15 Test.32; + let Test.28 : {} = CallByName Test.3 Test.31; + dec Test.31; + let Test.30 : {} = Struct {}; + let Test.29 : Str = CallByName Test.11 Test.30; + ret Test.29; procedure Test.0 (): let Test.5 : Int1 = true; - joinpoint Test.25 Test.6: + joinpoint Test.22 Test.6: let Test.20 : {} = Struct {}; let Test.21 : U8 = GetTagId Test.6; - joinpoint Test.22 Test.19: - ret Test.19; - in switch Test.21: case 0: - let Test.23 : Str = CallByName Test.9 Test.20 Test.6; - jump Test.22 Test.23; + let Test.19 : Str = CallByName Test.9 Test.20 Test.6; + ret Test.19; default: - let Test.24 : Str = CallByName Test.9 Test.20 Test.6; - jump Test.22 Test.24; + let Test.19 : Str = CallByName Test.9 Test.20 Test.6; + ret Test.19; in - let Test.57 : Int1 = true; - let Test.58 : Int1 = lowlevel Eq Test.57 Test.5; - if Test.58 then - let Test.27 : {} = Struct {}; - let Test.28 : {} = Struct {}; - let Test.26 : [C {} {}, C {} {}] = CallByName Test.2 Test.27 Test.28; - jump Test.25 Test.26; + let Test.54 : Int1 = true; + let Test.55 : Int1 = lowlevel Eq Test.54 Test.5; + if Test.55 then + let Test.24 : {} = Struct {}; + let Test.25 : {} = Struct {}; + let Test.23 : [C {} {}, C {} {}] = CallByName Test.2 Test.24 Test.25; + jump Test.22 Test.23; else - let Test.42 : {} = Struct {}; - let Test.43 : {} = Struct {}; - let Test.41 : [C {} {}, C {} {}] = CallByName Test.2 Test.42 Test.43; - jump Test.25 Test.41; + let Test.39 : {} = Struct {}; + let Test.40 : {} = Struct {}; + let Test.38 : [C {} {}, C {} {}] = CallByName Test.2 Test.39 Test.40; + jump Test.22 Test.38; diff --git a/crates/compiler/test_mono/generated/lambda_capture_niches_with_non_capturing_function.txt b/crates/compiler/test_mono/generated/lambda_capture_niches_with_non_capturing_function.txt index 4985129845..32d303f9ea 100644 --- a/crates/compiler/test_mono/generated/lambda_capture_niches_with_non_capturing_function.txt +++ b/crates/compiler/test_mono/generated/lambda_capture_niches_with_non_capturing_function.txt @@ -1,59 +1,56 @@ procedure Test.1 (Test.5): - let Test.19 : [C , C {}, C U64] = TagId(1) Test.5; - ret Test.19; + let Test.15 : [C , C {}, C U64] = TagId(1) Test.5; + ret Test.15; procedure Test.1 (Test.5): - let Test.27 : [C , C {}, C U64] = TagId(2) Test.5; - ret Test.27; + let Test.23 : [C , C {}, C U64] = TagId(2) Test.5; + ret Test.23; procedure Test.2 (Test.8): - let Test.24 : Str = ""; - ret Test.24; + let Test.20 : Str = ""; + ret Test.20; -procedure Test.6 (Test.20, #Attr.12): +procedure Test.6 (Test.16, #Attr.12): let Test.5 : U64 = UnionAtIndex (Id 2) (Index 0) #Attr.12; - let Test.30 : Str = ""; - ret Test.30; + let Test.26 : Str = ""; + ret Test.26; -procedure Test.6 (Test.20, #Attr.12): +procedure Test.6 (Test.16, #Attr.12): let Test.5 : {} = UnionAtIndex (Id 1) (Index 0) #Attr.12; - let Test.22 : Str = ""; - ret Test.22; + let Test.18 : Str = ""; + ret Test.18; procedure Test.0 (): let Test.3 : U8 = 0u8; - joinpoint Test.16 Test.4: + joinpoint Test.12 Test.4: let Test.10 : {} = Struct {}; let Test.11 : U8 = GetTagId Test.4; - joinpoint Test.12 Test.9: - ret Test.9; - in switch Test.11: case 0: - let Test.13 : Str = CallByName Test.2 Test.10; - jump Test.12 Test.13; + let Test.9 : Str = CallByName Test.2 Test.10; + ret Test.9; case 1: - let Test.14 : Str = CallByName Test.6 Test.10 Test.4; - jump Test.12 Test.14; + let Test.9 : Str = CallByName Test.6 Test.10 Test.4; + ret Test.9; default: - let Test.15 : Str = CallByName Test.6 Test.10 Test.4; - jump Test.12 Test.15; + let Test.9 : Str = CallByName Test.6 Test.10 Test.4; + ret Test.9; in switch Test.3: case 0: - let Test.18 : {} = Struct {}; - let Test.17 : [C , C {}, C U64] = CallByName Test.1 Test.18; - jump Test.16 Test.17; + let Test.14 : {} = Struct {}; + let Test.13 : [C , C {}, C U64] = CallByName Test.1 Test.14; + jump Test.12 Test.13; case 1: - let Test.23 : [C , C {}, C U64] = TagId(0) ; - jump Test.16 Test.23; + let Test.19 : [C , C {}, C U64] = TagId(0) ; + jump Test.12 Test.19; default: - let Test.26 : U64 = 1i64; - let Test.25 : [C , C {}, C U64] = CallByName Test.1 Test.26; - jump Test.16 Test.25; + let Test.22 : U64 = 1i64; + let Test.21 : [C , C {}, C U64] = CallByName Test.1 Test.22; + jump Test.12 Test.21; diff --git a/crates/compiler/test_mono/generated/lambda_capture_niches_with_other_lambda_capture.txt b/crates/compiler/test_mono/generated/lambda_capture_niches_with_other_lambda_capture.txt index c41608e5c6..c87461357e 100644 --- a/crates/compiler/test_mono/generated/lambda_capture_niches_with_other_lambda_capture.txt +++ b/crates/compiler/test_mono/generated/lambda_capture_niches_with_other_lambda_capture.txt @@ -1,28 +1,28 @@ procedure Test.1 (Test.5): - let Test.20 : [C {}, C U64, C Str] = TagId(0) Test.5; - ret Test.20; + let Test.16 : [C {}, C U64, C Str] = TagId(0) Test.5; + ret Test.16; procedure Test.1 (Test.5): - let Test.32 : [C {}, C U64, C Str] = TagId(1) Test.5; - ret Test.32; + let Test.28 : [C {}, C U64, C Str] = TagId(1) Test.5; + ret Test.28; procedure Test.2 (Test.7): - let Test.26 : [C {}, C U64, C Str] = TagId(2) Test.7; - ret Test.26; + let Test.22 : [C {}, C U64, C Str] = TagId(2) Test.7; + ret Test.22; -procedure Test.6 (Test.21, #Attr.12): +procedure Test.6 (Test.17, #Attr.12): let Test.5 : U64 = UnionAtIndex (Id 1) (Index 0) #Attr.12; dec #Attr.12; - let Test.35 : Str = ""; - ret Test.35; + let Test.31 : Str = ""; + ret Test.31; -procedure Test.6 (Test.21, #Attr.12): +procedure Test.6 (Test.17, #Attr.12): let Test.5 : {} = UnionAtIndex (Id 0) (Index 0) #Attr.12; dec #Attr.12; - let Test.23 : Str = ""; - ret Test.23; + let Test.19 : Str = ""; + ret Test.19; -procedure Test.8 (Test.27, #Attr.12): +procedure Test.8 (Test.23, #Attr.12): let Test.7 : Str = UnionAtIndex (Id 2) (Index 0) #Attr.12; inc Test.7; dec #Attr.12; @@ -30,39 +30,36 @@ procedure Test.8 (Test.27, #Attr.12): procedure Test.0 (): let Test.3 : U8 = 0u8; - joinpoint Test.17 Test.4: + joinpoint Test.13 Test.4: let Test.11 : {} = Struct {}; let Test.12 : U8 = GetTagId Test.4; - joinpoint Test.13 Test.10: - ret Test.10; - in switch Test.12: case 0: - let Test.14 : Str = CallByName Test.6 Test.11 Test.4; - jump Test.13 Test.14; + let Test.10 : Str = CallByName Test.6 Test.11 Test.4; + ret Test.10; case 1: - let Test.15 : Str = CallByName Test.6 Test.11 Test.4; - jump Test.13 Test.15; + let Test.10 : Str = CallByName Test.6 Test.11 Test.4; + ret Test.10; default: - let Test.16 : Str = CallByName Test.8 Test.11 Test.4; - jump Test.13 Test.16; + let Test.10 : Str = CallByName Test.8 Test.11 Test.4; + ret Test.10; in switch Test.3: case 0: - let Test.19 : {} = Struct {}; - let Test.18 : [C {}, C U64, C Str] = CallByName Test.1 Test.19; - jump Test.17 Test.18; + let Test.15 : {} = Struct {}; + let Test.14 : [C {}, C U64, C Str] = CallByName Test.1 Test.15; + jump Test.13 Test.14; case 1: - let Test.25 : Str = "foo"; - let Test.24 : [C {}, C U64, C Str] = CallByName Test.2 Test.25; - jump Test.17 Test.24; + let Test.21 : Str = "foo"; + let Test.20 : [C {}, C U64, C Str] = CallByName Test.2 Test.21; + jump Test.13 Test.20; default: - let Test.31 : U64 = 1i64; - let Test.30 : [C {}, C U64, C Str] = CallByName Test.1 Test.31; - jump Test.17 Test.30; + let Test.27 : U64 = 1i64; + let Test.26 : [C {}, C U64, C Str] = CallByName Test.1 Test.27; + jump Test.13 Test.26; diff --git a/crates/compiler/test_mono/generated/lambda_set_with_imported_toplevels_issue_4733.txt b/crates/compiler/test_mono/generated/lambda_set_with_imported_toplevels_issue_4733.txt index f771acb496..ef6c2e8aa4 100644 --- a/crates/compiler/test_mono/generated/lambda_set_with_imported_toplevels_issue_4733.txt +++ b/crates/compiler/test_mono/generated/lambda_set_with_imported_toplevels_issue_4733.txt @@ -7,34 +7,31 @@ procedure Bool.2 (): ret Bool.24; procedure Num.19 (#Attr.2, #Attr.3): - let Num.256 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.275; procedure Num.21 (#Attr.2, #Attr.3): - let Num.257 : U64 = lowlevel NumMul #Attr.2 #Attr.3; - ret Num.257; + let Num.276 : U64 = lowlevel NumMul #Attr.2 #Attr.3; + ret Num.276; procedure Test.0 (Test.8): - let Test.23 : Int1 = CallByName Bool.2; - if Test.23 then - let Test.24 : Int1 = true; - ret Test.24; + let Test.20 : Int1 = CallByName Bool.2; + if Test.20 then + let Test.21 : Int1 = true; + ret Test.21; else - let Test.22 : Int1 = false; - ret Test.22; + let Test.19 : Int1 = false; + ret Test.19; procedure Test.5 (Test.6, Test.2): - joinpoint Test.19 Test.18: - ret Test.18; - in switch Test.2: case 0: - let Test.20 : U64 = CallByName Num.19 Test.6 Test.6; - jump Test.19 Test.20; + let Test.18 : U64 = CallByName Num.19 Test.6 Test.6; + ret Test.18; default: - let Test.21 : U64 = CallByName Num.21 Test.6 Test.6; - jump Test.19 Test.21; + let Test.18 : U64 = CallByName Num.21 Test.6 Test.6; + ret Test.18; procedure Test.7 (): diff --git a/crates/compiler/test_mono/generated/list_append.txt b/crates/compiler/test_mono/generated/list_append.txt index e595974541..0ce199ed3f 100644 --- a/crates/compiler/test_mono/generated/list_append.txt +++ b/crates/compiler/test_mono/generated/list_append.txt @@ -1,16 +1,16 @@ procedure List.4 (List.106, List.107): - let List.481 : U64 = 1i64; - let List.479 : List I64 = CallByName List.70 List.106 List.481; - let List.478 : List I64 = CallByName List.71 List.479 List.107; - ret List.478; + let List.496 : U64 = 1i64; + let List.494 : List I64 = CallByName List.70 List.106 List.496; + let List.493 : List I64 = CallByName List.71 List.494 List.107; + ret List.493; procedure List.70 (#Attr.2, #Attr.3): - let List.482 : List I64 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.482; + let List.497 : List I64 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.497; procedure List.71 (#Attr.2, #Attr.3): - let List.480 : List I64 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.480; + let List.495 : List I64 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.495; procedure Test.0 (): let Test.2 : List I64 = Array [1i64]; diff --git a/crates/compiler/test_mono/generated/list_append_closure.txt b/crates/compiler/test_mono/generated/list_append_closure.txt index 1c0aa8ab40..bd08a2b80e 100644 --- a/crates/compiler/test_mono/generated/list_append_closure.txt +++ b/crates/compiler/test_mono/generated/list_append_closure.txt @@ -1,16 +1,16 @@ procedure List.4 (List.106, List.107): - let List.481 : U64 = 1i64; - let List.479 : List I64 = CallByName List.70 List.106 List.481; - let List.478 : List I64 = CallByName List.71 List.479 List.107; - ret List.478; + let List.496 : U64 = 1i64; + let List.494 : List I64 = CallByName List.70 List.106 List.496; + let List.493 : List I64 = CallByName List.71 List.494 List.107; + ret List.493; procedure List.70 (#Attr.2, #Attr.3): - let List.482 : List I64 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.482; + let List.497 : List I64 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.497; procedure List.71 (#Attr.2, #Attr.3): - let List.480 : List I64 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.480; + let List.495 : List I64 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.495; procedure Test.1 (Test.2): let Test.6 : I64 = 42i64; diff --git a/crates/compiler/test_mono/generated/list_cannot_update_inplace.txt b/crates/compiler/test_mono/generated/list_cannot_update_inplace.txt index ff5f26ca01..45f158c3c8 100644 --- a/crates/compiler/test_mono/generated/list_cannot_update_inplace.txt +++ b/crates/compiler/test_mono/generated/list_cannot_update_inplace.txt @@ -1,35 +1,35 @@ procedure List.3 (List.103, List.104, List.105): - let List.481 : {List I64, I64} = CallByName List.64 List.103 List.104 List.105; - let List.480 : List I64 = StructAtIndex 0 List.481; - inc List.480; - dec List.481; - ret List.480; + let List.496 : {List I64, I64} = CallByName List.64 List.103 List.104 List.105; + let List.495 : List I64 = StructAtIndex 0 List.496; + inc List.495; + dec List.496; + ret List.495; procedure List.6 (#Attr.2): - let List.479 : U64 = lowlevel ListLen #Attr.2; - ret List.479; + let List.494 : U64 = lowlevel ListLen #Attr.2; + ret List.494; procedure List.64 (List.100, List.101, List.102): - let List.486 : U64 = CallByName List.6 List.100; - let List.483 : Int1 = CallByName Num.22 List.101 List.486; - if List.483 then - let List.484 : {List I64, I64} = CallByName List.67 List.100 List.101 List.102; - ret List.484; + let List.501 : U64 = CallByName List.6 List.100; + let List.498 : Int1 = CallByName Num.22 List.101 List.501; + if List.498 then + let List.499 : {List I64, I64} = CallByName List.67 List.100 List.101 List.102; + ret List.499; else - let List.482 : {List I64, I64} = Struct {List.100, List.102}; - ret List.482; + let List.497 : {List I64, I64} = Struct {List.100, List.102}; + ret List.497; procedure List.67 (#Attr.2, #Attr.3, #Attr.4): - let List.485 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; - ret List.485; + let List.500 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; + ret List.500; procedure Num.19 (#Attr.2, #Attr.3): - let Num.256 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.275; procedure Num.22 (#Attr.2, #Attr.3): - let Num.257 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; - ret Num.257; + let Num.276 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.276; procedure Test.1 (): let Test.8 : List I64 = Array [1i64, 2i64, 3i64]; diff --git a/crates/compiler/test_mono/generated/list_get.txt b/crates/compiler/test_mono/generated/list_get.txt index df01e372ca..8b71194b57 100644 --- a/crates/compiler/test_mono/generated/list_get.txt +++ b/crates/compiler/test_mono/generated/list_get.txt @@ -1,26 +1,26 @@ procedure List.2 (List.95, List.96): - let List.484 : U64 = CallByName List.6 List.95; - let List.480 : Int1 = CallByName Num.22 List.96 List.484; - if List.480 then - let List.482 : I64 = CallByName List.66 List.95 List.96; - let List.481 : [C {}, C I64] = TagId(1) List.482; - ret List.481; + let List.499 : U64 = CallByName List.6 List.95; + let List.495 : Int1 = CallByName Num.22 List.96 List.499; + if List.495 then + let List.497 : I64 = CallByName List.66 List.95 List.96; + let List.496 : [C {}, C I64] = TagId(1) List.497; + ret List.496; else - let List.479 : {} = Struct {}; - let List.478 : [C {}, C I64] = TagId(0) List.479; - ret List.478; + let List.494 : {} = Struct {}; + let List.493 : [C {}, C I64] = TagId(0) List.494; + ret List.493; procedure List.6 (#Attr.2): - let List.485 : U64 = lowlevel ListLen #Attr.2; - ret List.485; + let List.500 : U64 = lowlevel ListLen #Attr.2; + ret List.500; procedure List.66 (#Attr.2, #Attr.3): - let List.483 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.483; + let List.498 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.498; procedure Num.22 (#Attr.2, #Attr.3): - let Num.256 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.275; procedure Test.1 (Test.2): let Test.6 : List I64 = Array [1i64, 2i64, 3i64]; diff --git a/crates/compiler/test_mono/generated/list_len.txt b/crates/compiler/test_mono/generated/list_len.txt index faf9917673..6bb48e2720 100644 --- a/crates/compiler/test_mono/generated/list_len.txt +++ b/crates/compiler/test_mono/generated/list_len.txt @@ -1,14 +1,14 @@ procedure List.6 (#Attr.2): - let List.478 : U64 = lowlevel ListLen #Attr.2; - ret List.478; + let List.493 : U64 = lowlevel ListLen #Attr.2; + ret List.493; procedure List.6 (#Attr.2): - let List.479 : U64 = lowlevel ListLen #Attr.2; - ret List.479; + let List.494 : U64 = lowlevel ListLen #Attr.2; + ret List.494; procedure Num.19 (#Attr.2, #Attr.3): - let Num.256 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.275; procedure Test.0 (): let Test.1 : List I64 = Array [1i64, 2i64, 3i64]; diff --git a/crates/compiler/test_mono/generated/list_map_closure_borrows.txt b/crates/compiler/test_mono/generated/list_map_closure_borrows.txt index f793d3b887..88b6c60de9 100644 --- a/crates/compiler/test_mono/generated/list_map_closure_borrows.txt +++ b/crates/compiler/test_mono/generated/list_map_closure_borrows.txt @@ -1,30 +1,30 @@ procedure List.2 (List.95, List.96): - let List.484 : U64 = CallByName List.6 List.95; - let List.480 : Int1 = CallByName Num.22 List.96 List.484; - if List.480 then - let List.482 : Str = CallByName List.66 List.95 List.96; - let List.481 : [C {}, C Str] = TagId(1) List.482; - ret List.481; + let List.499 : U64 = CallByName List.6 List.95; + let List.495 : Int1 = CallByName Num.22 List.96 List.499; + if List.495 then + let List.497 : Str = CallByName List.66 List.95 List.96; + let List.496 : [C {}, C Str] = TagId(1) List.497; + ret List.496; else - let List.479 : {} = Struct {}; - let List.478 : [C {}, C Str] = TagId(0) List.479; - ret List.478; + let List.494 : {} = Struct {}; + let List.493 : [C {}, C Str] = TagId(0) List.494; + ret List.493; procedure List.5 (#Attr.2, #Attr.3): - let List.486 : List Str = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.3 #Attr.3; - ret List.486; + let List.501 : List Str = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.3 #Attr.3; + ret List.501; procedure List.6 (#Attr.2): - let List.485 : U64 = lowlevel ListLen #Attr.2; - ret List.485; + let List.500 : U64 = lowlevel ListLen #Attr.2; + ret List.500; procedure List.66 (#Attr.2, #Attr.3): - let List.483 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.483; + let List.498 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.498; procedure Num.22 (#Attr.2, #Attr.3): - let Num.256 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.275; procedure Str.16 (#Attr.2, #Attr.3): let Str.265 : Str = lowlevel StrRepeat #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/list_map_closure_owns.txt b/crates/compiler/test_mono/generated/list_map_closure_owns.txt index 6f9219cdd4..a15a639d0f 100644 --- a/crates/compiler/test_mono/generated/list_map_closure_owns.txt +++ b/crates/compiler/test_mono/generated/list_map_closure_owns.txt @@ -1,31 +1,31 @@ procedure List.2 (List.95, List.96): - let List.484 : U64 = CallByName List.6 List.95; - let List.480 : Int1 = CallByName Num.22 List.96 List.484; - if List.480 then - let List.482 : Str = CallByName List.66 List.95 List.96; - let List.481 : [C {}, C Str] = TagId(1) List.482; - ret List.481; + let List.499 : U64 = CallByName List.6 List.95; + let List.495 : Int1 = CallByName Num.22 List.96 List.499; + if List.495 then + let List.497 : Str = CallByName List.66 List.95 List.96; + let List.496 : [C {}, C Str] = TagId(1) List.497; + ret List.496; else - let List.479 : {} = Struct {}; - let List.478 : [C {}, C Str] = TagId(0) List.479; - ret List.478; + let List.494 : {} = Struct {}; + let List.493 : [C {}, C Str] = TagId(0) List.494; + ret List.493; procedure List.5 (#Attr.2, #Attr.3): - let List.486 : List Str = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.3 #Attr.3; + let List.501 : List Str = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.3 #Attr.3; decref #Attr.2; - ret List.486; + ret List.501; procedure List.6 (#Attr.2): - let List.485 : U64 = lowlevel ListLen #Attr.2; - ret List.485; + let List.500 : U64 = lowlevel ListLen #Attr.2; + ret List.500; procedure List.66 (#Attr.2, #Attr.3): - let List.483 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.483; + let List.498 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.498; procedure Num.22 (#Attr.2, #Attr.3): - let Num.256 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.275; procedure Str.3 (#Attr.2, #Attr.3): let Str.266 : Str = lowlevel StrConcat #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/list_map_take_capturing_or_noncapturing.txt b/crates/compiler/test_mono/generated/list_map_take_capturing_or_noncapturing.txt index 4cd6b80ef2..0102a3b573 100644 --- a/crates/compiler/test_mono/generated/list_map_take_capturing_or_noncapturing.txt +++ b/crates/compiler/test_mono/generated/list_map_take_capturing_or_noncapturing.txt @@ -1,29 +1,29 @@ procedure List.5 (#Attr.2, #Attr.3): - let List.479 : U8 = GetTagId #Attr.3; - joinpoint List.480 List.478: - inc List.478; - ret List.478; + let List.494 : U8 = GetTagId #Attr.3; + joinpoint List.495 List.493: + inc List.493; + ret List.493; in - switch List.479: + switch List.494: case 0: - let List.481 : List U8 = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.4 #Attr.3; + let List.496 : List U8 = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.4 #Attr.3; decref #Attr.2; - jump List.480 List.481; + jump List.495 List.496; case 1: - let List.482 : List U8 = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.6 #Attr.3; + let List.497 : List U8 = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.6 #Attr.3; decref #Attr.2; - jump List.480 List.482; + jump List.495 List.497; default: - let List.483 : List U8 = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.8 #Attr.3; + let List.498 : List U8 = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.8 #Attr.3; decref #Attr.2; - jump List.480 List.483; + jump List.495 List.498; procedure Num.19 (#Attr.2, #Attr.3): - let Num.258 : U8 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.258; + let Num.277 : U8 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.277; procedure Test.4 (Test.5, #Attr.12): let Test.1 : U8 = UnionAtIndex (Id 0) (Index 0) #Attr.12; diff --git a/crates/compiler/test_mono/generated/list_pass_to_function.txt b/crates/compiler/test_mono/generated/list_pass_to_function.txt index 4fc891ee2c..cd04a5cad3 100644 --- a/crates/compiler/test_mono/generated/list_pass_to_function.txt +++ b/crates/compiler/test_mono/generated/list_pass_to_function.txt @@ -1,31 +1,31 @@ procedure List.3 (List.103, List.104, List.105): - let List.479 : {List I64, I64} = CallByName List.64 List.103 List.104 List.105; - let List.478 : List I64 = StructAtIndex 0 List.479; - inc List.478; - dec List.479; - ret List.478; + let List.494 : {List I64, I64} = CallByName List.64 List.103 List.104 List.105; + let List.493 : List I64 = StructAtIndex 0 List.494; + inc List.493; + dec List.494; + ret List.493; procedure List.6 (#Attr.2): - let List.485 : U64 = lowlevel ListLen #Attr.2; - ret List.485; + let List.500 : U64 = lowlevel ListLen #Attr.2; + ret List.500; procedure List.64 (List.100, List.101, List.102): - let List.484 : U64 = CallByName List.6 List.100; - let List.481 : Int1 = CallByName Num.22 List.101 List.484; - if List.481 then - let List.482 : {List I64, I64} = CallByName List.67 List.100 List.101 List.102; - ret List.482; + let List.499 : U64 = CallByName List.6 List.100; + let List.496 : Int1 = CallByName Num.22 List.101 List.499; + if List.496 then + let List.497 : {List I64, I64} = CallByName List.67 List.100 List.101 List.102; + ret List.497; else - let List.480 : {List I64, I64} = Struct {List.100, List.102}; - ret List.480; + let List.495 : {List I64, I64} = Struct {List.100, List.102}; + ret List.495; procedure List.67 (#Attr.2, #Attr.3, #Attr.4): - let List.483 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; - ret List.483; + let List.498 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; + ret List.498; procedure Num.22 (#Attr.2, #Attr.3): - let Num.256 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.275; procedure Test.2 (Test.3): let Test.6 : U64 = 0i64; diff --git a/crates/compiler/test_mono/generated/list_sort_asc.txt b/crates/compiler/test_mono/generated/list_sort_asc.txt index e1a3bbc88e..5573987bb6 100644 --- a/crates/compiler/test_mono/generated/list_sort_asc.txt +++ b/crates/compiler/test_mono/generated/list_sort_asc.txt @@ -1,20 +1,20 @@ procedure List.28 (#Attr.2, #Attr.3): - let List.480 : List I64 = lowlevel ListSortWith { xs: `#Attr.#arg1` } #Attr.2 Num.46 #Attr.3; + let List.495 : List I64 = lowlevel ListSortWith { xs: `#Attr.#arg1` } #Attr.2 Num.46 #Attr.3; let #Derived_gen.0 : Int1 = lowlevel ListIsUnique #Attr.2; if #Derived_gen.0 then - ret List.480; + ret List.495; else decref #Attr.2; - ret List.480; + ret List.495; -procedure List.59 (List.278): - let List.479 : {} = Struct {}; - let List.478 : List I64 = CallByName List.28 List.278 List.479; - ret List.478; +procedure List.59 (List.281): + let List.494 : {} = Struct {}; + let List.493 : List I64 = CallByName List.28 List.281 List.494; + ret List.493; procedure Num.46 (#Attr.2, #Attr.3): - let Num.256 : U8 = lowlevel NumCompare #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : U8 = lowlevel NumCompare #Attr.2 #Attr.3; + ret Num.275; procedure Test.0 (): let Test.2 : List I64 = Array [4i64, 3i64, 2i64, 1i64]; diff --git a/crates/compiler/test_mono/generated/nested_pattern_match.txt b/crates/compiler/test_mono/generated/nested_pattern_match.txt index 4b2af8c406..3da4e73dcc 100644 --- a/crates/compiler/test_mono/generated/nested_pattern_match.txt +++ b/crates/compiler/test_mono/generated/nested_pattern_match.txt @@ -1,6 +1,6 @@ procedure Num.19 (#Attr.2, #Attr.3): - let Num.256 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.275; procedure Test.0 (): let Test.19 : I64 = 41i64; diff --git a/crates/compiler/test_mono/generated/num_width_gt_u8_layout_as_float.txt b/crates/compiler/test_mono/generated/num_width_gt_u8_layout_as_float.txt index e5c7df8fe3..ef70723086 100644 --- a/crates/compiler/test_mono/generated/num_width_gt_u8_layout_as_float.txt +++ b/crates/compiler/test_mono/generated/num_width_gt_u8_layout_as_float.txt @@ -1,6 +1,6 @@ procedure Num.37 (#Attr.2, #Attr.3): - let Num.256 : Float64 = lowlevel NumDivFrac #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : Float64 = lowlevel NumDivFrac #Attr.2 #Attr.3; + ret Num.275; procedure Test.0 (): let Test.2 : Float64 = 1f64; diff --git a/crates/compiler/test_mono/generated/optional_when.txt b/crates/compiler/test_mono/generated/optional_when.txt index 28667ba1d6..191cc305b4 100644 --- a/crates/compiler/test_mono/generated/optional_when.txt +++ b/crates/compiler/test_mono/generated/optional_when.txt @@ -1,6 +1,6 @@ procedure Num.21 (#Attr.2, #Attr.3): - let Num.258 : I64 = lowlevel NumMul #Attr.2 #Attr.3; - ret Num.258; + let Num.277 : I64 = lowlevel NumMul #Attr.2 #Attr.3; + ret Num.277; procedure Test.1 (Test.6): let Test.21 : Int1 = false; diff --git a/crates/compiler/test_mono/generated/quicksort_help.txt b/crates/compiler/test_mono/generated/quicksort_help.txt index 8be05e9641..f00adf21db 100644 --- a/crates/compiler/test_mono/generated/quicksort_help.txt +++ b/crates/compiler/test_mono/generated/quicksort_help.txt @@ -1,14 +1,14 @@ procedure Num.19 (#Attr.2, #Attr.3): - let Num.256 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.275; procedure Num.20 (#Attr.2, #Attr.3): - let Num.257 : I64 = lowlevel NumSub #Attr.2 #Attr.3; - ret Num.257; + let Num.276 : I64 = lowlevel NumSub #Attr.2 #Attr.3; + ret Num.276; procedure Num.22 (#Attr.2, #Attr.3): - let Num.258 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; - ret Num.258; + let Num.277 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.277; procedure Test.1 (Test.24, Test.25, Test.26): joinpoint Test.12 Test.2 Test.3 Test.4: diff --git a/crates/compiler/test_mono/generated/quicksort_swap.txt b/crates/compiler/test_mono/generated/quicksort_swap.txt index 5a6c27d6d5..b8c7cc6571 100644 --- a/crates/compiler/test_mono/generated/quicksort_swap.txt +++ b/crates/compiler/test_mono/generated/quicksort_swap.txt @@ -1,47 +1,47 @@ procedure List.2 (List.95, List.96): - let List.500 : U64 = CallByName List.6 List.95; - let List.497 : Int1 = CallByName Num.22 List.96 List.500; - if List.497 then - let List.499 : I64 = CallByName List.66 List.95 List.96; - let List.498 : [C {}, C I64] = TagId(1) List.499; - ret List.498; + let List.515 : U64 = CallByName List.6 List.95; + let List.512 : Int1 = CallByName Num.22 List.96 List.515; + if List.512 then + let List.514 : I64 = CallByName List.66 List.95 List.96; + let List.513 : [C {}, C I64] = TagId(1) List.514; + ret List.513; else - let List.496 : {} = Struct {}; - let List.495 : [C {}, C I64] = TagId(0) List.496; - ret List.495; + let List.511 : {} = Struct {}; + let List.510 : [C {}, C I64] = TagId(0) List.511; + ret List.510; procedure List.3 (List.103, List.104, List.105): - let List.487 : {List I64, I64} = CallByName List.64 List.103 List.104 List.105; - let List.486 : List I64 = StructAtIndex 0 List.487; - inc List.486; - dec List.487; - ret List.486; + let List.502 : {List I64, I64} = CallByName List.64 List.103 List.104 List.105; + let List.501 : List I64 = StructAtIndex 0 List.502; + inc List.501; + dec List.502; + ret List.501; procedure List.6 (#Attr.2): - let List.485 : U64 = lowlevel ListLen #Attr.2; - ret List.485; + let List.500 : U64 = lowlevel ListLen #Attr.2; + ret List.500; procedure List.64 (List.100, List.101, List.102): - let List.484 : U64 = CallByName List.6 List.100; - let List.481 : Int1 = CallByName Num.22 List.101 List.484; - if List.481 then - let List.482 : {List I64, I64} = CallByName List.67 List.100 List.101 List.102; - ret List.482; + let List.499 : U64 = CallByName List.6 List.100; + let List.496 : Int1 = CallByName Num.22 List.101 List.499; + if List.496 then + let List.497 : {List I64, I64} = CallByName List.67 List.100 List.101 List.102; + ret List.497; else - let List.480 : {List I64, I64} = Struct {List.100, List.102}; - ret List.480; + let List.495 : {List I64, I64} = Struct {List.100, List.102}; + ret List.495; procedure List.66 (#Attr.2, #Attr.3): - let List.493 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.493; + let List.508 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.508; procedure List.67 (#Attr.2, #Attr.3, #Attr.4): - let List.483 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; - ret List.483; + let List.498 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; + ret List.498; procedure Num.22 (#Attr.2, #Attr.3): - let Num.258 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; - ret Num.258; + let Num.277 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.277; procedure Test.1 (Test.2): let Test.28 : U64 = 0i64; diff --git a/crates/compiler/test_mono/generated/record_optional_field_function_no_use_default.txt b/crates/compiler/test_mono/generated/record_optional_field_function_no_use_default.txt index 2f7c2c8b22..eea16dcef9 100644 --- a/crates/compiler/test_mono/generated/record_optional_field_function_no_use_default.txt +++ b/crates/compiler/test_mono/generated/record_optional_field_function_no_use_default.txt @@ -1,6 +1,6 @@ procedure Num.19 (#Attr.2, #Attr.3): - let Num.256 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.275; procedure Test.1 (Test.4): let Test.2 : I64 = StructAtIndex 0 Test.4; diff --git a/crates/compiler/test_mono/generated/record_optional_field_function_use_default.txt b/crates/compiler/test_mono/generated/record_optional_field_function_use_default.txt index 49267ae4b1..74a2941f14 100644 --- a/crates/compiler/test_mono/generated/record_optional_field_function_use_default.txt +++ b/crates/compiler/test_mono/generated/record_optional_field_function_use_default.txt @@ -1,6 +1,6 @@ procedure Num.19 (#Attr.2, #Attr.3): - let Num.256 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.275; procedure Test.1 (Test.4): let Test.2 : I64 = 10i64; diff --git a/crates/compiler/test_mono/generated/record_optional_field_let_no_use_default.txt b/crates/compiler/test_mono/generated/record_optional_field_let_no_use_default.txt index 21ebd109c8..f9d2495d40 100644 --- a/crates/compiler/test_mono/generated/record_optional_field_let_no_use_default.txt +++ b/crates/compiler/test_mono/generated/record_optional_field_let_no_use_default.txt @@ -1,6 +1,6 @@ procedure Num.19 (#Attr.2, #Attr.3): - let Num.256 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.275; procedure Test.1 (Test.2): let Test.3 : I64 = StructAtIndex 0 Test.2; diff --git a/crates/compiler/test_mono/generated/record_optional_field_let_use_default.txt b/crates/compiler/test_mono/generated/record_optional_field_let_use_default.txt index c960fd1fb2..feb8083f78 100644 --- a/crates/compiler/test_mono/generated/record_optional_field_let_use_default.txt +++ b/crates/compiler/test_mono/generated/record_optional_field_let_use_default.txt @@ -1,6 +1,6 @@ procedure Num.19 (#Attr.2, #Attr.3): - let Num.256 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.275; procedure Test.1 (Test.2): let Test.3 : I64 = 10i64; diff --git a/crates/compiler/test_mono/generated/recursive_call_capturing_function.txt b/crates/compiler/test_mono/generated/recursive_call_capturing_function.txt index b969b12528..eca9933033 100644 --- a/crates/compiler/test_mono/generated/recursive_call_capturing_function.txt +++ b/crates/compiler/test_mono/generated/recursive_call_capturing_function.txt @@ -3,8 +3,8 @@ procedure Bool.2 (): ret Bool.23; procedure Num.19 (#Attr.2, #Attr.3): - let Num.256 : U32 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : U32 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.275; procedure Test.1 (Test.2): let Test.8 : U32 = 0i64; diff --git a/crates/compiler/test_mono/generated/recursive_lambda_set_has_nested_non_recursive_lambda_sets_issue_5026.txt b/crates/compiler/test_mono/generated/recursive_lambda_set_has_nested_non_recursive_lambda_sets_issue_5026.txt index 571e8da4fa..ebb13ee424 100644 --- a/crates/compiler/test_mono/generated/recursive_lambda_set_has_nested_non_recursive_lambda_sets_issue_5026.txt +++ b/crates/compiler/test_mono/generated/recursive_lambda_set_has_nested_non_recursive_lambda_sets_issue_5026.txt @@ -2,18 +2,18 @@ procedure Bool.2 (): let Bool.23 : Int1 = true; ret Bool.23; -procedure Test.10 (Test.28): - let Test.32 : Int1 = CallByName Bool.2; - if Test.32 then - let Test.33 : [, C {}] = CallByName Test.0; - ret Test.33; +procedure Test.10 (Test.25): + let Test.29 : Int1 = CallByName Bool.2; + if Test.29 then + let Test.30 : [, C {}] = CallByName Test.0; + ret Test.30; else - let Test.29 : [, C {}] = TagId(1) ; - ret Test.29; + let Test.26 : [, C {}] = TagId(1) ; + ret Test.26; -procedure Test.11 (Test.30): - let Test.31 : Str = "done"; - ret Test.31; +procedure Test.11 (Test.27): + let Test.28 : Str = "done"; + ret Test.28; procedure Test.2 (Test.5): let Test.17 : [, C {}] = TagId(0) Test.5; @@ -27,27 +27,24 @@ procedure Test.6 (Test.16, #Attr.12): let Test.5 : {} = UnionAtIndex (Id 0) (Index 0) #Attr.12; dec #Attr.12; let Test.19 : {} = Struct {}; - let Test.25 : Str = "foobar"; - let Test.20 : [, C {}] = CallByName Test.8 Test.25 Test.5; - dec Test.25; + let Test.22 : Str = "foobar"; + let Test.20 : [, C {}] = CallByName Test.8 Test.22 Test.5; + dec Test.22; let Test.21 : U8 = GetTagId Test.20; - joinpoint Test.22 Test.18: - ret Test.18; - in switch Test.21: case 0: - let Test.23 : Str = CallByName Test.6 Test.19 Test.20; - jump Test.22 Test.23; + let Test.18 : Str = CallByName Test.6 Test.19 Test.20; + ret Test.18; default: dec Test.20; - let Test.24 : Str = CallByName Test.11 Test.19; - jump Test.22 Test.24; + let Test.18 : Str = CallByName Test.11 Test.19; + ret Test.18; procedure Test.8 (Test.9, Test.7): - let Test.27 : [, C {}] = CallByName Test.10 Test.9; - ret Test.27; + let Test.24 : [, C {}] = CallByName Test.10 Test.9; + ret Test.24; procedure Test.0 (): let Test.13 : {} = Struct {}; diff --git a/crates/compiler/test_mono/generated/recursively_build_effect.txt b/crates/compiler/test_mono/generated/recursively_build_effect.txt index 2b56ff88e8..c4b0878981 100644 --- a/crates/compiler/test_mono/generated/recursively_build_effect.txt +++ b/crates/compiler/test_mono/generated/recursively_build_effect.txt @@ -1,6 +1,6 @@ procedure Num.20 (#Attr.2, #Attr.3): - let Num.256 : I64 = lowlevel NumSub #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : I64 = lowlevel NumSub #Attr.2 #Attr.3; + ret Num.275; procedure Str.3 (#Attr.2, #Attr.3): let Str.267 : Str = lowlevel StrConcat #Attr.2 #Attr.3; @@ -14,27 +14,26 @@ procedure Test.11 (Test.29, #Attr.12): procedure Test.11 (Test.29, Test.10): ret Test.10; -procedure Test.14 (Test.36, #Attr.12): - let Test.12 : {} = UnionAtIndex (Id 1) (Index 1) #Attr.12; - let Test.13 : I64 = UnionAtIndex (Id 1) (Index 0) #Attr.12; - dec #Attr.12; - let Test.46 : {} = Struct {}; - let Test.45 : {} = CallByName Test.11 Test.46 Test.12; - let Test.38 : [C {}, C I64 {}] = CallByName Test.9 Test.45 Test.13; - let Test.40 : {} = Struct {}; - let Test.41 : U8 = GetTagId Test.38; - joinpoint Test.42 Test.39: - ret Test.39; +procedure Test.14 (Test.62, Test.63): + joinpoint Test.37 Test.36 #Attr.12: + let Test.12 : {} = UnionAtIndex (Id 1) (Index 1) #Attr.12; + let Test.13 : I64 = UnionAtIndex (Id 1) (Index 0) #Attr.12; + dec #Attr.12; + let Test.43 : {} = Struct {}; + let Test.42 : {} = CallByName Test.11 Test.43 Test.12; + let Test.38 : [C {}, C I64 {}] = CallByName Test.9 Test.42 Test.13; + let Test.40 : {} = Struct {}; + let Test.41 : U8 = GetTagId Test.38; + switch Test.41: + case 0: + let Test.39 : {} = CallByName Test.11 Test.40 Test.38; + ret Test.39; + + default: + jump Test.37 Test.40 Test.38; + in - switch Test.41: - case 0: - let Test.43 : {} = CallByName Test.11 Test.40 Test.38; - jump Test.42 Test.43; - - default: - let Test.44 : {} = CallByName Test.14 Test.40 Test.38; - jump Test.42 Test.44; - + jump Test.37 Test.62 Test.63; procedure Test.2 (): let Test.6 : Str = "Hello"; @@ -50,15 +49,15 @@ procedure Test.2 (): ret Test.19; procedure Test.3 (Test.8): - let Test.57 : I64 = 0i64; - let Test.58 : Int1 = lowlevel Eq Test.57 Test.8; - if Test.58 then + let Test.54 : I64 = 0i64; + let Test.55 : Int1 = lowlevel Eq Test.54 Test.8; + if Test.55 then let Test.27 : {} = Struct {}; let Test.26 : [C {}, C I64 {}] = CallByName Test.4 Test.27; ret Test.26; else - let Test.52 : {} = Struct {}; - let Test.33 : {} = CallByName Test.4 Test.52; + let Test.49 : {} = Struct {}; + let Test.33 : {} = CallByName Test.4 Test.49; let Test.32 : [C {}, C I64 {}] = CallByName Test.5 Test.33 Test.8; ret Test.32; @@ -73,11 +72,11 @@ procedure Test.5 (Test.16, Test.13): let Test.35 : [C {}, C I64 {}] = TagId(1) Test.13 Test.16; ret Test.35; -procedure Test.9 (Test.47, Test.8): - let Test.51 : I64 = 1i64; - let Test.50 : I64 = CallByName Num.20 Test.8 Test.51; - let Test.49 : [C {}, C I64 {}] = CallByName Test.3 Test.50; - ret Test.49; +procedure Test.9 (Test.44, Test.8): + let Test.48 : I64 = 1i64; + let Test.47 : I64 = CallByName Num.20 Test.8 Test.48; + let Test.46 : [C {}, C I64 {}] = CallByName Test.3 Test.47; + ret Test.46; procedure Test.0 (): let Test.24 : I64 = 4i64; diff --git a/crates/compiler/test_mono/generated/rigids.txt b/crates/compiler/test_mono/generated/rigids.txt index edff70c703..21d37aafef 100644 --- a/crates/compiler/test_mono/generated/rigids.txt +++ b/crates/compiler/test_mono/generated/rigids.txt @@ -1,47 +1,47 @@ procedure List.2 (List.95, List.96): - let List.500 : U64 = CallByName List.6 List.95; - let List.497 : Int1 = CallByName Num.22 List.96 List.500; - if List.497 then - let List.499 : I64 = CallByName List.66 List.95 List.96; - let List.498 : [C {}, C I64] = TagId(1) List.499; - ret List.498; + let List.515 : U64 = CallByName List.6 List.95; + let List.512 : Int1 = CallByName Num.22 List.96 List.515; + if List.512 then + let List.514 : I64 = CallByName List.66 List.95 List.96; + let List.513 : [C {}, C I64] = TagId(1) List.514; + ret List.513; else - let List.496 : {} = Struct {}; - let List.495 : [C {}, C I64] = TagId(0) List.496; - ret List.495; + let List.511 : {} = Struct {}; + let List.510 : [C {}, C I64] = TagId(0) List.511; + ret List.510; procedure List.3 (List.103, List.104, List.105): - let List.487 : {List I64, I64} = CallByName List.64 List.103 List.104 List.105; - let List.486 : List I64 = StructAtIndex 0 List.487; - inc List.486; - dec List.487; - ret List.486; + let List.502 : {List I64, I64} = CallByName List.64 List.103 List.104 List.105; + let List.501 : List I64 = StructAtIndex 0 List.502; + inc List.501; + dec List.502; + ret List.501; procedure List.6 (#Attr.2): - let List.485 : U64 = lowlevel ListLen #Attr.2; - ret List.485; + let List.500 : U64 = lowlevel ListLen #Attr.2; + ret List.500; procedure List.64 (List.100, List.101, List.102): - let List.484 : U64 = CallByName List.6 List.100; - let List.481 : Int1 = CallByName Num.22 List.101 List.484; - if List.481 then - let List.482 : {List I64, I64} = CallByName List.67 List.100 List.101 List.102; - ret List.482; + let List.499 : U64 = CallByName List.6 List.100; + let List.496 : Int1 = CallByName Num.22 List.101 List.499; + if List.496 then + let List.497 : {List I64, I64} = CallByName List.67 List.100 List.101 List.102; + ret List.497; else - let List.480 : {List I64, I64} = Struct {List.100, List.102}; - ret List.480; + let List.495 : {List I64, I64} = Struct {List.100, List.102}; + ret List.495; procedure List.66 (#Attr.2, #Attr.3): - let List.493 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.493; + let List.508 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.508; procedure List.67 (#Attr.2, #Attr.3, #Attr.4): - let List.483 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; - ret List.483; + let List.498 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; + ret List.498; procedure Num.22 (#Attr.2, #Attr.3): - let Num.258 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; - ret Num.258; + let Num.277 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.277; procedure Test.1 (Test.2, Test.3, Test.4): let Test.29 : [C {}, C I64] = CallByName List.2 Test.4 Test.3; diff --git a/crates/compiler/test_mono/generated/specialize_closures.txt b/crates/compiler/test_mono/generated/specialize_closures.txt index 7d96852e4f..4d1ee3ac7e 100644 --- a/crates/compiler/test_mono/generated/specialize_closures.txt +++ b/crates/compiler/test_mono/generated/specialize_closures.txt @@ -3,39 +3,36 @@ procedure Bool.2 (): ret Bool.24; procedure Num.19 (#Attr.2, #Attr.3): - let Num.257 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.257; + let Num.276 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.276; procedure Num.21 (#Attr.2, #Attr.3): - let Num.256 : I64 = lowlevel NumMul #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : I64 = lowlevel NumMul #Attr.2 #Attr.3; + ret Num.275; procedure Test.1 (Test.2, Test.3): let Test.15 : U8 = GetTagId Test.2; - joinpoint Test.16 Test.14: - ret Test.14; - in switch Test.15: case 0: - let Test.17 : I64 = CallByName Test.7 Test.3 Test.2; - jump Test.16 Test.17; + let Test.14 : I64 = CallByName Test.7 Test.3 Test.2; + ret Test.14; default: - let Test.18 : I64 = CallByName Test.8 Test.3 Test.2; - jump Test.16 Test.18; + let Test.14 : I64 = CallByName Test.8 Test.3 Test.2; + ret Test.14; procedure Test.7 (Test.9, #Attr.12): let Test.4 : I64 = UnionAtIndex (Id 0) (Index 0) #Attr.12; - let Test.24 : I64 = CallByName Num.19 Test.9 Test.4; - ret Test.24; + let Test.21 : I64 = CallByName Num.19 Test.9 Test.4; + ret Test.21; procedure Test.8 (Test.10, #Attr.12): let Test.6 : Int1 = UnionAtIndex (Id 1) (Index 1) #Attr.12; let Test.5 : I64 = UnionAtIndex (Id 1) (Index 0) #Attr.12; if Test.6 then - let Test.22 : I64 = CallByName Num.21 Test.10 Test.5; - ret Test.22; + let Test.19 : I64 = CallByName Num.21 Test.10 Test.5; + ret Test.19; else ret Test.10; @@ -43,15 +40,15 @@ procedure Test.0 (): let Test.4 : I64 = 1i64; let Test.5 : I64 = 2i64; let Test.6 : Int1 = CallByName Bool.2; - joinpoint Test.20 Test.12: + joinpoint Test.17 Test.12: let Test.13 : I64 = 42i64; let Test.11 : I64 = CallByName Test.1 Test.12 Test.13; ret Test.11; in - let Test.23 : Int1 = CallByName Bool.2; - if Test.23 then - let Test.19 : [C I64, C I64 Int1] = TagId(0) Test.4; - jump Test.20 Test.19; + let Test.20 : Int1 = CallByName Bool.2; + if Test.20 then + let Test.16 : [C I64, C I64 Int1] = TagId(0) Test.4; + jump Test.17 Test.16; else - let Test.19 : [C I64, C I64 Int1] = TagId(1) Test.5 Test.6; - jump Test.20 Test.19; + let Test.16 : [C I64, C I64 Int1] = TagId(1) Test.5 Test.6; + jump Test.17 Test.16; diff --git a/crates/compiler/test_mono/generated/specialize_lowlevel.txt b/crates/compiler/test_mono/generated/specialize_lowlevel.txt index aeb27ec1c2..38ce048821 100644 --- a/crates/compiler/test_mono/generated/specialize_lowlevel.txt +++ b/crates/compiler/test_mono/generated/specialize_lowlevel.txt @@ -3,46 +3,43 @@ procedure Bool.2 (): ret Bool.23; procedure Num.19 (#Attr.2, #Attr.3): - let Num.257 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.257; + let Num.276 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.276; procedure Num.21 (#Attr.2, #Attr.3): - let Num.256 : I64 = lowlevel NumMul #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : I64 = lowlevel NumMul #Attr.2 #Attr.3; + ret Num.275; procedure Test.6 (Test.8, #Attr.12): let Test.4 : I64 = UnionAtIndex (Id 0) (Index 0) #Attr.12; - let Test.21 : I64 = CallByName Num.19 Test.8 Test.4; - ret Test.21; + let Test.18 : I64 = CallByName Num.19 Test.8 Test.4; + ret Test.18; procedure Test.7 (Test.9, #Attr.12): let Test.5 : I64 = UnionAtIndex (Id 1) (Index 0) #Attr.12; - let Test.19 : I64 = CallByName Num.21 Test.9 Test.5; - ret Test.19; + let Test.16 : I64 = CallByName Num.21 Test.9 Test.5; + ret Test.16; procedure Test.0 (): let Test.4 : I64 = 1i64; let Test.5 : I64 = 2i64; let Test.11 : I64 = 42i64; - joinpoint Test.18 Test.12: + joinpoint Test.15 Test.12: let Test.13 : U8 = GetTagId Test.12; - joinpoint Test.14 Test.10: - ret Test.10; - in switch Test.13: case 0: - let Test.15 : I64 = CallByName Test.6 Test.11 Test.12; - jump Test.14 Test.15; + let Test.10 : I64 = CallByName Test.6 Test.11 Test.12; + ret Test.10; default: - let Test.16 : I64 = CallByName Test.7 Test.11 Test.12; - jump Test.14 Test.16; + let Test.10 : I64 = CallByName Test.7 Test.11 Test.12; + ret Test.10; in - let Test.20 : Int1 = CallByName Bool.2; - if Test.20 then - let Test.17 : [C I64, C I64] = TagId(0) Test.4; - jump Test.18 Test.17; + let Test.17 : Int1 = CallByName Bool.2; + if Test.17 then + let Test.14 : [C I64, C I64] = TagId(0) Test.4; + jump Test.15 Test.14; else - let Test.17 : [C I64, C I64] = TagId(1) Test.5; - jump Test.18 Test.17; + let Test.14 : [C I64, C I64] = TagId(1) Test.5; + jump Test.15 Test.14; diff --git a/crates/compiler/test_mono/generated/tail_call_elimination.txt b/crates/compiler/test_mono/generated/tail_call_elimination.txt index 8d5dd76e08..9d990096aa 100644 --- a/crates/compiler/test_mono/generated/tail_call_elimination.txt +++ b/crates/compiler/test_mono/generated/tail_call_elimination.txt @@ -1,10 +1,10 @@ procedure Num.19 (#Attr.2, #Attr.3): - let Num.256 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.275; procedure Num.20 (#Attr.2, #Attr.3): - let Num.257 : I64 = lowlevel NumSub #Attr.2 #Attr.3; - ret Num.257; + let Num.276 : I64 = lowlevel NumSub #Attr.2 #Attr.3; + ret Num.276; procedure Test.1 (Test.15, Test.16): joinpoint Test.7 Test.2 Test.3: diff --git a/crates/compiler/test_mono/generated/unreachable_branch_is_eliminated_but_produces_lambda_specializations.txt b/crates/compiler/test_mono/generated/unreachable_branch_is_eliminated_but_produces_lambda_specializations.txt index b56a7e1301..0ed3c650c9 100644 --- a/crates/compiler/test_mono/generated/unreachable_branch_is_eliminated_but_produces_lambda_specializations.txt +++ b/crates/compiler/test_mono/generated/unreachable_branch_is_eliminated_but_produces_lambda_specializations.txt @@ -1,29 +1,26 @@ procedure Test.1 (Test.2): - let Test.14 : Int1 = false; - ret Test.14; + let Test.11 : Int1 = false; + ret Test.11; -procedure Test.3 (Test.13): - let Test.15 : Str = "t1"; +procedure Test.3 (Test.10): + let Test.12 : Str = "t1"; + ret Test.12; + +procedure Test.4 (Test.13): + let Test.15 : Str = "t2"; ret Test.15; -procedure Test.4 (Test.16): - let Test.18 : Str = "t2"; - ret Test.18; - procedure Test.0 (): - let Test.19 : Str = "abc"; - let Test.6 : Int1 = CallByName Test.1 Test.19; - dec Test.19; + let Test.16 : Str = "abc"; + let Test.6 : Int1 = CallByName Test.1 Test.16; + dec Test.16; let Test.9 : {} = Struct {}; - joinpoint Test.10 Test.8: - ret Test.8; - in switch Test.6: case 0: - let Test.11 : Str = CallByName Test.3 Test.9; - jump Test.10 Test.11; + let Test.8 : Str = CallByName Test.3 Test.9; + ret Test.8; default: - let Test.12 : Str = CallByName Test.4 Test.9; - jump Test.10 Test.12; + let Test.8 : Str = CallByName Test.4 Test.9; + ret Test.8; diff --git a/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_does_not_duplicate_identical_concrete_types.txt b/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_does_not_duplicate_identical_concrete_types.txt new file mode 100644 index 0000000000..5999e4f590 --- /dev/null +++ b/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_does_not_duplicate_identical_concrete_types.txt @@ -0,0 +1,235 @@ +procedure Bool.2 (): + let Bool.23 : Int1 = true; + ret Bool.23; + +procedure Encode.22 (Encode.93): + ret Encode.93; + +procedure Encode.22 (Encode.93): + ret Encode.93; + +procedure Encode.22 (Encode.93): + ret Encode.93; + +procedure Encode.23 (Encode.94, Encode.102, Encode.96): + let Encode.106 : List U8 = CallByName Test.5 Encode.94 Encode.96 Encode.102; + ret Encode.106; + +procedure Encode.23 (Encode.94, Encode.102, Encode.96): + let Encode.113 : List U8 = CallByName Json.129 Encode.94 Encode.96 Encode.102; + ret Encode.113; + +procedure Encode.23 (Encode.94, Encode.102, Encode.96): + let Encode.118 : List U8 = CallByName Json.99 Encode.94 Encode.96 Encode.102; + ret Encode.118; + +procedure Encode.25 (Encode.100, Encode.101): + let Encode.104 : List U8 = Array []; + let Encode.105 : {Str, Str} = CallByName Test.2 Encode.100; + let Encode.103 : List U8 = CallByName Encode.23 Encode.104 Encode.105 Encode.101; + ret Encode.103; + +procedure Json.1 (): + let Json.425 : {} = Struct {}; + ret Json.425; + +procedure Json.129 (Json.130, Json.428, #Attr.12): + let Json.128 : List Str = StructAtIndex 1 #Attr.12; + inc Json.128; + let Json.127 : Str = StructAtIndex 0 #Attr.12; + inc Json.127; + dec #Attr.12; + let Json.466 : I64 = 123i64; + let Json.465 : U8 = CallByName Num.127 Json.466; + let Json.462 : List U8 = CallByName List.4 Json.130 Json.465; + let Json.464 : I64 = 34i64; + let Json.463 : U8 = CallByName Num.127 Json.464; + let Json.460 : List U8 = CallByName List.4 Json.462 Json.463; + let Json.461 : List U8 = CallByName Str.12 Json.127; + let Json.457 : List U8 = CallByName List.8 Json.460 Json.461; + let Json.459 : I64 = 34i64; + let Json.458 : U8 = CallByName Num.127 Json.459; + let Json.454 : List U8 = CallByName List.4 Json.457 Json.458; + let Json.456 : I64 = 58i64; + let Json.455 : U8 = CallByName Num.127 Json.456; + let Json.451 : List U8 = CallByName List.4 Json.454 Json.455; + let Json.453 : I64 = 91i64; + let Json.452 : U8 = CallByName Num.127 Json.453; + let Json.132 : List U8 = CallByName List.4 Json.451 Json.452; + let Json.450 : U64 = CallByName List.6 Json.128; + let Json.438 : {List U8, U64} = Struct {Json.132, Json.450}; + let Json.439 : {} = Struct {}; + let Json.437 : {List U8, U64} = CallByName List.18 Json.128 Json.438 Json.439; + dec Json.128; + let Json.134 : List U8 = StructAtIndex 0 Json.437; + inc Json.134; + dec Json.437; + let Json.436 : I64 = 93i64; + let Json.435 : U8 = CallByName Num.127 Json.436; + let Json.432 : List U8 = CallByName List.4 Json.134 Json.435; + let Json.434 : I64 = 125i64; + let Json.433 : U8 = CallByName Num.127 Json.434; + let Json.431 : List U8 = CallByName List.4 Json.432 Json.433; + ret Json.431; + +procedure Json.131 (Json.430, Json.137): + let Json.135 : List U8 = StructAtIndex 0 Json.430; + inc Json.135; + let Json.136 : U64 = StructAtIndex 1 Json.430; + dec Json.430; + let Json.449 : {} = Struct {}; + let Json.138 : List U8 = CallByName Encode.23 Json.135 Json.137 Json.449; + joinpoint Json.444 Json.139: + let Json.442 : U64 = 1i64; + let Json.441 : U64 = CallByName Num.20 Json.136 Json.442; + let Json.440 : {List U8, U64} = Struct {Json.139, Json.441}; + ret Json.440; + in + let Json.448 : U64 = 1i64; + let Json.445 : Int1 = CallByName Num.24 Json.136 Json.448; + if Json.445 then + let Json.447 : I64 = 44i64; + let Json.446 : U8 = CallByName Num.127 Json.447; + let Json.443 : List U8 = CallByName List.4 Json.138 Json.446; + jump Json.444 Json.443; + else + jump Json.444 Json.138; + +procedure Json.18 (Json.98): + let Json.482 : Str = CallByName Encode.22 Json.98; + ret Json.482; + +procedure Json.21 (Json.127, Json.128): + let Json.468 : {Str, List Str} = Struct {Json.127, Json.128}; + let Json.467 : {Str, List Str} = CallByName Encode.22 Json.468; + ret Json.467; + +procedure Json.99 (Json.100, Json.472, Json.98): + let Json.481 : I64 = 34i64; + let Json.480 : U8 = CallByName Num.127 Json.481; + let Json.478 : List U8 = CallByName List.4 Json.100 Json.480; + let Json.479 : List U8 = CallByName Str.12 Json.98; + let Json.475 : List U8 = CallByName List.8 Json.478 Json.479; + let Json.477 : I64 = 34i64; + let Json.476 : U8 = CallByName Num.127 Json.477; + let Json.474 : List U8 = CallByName List.4 Json.475 Json.476; + ret Json.474; + +procedure List.138 (List.139, List.140, List.137): + let List.544 : {List U8, U64} = CallByName Json.131 List.139 List.140; + ret List.544; + +procedure List.18 (List.135, List.136, List.137): + let List.525 : {List U8, U64} = CallByName List.91 List.135 List.136 List.137; + ret List.525; + +procedure List.4 (List.106, List.107): + let List.524 : U64 = 1i64; + let List.523 : List U8 = CallByName List.70 List.106 List.524; + let List.522 : List U8 = CallByName List.71 List.523 List.107; + ret List.522; + +procedure List.6 (#Attr.2): + let List.545 : U64 = lowlevel ListLen #Attr.2; + ret List.545; + +procedure List.66 (#Attr.2, #Attr.3): + let List.541 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.541; + +procedure List.70 (#Attr.2, #Attr.3): + let List.497 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.497; + +procedure List.71 (#Attr.2, #Attr.3): + let List.495 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.495; + +procedure List.8 (#Attr.2, #Attr.3): + let List.547 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.547; + +procedure List.80 (List.557, List.558, List.559, List.560, List.561): + joinpoint List.531 List.432 List.433 List.434 List.435 List.436: + let List.533 : Int1 = CallByName Num.22 List.435 List.436; + if List.533 then + let List.540 : Str = CallByName List.66 List.432 List.435; + let List.534 : {List U8, U64} = CallByName List.138 List.433 List.540 List.434; + let List.537 : U64 = 1i64; + let List.536 : U64 = CallByName Num.19 List.435 List.537; + jump List.531 List.432 List.534 List.434 List.536 List.436; + else + ret List.433; + in + jump List.531 List.557 List.558 List.559 List.560 List.561; + +procedure List.91 (List.429, List.430, List.431): + let List.529 : U64 = 0i64; + let List.530 : U64 = CallByName List.6 List.429; + let List.528 : {List U8, U64} = CallByName List.80 List.429 List.430 List.431 List.529 List.530; + ret List.528; + +procedure Num.127 (#Attr.2): + let Num.284 : U8 = lowlevel NumIntCast #Attr.2; + ret Num.284; + +procedure Num.19 (#Attr.2, #Attr.3): + let Num.287 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.287; + +procedure Num.20 (#Attr.2, #Attr.3): + let Num.285 : U64 = lowlevel NumSub #Attr.2 #Attr.3; + ret Num.285; + +procedure Num.22 (#Attr.2, #Attr.3): + let Num.288 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.288; + +procedure Num.24 (#Attr.2, #Attr.3): + let Num.286 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; + ret Num.286; + +procedure Str.12 (#Attr.2): + let Str.266 : List U8 = lowlevel StrToUtf8 #Attr.2; + ret Str.266; + +procedure Test.2 (Test.10): + let Test.15 : {Str, Str} = CallByName Encode.22 Test.10; + ret Test.15; + +procedure Test.3 (): + let Test.9 : Str = ""; + inc Test.9; + let Test.14 : {Str, Str} = Struct {Test.9, Test.9}; + ret Test.14; + +procedure Test.5 (Test.6, Test.7, Test.4): + joinpoint Test.20 Test.8: + let Test.18 : List U8 = CallByName Encode.23 Test.6 Test.8 Test.7; + ret Test.18; + in + let Test.25 : Int1 = CallByName Bool.2; + if Test.25 then + let Test.26 : Str = "A"; + let Test.29 : Str = StructAtIndex 0 Test.4; + inc Test.29; + dec Test.4; + let Test.28 : Str = CallByName Json.18 Test.29; + let Test.27 : List Str = Array [Test.28]; + let Test.19 : {Str, List Str} = CallByName Json.21 Test.26 Test.27; + jump Test.20 Test.19; + else + let Test.21 : Str = "B"; + let Test.24 : Str = StructAtIndex 1 Test.4; + inc Test.24; + dec Test.4; + let Test.23 : Str = CallByName Json.18 Test.24; + let Test.22 : List Str = Array [Test.23]; + let Test.19 : {Str, List Str} = CallByName Json.21 Test.21 Test.22; + jump Test.20 Test.19; + +procedure Test.0 (): + let Test.12 : {Str, Str} = CallByName Test.3; + let Test.13 : {} = CallByName Json.1; + let Test.11 : List U8 = CallByName Encode.25 Test.12 Test.13; + ret Test.11; diff --git a/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unification.txt b/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unification.txt new file mode 100644 index 0000000000..adc95cb888 --- /dev/null +++ b/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unification.txt @@ -0,0 +1,79 @@ +procedure Bool.2 (): + let Bool.23 : Int1 = true; + ret Bool.23; + +procedure Test.12 (Test.52): + let Test.72 : Int1 = false; + ret Test.72; + +procedure Test.13 (Test.51): + let Test.80 : Int1 = true; + ret Test.80; + +procedure Test.14 (Test.50): + ret Test.50; + +procedure Test.15 (Test.49): + let Test.71 : {} = Struct {}; + let Test.70 : Int1 = CallByName Test.12 Test.71; + ret Test.70; + +procedure Test.16 (Test.48): + let Test.79 : {} = Struct {}; + let Test.78 : Int1 = CallByName Test.13 Test.79; + ret Test.78; + +procedure Test.17 (Test.47): + ret Test.47; + +procedure Test.35 (Test.36, Test.73): + inc Test.36; + ret Test.36; + +procedure Test.37 (Test.38, Test.81): + inc Test.38; + ret Test.38; + +procedure Test.40 (Test.41, Test.65, Test.39): + let Test.68 : {} = Struct {}; + switch Test.39: + case 0: + let Test.67 : List U8 = CallByName Test.35 Test.41 Test.68; + ret Test.67; + + default: + let Test.67 : List U8 = CallByName Test.37 Test.41 Test.68; + ret Test.67; + + +procedure Test.43 (Test.44, Test.42): + joinpoint Test.62 Test.60: + let Test.59 : List U8 = Array []; + let Test.58 : List U8 = CallByName Test.40 Test.59 Test.44 Test.60; + dec Test.59; + ret Test.58; + in + let Test.75 : Int1 = CallByName Bool.2; + if Test.75 then + let Test.77 : Str = StructAtIndex 0 Test.42; + inc Test.77; + dec Test.42; + let Test.76 : Int1 = CallByName Test.16 Test.77; + dec Test.77; + let Test.61 : Int1 = CallByName Test.14 Test.76; + jump Test.62 Test.61; + else + let Test.69 : U8 = StructAtIndex 1 Test.42; + dec Test.42; + let Test.63 : Int1 = CallByName Test.15 Test.69; + let Test.61 : Int1 = CallByName Test.14 Test.63; + jump Test.62 Test.61; + +procedure Test.0 (): + let Test.83 : Str = ""; + let Test.84 : U8 = 7i64; + let Test.55 : {Str, U8} = Struct {Test.83, Test.84}; + let Test.46 : {Str, U8} = CallByName Test.17 Test.55; + let Test.54 : {} = Struct {}; + let Test.53 : List U8 = CallByName Test.43 Test.54 Test.46; + ret Test.53; diff --git a/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unification_of_unifiable.txt b/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unification_of_unifiable.txt new file mode 100644 index 0000000000..897d83996e --- /dev/null +++ b/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unification_of_unifiable.txt @@ -0,0 +1,371 @@ +procedure #Derived.0 (#Derived.1): + let #Derived_gen.10 : [C {}, C {}] = TagId(0) #Derived.1; + let #Derived_gen.9 : [C {}, C {}] = CallByName Encode.22 #Derived_gen.10; + ret #Derived_gen.9; + +procedure #Derived.2 (#Derived.3, #Derived.4, #Attr.12): + let #Derived.1 : {} = UnionAtIndex (Id 0) (Index 0) #Attr.12; + joinpoint #Derived_gen.14 #Derived_gen.13: + let #Derived_gen.12 : List U8 = CallByName Encode.23 #Derived.3 #Derived_gen.13 #Derived.4; + ret #Derived_gen.12; + in + let #Derived_gen.16 : Str = "A"; + let #Derived_gen.17 : List [] = Array []; + let #Derived_gen.15 : {Str, List []} = CallByName Json.21 #Derived_gen.16 #Derived_gen.17; + jump #Derived_gen.14 #Derived_gen.15; + +procedure #Derived.5 (#Derived.6): + let #Derived_gen.1 : [C {}, C {}] = TagId(1) #Derived.6; + let #Derived_gen.0 : [C {}, C {}] = CallByName Encode.22 #Derived_gen.1; + ret #Derived_gen.0; + +procedure #Derived.7 (#Derived.8, #Derived.9, #Attr.12): + let #Derived.6 : {} = UnionAtIndex (Id 1) (Index 0) #Attr.12; + joinpoint #Derived_gen.5 #Derived_gen.4: + let #Derived_gen.3 : List U8 = CallByName Encode.23 #Derived.8 #Derived_gen.4 #Derived.9; + ret #Derived_gen.3; + in + let #Derived_gen.7 : Str = "B"; + let #Derived_gen.8 : List [] = Array []; + let #Derived_gen.6 : {Str, List []} = CallByName Json.21 #Derived_gen.7 #Derived_gen.8; + jump #Derived_gen.5 #Derived_gen.6; + +procedure Bool.2 (): + let Bool.23 : Int1 = true; + ret Bool.23; + +procedure Encode.22 (Encode.93): + ret Encode.93; + +procedure Encode.22 (Encode.93): + ret Encode.93; + +procedure Encode.22 (Encode.93): + ret Encode.93; + +procedure Encode.22 (Encode.93): + ret Encode.93; + +procedure Encode.23 (Encode.94, Encode.102, Encode.96): + let Encode.106 : List U8 = CallByName Test.5 Encode.94 Encode.96 Encode.102; + ret Encode.106; + +procedure Encode.23 (Encode.94, Encode.102, Encode.96): + let Encode.113 : List U8 = CallByName Json.129 Encode.94 Encode.96 Encode.102; + ret Encode.113; + +procedure Encode.23 (Encode.94, Encode.102, Encode.96): + let Encode.117 : U8 = GetTagId Encode.102; + switch Encode.117: + case 0: + let Encode.116 : List U8 = CallByName #Derived.2 Encode.94 Encode.96 Encode.102; + ret Encode.116; + + default: + let Encode.116 : List U8 = CallByName #Derived.7 Encode.94 Encode.96 Encode.102; + ret Encode.116; + + +procedure Encode.23 (Encode.94, Encode.102, Encode.96): + let Encode.129 : List U8 = CallByName Json.129 Encode.94 Encode.96 Encode.102; + ret Encode.129; + +procedure Encode.23 (Encode.94, Encode.102, Encode.96): + let Encode.133 : Str = "a Lambda Set is empty. Most likely there is a type error in your program."; + Crash Encode.133 + +procedure Encode.25 (Encode.100, Encode.101): + let Encode.104 : List U8 = Array []; + let Encode.105 : {{}, {}} = CallByName Test.2 Encode.100; + let Encode.103 : List U8 = CallByName Encode.23 Encode.104 Encode.105 Encode.101; + ret Encode.103; + +procedure Json.1 (): + let Json.425 : {} = Struct {}; + ret Json.425; + +procedure Json.129 (Json.130, Json.428, #Attr.12): + let Json.128 : List [C {}, C {}] = StructAtIndex 1 #Attr.12; + inc Json.128; + let Json.127 : Str = StructAtIndex 0 #Attr.12; + inc Json.127; + dec #Attr.12; + let Json.466 : I64 = 123i64; + let Json.465 : U8 = CallByName Num.127 Json.466; + let Json.462 : List U8 = CallByName List.4 Json.130 Json.465; + let Json.464 : I64 = 34i64; + let Json.463 : U8 = CallByName Num.127 Json.464; + let Json.460 : List U8 = CallByName List.4 Json.462 Json.463; + let Json.461 : List U8 = CallByName Str.12 Json.127; + let Json.457 : List U8 = CallByName List.8 Json.460 Json.461; + let Json.459 : I64 = 34i64; + let Json.458 : U8 = CallByName Num.127 Json.459; + let Json.454 : List U8 = CallByName List.4 Json.457 Json.458; + let Json.456 : I64 = 58i64; + let Json.455 : U8 = CallByName Num.127 Json.456; + let Json.451 : List U8 = CallByName List.4 Json.454 Json.455; + let Json.453 : I64 = 91i64; + let Json.452 : U8 = CallByName Num.127 Json.453; + let Json.132 : List U8 = CallByName List.4 Json.451 Json.452; + let Json.450 : U64 = CallByName List.6 Json.128; + let Json.438 : {List U8, U64} = Struct {Json.132, Json.450}; + let Json.439 : {} = Struct {}; + let Json.437 : {List U8, U64} = CallByName List.18 Json.128 Json.438 Json.439; + dec Json.128; + let Json.134 : List U8 = StructAtIndex 0 Json.437; + inc Json.134; + dec Json.437; + let Json.436 : I64 = 93i64; + let Json.435 : U8 = CallByName Num.127 Json.436; + let Json.432 : List U8 = CallByName List.4 Json.134 Json.435; + let Json.434 : I64 = 125i64; + let Json.433 : U8 = CallByName Num.127 Json.434; + let Json.431 : List U8 = CallByName List.4 Json.432 Json.433; + ret Json.431; + +procedure Json.129 (Json.130, Json.428, #Attr.12): + let Json.128 : List [] = StructAtIndex 1 #Attr.12; + inc Json.128; + let Json.127 : Str = StructAtIndex 0 #Attr.12; + inc Json.127; + dec #Attr.12; + let Json.516 : I64 = 123i64; + let Json.515 : U8 = CallByName Num.127 Json.516; + let Json.512 : List U8 = CallByName List.4 Json.130 Json.515; + let Json.514 : I64 = 34i64; + let Json.513 : U8 = CallByName Num.127 Json.514; + let Json.510 : List U8 = CallByName List.4 Json.512 Json.513; + let Json.511 : List U8 = CallByName Str.12 Json.127; + let Json.507 : List U8 = CallByName List.8 Json.510 Json.511; + let Json.509 : I64 = 34i64; + let Json.508 : U8 = CallByName Num.127 Json.509; + let Json.504 : List U8 = CallByName List.4 Json.507 Json.508; + let Json.506 : I64 = 58i64; + let Json.505 : U8 = CallByName Num.127 Json.506; + let Json.501 : List U8 = CallByName List.4 Json.504 Json.505; + let Json.503 : I64 = 91i64; + let Json.502 : U8 = CallByName Num.127 Json.503; + let Json.132 : List U8 = CallByName List.4 Json.501 Json.502; + let Json.500 : U64 = CallByName List.6 Json.128; + let Json.488 : {List U8, U64} = Struct {Json.132, Json.500}; + let Json.489 : {} = Struct {}; + let Json.487 : {List U8, U64} = CallByName List.18 Json.128 Json.488 Json.489; + dec Json.128; + let Json.134 : List U8 = StructAtIndex 0 Json.487; + inc Json.134; + dec Json.487; + let Json.486 : I64 = 93i64; + let Json.485 : U8 = CallByName Num.127 Json.486; + let Json.482 : List U8 = CallByName List.4 Json.134 Json.485; + let Json.484 : I64 = 125i64; + let Json.483 : U8 = CallByName Num.127 Json.484; + let Json.481 : List U8 = CallByName List.4 Json.482 Json.483; + ret Json.481; + +procedure Json.131 (Json.430, Json.137): + let Json.135 : List U8 = StructAtIndex 0 Json.430; + inc Json.135; + let Json.136 : U64 = StructAtIndex 1 Json.430; + dec Json.430; + let Json.449 : {} = Struct {}; + let Json.138 : List U8 = CallByName Encode.23 Json.135 Json.137 Json.449; + joinpoint Json.444 Json.139: + let Json.442 : U64 = 1i64; + let Json.441 : U64 = CallByName Num.20 Json.136 Json.442; + let Json.440 : {List U8, U64} = Struct {Json.139, Json.441}; + ret Json.440; + in + let Json.448 : U64 = 1i64; + let Json.445 : Int1 = CallByName Num.24 Json.136 Json.448; + if Json.445 then + let Json.447 : I64 = 44i64; + let Json.446 : U8 = CallByName Num.127 Json.447; + let Json.443 : List U8 = CallByName List.4 Json.138 Json.446; + jump Json.444 Json.443; + else + jump Json.444 Json.138; + +procedure Json.131 (Json.430, Json.137): + let Json.135 : List U8 = StructAtIndex 0 Json.430; + inc Json.135; + let Json.136 : U64 = StructAtIndex 1 Json.430; + dec Json.430; + let Json.499 : {} = Struct {}; + let Json.138 : List U8 = CallByName Encode.23 Json.135 Json.137 Json.499; + dec Json.135; + joinpoint Json.494 Json.139: + let Json.492 : U64 = 1i64; + let Json.491 : U64 = CallByName Num.20 Json.136 Json.492; + let Json.490 : {List U8, U64} = Struct {Json.139, Json.491}; + ret Json.490; + in + let Json.498 : U64 = 1i64; + let Json.495 : Int1 = CallByName Num.24 Json.136 Json.498; + if Json.495 then + let Json.497 : I64 = 44i64; + let Json.496 : U8 = CallByName Num.127 Json.497; + let Json.493 : List U8 = CallByName List.4 Json.138 Json.496; + jump Json.494 Json.493; + else + jump Json.494 Json.138; + +procedure Json.21 (Json.127, Json.128): + let Json.468 : {Str, List [C {}, C {}]} = Struct {Json.127, Json.128}; + let Json.467 : {Str, List [C {}, C {}]} = CallByName Encode.22 Json.468; + ret Json.467; + +procedure Json.21 (Json.127, Json.128): + let Json.518 : {Str, List []} = Struct {Json.127, Json.128}; + let Json.517 : {Str, List []} = CallByName Encode.22 Json.518; + ret Json.517; + +procedure List.138 (List.139, List.140, List.137): + let List.538 : {List U8, U64} = CallByName Json.131 List.139 List.140; + ret List.538; + +procedure List.138 (List.139, List.140, List.137): + let List.611 : {List U8, U64} = CallByName Json.131 List.139 List.140; + ret List.611; + +procedure List.18 (List.135, List.136, List.137): + let List.519 : {List U8, U64} = CallByName List.91 List.135 List.136 List.137; + ret List.519; + +procedure List.18 (List.135, List.136, List.137): + let List.592 : {List U8, U64} = CallByName List.91 List.135 List.136 List.137; + ret List.592; + +procedure List.4 (List.106, List.107): + let List.591 : U64 = 1i64; + let List.590 : List U8 = CallByName List.70 List.106 List.591; + let List.589 : List U8 = CallByName List.71 List.590 List.107; + ret List.589; + +procedure List.6 (#Attr.2): + let List.539 : U64 = lowlevel ListLen #Attr.2; + ret List.539; + +procedure List.6 (#Attr.2): + let List.612 : U64 = lowlevel ListLen #Attr.2; + ret List.612; + +procedure List.66 (#Attr.2, #Attr.3): + let List.535 : [C {}, C {}] = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.535; + +procedure List.66 (#Attr.2, #Attr.3): + let List.608 : [] = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.608; + +procedure List.70 (#Attr.2, #Attr.3): + let List.570 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.570; + +procedure List.71 (#Attr.2, #Attr.3): + let List.568 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.568; + +procedure List.8 (#Attr.2, #Attr.3): + let List.613 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.613; + +procedure List.80 (List.550, List.551, List.552, List.553, List.554): + joinpoint List.525 List.432 List.433 List.434 List.435 List.436: + let List.527 : Int1 = CallByName Num.22 List.435 List.436; + if List.527 then + let List.534 : [C {}, C {}] = CallByName List.66 List.432 List.435; + let List.528 : {List U8, U64} = CallByName List.138 List.433 List.534 List.434; + let List.531 : U64 = 1i64; + let List.530 : U64 = CallByName Num.19 List.435 List.531; + jump List.525 List.432 List.528 List.434 List.530 List.436; + else + ret List.433; + in + jump List.525 List.550 List.551 List.552 List.553 List.554; + +procedure List.80 (List.623, List.624, List.625, List.626, List.627): + joinpoint List.598 List.432 List.433 List.434 List.435 List.436: + let List.600 : Int1 = CallByName Num.22 List.435 List.436; + if List.600 then + let List.607 : [] = CallByName List.66 List.432 List.435; + let List.601 : {List U8, U64} = CallByName List.138 List.433 List.607 List.434; + let List.604 : U64 = 1i64; + let List.603 : U64 = CallByName Num.19 List.435 List.604; + jump List.598 List.432 List.601 List.434 List.603 List.436; + else + ret List.433; + in + jump List.598 List.623 List.624 List.625 List.626 List.627; + +procedure List.91 (List.429, List.430, List.431): + let List.523 : U64 = 0i64; + let List.524 : U64 = CallByName List.6 List.429; + let List.522 : {List U8, U64} = CallByName List.80 List.429 List.430 List.431 List.523 List.524; + ret List.522; + +procedure List.91 (List.429, List.430, List.431): + let List.596 : U64 = 0i64; + let List.597 : U64 = CallByName List.6 List.429; + let List.595 : {List U8, U64} = CallByName List.80 List.429 List.430 List.431 List.596 List.597; + ret List.595; + +procedure Num.127 (#Attr.2): + let Num.303 : U8 = lowlevel NumIntCast #Attr.2; + ret Num.303; + +procedure Num.19 (#Attr.2, #Attr.3): + let Num.306 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.306; + +procedure Num.20 (#Attr.2, #Attr.3): + let Num.304 : U64 = lowlevel NumSub #Attr.2 #Attr.3; + ret Num.304; + +procedure Num.22 (#Attr.2, #Attr.3): + let Num.307 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.307; + +procedure Num.24 (#Attr.2, #Attr.3): + let Num.305 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; + ret Num.305; + +procedure Str.12 (#Attr.2): + let Str.267 : List U8 = lowlevel StrToUtf8 #Attr.2; + ret Str.267; + +procedure Test.2 (Test.11): + let Test.18 : {{}, {}} = CallByName Encode.22 Test.11; + ret Test.18; + +procedure Test.3 (): + let Test.16 : {} = Struct {}; + let Test.17 : {} = Struct {}; + let Test.15 : {{}, {}} = Struct {Test.16, Test.17}; + ret Test.15; + +procedure Test.5 (Test.6, Test.7, Test.4): + joinpoint Test.23 Test.8: + let Test.21 : List U8 = CallByName Encode.23 Test.6 Test.8 Test.7; + ret Test.21; + in + let Test.28 : Int1 = CallByName Bool.2; + if Test.28 then + let Test.29 : Str = "A"; + let Test.32 : {} = StructAtIndex 0 Test.4; + let Test.31 : [C {}, C {}] = CallByName #Derived.0 Test.32; + let Test.30 : List [C {}, C {}] = Array [Test.31]; + let Test.22 : {Str, List [C {}, C {}]} = CallByName Json.21 Test.29 Test.30; + jump Test.23 Test.22; + else + let Test.24 : Str = "B"; + let Test.27 : {} = StructAtIndex 1 Test.4; + let Test.26 : [C {}, C {}] = CallByName #Derived.5 Test.27; + let Test.25 : List [C {}, C {}] = Array [Test.26]; + let Test.22 : {Str, List [C {}, C {}]} = CallByName Json.21 Test.24 Test.25; + jump Test.23 Test.22; + +procedure Test.0 (): + let Test.13 : {{}, {}} = CallByName Test.3; + let Test.14 : {} = CallByName Json.1; + let Test.12 : List U8 = CallByName Encode.25 Test.13 Test.14; + ret Test.12; diff --git a/crates/compiler/test_mono/generated/weakening_avoids_overspecialization.txt b/crates/compiler/test_mono/generated/weakening_avoids_overspecialization.txt index 6720a3c26e..8744a752eb 100644 --- a/crates/compiler/test_mono/generated/weakening_avoids_overspecialization.txt +++ b/crates/compiler/test_mono/generated/weakening_avoids_overspecialization.txt @@ -3,97 +3,97 @@ procedure Bool.11 (#Attr.2, #Attr.3): ret Bool.24; procedure List.26 (List.152, List.153, List.154): - let List.493 : [C U64, C U64] = CallByName List.90 List.152 List.153 List.154; - let List.496 : U8 = 1i64; - let List.497 : U8 = GetTagId List.493; - let List.498 : Int1 = lowlevel Eq List.496 List.497; - if List.498 then - let List.155 : U64 = UnionAtIndex (Id 1) (Index 0) List.493; + let List.508 : [C U64, C U64] = CallByName List.91 List.152 List.153 List.154; + let List.511 : U8 = 1i64; + let List.512 : U8 = GetTagId List.508; + let List.513 : Int1 = lowlevel Eq List.511 List.512; + if List.513 then + let List.155 : U64 = UnionAtIndex (Id 1) (Index 0) List.508; ret List.155; else - let List.156 : U64 = UnionAtIndex (Id 0) (Index 0) List.493; + let List.156 : U64 = UnionAtIndex (Id 0) (Index 0) List.508; ret List.156; -procedure List.29 (List.294, List.295): - let List.492 : U64 = CallByName List.6 List.294; - let List.296 : U64 = CallByName Num.77 List.492 List.295; - let List.478 : List U8 = CallByName List.43 List.294 List.296; - ret List.478; +procedure List.29 (List.297, List.298): + let List.507 : U64 = CallByName List.6 List.297; + let List.299 : U64 = CallByName Num.77 List.507 List.298; + let List.493 : List U8 = CallByName List.43 List.297 List.299; + ret List.493; -procedure List.43 (List.292, List.293): - let List.490 : U64 = CallByName List.6 List.292; - let List.489 : U64 = CallByName Num.77 List.490 List.293; - let List.480 : {U64, U64} = Struct {List.293, List.489}; - let List.479 : List U8 = CallByName List.49 List.292 List.480; - ret List.479; +procedure List.43 (List.295, List.296): + let List.505 : U64 = CallByName List.6 List.295; + let List.504 : U64 = CallByName Num.77 List.505 List.296; + let List.495 : {U64, U64} = Struct {List.296, List.504}; + let List.494 : List U8 = CallByName List.49 List.295 List.495; + ret List.494; -procedure List.49 (List.366, List.367): - let List.487 : U64 = StructAtIndex 0 List.367; - let List.488 : U64 = 0i64; - let List.485 : Int1 = CallByName Bool.11 List.487 List.488; - if List.485 then - dec List.366; - let List.486 : List U8 = Array []; - ret List.486; +procedure List.49 (List.369, List.370): + let List.502 : U64 = StructAtIndex 0 List.370; + let List.503 : U64 = 0i64; + let List.500 : Int1 = CallByName Bool.11 List.502 List.503; + if List.500 then + dec List.369; + let List.501 : List U8 = Array []; + ret List.501; else - let List.482 : U64 = StructAtIndex 1 List.367; - let List.483 : U64 = StructAtIndex 0 List.367; - let List.481 : List U8 = CallByName List.72 List.366 List.482 List.483; - ret List.481; + let List.497 : U64 = StructAtIndex 1 List.370; + let List.498 : U64 = StructAtIndex 0 List.370; + let List.496 : List U8 = CallByName List.72 List.369 List.497 List.498; + ret List.496; procedure List.6 (#Attr.2): - let List.491 : U64 = lowlevel ListLen #Attr.2; - ret List.491; + let List.506 : U64 = lowlevel ListLen #Attr.2; + ret List.506; procedure List.66 (#Attr.2, #Attr.3): - let List.514 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.514; + let List.529 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.529; procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.484 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.484; - -procedure List.90 (List.426, List.427, List.428): - let List.500 : U64 = 0i64; - let List.501 : U64 = CallByName List.6 List.426; - let List.499 : [C U64, C U64] = CallByName List.91 List.426 List.427 List.428 List.500 List.501; + let List.499 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; ret List.499; -procedure List.91 (List.528, List.529, List.530, List.531, List.532): - joinpoint List.502 List.429 List.430 List.431 List.432 List.433: - let List.504 : Int1 = CallByName Num.22 List.432 List.433; - if List.504 then - let List.513 : U8 = CallByName List.66 List.429 List.432; - let List.505 : [C U64, C U64] = CallByName Test.3 List.430 List.513; - let List.510 : U8 = 1i64; - let List.511 : U8 = GetTagId List.505; - let List.512 : Int1 = lowlevel Eq List.510 List.511; - if List.512 then - let List.434 : U64 = UnionAtIndex (Id 1) (Index 0) List.505; - let List.508 : U64 = 1i64; - let List.507 : U64 = CallByName Num.19 List.432 List.508; - jump List.502 List.429 List.434 List.431 List.507 List.433; +procedure List.80 (List.543, List.544, List.545, List.546, List.547): + joinpoint List.517 List.432 List.433 List.434 List.435 List.436: + let List.519 : Int1 = CallByName Num.22 List.435 List.436; + if List.519 then + let List.528 : U8 = CallByName List.66 List.432 List.435; + let List.520 : [C U64, C U64] = CallByName Test.3 List.433 List.528; + let List.525 : U8 = 1i64; + let List.526 : U8 = GetTagId List.520; + let List.527 : Int1 = lowlevel Eq List.525 List.526; + if List.527 then + let List.437 : U64 = UnionAtIndex (Id 1) (Index 0) List.520; + let List.523 : U64 = 1i64; + let List.522 : U64 = CallByName Num.19 List.435 List.523; + jump List.517 List.432 List.437 List.434 List.522 List.436; else - let List.435 : U64 = UnionAtIndex (Id 0) (Index 0) List.505; - let List.509 : [C U64, C U64] = TagId(0) List.435; - ret List.509; + let List.438 : U64 = UnionAtIndex (Id 0) (Index 0) List.520; + let List.524 : [C U64, C U64] = TagId(0) List.438; + ret List.524; else - let List.503 : [C U64, C U64] = TagId(1) List.430; - ret List.503; + let List.518 : [C U64, C U64] = TagId(1) List.433; + ret List.518; in - jump List.502 List.528 List.529 List.530 List.531 List.532; + jump List.517 List.543 List.544 List.545 List.546 List.547; + +procedure List.91 (List.429, List.430, List.431): + let List.515 : U64 = 0i64; + let List.516 : U64 = CallByName List.6 List.429; + let List.514 : [C U64, C U64] = CallByName List.80 List.429 List.430 List.431 List.515 List.516; + ret List.514; procedure Num.19 (#Attr.2, #Attr.3): - let Num.258 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.258; + let Num.277 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.277; procedure Num.22 (#Attr.2, #Attr.3): - let Num.259 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; - ret Num.259; + let Num.278 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.278; procedure Num.77 (#Attr.2, #Attr.3): - let Num.257 : U64 = lowlevel NumSubSaturated #Attr.2 #Attr.3; - ret Num.257; + let Num.276 : U64 = lowlevel NumSubSaturated #Attr.2 #Attr.3; + ret Num.276; procedure Test.3 (Test.4, Test.12): let Test.13 : [C U64, C U64] = TagId(0) Test.4; diff --git a/crates/compiler/test_mono/generated/when_nested_maybe.txt b/crates/compiler/test_mono/generated/when_nested_maybe.txt index 4b2af8c406..3da4e73dcc 100644 --- a/crates/compiler/test_mono/generated/when_nested_maybe.txt +++ b/crates/compiler/test_mono/generated/when_nested_maybe.txt @@ -1,6 +1,6 @@ procedure Num.19 (#Attr.2, #Attr.3): - let Num.256 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.275; procedure Test.0 (): let Test.19 : I64 = 41i64; diff --git a/crates/compiler/test_mono/generated/when_on_record.txt b/crates/compiler/test_mono/generated/when_on_record.txt index 83aabd4e7f..6735c9b9bb 100644 --- a/crates/compiler/test_mono/generated/when_on_record.txt +++ b/crates/compiler/test_mono/generated/when_on_record.txt @@ -1,6 +1,6 @@ procedure Num.19 (#Attr.2, #Attr.3): - let Num.256 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.275; procedure Test.0 (): let Test.5 : I64 = 2i64; diff --git a/crates/compiler/test_mono/generated/when_on_two_values.txt b/crates/compiler/test_mono/generated/when_on_two_values.txt index 14788ffbaf..263451ff02 100644 --- a/crates/compiler/test_mono/generated/when_on_two_values.txt +++ b/crates/compiler/test_mono/generated/when_on_two_values.txt @@ -1,6 +1,6 @@ procedure Num.19 (#Attr.2, #Attr.3): - let Num.256 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.256; + let Num.275 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.275; procedure Test.0 (): let Test.15 : I64 = 3i64; diff --git a/crates/compiler/test_mono/src/tests.rs b/crates/compiler/test_mono/src/tests.rs index 0fb8eaab3a..5870f882b4 100644 --- a/crates/compiler/test_mono/src/tests.rs +++ b/crates/compiler/test_mono/src/tests.rs @@ -2571,3 +2571,200 @@ fn recursive_lambda_set_has_nested_non_recursive_lambda_sets_issue_5026() { "# ) } + +#[mono_test] +fn unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unification() { + // This is a regression test for the ambient lambda set specialization algorithm. + // + // In the program below, monomorphization of `toEncoderQ` with the `Q` in `main` induces the + // resolution of `t.a` and `t.b`, and the unification of their pending unspecialization lambda + // sets, when `t.a` and `t.b` have been resolved to concrete types, but before the + // specialization procedure steps in to resolve the lambda sets concretely. That's because + // monomorphization unifies the general type of `toEncoderQ` with the concrete type, forcing + // concretization of `t`, but the specialization procedure runs only after the unification is + // complete. + // + // In this case, it's imperative that the unspecialized lambda sets of `toEncoder t.a` and + // `toEncoder t.b` wind up in the same lambda set, that is in + // + // tag : @MEncoder (Bytes, Linear -[[] + @MU8:toEncoder:1 + @MStr:toEncoder+1] -> Bytes) + // -[lTag]-> + // @MEncoder (Bytes, Linear -[[Linear:lTag:3 { @MEncoder (Bytes, Linear -[[] + @MU8:toEncoder:1 + @MStr:toEncoder:1] -> Bytes) }]] -> Bytes) + // + // rather than forcing the lambda set inside to `tag` to become disjoint, as e.g. + // + // tag : @MEncoder (Bytes, Linear -[[] + @MU8:toEncoder:1 + @MStr:toEncoder+1] -> Bytes) + // -[lTag]-> + // @MEncoder (Bytes, Linear -[[ + // Linear:lTag:3 { @MEncoder (Bytes, Linear -[[] + @MU8:toEncoder:1] -> Bytes) }, + // Linear:lTag:3 { @MEncoder (Bytes, Linear -[[] + @MStr:toEncoder:1] -> Bytes) }, + // ]] -> Bytes) + indoc!( + r#" + app "test" provides [main] to "./platform" + + MEncoder fmt := List U8, fmt -> List U8 | fmt has Format + + MEncoding has + toEncoder : val -> MEncoder fmt | val has MEncoding, fmt has Format + + Format has + u8 : {} -> MEncoder fmt | fmt has Format + str : {} -> MEncoder fmt | fmt has Format + tag : MEncoder fmt -> MEncoder fmt | fmt has Format + + Linear := {} has [Format {u8: lU8, str: lStr, tag: lTag}] + + MU8 := U8 has [MEncoding {toEncoder: toEncoderU8}] + MStr := Str has [MEncoding {toEncoder: toEncoderStr}] + + Q a b := { a: a, b: b } + + lU8 = \{} -> @MEncoder (\lst, @Linear {} -> lst) + lStr = \{} -> @MEncoder (\lst, @Linear {} -> lst) + + lTag = \@MEncoder doFormat -> @MEncoder (\lst, @Linear {} -> + doFormat lst (@Linear {}) + ) + + toEncoderU8 = \@MU8 _ -> u8 {} + + toEncoderStr = \@MStr _ -> str {} + + toEncoderQ = + \@Q t -> \fmt -> + @MEncoder doit = if Bool.true + then tag (toEncoder t.a) + else tag (toEncoder t.b) + + doit [] fmt + + main = + fmt = toEncoderQ (@Q {a : @MStr "", b: @MU8 7}) + fmt (@Linear {}) + "# + ) +} + +#[mono_test] +fn unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unification_of_unifiable() +{ + // This is a regression test for the ambient lambda set specialization algorithm. + // + // The principle of the test is equivalent to that of `unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unification`. + // + // However, this test requires a larger reproduction because it is negative behavior is only + // visible in the presence of builtin ability usage (in this case, `Encoding` and + // `EncoderFormatting`). + // + // In this test, the payload types `[A]*` and `[B]*` of the encoded type `Q` are unifiable in + // their unspecialized lambda set representations under `toEncoderQ`; however, they must not + // be, because they in fact represent to different specializations of needed encoders. In + // particular, the lambda set `[[] + [A]:toEncoder:1 + [B]:toEncoder:1]` must be preserved, + // rather than collapsing to `[[] + [A, B]:toEncoder:1]`. + indoc!( + r#" + app "test" imports [Json] provides [main] to "./platform" + + Q a b := { a: a, b: b } has [Encoding {toEncoder: toEncoderQ}] + + toEncoderQ = + \@Q t -> Encode.custom \bytes, fmt -> + f = if Bool.true + then Encode.tag "A" [Encode.toEncoder t.a] + else Encode.tag "B" [Encode.toEncoder t.b] + + Encode.appendWith bytes f fmt + + accessor = @Q {a : A, b: B} + + main = + Encode.toBytes accessor Json.toUtf8 + "# + ) +} + +#[mono_test] +fn unspecialized_lambda_set_unification_does_not_duplicate_identical_concrete_types() { + // This is a regression test for the ambient lambda set specialization algorithm. + // + // The principle of the test is equivalent to that of `unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unification`. + // + // However, this test requires a larger reproduction because it is negative behavior is only + // visible in the presence of builtin ability usage (in this case, `Encoding` and + // `EncoderFormatting`). + // + // In this test, the payload types `Str` and `Str` of the encoded type `Q` are unifiable in + // their unspecialized lambda set representations under `toEncoderQ`, and moreoever they are + // equivalent specializations, since they both come from the same root variable `x`. In as + // such, the lambda set `[[] + Str:toEncoder:1]` should be produced during compaction, rather + // than staying as the expanded `[[] + Str:toEncoder:1 + Str:toEncoder:1]` after the types of + // `t.a` and `t.b` are filled in. + indoc!( + r#" + app "test" imports [Json] provides [main] to "./platform" + + Q a b := { a: a, b: b } has [Encoding {toEncoder: toEncoderQ}] + + toEncoderQ = + \@Q t -> Encode.custom \bytes, fmt -> + f = if Bool.true + then Encode.tag "A" [Encode.toEncoder t.a] + else Encode.tag "B" [Encode.toEncoder t.b] + + Encode.appendWith bytes f fmt + + accessor = + x = "" + @Q {a : x, b: x} + + main = + Encode.toBytes accessor Json.toUtf8 + "# + ) +} + +#[mono_test] +fn inline_return_joinpoints_in_bool_lambda_set() { + indoc!( + r#" + app "test" provides [f] to "./platform" + + f = \x -> + caller = if Bool.false then f else \n -> n + caller (x + 1) + "# + ) +} + +#[mono_test] +fn inline_return_joinpoints_in_enum_lambda_set() { + indoc!( + r#" + app "test" provides [f] to "./platform" + + f = \x -> + caller = \t -> when t is + A -> f + B -> \n -> n + C -> \n -> n + 1 + D -> \n -> n + 2 + (caller A) (x + 1) + "# + ) +} + +#[mono_test] +fn inline_return_joinpoints_in_union_lambda_set() { + indoc!( + r#" + app "test" provides [f] to "./platform" + + f = \x -> + caller = \t -> when t is + A -> f + B -> \n -> n + x + (caller A) (x + 1) + "# + ) +} diff --git a/crates/compiler/test_mono_macros/Cargo.lock b/crates/compiler/test_mono_macros/Cargo.lock deleted file mode 100644 index be4e5474f6..0000000000 --- a/crates/compiler/test_mono_macros/Cargo.lock +++ /dev/null @@ -1,47 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "proc-macro2" -version = "1.0.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "quote" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "syn" -version = "1.0.81" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "test_mono_macros" -version = "0.0.1" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" diff --git a/crates/compiler/test_mono_macros/Cargo.toml b/crates/compiler/test_mono_macros/Cargo.toml index b649dcab2d..2043423840 100644 --- a/crates/compiler/test_mono_macros/Cargo.toml +++ b/crates/compiler/test_mono_macros/Cargo.toml @@ -1,15 +1,16 @@ [package] name = "test_mono_macros" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Macros for use in test_mono." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [lib] proc-macro = true [dependencies] -syn = { version = "1.0.81", features = ["full", "extra-traits"] } -quote = "1.0.10" -proc-macro2 = "1.0.32" +proc-macro2.workspace = true +quote.workspace = true +syn.workspace = true diff --git a/crates/compiler/test_syntax/Cargo.toml b/crates/compiler/test_syntax/Cargo.toml index 513aea2d70..cb22da5c1f 100644 --- a/crates/compiler/test_syntax/Cargo.toml +++ b/crates/compiler/test_syntax/Cargo.toml @@ -1,24 +1,25 @@ [package] name = "test_syntax" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Tests for the parse + fmt crates." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [features] "parse_debug_trace" = ["roc_parse/parse_debug_trace"] [dependencies] +bumpalo.workspace = true roc_collections = { path = "../collections" } -roc_region = { path = "../region" } +roc_fmt = { path = "../fmt" } roc_module = { path = "../module" } roc_parse = { path = "../parse" } -roc_fmt = { path = "../fmt" } +roc_region = { path = "../region" } roc_test_utils = { path = "../../test_utils" } -bumpalo.workspace = true [dev-dependencies] -pretty_assertions.workspace = true indoc.workspace = true +pretty_assertions.workspace = true walkdir.workspace = true diff --git a/crates/compiler/test_syntax/fuzz/Cargo.lock b/crates/compiler/test_syntax/fuzz/Cargo.lock deleted file mode 100644 index 8c0eef0753..0000000000 --- a/crates/compiler/test_syntax/fuzz/Cargo.lock +++ /dev/null @@ -1,654 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "ahash" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - -[[package]] -name = "arbitrary" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db55d72333851e17d572bec876e390cd3b11eb1ef53ae821dd9f3b653d2b4569" - -[[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.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "bitmaps" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" -dependencies = [ - "typenum", -] - -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - -[[package]] -name = "bumpalo" -version = "3.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" - -[[package]] -name = "cc" -version = "1.0.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "crossbeam-channel" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" -dependencies = [ - "cfg-if", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" -dependencies = [ - "autocfg", - "cfg-if", - "crossbeam-utils", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "ctor" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "diff" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" - -[[package]] -name = "doc-comment" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" - -[[package]] -name = "either" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" - -[[package]] -name = "encode_unicode" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - -[[package]] -name = "getrandom" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "gimli" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash", - "bumpalo", -] - -[[package]] -name = "heck" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "im" -version = "15.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9" -dependencies = [ - "bitmaps", - "rand_core", - "rand_xoshiro", - "sized-chunks", - "typenum", - "version_check", -] - -[[package]] -name = "im-rc" -version = "15.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe" -dependencies = [ - "bitmaps", - "rand_core", - "rand_xoshiro", - "sized-chunks", - "typenum", - "version_check", -] - -[[package]] -name = "libc" -version = "0.2.131" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04c3b4822ccebfa39c02fc03d1534441b22ead323fa0f48bb7ddd8e6ba076a40" - -[[package]] -name = "libfuzzer-sys" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee8c42ab62f43795ed77a965ed07994c5584cdc94fd0ebf14b22ac1524077acc" -dependencies = [ - "arbitrary", - "cc", -] - -[[package]] -name = "log" -version = "0.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "memchr" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "memoffset" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg", -] - -[[package]] -name = "miniz_oxide" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" -dependencies = [ - "adler", -] - -[[package]] -name = "num_cpus" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "object" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" - -[[package]] -name = "output_vt100" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66" -dependencies = [ - "winapi", -] - -[[package]] -name = "pretty_assertions" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755" -dependencies = [ - "ctor", - "diff", - "output_vt100", - "yansi", -] - -[[package]] -name = "proc-macro2" -version = "1.0.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - -[[package]] -name = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" - -[[package]] -name = "rand_xoshiro" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rayon" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-utils", - "num_cpus", -] - -[[package]] -name = "remove_dir_all" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "882f368737489ea543bc5c340e6f3d34a28c39980bd9a979e47322b26f60ac40" -dependencies = [ - "libc", - "log", - "num_cpus", - "rayon", - "winapi", -] - -[[package]] -name = "roc_collections" -version = "0.0.1" -dependencies = [ - "bitvec", - "bumpalo", - "fnv", - "hashbrown", - "im", - "im-rc", - "wyhash", -] - -[[package]] -name = "roc_error_macros" -version = "0.0.1" - -[[package]] -name = "roc_fmt" -version = "0.0.1" -dependencies = [ - "bumpalo", - "roc_collections", - "roc_module", - "roc_parse", - "roc_region", -] - -[[package]] -name = "roc_ident" -version = "0.0.1" - -[[package]] -name = "roc_module" -version = "0.0.1" -dependencies = [ - "bumpalo", - "roc_collections", - "roc_error_macros", - "roc_ident", - "roc_region", - "snafu", - "static_assertions", -] - -[[package]] -name = "roc_parse" -version = "0.0.1" -dependencies = [ - "bumpalo", - "encode_unicode", - "roc_collections", - "roc_module", - "roc_region", -] - -[[package]] -name = "roc_region" -version = "0.0.1" -dependencies = [ - "static_assertions", -] - -[[package]] -name = "roc_test_utils" -version = "0.0.1" -dependencies = [ - "pretty_assertions", - "remove_dir_all", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "sized-chunks" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" -dependencies = [ - "bitmaps", - "typenum", -] - -[[package]] -name = "snafu" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5177903bf45656592d9eb5c0e22f408fc023aae51dbe2088889b71633ba451f2" -dependencies = [ - "backtrace", - "doc-comment", - "snafu-derive", -] - -[[package]] -name = "snafu-derive" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "410b26ed97440d90ced3e2488c868d56a86e2064f5d7d6f417909b286afe25e5" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "syn" -version = "1.0.99" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "test_syntax" -version = "0.0.1" -dependencies = [ - "bumpalo", - "roc_collections", - "roc_fmt", - "roc_module", - "roc_parse", - "roc_region", - "roc_test_utils", -] - -[[package]] -name = "test_syntax-fuzz" -version = "0.0.0" -dependencies = [ - "bumpalo", - "libfuzzer-sys", - "test_syntax", -] - -[[package]] -name = "typenum" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" - -[[package]] -name = "unicode-ident" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" - -[[package]] -name = "version_check" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[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-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "wyhash" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf6e163c25e3fac820b4b453185ea2dea3b6a3e0a721d4d23d75bd33734c295" -dependencies = [ - "rand_core", -] - -[[package]] -name = "wyz" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b31594f29d27036c383b53b59ed3476874d518f0efb151b27a4c275141390e" -dependencies = [ - "tap", -] - -[[package]] -name = "yansi" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" diff --git a/crates/compiler/test_syntax/fuzz/Cargo.toml b/crates/compiler/test_syntax/fuzz/Cargo.toml index 65ce2f8e36..26a786ff2a 100644 --- a/crates/compiler/test_syntax/fuzz/Cargo.toml +++ b/crates/compiler/test_syntax/fuzz/Cargo.toml @@ -1,18 +1,20 @@ [package] name = "test_syntax-fuzz" -version = "0.0.0" -authors = ["Automatically generated"] publish = false -edition = "2021" + +authors.workspace = true +edition.workspace = true +version.workspace = true [package.metadata] cargo-fuzz = true [dependencies] -libfuzzer-sys = "0.3" -bumpalo = { version = "3.6.1", features = ["collections"] } test_syntax = { path = "../../test_syntax" } +bumpalo.workspace = true +libfuzzer-sys.workspace = true + # Prevent this from interfering with workspaces [workspace] members = ["."] diff --git a/crates/compiler/test_syntax/src/test_helpers.rs b/crates/compiler/test_syntax/src/test_helpers.rs index 27e9f22a8a..e0038c5705 100644 --- a/crates/compiler/test_syntax/src/test_helpers.rs +++ b/crates/compiler/test_syntax/src/test_helpers.rs @@ -243,10 +243,11 @@ impl<'a> Input<'a> { let reformatted = reparsed_ast.format(); if output != reformatted { - eprintln!("Formatting bug; formatting is not stable.\nOriginal code:\n{}\n\nFormatted code:\n{}\n\nAST:\n{:#?}\n\n", + eprintln!("Formatting bug; formatting is not stable.\nOriginal code:\n{}\n\nFormatted code:\n{}\n\nAST:\n{:#?}\n\nReparsed AST:\n{:#?}\n\n", self.as_str(), output.as_ref().as_str(), - actual); + actual, + reparsed_ast); eprintln!("Reformatting the formatted code changed it again, as follows:\n\n"); assert_multiline_str_eq!(output.as_ref().as_str(), reformatted.as_ref().as_str()); diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/empty_record_update.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/empty_record_update.expr.formatted.roc new file mode 100644 index 0000000000..727025b89a --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/empty_record_update.expr.formatted.roc @@ -0,0 +1 @@ +{ e & } \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/empty_record_update.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/empty_record_update.expr.result-ast new file mode 100644 index 0000000000..f80fadf9a5 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/empty_record_update.expr.result-ast @@ -0,0 +1,7 @@ +RecordUpdate { + update: @1-2 Var { + module_name: "", + ident: "e", + }, + fields: [], +} diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/empty_record_update.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/empty_record_update.expr.roc new file mode 100644 index 0000000000..41c40656bf --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/empty_record_update.expr.roc @@ -0,0 +1 @@ +{e&} \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/fn_with_record_arg.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/fn_with_record_arg.expr.formatted.roc new file mode 100644 index 0000000000..914592c776 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/fn_with_record_arg.expr.formatted.roc @@ -0,0 +1,7 @@ +table : + { + height : Pixels, + } + -> Table +table = \{ height } -> crash "not implemented" +table \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/fn_with_record_arg.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/fn_with_record_arg.expr.result-ast new file mode 100644 index 0000000000..af396a0186 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/fn_with_record_arg.expr.result-ast @@ -0,0 +1,131 @@ +Defs( + Defs { + tags: [ + Index(2147483649), + ], + regions: [ + @0-89, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ + Annotation( + @0-5 Identifier( + "table", + ), + @8-44 Function( + [ + @8-35 Record { + fields: [ + @14-29 SpaceBefore( + SpaceAfter( + RequiredValue( + @14-20 "height", + [], + @23-29 Apply( + "", + "Pixels", + [], + ), + ), + [ + Newline, + ], + ), + [ + Newline, + ], + ), + ], + ext: None, + }, + ], + @39-44 Apply( + "", + "Table", + [], + ), + ), + ), + AnnotatedBody { + ann_pattern: @0-5 Identifier( + "table", + ), + ann_type: @8-44 Function( + [ + @8-35 Record { + fields: [ + @14-29 SpaceBefore( + SpaceAfter( + RequiredValue( + @14-20 "height", + [], + @23-29 Apply( + "", + "Pixels", + [], + ), + ), + [ + Newline, + ], + ), + [ + Newline, + ], + ), + ], + ext: None, + }, + ], + @39-44 Apply( + "", + "Table", + [], + ), + ), + comment: None, + body_pattern: @45-50 Identifier( + "table", + ), + body_expr: @53-89 Closure( + [ + @54-62 RecordDestructure( + [ + @55-61 Identifier( + "height", + ), + ], + ), + ], + @66-89 Apply( + @66-71 Crash, + [ + @72-89 Str( + PlainLine( + "not implemented", + ), + ), + ], + Space, + ), + ), + }, + ], + }, + @90-95 SpaceBefore( + Var { + module_name: "", + ident: "table", + }, + [ + Newline, + ], + ), +) diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/fn_with_record_arg.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/fn_with_record_arg.expr.roc new file mode 100644 index 0000000000..67ad2e42bb --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/fn_with_record_arg.expr.roc @@ -0,0 +1,5 @@ +table : { + height : Pixels + } -> Table +table = \{height} -> crash "not implemented" +table \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/list_minus_newlines.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/list_minus_newlines.expr.formatted.roc new file mode 100644 index 0000000000..4fa5c5f894 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/list_minus_newlines.expr.formatted.roc @@ -0,0 +1,4 @@ +[ + K, +] +- i \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/list_minus_newlines.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/list_minus_newlines.expr.result-ast new file mode 100644 index 0000000000..89d20368d7 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/list_minus_newlines.expr.result-ast @@ -0,0 +1,23 @@ +BinOps( + [ + ( + @0-5 List( + Collection { + items: [ + @1-2 Tag( + "K", + ), + ], + final_comments: [ + Newline, + ], + }, + ), + @5-6 Minus, + ), + ], + @6-7 Var { + module_name: "", + ident: "i", + }, +) diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/list_minus_newlines.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/list_minus_newlines.expr.roc new file mode 100644 index 0000000000..e8153c3ccb --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/list_minus_newlines.expr.roc @@ -0,0 +1,2 @@ +[K, +]-i \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/opaque_type_def_with_newline.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/opaque_type_def_with_newline.expr.formatted.roc new file mode 100644 index 0000000000..d8c2642763 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/opaque_type_def_with_newline.expr.formatted.roc @@ -0,0 +1,4 @@ +a : e +Na := + e +e0 \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/opaque_type_def_with_newline.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/opaque_type_def_with_newline.expr.result-ast new file mode 100644 index 0000000000..caf6bad6a3 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/opaque_type_def_with_newline.expr.result-ast @@ -0,0 +1,54 @@ +Defs( + Defs { + tags: [ + Index(2147483648), + Index(0), + ], + regions: [ + @0-3, + @4-11, + ], + space_before: [ + Slice(start = 0, length = 0), + Slice(start = 0, length = 1), + ], + space_after: [ + Slice(start = 0, length = 0), + Slice(start = 1, length = 0), + ], + spaces: [ + Newline, + ], + type_defs: [ + Opaque { + header: TypeHeader { + name: @4-6 "Na", + vars: [], + }, + typ: @10-11 SpaceBefore( + BoundVariable( + "e", + ), + [ + Newline, + ], + ), + derived: None, + }, + ], + value_defs: [ + Annotation( + @0-1 Identifier( + "a", + ), + @2-3 BoundVariable( + "e", + ), + ), + ], + }, + @12-14 Var { + module_name: "", + ident: "e0", + }, +) diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/opaque_type_def_with_newline.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/opaque_type_def_with_newline.expr.roc new file mode 100644 index 0000000000..92ed4b6c5b --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/opaque_type_def_with_newline.expr.roc @@ -0,0 +1,3 @@ +a:e +Na:= + e e0 \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/test_snapshots.rs b/crates/compiler/test_syntax/tests/test_snapshots.rs index ffa00e0596..34d5062c1b 100644 --- a/crates/compiler/test_syntax/tests/test_snapshots.rs +++ b/crates/compiler/test_syntax/tests/test_snapshots.rs @@ -304,6 +304,7 @@ mod test_snapshots { pass/empty_package_header.header, pass/empty_platform_header.header, pass/empty_record.expr, + pass/empty_record_update.expr, pass/empty_string.expr, pass/equals.expr, pass/equals_with_spaces.expr, @@ -311,6 +312,7 @@ mod test_snapshots { pass/expect_fx.moduledefs, pass/extra_newline_in_parens.expr, pass/float_with_underscores.expr, + pass/fn_with_record_arg.expr, pass/full_app_header.header, pass/full_app_header_trailing_commas.header, pass/function_effect_types.header, @@ -326,6 +328,7 @@ mod test_snapshots { pass/list_closing_indent_not_enough.expr, pass/list_closing_same_indent_no_trailing_comma.expr, pass/list_closing_same_indent_with_trailing_comma.expr, + pass/list_minus_newlines.expr, pass/list_pattern_weird_indent.expr, pass/list_patterns.expr, pass/lowest_float.expr, @@ -388,6 +391,7 @@ mod test_snapshots { pass/opaque_reference_pattern.expr, pass/opaque_reference_pattern_with_arguments.expr, pass/opaque_simple.moduledefs, + pass/opaque_type_def_with_newline.expr, pass/opaque_with_type_arguments.moduledefs, pass/ops_with_newlines.expr, pass/outdented_app_with_record.expr, @@ -564,6 +568,15 @@ mod test_snapshots { Err(err) => Err(format!("{:?}", err)), }; + if expect == TestExpectation::Pass { + let tokens = roc_parse::highlight::highlight(&source); + for token in tokens { + if token.value == roc_parse::highlight::Token::Error { + panic!("Found an error highlight token in the input: {:?}", token); + } + } + } + let actual_result = if expect == TestExpectation::Pass || expect == TestExpectation::Malformed { result.expect("The source code for this test did not successfully parse!") diff --git a/crates/compiler/types/Cargo.toml b/crates/compiler/types/Cargo.toml index 1922eeb2c8..bb727200ea 100644 --- a/crates/compiler/types/Cargo.toml +++ b/crates/compiler/types/Cargo.toml @@ -1,18 +1,19 @@ [package] name = "roc_types" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Various representations and utilities for dealing with types in the Roc compiler." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] roc_collections = { path = "../collections" } -roc_region = { path = "../region" } +roc_debug_flags = { path = "../debug_flags" } +roc_error_macros = { path = "../../error_macros" } roc_module = { path = "../module" } -roc_error_macros = {path="../../error_macros"} -roc_debug_flags = {path="../debug_flags"} -roc_serialize = {path="../serialize"} +roc_region = { path = "../region" } +roc_serialize = { path = "../serialize" } ven_pretty = { path = "../../vendor/pretty" } diff --git a/crates/compiler/unify/Cargo.toml b/crates/compiler/unify/Cargo.toml index d8823b0967..4f2f899ca3 100644 --- a/crates/compiler/unify/Cargo.toml +++ b/crates/compiler/unify/Cargo.toml @@ -1,13 +1,14 @@ [package] -authors = ["The Roc Contributors"] -edition = "2021" -license = "UPL-1.0" name = "roc_unify" -version = "0.0.1" description = "Implements Roc's unification algorithm, the heartstone of Roc's type inference." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] -bitflags = "1.3.2" +bitflags.workspace = true [dependencies.roc_collections] path = "../collections" @@ -24,11 +25,5 @@ path = "../types" [dependencies.roc_debug_flags] path = "../debug_flags" -[dependencies.roc_can] -path = "../can" - -[dependencies.roc_solve_problem] -path = "../solve_problem" - [dependencies.roc_tracing] path = "../../tracing" diff --git a/crates/compiler/unify/src/unify.rs b/crates/compiler/unify/src/unify.rs index 77c3317306..c38e9b73ae 100644 --- a/crates/compiler/unify/src/unify.rs +++ b/crates/compiler/unify/src/unify.rs @@ -1568,8 +1568,10 @@ fn unspecialized_lambda_set_sorter(subs: &Subs, uls1: Uls, uls2: Uls) -> std::cm } (FlexAbleVar(..), _) => Greater, (_, FlexAbleVar(..)) => Less, - // For everything else, the order is irrelevant - (_, _) => Less, + // For everything else, sort by the root key + (_, _) => subs + .get_root_key_without_compacting(var1) + .cmp(&subs.get_root_key_without_compacting(var2)), } } ord => ord, @@ -1731,6 +1733,8 @@ fn unify_unspecialized_lambdas( let kept = uls_left.next().unwrap(); merged_uls.push(*kept); } else { + // CASE: disjoint_flex_specializations + // // ... a1 ... // ... b1 ... // => ... a1, b1 ... @@ -1800,20 +1804,47 @@ fn unify_unspecialized_lambdas( let _dropped = uls_left.next().unwrap(); } (_, _) => { - // ... {foo: _} ... - // ... {foo: _} ... - // => ... {foo: _} ... - // - // Unify them, then advance one. - // (the choice is arbitrary, so we choose the left) + if env.subs.equivalent_without_compacting(var_l, var_r) { + // ... a1 ... + // ... b1=a1 ... + // => ... a1 ... + // + // Keep the one on the left, drop the one on the right. Then progress + // both, because the next variable on the left must be disjoint from + // the current on the right (resp. next variable on the right vs. + // current left) - if they aren't, then the invariant was broken. + // + // Then progress both, because the invariant tells us they must be + // disjoint, and if there were any concrete variables, they would have + // appeared earlier. + let _dropped = uls_right.next().unwrap(); + let kept = uls_left.next().unwrap(); + merged_uls.push(*kept); - let outcome = unify_pool(env, pool, var_l, var_r, mode); - if !outcome.mismatches.is_empty() { - return Err(outcome); + debug_assert!(uls_right + .peek() + .map(|r| env.subs.equivalent_without_compacting(var_l, r.0)) + .unwrap_or(true)); + debug_assert!(uls_left + .peek() + .map(|l| env.subs.equivalent_without_compacting(l.0, var_r)) + .unwrap_or(true)); + } else { + // Even if these two variables unify, since they are not equivalent, + // they correspond to different specializations! As such we must not + // merge them. + // + // Instead, keep both, but do so by adding and advancing the side with + // the lower root. See CASE disjoint_flex_specializations for + // reasoning. + if env.subs.get_root_key(var_l) < env.subs.get_root_key(var_r) { + let kept = uls_left.next().unwrap(); + merged_uls.push(*kept); + } else { + let kept = uls_right.next().unwrap(); + merged_uls.push(*kept); + } } - whole_outcome.union(outcome); - - let _dropped = uls_left.next().unwrap(); } } } diff --git a/crates/docs/Cargo.toml b/crates/docs/Cargo.toml index 4a31e1740f..b29d35a0a7 100644 --- a/crates/docs/Cargo.toml +++ b/crates/docs/Cargo.toml @@ -1,30 +1,32 @@ [package] name = "roc_docs" -version = "0.0.1" -license = "UPL-1.0" -authors = ["The Roc Contributors"] -edition = "2021" description = "Generates html documentation from Roc files and is used for Rocs builtins." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] -pulldown-cmark = { version = "0.9.2", default-features = false } roc_ast = { path = "../ast" } -roc_load = { path = "../compiler/load" } roc_builtins = { path = "../compiler/builtins" } roc_can = { path = "../compiler/can" } -roc_code_markup = { path = "../code_markup"} -roc_module = { path = "../compiler/module" } -roc_region = { path = "../compiler/region" } -roc_types = { path = "../compiler/types" } -roc_parse = { path = "../compiler/parse" } -roc_target = { path = "../compiler/roc_target" } +roc_code_markup = { path = "../code_markup" } roc_collections = { path = "../compiler/collections" } -roc_highlight = { path = "../highlight"} -roc_packaging = { path = "../packaging"} -roc_reporting = { path = "../reporting"} +roc_highlight = { path = "../highlight" } +roc_load = { path = "../compiler/load" } +roc_module = { path = "../compiler/module" } +roc_packaging = { path = "../packaging" } +roc_parse = { path = "../compiler/parse" } +roc_region = { path = "../compiler/region" } +roc_reporting = { path = "../reporting" } +roc_target = { path = "../compiler/roc_target" } +roc_types = { path = "../compiler/types" } + bumpalo.workspace = true -snafu.workspace = true peg.workspace = true +pulldown-cmark.workspace = true +snafu.workspace = true [dev-dependencies] pretty_assertions.workspace = true diff --git a/crates/docs/src/docs_error.rs b/crates/docs/src/docs_error.rs deleted file mode 100644 index 7ee2f06ced..0000000000 --- a/crates/docs/src/docs_error.rs +++ /dev/null @@ -1,55 +0,0 @@ -use peg::error::ParseError; -use roc_ast::ast_error::ASTError; -use roc_module::module_err::ModuleError; -use roc_parse::parser::SyntaxError; -use snafu::Snafu; - -#[derive(Debug, Snafu)] -#[snafu(visibility(pub))] -#[allow(clippy::enum_variant_names)] -pub enum DocsError { - WrapASTError { - #[snafu(backtrace)] - source: ASTError, - }, - WrapModuleError { - #[snafu(backtrace)] - source: ModuleError, - }, - WrapSyntaxError { - msg: String, - }, - WrapPegParseError { - source: ParseError, - }, -} - -pub type DocsResult = std::result::Result; - -impl<'a> From> for DocsError { - fn from(syntax_err: SyntaxError) -> Self { - Self::WrapSyntaxError { - msg: format!("{:?}", syntax_err), - } - } -} - -impl From for DocsError { - fn from(ast_err: ASTError) -> Self { - Self::WrapASTError { source: ast_err } - } -} - -impl From for DocsError { - fn from(module_err: ModuleError) -> Self { - Self::WrapModuleError { source: module_err } - } -} - -impl From> for DocsError { - fn from(peg_parse_err: ParseError) -> Self { - Self::WrapPegParseError { - source: peg_parse_err, - } - } -} diff --git a/crates/docs/src/html.rs b/crates/docs/src/html.rs deleted file mode 100644 index baad3715db..0000000000 --- a/crates/docs/src/html.rs +++ /dev/null @@ -1,85 +0,0 @@ -use roc_code_markup::{markup::nodes::MarkupNode, slow_pool::SlowPool}; - -// determine appropriate css class for MarkupNode -pub fn mark_node_to_html(mark_node: &MarkupNode, mark_node_pool: &SlowPool, buf: &mut String) { - let mut additional_newlines = 0; - - match mark_node { - MarkupNode::Nested { - children_ids, - newlines_at_end, - .. - } => { - for &child_id in children_ids { - mark_node_to_html(mark_node_pool.get(child_id), mark_node_pool, buf) - } - - additional_newlines = *newlines_at_end; - } - MarkupNode::Text { - content, - syn_high_style, - newlines_at_end, - .. - } => { - use roc_code_markup::syntax_highlight::HighlightStyle::*; - - let css_class = match syn_high_style { - Operator => "operator", - String => "string", - FunctionName => "function-name", - FunctionArgName => "function-arg-name", - Type => "type", - Bracket => "bracket", - Number => "number", - PackageRelated => "package-related", - Value => "value", - RecordField => "recordfield", - Import => "import", - Provides => "provides", - Blank => "blank", - Comment => "comment", - DocsComment => "docs-comment", - UppercaseIdent => "uppercase-ident", - LowercaseIdent => "lowercase-ident", - Keyword => "keyword-ident", - }; - - write_html_to_buf(content, css_class, buf); - - additional_newlines = *newlines_at_end; - } - MarkupNode::Blank { - newlines_at_end, .. - } => { - let mut content_str = " ".to_string(); - - for _ in 0..*newlines_at_end { - content_str.push('\n'); - } - - write_html_to_buf(&content_str, "blank", buf); - - additional_newlines = *newlines_at_end; - } - MarkupNode::Indent { .. } => { - let content_str = mark_node.get_content(); - - write_html_to_buf(&content_str, "indent", buf); - } - } - - for _ in 0..additional_newlines { - buf.push('\n') - } -} - -fn write_html_to_buf(content: &str, css_class: &'static str, buf: &mut String) { - let opening_tag: String = [""].concat(); - - buf.push_str(opening_tag.as_str()); - - buf.push_str(content); - - buf.push_str(""); -} diff --git a/crates/docs/src/lib.rs b/crates/docs/src/lib.rs index bafc84bb7d..77d65f7126 100644 --- a/crates/docs/src/lib.rs +++ b/crates/docs/src/lib.rs @@ -3,13 +3,8 @@ extern crate pulldown_cmark; extern crate roc_load; use bumpalo::Bump; -use docs_error::{DocsError, DocsResult}; -use html::mark_node_to_html; use roc_can::scope::Scope; -use roc_code_markup::markup::nodes::MarkupNode; -use roc_code_markup::slow_pool::SlowPool; use roc_collections::VecSet; -use roc_highlight::highlight_parser::{highlight_defs, highlight_expr}; use roc_load::docs::{DocEntry, TypeAnnotation}; use roc_load::docs::{ModuleDocumentation, RecordField}; use roc_load::{ExecutionMode, LoadConfig, LoadedModule, LoadingProblem, Threading}; @@ -21,9 +16,6 @@ use roc_region::all::Region; use std::fs; use std::path::{Path, PathBuf}; -mod docs_error; -mod html; - const BUILD_DIR: &str = "./generated-docs"; pub fn generate_docs_html(root_file: PathBuf) { @@ -131,49 +123,6 @@ fn page_title(package_name: &str, module_name: &str) -> String { format!("{module_name} - {package_name}") } -// converts plain-text code to highlighted html -pub fn syntax_highlight_expr(code_str: &str) -> DocsResult { - let trimmed_code_str = code_str.trim_end().trim(); - let mut mark_node_pool = SlowPool::default(); - - let mut highlighted_html_str = String::new(); - - match highlight_expr(trimmed_code_str, &mut mark_node_pool) { - Ok(root_mark_node_id) => { - let root_mark_node = mark_node_pool.get(root_mark_node_id); - mark_node_to_html(root_mark_node, &mark_node_pool, &mut highlighted_html_str); - - Ok(highlighted_html_str) - } - Err(err) => Err(DocsError::from(err)), - } -} - -// converts plain-text code to highlighted html -pub fn syntax_highlight_top_level_defs(code_str: &str) -> DocsResult { - let trimmed_code_str = code_str.trim_end().trim(); - - let mut mark_node_pool = SlowPool::default(); - - let mut highlighted_html_str = String::new(); - - match highlight_defs(trimmed_code_str, &mut mark_node_pool) { - Ok(mark_node_id_vec) => { - let def_mark_nodes: Vec<&MarkupNode> = mark_node_id_vec - .iter() - .map(|mn_id| mark_node_pool.get(*mn_id)) - .collect(); - - for mn in def_mark_nodes { - mark_node_to_html(mn, &mark_node_pool, &mut highlighted_html_str) - } - - Ok(highlighted_html_str) - } - Err(err) => Err(DocsError::from(err)), - } -} - fn render_module_documentation( module: &ModuleDocumentation, root_module: &LoadedModule, @@ -728,7 +677,6 @@ fn doc_url<'a>( module_name = symbol.module_string(interns); } Err(_) => { - dbg!(scope); // TODO return Err here panic!( "Tried to generate an automatic link in docs for symbol `{}`, but that symbol was not in scope in this module.", @@ -857,65 +805,24 @@ fn markdown_to_html( let markdown_options = pulldown_cmark::Options::ENABLE_TABLES; - let mut expecting_code_block = false; + let mut in_code_block: Option = None; + let mut to_highlight = String::new(); let mut docs_parser = vec![]; - let (_, _) = pulldown_cmark::Parser::new_with_broken_link_callback( + let parser = pulldown_cmark::Parser::new_with_broken_link_callback( markdown, markdown_options, Some(&mut broken_link_callback), - ) - .fold((0, 0), |(start_quote_count, end_quote_count), event| { + ); - match &event { - // Replace this sequence (`>>>` syntax): - // Start(BlockQuote) - // Start(BlockQuote) - // Start(BlockQuote) - // Start(Paragraph) - // For `Start(CodeBlock(Fenced(Borrowed("roc"))))` - Event::Start(BlockQuote) => { - docs_parser.push(event); - (start_quote_count + 1, 0) + for event in parser { + match event { + Event::Code(cow_str) => { + let highlighted_html = + roc_highlight::highlight_roc_code_inline(cow_str.to_string().as_str()); + docs_parser.push(Event::Html(CowStr::from(highlighted_html))); } - Event::Start(Paragraph) => { - if start_quote_count == 3 { - docs_parser.pop(); - docs_parser.pop(); - docs_parser.pop(); - docs_parser.push(Event::Start(CodeBlock(CodeBlockKind::Fenced( - CowStr::Borrowed("roc"), - )))); - } else { - docs_parser.push(event); - } - (0, 0) - } - // Replace this sequence (`>>>` syntax): - // End(Paragraph) - // End(BlockQuote) - // End(BlockQuote) - // End(BlockQuote) - // For `End(CodeBlock(Fenced(Borrowed("roc"))))` - Event::End(Paragraph) => { - docs_parser.push(event); - (0, 1) - } - Event::End(BlockQuote) => { - if end_quote_count == 3 { - docs_parser.pop(); - docs_parser.pop(); - docs_parser.pop(); - docs_parser.push(Event::End(CodeBlock(CodeBlockKind::Fenced( - CowStr::Borrowed("roc"), - )))); - (0, 0) - } else { - docs_parser.push(event); - (0, end_quote_count + 1) - } - } - Event::End(Link(LinkType::ShortcutUnknown, _url, _title)) => { + Event::End(Link(LinkType::ShortcutUnknown, ref _url, ref _title)) => { // Replace the preceding Text node with a Code node, so it // renders as the equivalent of [`List.len`] instead of [List.len] match docs_parser.pop() { @@ -929,41 +836,56 @@ fn markdown_to_html( } docs_parser.push(event); - - (start_quote_count, end_quote_count) } - Event::Start(CodeBlock(CodeBlockKind::Fenced(_))) => { - expecting_code_block = true; - docs_parser.push(event); - (0, 0) + Event::Start(CodeBlock(CodeBlockKind::Fenced(cow_str))) => { + in_code_block = Some(cow_str); } Event::End(CodeBlock(_)) => { - expecting_code_block = false; - docs_parser.push(event); - (0, 0) - } - Event::Text(CowStr::Borrowed(code_str)) if expecting_code_block => { + match in_code_block { + Some(cow_str) => { + if cow_str.contains("unchecked") { + // TODO HANDLE UNCHECKED + } - match syntax_highlight_expr( - code_str - ) - { - Ok(highlighted_code_str) => { - docs_parser.push(Event::Html(CowStr::from(highlighted_code_str))); - } - Err(syntax_error) => { - panic!("Unexpected parse failure when parsing this for rendering in docs:\n\n{}\n\nParse error was:\n\n{:?}\n\n", code_str, syntax_error) - } - }; + if cow_str.contains("repl") { + // TODO HANDLE REPL + } - (0, 0) - } - _ => { + // TODO HANDLE CHECKING BY DEFAULT + let highlighted_html = roc_highlight::highlight_roc_code(&to_highlight); + docs_parser.push(Event::Html(CowStr::from(highlighted_html))); + } + None => { + // Indented code block + + let highlighted_html = roc_highlight::highlight_roc_code(&to_highlight); + docs_parser.push(Event::Html(CowStr::from(highlighted_html))); + } + } + + // Reset codeblock buffer + to_highlight = String::new(); + in_code_block = None; + + // Push Event::End(CodeBlock) docs_parser.push(event); - (0, 0) + } + Event::Text(t) => { + match in_code_block { + Some(_) => { + // If we're in a code block, build up the string of text + to_highlight.push_str(&t); + } + None => { + docs_parser.push(Event::Text(t)); + } + } + } + e => { + docs_parser.push(e); } } - }); + } pulldown_cmark::html::push_html(buf, docs_parser.into_iter()); } diff --git a/crates/docs/src/static/styles.css b/crates/docs/src/static/styles.css index 3c73586699..f21fdd18b4 100644 --- a/crates/docs/src/static/styles.css +++ b/crates/docs/src/static/styles.css @@ -1,43 +1,40 @@ :root { - --purple-1: #f2f1f9; - --purple-2: #d9d2ef; - --purple-3: #a17ef1; - --purple-4: #8d51f6; - --purple-5: #742af4; - --purple-6: #23143d; - --purple-7: #25222a; - --purple-8: #161519; - --purple-9: #111014; - --gray-1: #f8f8f8; - --gray-2: #f0f0f0; - --gray-3: #dddddd; - --gray-4: #5b5b5b; - --gray-5: #212121; - --link-color: var(--purple-5); - --code-link-color: #5721d4; - --text-color: var(--gray-5); - --code-color: #222222; - --code-bg-color: var(--gray-2); + /* WCAG AAA Compliant colors */ + --code-bg: #f4f8f9; + --gray: #717171; + --orange: #bf5000; + --green: #0b8400; + --cyan: #067c94; + --blue: #05006d; + --violet: #7c38f5; + --violet-bg: #ece2fd; + --magenta: #a20031; + + --link-color: var(--violet); + --code-link-color: var(--violet); + --text-color: #000; + --text-hover-color: var(--violet); --body-bg-color: #ffffff; - --border-color: #e9e9e9; + --border-color: #717171; --faded-color: #4c4c4c; - --font-sans: -apple-system, BlinkMacSystemFont, Roboto, Helvetica, Arial, sans-serif; - --font-mono: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; + --font-sans: -apple-system, BlinkMacSystemFont, Roboto, Helvetica, Arial, + sans-serif; + --font-mono: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, + monospace; --top-header-height: 67px; --sidebar-width: 280px; - --top-bar-bg: #8257e5; - --top-bar-fg: #ffffff; - --nav-link-hover-color: #000000; - --type-signature-color: var(--purple-5); - --type-signature-bg-color: var(--purple-1); - --module-entry-border-color: var(--gray-3); } a { - color: #972395; + color: var(--violet); } -table tr th, table tr td { +table tr th { + border: 1px solid var(--gray); +} + +table tr th, +table tr td { padding: 6px 13px; } @@ -48,7 +45,7 @@ table tr th, table tr td { .logo svg { height: 48px; width: 48px; - fill: var(--top-bar-fg); + fill: var(--violet); } .logo:hover { @@ -56,11 +53,10 @@ table tr th, table tr td { } .logo svg:hover { - fill: var(--nav-link-hover-color); + fill: var(--green); } .pkg-full-name { - color: var(--text-color); display: flex; align-items: center; font-size: 32px; @@ -77,22 +73,27 @@ table tr th, table tr td { font-family: var(--font-mono); font-size: 18px; font-weight: normal; - color: var(--type-signature-color); - background-color: var(--type-signature-bg-color); - width: fit-content; + color: var(--violet); + background-color: var(--code-bg); + width: auto; margin-top: 0; margin-bottom: 24px; padding: 8px 16px; - border-radius: 8px; + border-radius: 8px 8px 0px 0px; + border-bottom: 1px solid var(--border-color); } .entry-name a { font-weight: bold; - color: var(--type-signature-color); + color: var(--violet); } .entry-name a:visited { - color: var(--type-signature-color); + color: var(--violet); +} + +.entry-name a:hover { +color: var(--green); } .pkg-full-name a { @@ -104,7 +105,8 @@ a { text-decoration: none; } -a:hover, a:hover code { +a:hover, +a:hover code { text-decoration: underline; } @@ -113,15 +115,16 @@ a:hover, a:hover code { display: flex; align-items: center; height: 100%; - background-color: var(--top-bar-bg); + background-color: var(--violet-bg); } -.pkg-and-logo a, .pkg-and-logo a:visited { - color: var(--top-bar-fg); +.pkg-and-logo a, +.pkg-and-logo a:visited { + color: var(--violet); } .pkg-and-logo a:hover { - color: var(--nav-link-hover-color); + color: var(--green); text-decoration: none; } @@ -140,7 +143,10 @@ a:hover, a:hover code { body { display: grid; - grid-template-columns: [before-sidebar] 1fr [sidebar] var(--sidebar-width) [main-content] fit-content(calc(1280px - var(--sidebar-width))) [end] 1fr; + grid-template-columns: + [before-sidebar] 1fr [sidebar] var(--sidebar-width) + [main-content] fit-content(calc(1280px - var(--sidebar-width))) + [end] 1fr; grid-template-rows: [top-header] var(--top-header-height) [above-footer] auto [footer] auto; box-sizing: border-box; margin: 0; @@ -166,16 +172,20 @@ main { } section { - border: 1px solid var(--module-entry-border-color); + border: 2px solid var(--border-color); border-radius: 8px; - padding: 32px; - margin: 32px 0; + padding: 0px 0px 16px 0px; + margin: 72px 16px; } section > *:last-child { margin-bottom: 0; } +section p { +padding: 0px 16px; +} + #sidebar-nav { grid-column-start: sidebar; grid-column-end: sidebar; @@ -195,7 +205,7 @@ section > *:last-child { grid-column-end: sidebar; grid-row-start: top-header; grid-row-end: top-header; - background-color: var(--top-bar-bg); + background-color: var(--violet-bg); } .top-header { @@ -216,18 +226,18 @@ section > *:last-child { .top-header-triangle { /* This used to be a clip-path, but Firefox on Android (at least as of early 2020) - * rendered the page extremely slowly in that version. With this approach it's super fast. - */ + * rendered the page extremely slowly in that version. With this approach it's super fast. + */ width: 0; height: 0; border-style: solid; border-width: var(--top-header-height) 0 0 48px; - border-color: transparent transparent transparent var(--top-bar-bg); + border-color: transparent transparent transparent var(--violet-bg); } p { - overflow-wrap: break-word; - margin: 24px 0; + overflow-wrap: break-word; + margin: 24px 0; } footer { @@ -288,10 +298,16 @@ footer p { font-weight: bold; margin-top: 18px; margin-bottom: 48px; + color: var(--violet); } -.module-name a, .module-name a:visited { - color: inherit; +.module-name a, +.module-name a:visited { +color: inherit; +} + +.module-name a:hover { + color: var(--green); } .sidebar-module-link { @@ -311,7 +327,8 @@ footer p { font-weight: bold; } -a, a:visited { +a, +a:visited { color: var(--link-color); } @@ -335,13 +352,13 @@ h4 { box-sizing: border-box; border-radius: 8px; font-family: var(--font-mono); - background-color: var(--code-bg-color); + background-color: var(--code-bg); } code { font-family: var(--font-mono); color: var(--code-color); - background-color: var(--code-bg-color); + background-color: var(--code-bg); display: inline-block; } @@ -350,14 +367,16 @@ p code { border-radius: 4px; } -code a, a code { +code a, +a code { text-decoration: none; color: var(--code-link-color); background: none; padding: 0; } -code a:visited, a:visited code { +code a:visited, +a:visited code { color: var(--code-link-color); } @@ -365,8 +384,7 @@ pre { margin: 36px 0; padding: 8px 16px; box-sizing: border-box; - border-radius: 8px; - background-color: var(--code-bg-color); + background-color: var(--code-bg); overflow-x: auto; } @@ -375,36 +393,14 @@ pre { display: none !important; } -.syntax-number { - color: #60B7BF; -} -.syntax-string { - color:#F7577C; -} - -.syntax-bracket { - color:#FF335F; -} -.syntax-closure-dash, -.syntax-closure-arrow, -.syntax-operator -{ - color: #ffffff; -} -.syntax-comma { - color: #9573E6; -} -.syntax-comment { - color: #ff0000; -} - #module-search:placeholder-shown { padding: 0; opacity: 0; height: 0; } -#module-search, #module-search:focus { +#module-search, +#module-search:focus { opacity: 1; padding: 12px 16px; height: 48px; @@ -430,7 +426,7 @@ pre { margin-top: 6px; border: none; color: var(--faded-color); - background-color: var(--code-bg-color); + background-color: var(--code-bg); font-family: var(--font-serif); } @@ -476,133 +472,183 @@ pre { @media (prefers-color-scheme: dark) { :root { - --body-bg-color: var(--purple-8); - --code-bg-color: var(--purple-7); - --border-color: #555555; - --code-color: #eeeeee; - --text-color: var(--gray-1); - --logo-solid: #777777; - --faded-color: #bbbbbb; - --link-color: #c5a8ff; - --code-link-color: #b894ff; - --top-bar-bg: #6845b9; - --top-bar-fg: #eeeeee; - --type-signature-color: var(--grey-1); - --type-signature-bg-color: var(--purple-4); - --module-entry-border-color: var(--purple-7); + /* WCAG AAA Compliant colors */ + --code-bg: #202746; + --gray: #b6b6b6; + --orange: #fd6e08; + --green: #8ecc88; + --cyan: #12c9be; + --blue: #b1afdf; + --violet: #CAADFB; + --violet-bg: #332944; + --magenta: #f39bac; + + --link-color: var(--violet); + --code-link-color: var(--violet); + --text-color: #eaeaea; + --body-bg-color: #0e0e0f; + --border-color: var(--gray); + --code-color: #eeeeee; + --logo-solid: #8f8f8f; + --faded-color: #bbbbbb; + --gray: #6e6e6e; } html { - scrollbar-color: #444444 #2f2f2f; + scrollbar-color: #8f8f8f #2f2f2f; } } @media only screen and (max-device-width: 480px) and (orientation: portrait) { #search-link-hint { - display: none; + display: none; } .search-button { - display: block; /* This is only visible in mobile. */ + display: block; /* This is only visible in mobile. */ } .top-header { - justify-content: space-between; - width: auto; + justify-content: space-between; + width: auto; } .pkg-full-name { - margin-left: 8px; - margin-right: 12px; - font-size: 24px; - padding-bottom: 14px; + margin-left: 8px; + margin-right: 12px; + font-size: 24px; + padding-bottom: 14px; } .pkg-full-name a { - vertical-align: middle; - padding: 18px 0; + vertical-align: middle; + padding: 18px 0; } .logo { - padding-left: 2px; - width: 50px; - height: 54px; + padding-left: 2px; + width: 50px; + height: 54px; } .version { - margin: 0; - font-weight: normal; - font-size: 18px; - padding-bottom: 16px; + margin: 0; + font-weight: normal; + font-size: 18px; + padding-bottom: 16px; } .module-name { - font-size: 36px; - margin-top: 8px; - margin-bottom: 8px; - max-width: calc(100% - 18px); - overflow: hidden; - text-overflow: ellipsis; + font-size: 36px; + margin-top: 8px; + margin-bottom: 8px; + max-width: calc(100% - 18px); + overflow: hidden; + text-overflow: ellipsis; } main { - grid-column-start: none; - grid-column-end: none; - grid-row-start: above-footer; - grid-row-end: above-footer; - padding: 18px; - font-size: 16px; + grid-column-start: none; + grid-column-end: none; + grid-row-start: above-footer; + grid-row-end: above-footer; + padding: 18px; + font-size: 16px; } #sidebar-nav { - grid-column-start: none; - grid-column-end: none; - grid-row-start: sidebar; - grid-row-end: sidebar; - margin-top: 0; - padding-left: 0; - width: auto; + grid-column-start: none; + grid-column-end: none; + grid-row-start: sidebar; + grid-row-end: sidebar; + margin-top: 0; + padding-left: 0; + width: auto; } #sidebar-heading { - font-size: 24px; - margin: 16px; + font-size: 24px; + margin: 16px; } h3 { - font-size: 18px; - margin: 0; - padding: 0; + font-size: 18px; + margin: 0; + padding: 0; } h4 { - font-size: 16px; + font-size: 16px; } body { - grid-template-columns: auto; - grid-template-rows: [top-header] var(--top-header-height) [before-sidebar] auto [sidebar] auto [above-footer] auto [footer] auto; -/* [before-sidebar] 1fr [sidebar] var(--sidebar-width) [main-content] fit-content(calc(1280px - var(--sidebar-width))) [end] 1fr; */ + grid-template-columns: auto; + grid-template-rows: [top-header] var(--top-header-height) [before-sidebar] auto [sidebar] auto [above-footer] auto [footer] auto; + /* [before-sidebar] 1fr [sidebar] var(--sidebar-width) [main-content] fit-content(calc(1280px - var(--sidebar-width))) [end] 1fr; */ - margin: 0; - min-width: 320px; - max-width: 100%; + margin: 0; + min-width: 320px; + max-width: 100%; } .top-header-triangle { - display: none; + display: none; } .pkg-and-logo { - width: 100%; + width: 100%; } .pkg-full-name { - flex-grow: 1; + flex-grow: 1; } .pkg-full-name a { - padding-top: 24px; - padding-bottom: 12px; + padding-top: 24px; + padding-bottom: 12px; } } + +/* Comments `#` and Documentation comments `##` */ +samp .comment, +code .comment { + color: var(--green); +} +/* Number, String, Tag, Type literals */ +samp .literal, +code .literal { + color: var(--cyan); +} +/* Keywords and punctuation */ +samp .kw, +code .kw { + color: var(--magenta); +} +/* Operators */ +samp .op, +code .op { + color: var(--orange); +} + +/* Delimieters */ +samp .delimeter, +code .delimeter { + color: var(--gray); +} + +/* Variables modules and field names */ +samp .lowerident, +code .lowerident { + color: var(--blue); +} + +/* Types, Tags, and Modules */ +samp .upperident, +code .upperident { + color: var(--green); +} + +samp .dim, +code .dim { + opacity: 0.55; +} diff --git a/crates/docs/tests/insert_syntax_highlighting.rs b/crates/docs/tests/insert_syntax_highlighting.rs deleted file mode 100644 index e3ecc67195..0000000000 --- a/crates/docs/tests/insert_syntax_highlighting.rs +++ /dev/null @@ -1,168 +0,0 @@ -#[macro_use] -extern crate pretty_assertions; -// Keep this around until the commented out tests can be enabled again. -/*#[macro_use] -extern crate indoc;*/ - -#[cfg(test)] -mod insert_doc_syntax_highlighting { - - use roc_docs::{syntax_highlight_expr, syntax_highlight_top_level_defs}; - - fn expect_html(code_str: &str, want: &str, use_expr: bool) { - if use_expr { - match syntax_highlight_expr(code_str) { - Ok(highlighted_code_str) => { - assert_eq!(highlighted_code_str, want); - } - Err(syntax_error) => { - panic!("Unexpected parse failure when parsing this for rendering in docs:\n\n{}\n\nParse error was:\n\n{:?}\n\n", code_str, syntax_error) - } - }; - } else { - match syntax_highlight_top_level_defs(code_str) { - Ok(highlighted_code_str) => { - assert_eq!(highlighted_code_str, want); - } - Err(syntax_error) => { - panic!("Unexpected parse failure when parsing this for rendering in docs:\n\n{}\n\nParse error was:\n\n{:?}\n\n", code_str, syntax_error) - } - }; - } - } - - fn expect_html_expr(code_str: &str, want: &str) { - expect_html(code_str, want, true) - } - - fn expect_html_def(code_str: &str, want: &str) { - expect_html(code_str, want, false) - } - - #[test] - fn number_expr() { - expect_html_expr("2", r#"2"#); - } - - // These tests have been commented out due to introduction of a new syntax highlighting approach. - // You can make these tests work by following the instructions at the top of this file here: roc/highlight/src/highlight_parser.rs - /*#[test] - fn string_expr() { - expect_html_expr(r#""abc""#, r#""abc""#); - } - - #[test] - fn empty_list_expr() { - expect_html_expr( - r#"[]"#, - r#"[ ]"#, - ); - } - - #[test] - fn single_elt_list_expr() { - expect_html_expr( - r#"[ 0 ]"#, - r#"[ 0 ]"#, - ); - } - - #[test] - fn multi_elt_list_expr() { - expect_html_expr( - r#"[ "hello", "WoRlD" ]"#, - r#"[ "hello", "WoRlD" ]"#, - ); - } - - #[test] - fn record_expr() { - expect_html_expr( - r#"{ a: "hello!" }"#, - "{ a: \"hello!\" }", - ); - } - - #[test] - fn nested_record_expr() { - expect_html_expr( - r#"{ a: { bB: "WoRlD" } }"#, - "{ a: { bB: \"WoRlD\" } }", - ); - }*/ - - #[test] - fn top_level_def_val_num() { - expect_html_def( - r#"myVal = 0"#, - "myVal = 0\n\n", - ); - } - - /*#[test] - fn top_level_def_val_str() { - expect_html_def( - r#"myVal = "Hello, World!""#, - "myVal = \"Hello, World!\"\n\n\n", - ); - } - - #[test] - fn tld_newline_in_str() { - expect_html_def( - r#"myVal = "Hello, Newline!\n""#, - "myVal = \"Hello, Newline!\n\"\n\n\n", - ); - } - - #[test] - fn tld_list() { - expect_html_def( - r#"myVal = [ 1, 2, 3 ]"#, - "myVal = [ 1, 2, 3 ]\n\n\n", - ); - } - - #[test] - fn call_builtin() { - expect_html_def( - r#"myVal = Num.toStr 1234"#, - "myVal = Num.toStr 1234\n\n\n", - ); - } - - #[test] - fn function() { - expect_html_def( - r#"myId = \something -> - something"#, - "myId = \\something -> \n something\n\n\n", - ); - } - - #[test] - fn tld_with_comment_before() { - expect_html_def( - indoc!( - r#" - # COMMENT - myVal = "Hello, World!" - "#, - ), - "# COMMENT\nmyVal = \"Hello, World!\"\n\n\n\n\n", - ); - }*/ - - // TODO see issue #2134 - /*#[test] - fn tld_with_comment_after() { - expect_html_def( - indoc!( - r#" - myVal = "Hello, World!" # COMMENT - "#, - ), - "myVal = \"Hello, World!\"# COMMENT\n\n\n\n", - ); - }*/ -} diff --git a/crates/docs_cli/Cargo.toml b/crates/docs_cli/Cargo.toml index afe9dd2784..8495e48179 100644 --- a/crates/docs_cli/Cargo.toml +++ b/crates/docs_cli/Cargo.toml @@ -1,11 +1,12 @@ [package] name = "roc_docs_cli" -version = "0.0.1" -license = "UPL-1.0" -authors = ["The Roc Contributors"] -edition = "2021" description = "Provides a binary that is only used for static build servers." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + # This binary is only used on static build servers, e.g. Netlify. # Having its own (extremely minimal) CLI means docs can be generated # on a build server after building this crate from source, without @@ -19,7 +20,8 @@ bench = false [dependencies] roc_docs = { path = "../docs" } -clap = { version = "3.2.20", default-features = false, features = ["std", "color", "suggestions", "derive"] } + +clap.workspace = true [target.'cfg(windows)'.dependencies] -libc.workspace = true +libc.workspace = true diff --git a/crates/editor/Cargo.toml b/crates/editor/Cargo.toml index 95162b1a44..10966b1ccc 100644 --- a/crates/editor/Cargo.toml +++ b/crates/editor/Cargo.toml @@ -1,11 +1,12 @@ [package] name = "roc_editor" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "An editor for Roc" +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [package.metadata.cargo-udeps.ignore] # confy is currently unused but should not be removed normal = ["confy"] @@ -14,59 +15,51 @@ normal = ["confy"] [features] default = [] -with_sound = ["rodio"] [dependencies] roc_ast = { path = "../ast" } -roc_collections = { path = "../compiler/collections" } -roc_load = { path = "../compiler/load" } roc_builtins = { path = "../compiler/builtins" } roc_can = { path = "../compiler/can" } -roc_code_markup = { path = "../code_markup"} -roc_parse = { path = "../compiler/parse" } -roc_region = { path = "../compiler/region" } +roc_code_markup = { path = "../code_markup" } +roc_collections = { path = "../compiler/collections" } +roc_command_utils = { path = "../utils/command" } +roc_load = { path = "../compiler/load" } roc_module = { path = "../compiler/module" } -roc_problem = { path = "../compiler/problem" } -roc_types = { path = "../compiler/types" } -roc_unify = { path = "../compiler/unify" } -roc_utils = { path = "../utils"} roc_packaging = { path = "../packaging" } +roc_parse = { path = "../compiler/parse" } +roc_problem = { path = "../compiler/problem" } +roc_region = { path = "../compiler/region" } roc_reporting = { path = "../reporting" } roc_solve = { path = "../compiler/solve" } +roc_types = { path = "../compiler/types" } +roc_unify = { path = "../compiler/unify" } ven_graph = { path = "../vendor/pathfinding" } -bumpalo = { version = "3.11.1", features = ["collections"] } -arrayvec = "0.7.2" -libc = "0.2.135" -page_size = "0.4.2" -# once winit 0.26 is out, check if copypasta can be updated simultaneously so they use the same versions for their dependencies. This will save build time. -winit = "0.26.0" -wgpu = "0.12.0" -wgpu_glyph = "0.16.0" -glyph_brush = "0.7.5" -log = "0.4.14" -futures = "0.3.24" -cgmath = "0.18.0" -snafu = { version = "0.7.1", features = ["backtraces"] } -colored = "2.0.0" -pest = "2.3.1" -pest_derive = "2.3.1" -copypasta = "0.8.1" -palette = "0.6.1" -confy = { git = 'https://github.com/rust-cli/confy', features = [ - "yaml_conf" -], default-features = false } -serde = { version = "1.0.144", features = ["derive"] } -nonempty = "0.8.0" -rodio = { version = "0.15.0", optional = true } # to play sounds -threadpool = "1.8.1" +arrayvec.workspace = true +bumpalo.workspace = true +bytemuck.workspace = true +cgmath.workspace = true +colored.workspace = true +confy.workspace = true +copypasta.workspace = true fs_extra.workspace = true - -[dependencies.bytemuck] -version = "1.12.1" -features = ["derive"] +futures.workspace = true +glyph_brush.workspace = true +libc.workspace = true +log.workspace = true +nonempty.workspace = true +page_size.workspace = true +palette.workspace = true +pest.workspace = true +pest_derive.workspace = true +serde.workspace = true +snafu.workspace = true +threadpool.workspace = true +wgpu.workspace = true +wgpu_glyph.workspace = true +winit.workspace = true [dev-dependencies] -rand = "0.8.4" -tempfile = "3.2.0" -uuid = { version = "1.1.2", features = ["v4"] } +rand.workspace = true +tempfile.workspace = true +uuid.workspace = true diff --git a/crates/editor/src/editor/main.rs b/crates/editor/src/editor/main.rs index 28bb97c9ff..3bb28ef407 100644 --- a/crates/editor/src/editor/main.rs +++ b/crates/editor/src/editor/main.rs @@ -32,7 +32,7 @@ use roc_packaging::cache::{self, RocCacheDir}; use roc_types::subs::VarStore; use std::collections::HashSet; use std::env; -use std::fs::{self, File}; +use std::fs::{self, metadata, File}; use std::io::Write; use std::path::PathBuf; use std::{error::Error, io, path::Path}; @@ -54,13 +54,13 @@ use winit::{ /// The editor is actually launched from the CLI if you pass it zero arguments, /// or if you provide it 1 or more files or directories to open on launch. -pub fn launch(project_dir_path_opt: Option<&Path>) -> io::Result<()> { - run_event_loop(project_dir_path_opt).expect("Error running event loop"); +pub fn launch(project_path_opt: Option<&Path>) -> io::Result<()> { + run_event_loop(project_path_opt).expect("Error running event loop"); Ok(()) } -fn run_event_loop(project_dir_path_opt: Option<&Path>) -> Result<(), Box> { +fn run_event_loop(project_path_opt: Option<&Path>) -> Result<(), Box> { // Open window and create a surface let mut event_loop = winit::event_loop::EventLoop::new(); @@ -124,10 +124,10 @@ fn run_event_loop(project_dir_path_opt: Option<&Path>) -> Result<(), Box( const ROC_PROJECTS_FOLDER: &str = "roc-projects"; const ROC_NEW_PROJECT_FOLDER: &str = "new-roc-project-1"; -fn read_main_roc_file(project_dir_path_opt: Option<&Path>) -> (PathBuf, String) { - if let Some(project_dir_path) = project_dir_path_opt { +fn read_main_roc_file(project_path_opt: Option<&Path>) -> (PathBuf, String) { + if let Some(project_path) = project_path_opt { + let path_metadata = metadata(project_path).unwrap_or_else(|err| panic!("You provided the path {:?}, but I could not read the metadata for the provided path; error: {:?}", &project_path, err)); + + if path_metadata.is_file() { + let file_content_as_str = std::fs::read_to_string(project_path).unwrap_or_else(|err| { + panic!( + "You provided the file {:?}, but I could not read it; error: {}", + &project_path, err + ) + }); + + return (project_path.to_path_buf(), file_content_as_str); + } + let mut ls_config = HashSet::new(); ls_config.insert(DirEntryAttr::FullName); - let dir_items = ls(project_dir_path, &ls_config) - .unwrap_or_else(|err| panic!("Failed to list items in project directory: {:?}", err)) + let dir_items = ls(project_path, &ls_config) + .unwrap_or_else(|err| { + panic!( + "Failed to list items in project directory; error: {:?}", + err + ) + }) .items; let file_names = dir_items.iter().flat_map(|info_hash_map| { @@ -514,13 +532,13 @@ fn read_main_roc_file(project_dir_path_opt: Option<&Path>) -> (PathBuf, String) .collect(); if let Some(&roc_file_name) = roc_file_names.first() { - let full_roc_file_path = project_dir_path.join(roc_file_name); - let file_as_str = std::fs::read_to_string(Path::new(&full_roc_file_path)) - .unwrap_or_else(|err| panic!("In the provided project {:?}, I found the roc file {:?}, but I failed to read it: {}", &project_dir_path, full_roc_file_path, err)); + let full_roc_file_path = project_path.join(roc_file_name); + let file_content_as_str = std::fs::read_to_string(Path::new(&full_roc_file_path)) + .unwrap_or_else(|err| panic!("In the provided project {:?}, I found the roc file {:?}, but I failed to read it: {}", &project_path, full_roc_file_path, err)); - (full_roc_file_path, file_as_str) + (full_roc_file_path, file_content_as_str) } else { - init_new_roc_project(project_dir_path) + init_new_roc_project(project_path) } } else { init_new_roc_project(&Path::new(ROC_PROJECTS_FOLDER).join(ROC_NEW_PROJECT_FOLDER)) diff --git a/crates/editor/src/editor/mod.rs b/crates/editor/src/editor/mod.rs index 23d273400d..5012aa0b4d 100644 --- a/crates/editor/src/editor/mod.rs +++ b/crates/editor/src/editor/mod.rs @@ -8,7 +8,5 @@ mod mvc; mod render_ast; mod render_debug; mod resources; -#[cfg(feature = "with_sound")] -mod sound; mod theme; mod util; diff --git a/crates/editor/src/editor/mvc/ed_update.rs b/crates/editor/src/editor/mvc/ed_update.rs index 507fd98358..ceb789a51d 100644 --- a/crates/editor/src/editor/mvc/ed_update.rs +++ b/crates/editor/src/editor/mvc/ed_update.rs @@ -21,8 +21,6 @@ use crate::editor::mvc::string_update::start_new_string; use crate::editor::mvc::string_update::update_small_string; use crate::editor::mvc::string_update::update_string; use crate::editor::mvc::tld_value_update::{start_new_tld_value, update_tld_val_name}; -#[cfg(feature = "with_sound")] -use crate::editor::sound::play_sound; use crate::ui::text::caret_w_select::CaretWSelect; use crate::ui::text::lines::MoveCaretFun; use crate::ui::text::selection::validate_raw_sel; @@ -55,6 +53,7 @@ use roc_code_markup::markup::nodes::EQUALS; use roc_code_markup::slow_pool::MarkNodeId; use roc_code_markup::slow_pool::SlowPool; use roc_collections::all::MutMap; +use roc_command_utils::cargo; use roc_module::ident::Lowercase; use roc_module::symbol::Symbol; use roc_region::all::Region; @@ -62,7 +61,6 @@ use roc_solve::module::Solved; use roc_types::pretty_print::name_and_print_var; use roc_types::pretty_print::DebugPrint; use roc_types::subs::{Subs, VarStore, Variable}; -use roc_utils::cargo; use snafu::OptionExt; use threadpool::ThreadPool; use winit::event::VirtualKeyCode; @@ -546,12 +544,6 @@ impl<'a> EdModel<'a> { self.show_debug_view = !self.show_debug_view; self.dirty = true; } - F12 => { - #[cfg(feature = "with_sound")] - _sound_thread_pool.execute(move || { - play_sound("./editor/src/editor/resources/sounds/bell_sound.mp3"); - }); - } _ => (), } diff --git a/crates/editor/src/editor/sound.rs b/crates/editor/src/editor/sound.rs deleted file mode 100644 index 76a9994de6..0000000000 --- a/crates/editor/src/editor/sound.rs +++ /dev/null @@ -1,45 +0,0 @@ -use rodio::{Decoder, OutputStream, Sink}; -use std::fs::File; -use std::io::BufReader; - -pub(crate) fn play_sound(sound_path_str: &str) { - let out_stream_res = OutputStream::try_default(); - - match out_stream_res { - Ok((_, out_stream_handle)) => match Sink::try_new(&out_stream_handle) { - Ok(sink) => match File::open(sound_path_str) { - Ok(file) => { - let reader = BufReader::new(file); - - match Decoder::new(reader) { - Ok(decoder) => { - sink.append(decoder); - sink.sleep_until_end(); - } - Err(e) => { - println!("Failed to create Decoder from BufReader from sound file at {}. Error message: {:?}", sound_path_str, e); - } - } - } - Err(e) => { - println!( - "Failed to open sound file at {}. Error message: {}", - sound_path_str, e - ); - } - }, - Err(e) => { - println!( - "Failed to create Sink to play sound. Error message: {:?}", - e - ); - } - }, - Err(e) => { - println!( - "Failed to create OutputStream to play sound. Error message: {:?}", - e - ); - } - } -} diff --git a/crates/error_macros/Cargo.toml b/crates/error_macros/Cargo.toml index dba08b9e44..812b2805e4 100644 --- a/crates/error_macros/Cargo.toml +++ b/crates/error_macros/Cargo.toml @@ -1,9 +1,10 @@ [package] name = "roc_error_macros" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Provides macros for consistent reporting of errors in Roc's rust code." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] diff --git a/crates/glue/Cargo.toml b/crates/glue/Cargo.toml index 0e2c145924..c0a1b50c6b 100644 --- a/crates/glue/Cargo.toml +++ b/crates/glue/Cargo.toml @@ -1,37 +1,38 @@ [package] name = "roc_glue" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Generates code needed for platform hosts to communicate with Roc apps. This tool is not necessary for writing a platform in another language, however, it's a great convenience! Currently supports Rust platforms, and the plan is to support any language via a plugin model." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] -roc_std = { path = "../roc_std"} -roc_can = { path = "../compiler/can" } -roc_mono = { path = "../compiler/mono" } -roc_load = { path = "../compiler/load" } -roc_reporting = { path = "../reporting" } -roc_packaging = { path = "../packaging" } -roc_types = { path = "../compiler/types" } roc_builtins = { path = "../compiler/builtins" } -roc_module = { path = "../compiler/module" } +roc_can = { path = "../compiler/can" } roc_collections = { path = "../compiler/collections" } -roc_target = { path = "../compiler/roc_target" } roc_error_macros = { path = "../error_macros" } +roc_load = { path = "../compiler/load" } +roc_module = { path = "../compiler/module" } +roc_mono = { path = "../compiler/mono" } +roc_packaging = { path = "../packaging" } +roc_reporting = { path = "../reporting" } +roc_std = { path = "../roc_std" } +roc_target = { path = "../compiler/roc_target" } roc_tracing = { path = "../tracing" } -bumpalo = { version = "3.11.1", features = ["collections"] } -target-lexicon = "0.12.3" -clap = { version = "3.2.20", default-features = false, features = ["std", "color", "suggestions", "derive"] } -strum = "0.24.0" -strum_macros = "0.24" -indexmap = "1.8.1" -fnv = "1.0.7" +roc_types = { path = "../compiler/types" } + +bumpalo.workspace = true +fnv.workspace = true +indexmap.workspace = true +strum.workspace = true +strum_macros.workspace = true +target-lexicon.workspace = true [dev-dependencies] -pretty_assertions = "1.3.0" -tempfile = "3.2.0" -indoc = "1.0.7" cli_utils = { path = "../cli_utils" } -roc_test_utils = { path = "../test_utils" } -dircpy = "0.3.13" +dircpy.workspace = true + +indoc.workspace = true +pretty_assertions.workspace = true +tempfile.workspace = true diff --git a/crates/glue/tests/fixture-templates/rust/Cargo.lock b/crates/glue/tests/fixture-templates/rust/Cargo.lock deleted file mode 100644 index 8114a43323..0000000000 --- a/crates/glue/tests/fixture-templates/rust/Cargo.lock +++ /dev/null @@ -1,37 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "host" -version = "0.0.1" -dependencies = [ - "indoc", - "libc", - "roc_std", -] - -[[package]] -name = "indoc" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05a0bd019339e5d968b37855180087b7b9d512c5046fbd244cf8c95687927d6e" - -[[package]] -name = "libc" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56d855069fafbb9b344c0f962150cd2c1187975cb1c22c1522c240d8c4986714" - -[[package]] -name = "roc_std" -version = "0.0.1" -dependencies = [ - "static_assertions", -] - -[[package]] -name = "static_assertions" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f406d6ee68db6796e11ffd7b4d171864c58b7451e79ef9460ea33c287a1f89a7" diff --git a/crates/highlight/Cargo.toml b/crates/highlight/Cargo.toml index 8277ed2cb9..d612c8a0e7 100644 --- a/crates/highlight/Cargo.toml +++ b/crates/highlight/Cargo.toml @@ -1,11 +1,14 @@ [package] name = "roc_highlight" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "For syntax highlighting, starts with a string and returns our markup nodes." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] -peg = "0.8.1" -roc_code_markup = { path = "../code_markup"} +html-escape = "0.2" +roc_parse = { path = "../compiler/parse" } +roc_region = { path = "../compiler/region" } + diff --git a/crates/highlight/src/highlight_parser.rs b/crates/highlight/src/highlight_parser.rs deleted file mode 100644 index ff1efc1e79..0000000000 --- a/crates/highlight/src/highlight_parser.rs +++ /dev/null @@ -1,244 +0,0 @@ -use peg::error::ParseError; -use roc_code_markup::markup::attribute::Attributes; -use roc_code_markup::markup::common_nodes::{ - else_mn, if_mn, new_assign_mn, new_dot_mn, new_equals_mn, new_if_expr_mn, - new_module_name_mn_id, new_module_var_mn, then_mn, -}; -use roc_code_markup::markup::nodes::MarkupNode; -use roc_code_markup::slow_pool::{MarkNodeId, SlowPool}; -use roc_code_markup::syntax_highlight::HighlightStyle; - -use crate::tokenizer::{full_tokenize, Token, TokenTable}; - -type T = Token; - -// Inspired by https://ziglang.org/documentation/0.7.1/#Grammar -// license information can be found in the LEGAL_DETAILS file in -// the root directory of this distribution. -// Thank you zig contributors! - -/* -HOW TO ADD NEW RULES: -- go to highlight/tests/peg_grammar.rs -- find for example a variant of common_expr that is not implemented yet, like `if_expr` -- we add `if_expr()` to the `common_expr` rule, in the same order as in peg_grammar::common_expr() -- we copy the if_expr rule from `peg_grammar.rs` -- we add ` -> MarkNodeId` to the if_expr rule -- we change the first full_expr in if_expr() to cond_e_id:full_expr(), the second to then_e_id:full_expr()... -- we add if_mn(), else_mn(), then_mn() and new_if_expr_mn() to common_nodes.rs -- we replace [T::KeywordIf],[T::KeywordThen]... with a new if(),... rule that adds an if,... node to the mark_node_pool. -- we bundle everything together in a nested node and save it in the mn_pool: -``` -{ - mn_pool.add( - new_if_expr_mn(if_id, cond_e_id, then_id, then_e_id, else_id, else_e_id) - ) -} -- we finsih up by adding a test: `test_highlight_if_expr` -``` -*/ -peg::parser! { - grammar highlightparser(t_table: &TokenTable, code_str: &str, mn_pool: &mut SlowPool) for [T] { - - pub rule full_expr() -> MarkNodeId = - common_expr() - - pub rule full_exprs() -> Vec = - opt_same_indent_expr()* - - rule opt_same_indent_expr() -> MarkNodeId = - [T::SameIndent]? e_id:full_expr() {e_id} - - rule opt_same_indent_def() -> MarkNodeId = - [T::SameIndent]? d_id:def() {d_id} - - rule common_expr() -> MarkNodeId = - if_expr() - / p:position!() [T::Number] { add_new_mn(t_table.extract_str(p, code_str), HighlightStyle::Number, mn_pool) } - / module_var() - / lowercase_ident() - - rule if_expr() -> MarkNodeId = - if_id:if() cond_e_id:full_expr() then_id:then() then_e_id:full_expr() else_id:else_rule() else_e_id:full_expr() - { - mn_pool.add( - new_if_expr_mn(if_id, cond_e_id, then_id, then_e_id, else_id, else_e_id) - ) - } - - rule if() -> MarkNodeId = - [T::KeywordIf] {mn_pool.add(if_mn())} - - rule then() -> MarkNodeId = - [T::KeywordThen] {mn_pool.add(then_mn())} - - rule else_rule() -> MarkNodeId = - [T::KeywordElse] {mn_pool.add(else_mn())} - - pub rule def() -> MarkNodeId = - // annotated_body() - // annotation() - /* / */ body() - // alias() - // expect() - - pub rule module_defs() -> Vec = - opt_same_indent_def()+ - - rule body() -> MarkNodeId = - ident_id:ident() as_id:assign() [T::OpenIndent] e_id:full_expr() /*TODO not sure when this is needed> es:full_exprs()*/ ([T::CloseIndent] / end_of_file()) - { - mn_pool.add( - new_assign_mn(ident_id, as_id, e_id) - ) - } - / - ident_id:ident() as_id:assign() e_id:full_expr() end_of_file()? - { - mn_pool.add( - new_assign_mn(ident_id, as_id, e_id) - ) - } - - rule module_var() -> MarkNodeId = - mod_name_id:module_name() dot_id:dot() ident_id:lowercase_ident() { - mn_pool.add( - new_module_var_mn(mod_name_id, dot_id, ident_id) - ) - } - - rule module_name() -> MarkNodeId = - first_ident_id:uppercase_ident() rest_ids:dot_idents() { - new_module_name_mn_id( - merge_ids(first_ident_id, rest_ids), - mn_pool - ) - } - - rule assign() -> MarkNodeId = - [T::OpAssignment] { mn_pool.add(new_equals_mn()) } - - rule dot() -> MarkNodeId = - [T::Dot] { mn_pool.add(new_dot_mn()) } - - rule dot_ident() -> (MarkNodeId, MarkNodeId) = - dot_id:dot() ident_id:uppercase_ident() { (dot_id, ident_id) } - - rule dot_idents() -> Vec = - di:dot_ident()* {flatten_tups(di)} - - rule ident() -> MarkNodeId = - uppercase_ident() - / lowercase_ident() - - rule uppercase_ident() -> MarkNodeId = - p:position!() [T::UppercaseIdent] { add_new_mn(t_table.extract_str(p, code_str), HighlightStyle::UppercaseIdent, mn_pool) } - - rule lowercase_ident() -> MarkNodeId = - p:position!() [T::LowercaseIdent] { add_new_mn(t_table.extract_str(p, code_str), HighlightStyle::LowercaseIdent, mn_pool) } - - rule end_of_file() = - ![_] - - } -} -fn merge_ids(mn_id: MarkNodeId, other_mn_id: Vec) -> Vec { - let mut ids = vec![mn_id]; - let mut rest_ids: Vec = other_mn_id; - - ids.append(&mut rest_ids); - - ids -} - -fn flatten_tups(tup_vec: Vec<(MarkNodeId, MarkNodeId)>) -> Vec { - tup_vec.iter().flat_map(|(a, b)| vec![*a, *b]).collect() -} - -fn add_new_mn( - text: &str, - highlight_style: HighlightStyle, - mark_node_pool: &mut SlowPool, -) -> MarkNodeId { - let m_node = MarkupNode::Text { - content: text.to_owned(), - syn_high_style: highlight_style, - attributes: Attributes::default(), - parent_id_opt: None, - newlines_at_end: 0, - }; - mark_node_pool.add(m_node) -} - -pub fn highlight_expr( - code_str: &str, - mark_node_pool: &mut SlowPool, -) -> Result> { - let token_table = full_tokenize(code_str); - - highlightparser::full_expr(&token_table.tokens, &token_table, code_str, mark_node_pool) -} - -pub fn highlight_defs( - code_str: &str, - mark_node_pool: &mut SlowPool, -) -> Result, ParseError> { - let token_table = full_tokenize(code_str); - - highlightparser::module_defs(&token_table.tokens, &token_table, code_str, mark_node_pool) -} - -#[cfg(test)] -pub mod highlight_tests { - use roc_code_markup::{markup::nodes::node_to_string_w_children, slow_pool::SlowPool}; - - use crate::highlight_parser::{highlight_defs, highlight_expr}; - - fn test_highlight_expr(input: &str, expected_output: &str) { - let mut mark_node_pool = SlowPool::default(); - - let mark_id = highlight_expr(input, &mut mark_node_pool).unwrap(); - - let mut str_buffer = String::new(); - - node_to_string_w_children(mark_id, &mut str_buffer, &mark_node_pool); - - assert_eq!(&str_buffer, expected_output); - } - - #[test] - fn test_highlight() { - test_highlight_expr("0", "0"); - } - - #[test] - fn test_highlight_module_var() { - test_highlight_expr("Foo.Bar.var", "Foo.Bar.var"); - } - - #[test] - fn test_highlight_if_expr() { - test_highlight_expr( - "if booly then 42 else 31415", - "if booly then 42 else 31415\n", - ) - } - - #[test] - fn test_highlight_defs() { - let mut mark_node_pool = SlowPool::default(); - - let mut str_buffer = String::new(); - - node_to_string_w_children( - *highlight_defs("a = 0", &mut mark_node_pool) - .unwrap() - .first() - .unwrap(), - &mut str_buffer, - &mark_node_pool, - ); - - assert_eq!(&str_buffer, "a = 0\n\n"); - } -} diff --git a/crates/highlight/src/lib.rs b/crates/highlight/src/lib.rs index 4c8dbad0b2..8929824f4c 100644 --- a/crates/highlight/src/lib.rs +++ b/crates/highlight/src/lib.rs @@ -1,3 +1,117 @@ -//! Provides syntax highlighting for the editor by transforming a string to markup nodes. -pub mod highlight_parser; -pub mod tokenizer; +use roc_parse::highlight::Token; +use roc_region::all::Loc; + +pub fn highlight_roc_code(code: &str) -> String { + let buf = highlight(code); + + format!("
{}
", buf.join("")) +} + +pub fn highlight_roc_code_inline(code: &str) -> String { + let buf = highlight(code); + + format!("{}", buf.join("")) +} + +pub fn highlight(code: &str) -> Vec { + let locations: Vec> = roc_parse::highlight::highlight(code); + let mut buf: Vec = Vec::new(); + let mut offset = 0; + + for location in locations { + let current_text = &code[offset..location.byte_range().end]; + + match location.value { + // Comments `#` and Documentation comments `##` + Token::LineComment | Token::DocComment => { + buf = push_html_span(buf, current_text, "comment"); + } + // Number, String, Tag, Type literals + Token::SingleQuote + | Token::String + | Token::UnicodeEscape + | Token::EscapedChar + | Token::Interpolated + | Token::Number => { + buf = push_html_span(buf, current_text, "literal"); + } + // Keywords and punctuation + Token::Keyword + | Token::Equals + | Token::Backslash + | Token::Pizza + | Token::Arrow + | Token::Backpass + | Token::ColonEquals + | Token::Colon + | Token::And + | Token::AtSign + | Token::QuestionMark => { + buf = push_html_span(buf, current_text, "kw"); + } + // Operators + Token::Percent + | Token::Caret + | Token::Bang + | Token::BangEquals + | Token::Slash + | Token::DoubleSlash + | Token::Pipe + | Token::GreaterThan + | Token::GreaterThanEquals + | Token::Minus + | Token::LessThan + | Token::LessThanEquals + | Token::DoubleEquals + | Token::DoubleBar + | Token::Multiply + | Token::Plus + | Token::DoubleAnd => { + buf = push_html_span(buf, current_text, "op"); + } + // Delimieters + Token::Paren + | Token::Bracket + | Token::Brace + | Token::Comma + | Token::Bar + | Token::Decimal => { + buf = push_html_span(buf, current_text, "delimeter"); + } + // Types, Tags, and Modules + Token::UpperIdent => { + buf = push_html_span(buf, current_text, "upperident"); + } + // Variables modules and field names + Token::LowerIdent | Token::Underscore => { + buf = push_html_span(buf, current_text, "lowerident"); + } + // Anyting else that wasn't tokenised + Token::Error | Token::Other => { + buf = push_html(buf, current_text); + } + } + + offset = location.byte_range().end; + } + + buf +} + +fn push_html_span(mut buf: Vec, curr: &str, class: &str) -> Vec { + // html escape strings from source code + let escaped = html_escape::encode_text(curr); + + buf.push(format!("{}", class, escaped)); + + buf +} + +fn push_html(mut buf: Vec, curr: &str) -> Vec { + // html escape strings from source code + let escaped = html_escape::encode_text(curr); + + buf.push(format!("{}", escaped)); + + buf +} diff --git a/crates/highlight/src/tokenizer.rs b/crates/highlight/src/tokenizer.rs deleted file mode 100644 index b6d03c9d06..0000000000 --- a/crates/highlight/src/tokenizer.rs +++ /dev/null @@ -1,654 +0,0 @@ -use std::cmp::Ordering; - -#[repr(u8)] -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -/// Tokens are full of very dense information to make checking properties about them -/// very fast. -/// Some bits have specific meanings: -/// * 0b_001*_****: "Identifier-like" things -/// * 0b_01**_****: "Punctuation" -/// * 0b_0100_1***: []{}() INDENT/DEDENT -/// * 0b_0100_1**0 [{(INDENT -/// * 0b_0100_1**1 ]})DEDENT -/// * 0b_011*_**** Operators -pub enum Token { - LowercaseIdent = 0b_0010_0000, - UppercaseIdent = 0b_0011_0011, - MalformedIdent = 0b_0010_0001, - - KeywordIf = 0b_0010_0010, - KeywordThen = 0b_0010_0011, - KeywordElse = 0b_0010_0100, - KeywordWhen = 0b_0010_0101, - KeywordAs = 0b_0010_0110, - KeywordIs = 0b_0010_0111, - KeywordExpect = 0b_0010_1000, - KeywordApp = 0b_0010_1001, - KeywordInterface = 0b_0010_1010, - KeywordPackages = 0b_0010_1011, - KeywordImports = 0b_0010_1100, - KeywordProvides = 0b_0010_1101, - KeywordTo = 0b_0010_1110, - KeywordExposes = 0b_0010_1111, - KeywordEffects = 0b_0011_0000, - KeywordPackage = 0b_0111_1100, - KeywordPlatform = 0b_0011_0001, - KeywordRequires = 0b_0011_0010, - KeywordDbg = 0b_0111_1011, - - Comma = 0b_0100_0000, - Colon = 0b_0100_0001, - - OpenParen = 0b_0100_1000, - CloseParen = 0b_0100_1001, - OpenCurly = 0b_0100_1010, - CloseCurly = 0b_0100_1011, - OpenSquare = 0b_0100_1100, - CloseSquare = 0b_0100_1101, - OpenIndent = 0b_0100_1110, - CloseIndent = 0b_0100_1111, - SameIndent = 0b_0101_0000, - - OpPlus = 0b_0110_0000, - OpMinus = 0b_0110_0001, - OpSlash = 0b_0110_0010, - OpPercent = 0b_0110_0011, - OpCaret = 0b_0110_0100, - OpGreaterThan = 0b_0110_0101, - OpLessThan = 0b_0110_0110, - OpAssignment = 0b_0110_0111, - OpPizza = 0b_0110_1000, - OpEquals = 0b_0110_1001, - OpNotEquals = 0b_0110_1010, - OpGreaterThanOrEq = 0b_0110_1011, - OpLessThanOrEq = 0b_0110_1100, - OpAnd = 0b_0110_1101, - OpOr = 0b_0110_1110, - OpDoubleSlash = 0b_0110_1111, - OpBackpassing = 0b_0111_1010, - - TodoNextThing = 0b_1000_0000, - - Malformed, - MalformedOperator, - - String, - - NumberBase, - Number, - - QuestionMark, - - Underscore, - - Ampersand, - Pipe, - Dot, - SpaceDot, // ` .` necessary to know difference between `Result.map .position` and `Result.map.position` - Bang, - LambdaStart, - Arrow, - FatArrow, - Asterisk, -} - -#[derive(Default)] -pub struct TokenTable { - pub tokens: Vec, - pub offsets: Vec, - pub lengths: Vec, -} - -#[derive(Default)] -pub struct LexState { - indents: Vec, -} - -trait ConsumeToken { - fn token(&mut self, token: Token, _offset: usize, _length: usize); -} - -#[derive(Default)] -struct TokenConsumer { - token_table: TokenTable, -} - -impl ConsumeToken for TokenConsumer { - fn token(&mut self, token: Token, offset: usize, length: usize) { - self.token_table.tokens.push(token); - self.token_table.offsets.push(offset); - self.token_table.lengths.push(length); - } -} - -pub fn tokenize(code_str: &str) -> Vec { - full_tokenize(code_str).tokens -} - -pub fn full_tokenize(code_str: &str) -> TokenTable { - let mut lex_state = LexState::default(); - let mut consumer = TokenConsumer::default(); - - consume_all_tokens(&mut lex_state, code_str.as_bytes(), &mut consumer); - - consumer.token_table -} - -fn consume_all_tokens(state: &mut LexState, bytes: &[u8], consumer: &mut impl ConsumeToken) { - let mut i = 0; - - while i < bytes.len() { - let bytes = &bytes[i..]; - - let (token, len) = match bytes[0] { - b'(' => (Token::OpenParen, 1), - b')' => (Token::CloseParen, 1), - b'{' => (Token::OpenCurly, 1), - b'}' => (Token::CloseCurly, 1), - b'[' => (Token::OpenSquare, 1), - b']' => (Token::CloseSquare, 1), - b',' => (Token::Comma, 1), - b'_' => lex_underscore(bytes), - b'a'..=b'z' => lex_ident(false, bytes), - b'A'..=b'Z' => lex_ident(true, bytes), - b'0'..=b'9' => lex_number(bytes), - b'-' | b':' | b'!' | b'.' | b'*' | b'/' | b'&' | b'%' | b'^' | b'+' | b'<' | b'=' - | b'>' | b'|' | b'\\' => lex_operator(bytes), - b' ' => match skip_whitespace(bytes) { - SpaceDotOrSpaces::SpacesWSpaceDot(skip) => { - i += skip; - (Token::SpaceDot, 1) - } - SpaceDotOrSpaces::Spaces(skip) => { - i += skip; - continue; - } - }, - b'\n' => { - // TODO: add newline to side_table - let skip_newline_return = skip_newlines_and_comments(bytes); - - match skip_newline_return { - SkipNewlineReturn::SkipWIndent(skipped_lines, curr_line_indent) => { - add_indents(skipped_lines, curr_line_indent, state, consumer, &mut i); - continue; - } - SkipNewlineReturn::WSpaceDot(skipped_lines, curr_line_indent) => { - add_indents(skipped_lines, curr_line_indent, state, consumer, &mut i); - (Token::SpaceDot, 1) - } - } - } - b'#' => { - // TODO: add comment to side_table - i += skip_comment(bytes); - continue; - } - b'"' => lex_string(bytes), - b => todo!("handle {:?}", b as char), - }; - - consumer.token(token, i, len); - i += len; - } -} - -fn add_indents( - skipped_lines: usize, - curr_line_indent: usize, - state: &mut LexState, - consumer: &mut impl ConsumeToken, - curr_byte_ctr: &mut usize, -) { - *curr_byte_ctr += skipped_lines; - - if let Some(&prev_indent) = state.indents.last() { - if curr_line_indent > prev_indent { - state.indents.push(curr_line_indent); - consumer.token(Token::OpenIndent, *curr_byte_ctr, 0); - } else { - *curr_byte_ctr += curr_line_indent; - - match prev_indent.cmp(&curr_line_indent) { - Ordering::Equal => { - consumer.token(Token::SameIndent, *curr_byte_ctr, 0); - } - Ordering::Greater => { - while state.indents.last().is_some() - && curr_line_indent < *state.indents.last().unwrap() - // safe unwrap because we check first - { - state.indents.pop(); - consumer.token(Token::CloseIndent, *curr_byte_ctr, 0); - } - } - Ordering::Less => {} - } - } - } else if curr_line_indent > 0 { - state.indents.push(curr_line_indent); - consumer.token(Token::OpenIndent, *curr_byte_ctr, 0); - } else { - consumer.token(Token::SameIndent, *curr_byte_ctr, 0); - } -} - -impl TokenTable { - pub fn extract_str<'a>(&self, index: usize, content: &'a str) -> &'a str { - // Not returning a result here because weaving it through highlight_parser makes it more difficult to expand and understand. - // The only way I think this can panic is by calling position! in highlight_parser after the last element, which does not make sense to begin with. - let len = *self.lengths.get(index).unwrap_or_else(|| { - panic!( - "Index {:?} was out of bounds for TokenTable.lengths with len {:?}", - index, - self.lengths.len() - ) - }); - let offset = *self.offsets.get(index).unwrap_or_else(|| { - panic!( - "Index {:?} was out of bounds for TokenTable.offsets with len {:?}", - index, - self.lengths.len() - ) - }); - - &content[offset..(offset + len)] - } -} - -fn skip_comment(bytes: &[u8]) -> usize { - let mut skip = 0; - while skip < bytes.len() && bytes[skip] != b'\n' { - skip += 1; - } - if (skip + 1) < bytes.len() && bytes[skip] == b'\n' && bytes[skip + 1] == b'#' { - skip += 1; - } - - skip -} - -#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)] -struct Indent(usize); - -enum SpaceDotOrSpaces { - SpacesWSpaceDot(usize), - Spaces(usize), -} - -fn skip_whitespace(bytes: &[u8]) -> SpaceDotOrSpaces { - debug_assert!(bytes[0] == b' '); - - let mut skip = 0; - while skip < bytes.len() && bytes[skip] == b' ' { - skip += 1; - } - - if skip < bytes.len() && bytes[skip] == b'.' { - SpaceDotOrSpaces::SpacesWSpaceDot(skip) - } else { - SpaceDotOrSpaces::Spaces(skip) - } -} - -enum SkipNewlineReturn { - SkipWIndent(usize, usize), - WSpaceDot(usize, usize), -} - -// also skips lines that contain only whitespace -fn skip_newlines_and_comments(bytes: &[u8]) -> SkipNewlineReturn { - let mut skip = 0; - let mut indent = 0; - - while skip < bytes.len() && bytes[skip] == b'\n' { - skip += indent + 1; - - if bytes.len() > skip { - if bytes[skip] == b' ' { - let space_dot_or_spaces = skip_whitespace(&bytes[skip..]); - - match space_dot_or_spaces { - SpaceDotOrSpaces::SpacesWSpaceDot(spaces) => { - return SkipNewlineReturn::WSpaceDot(skip, spaces) - } - SpaceDotOrSpaces::Spaces(spaces) => { - if bytes.len() > (skip + spaces) { - if bytes[skip + spaces] == b'\n' { - indent = 0; - skip += spaces; - } else if bytes[skip + spaces] == b'#' { - let comment_skip = skip_comment(&bytes[(skip + spaces)..]); - - indent = 0; - skip += spaces + comment_skip; - } else { - indent = spaces; - } - } else { - indent = spaces; - } - } - } - } else { - while bytes[skip] == b'#' { - let comment_skip = skip_comment(&bytes[skip..]); - - indent = 0; - skip += comment_skip; - } - } - } - } - - SkipNewlineReturn::SkipWIndent(skip, indent) -} - -fn is_op_continue(ch: u8) -> bool { - matches!( - ch, - b'-' | b':' - | b'!' - | b'.' - | b'*' - | b'/' - | b'&' - | b'%' - | b'^' - | b'+' - | b'<' - | b'=' - | b'>' - | b'|' - | b'\\' - ) -} - -fn lex_operator(bytes: &[u8]) -> (Token, usize) { - let mut i = 0; - while i < bytes.len() && is_op_continue(bytes[i]) { - i += 1; - } - let tok = match &bytes[0..i] { - b"+" => Token::OpPlus, - b"-" => Token::OpMinus, - b"*" => Token::Asterisk, - b"/" => Token::OpSlash, - b"%" => Token::OpPercent, - b"^" => Token::OpCaret, - b">" => Token::OpGreaterThan, - b"<" => Token::OpLessThan, - b"." => Token::Dot, - b"=" => Token::OpAssignment, - b":" => Token::Colon, - b"|" => Token::Pipe, - b"\\" => Token::LambdaStart, - b"|>" => Token::OpPizza, - b"==" => Token::OpEquals, - b"!" => Token::Bang, - b"!=" => Token::OpNotEquals, - b">=" => Token::OpGreaterThanOrEq, - b"<=" => Token::OpLessThanOrEq, - b"&&" => Token::OpAnd, - b"&" => Token::Ampersand, - b"||" => Token::OpOr, - b"//" => Token::OpDoubleSlash, - b"->" => Token::Arrow, - b"<-" => Token::OpBackpassing, - op => { - dbg!(std::str::from_utf8(op).unwrap()); - Token::MalformedOperator - } - }; - (tok, i) -} - -fn is_ident_continue(ch: u8) -> bool { - matches!(ch, b'a'..=b'z'|b'A'..=b'Z'|b'0'..=b'9'|b'_') -} - -fn lex_ident(uppercase: bool, bytes: &[u8]) -> (Token, usize) { - let mut i = 0; - while i < bytes.len() && is_ident_continue(bytes[i]) { - i += 1; - } - let tok = match &bytes[0..i] { - b"if" => Token::KeywordIf, - b"then" => Token::KeywordThen, - b"else" => Token::KeywordElse, - b"when" => Token::KeywordWhen, - b"as" => Token::KeywordAs, - b"is" => Token::KeywordIs, - b"dbg" => Token::KeywordDbg, - b"expect" => Token::KeywordExpect, - b"app" => Token::KeywordApp, - b"interface" => Token::KeywordInterface, - b"packages" => Token::KeywordPackages, - b"imports" => Token::KeywordImports, - b"provides" => Token::KeywordProvides, - b"to" => Token::KeywordTo, - b"exposes" => Token::KeywordExposes, - b"effects" => Token::KeywordEffects, - b"package" => Token::KeywordPackage, - b"platform" => Token::KeywordPlatform, - b"requires" => Token::KeywordRequires, - ident => { - if ident.contains(&b'_') { - Token::MalformedIdent - } else if uppercase { - Token::UppercaseIdent - } else { - Token::LowercaseIdent - } - } - }; - (tok, i) -} - -fn lex_underscore(bytes: &[u8]) -> (Token, usize) { - let mut i = 0; - while i < bytes.len() && is_ident_continue(bytes[i]) { - i += 1; - } - (Token::Underscore, i) -} - -fn is_int_continue(ch: u8) -> bool { - matches!(ch, b'0'..=b'9' | b'_') -} - -fn lex_number(bytes: &[u8]) -> (Token, usize) { - let mut i = 0; - while i < bytes.len() && is_int_continue(bytes[i]) { - i += 1; - } - - if i < bytes.len() && bytes[i] == b'.' { - i += 1; - while i < bytes.len() && is_int_continue(bytes[i]) { - i += 1; - } - } - - (Token::Number, i) -} - -fn lex_string(bytes: &[u8]) -> (Token, usize) { - let mut i = 0; - assert_eq!(bytes[i], b'"'); - i += 1; - - while i < bytes.len() { - match bytes[i] { - b'"' => break, - // TODO: escapes - _ => i += 1, - } - } - - assert_eq!(bytes[i], b'"'); - i += 1; - - (Token::String, i) -} - -#[cfg(test)] -mod test_tokenizer { - use super::Token; - use crate::tokenizer::tokenize; - - type T = Token; - - #[test] - fn test_indent_tokenization_1() { - let tokens = tokenize( - r#"showBool = \b -> - when b is - True -> - "True""#, - ); - - assert_eq!( - tokens, - [ - T::LowercaseIdent, - T::OpAssignment, - T::LambdaStart, - T::LowercaseIdent, - T::Arrow, - T::OpenIndent, - T::KeywordWhen, - T::LowercaseIdent, - T::KeywordIs, - T::OpenIndent, - T::UppercaseIdent, - T::Arrow, - T::OpenIndent, - T::String - ] - ); - } - - #[test] - fn test_indent_tokenization_2() { - let tokens = tokenize( - r#"showBool = \b -> - when b is - True -> - "True" - "#, - ); - - assert_eq!( - tokens, - [ - T::LowercaseIdent, - T::OpAssignment, - T::LambdaStart, - T::LowercaseIdent, - T::Arrow, - T::OpenIndent, - T::KeywordWhen, - T::LowercaseIdent, - T::KeywordIs, - T::OpenIndent, - T::UppercaseIdent, - T::Arrow, - T::OpenIndent, - T::String, - T::CloseIndent, - T::CloseIndent, - T::CloseIndent - ] - ); - } - - #[test] - fn test_tokenization_line_with_only_spaces() { - let tokens = tokenize( - r#"\key -> - when dict is - Empty -> - 4 - - Node -> - 5"#, - ); - - assert_eq!( - tokens, - [ - T::LambdaStart, - T::LowercaseIdent, - T::Arrow, - T::OpenIndent, - T::KeywordWhen, - T::LowercaseIdent, - T::KeywordIs, - T::OpenIndent, - T::UppercaseIdent, - T::Arrow, - T::OpenIndent, - T::Number, - T::CloseIndent, - T::UppercaseIdent, - T::Arrow, - T::OpenIndent, - T::Number - ] - ); - } - - #[test] - fn test_tokenization_empty_lines_and_comments() { - let tokens = tokenize( - r#"a = 5 - -# com1 -# com2 -b = 6"#, - ); - - assert_eq!( - tokens, - [ - T::LowercaseIdent, - T::OpAssignment, - T::Number, - T::SameIndent, - T::LowercaseIdent, - T::OpAssignment, - T::Number - ] - ); - } - - #[test] - fn test_tokenization_when_branch_comments() { - let tokens = tokenize( - r#"when errorCode is - # A -> Task.fail InvalidCharacter - # B -> Task.fail IOError - _ -> - Task.succeed -1"#, - ); - - assert_eq!( - tokens, - [ - T::KeywordWhen, - T::LowercaseIdent, - T::KeywordIs, - T::OpenIndent, - T::Underscore, - T::Arrow, - T::OpenIndent, - T::UppercaseIdent, - T::Dot, - T::LowercaseIdent, - T::OpMinus, - T::Number - ] - ); - } -} diff --git a/crates/highlight/tests/peg_grammar.rs b/crates/highlight/tests/peg_grammar.rs deleted file mode 100644 index f46054ca41..0000000000 --- a/crates/highlight/tests/peg_grammar.rs +++ /dev/null @@ -1,1453 +0,0 @@ -/* -To debug grammar, add `dbg!(&tokens);`, execute with: -``` -cargo test --features peg/trace test_fibo -- --nocapture -``` -With visualization, see necessary format for temp_trace.txt [here](https://github.com/fasterthanlime/pegviz): -``` -cat highlight/temp_trace.txt | pegviz --output ./pegviz.html -``` -*/ - -#[cfg(test)] -mod test_peg_grammar { - use roc_highlight::tokenizer::{tokenize, Token}; - - type T = Token; - - // Inspired by https://ziglang.org/documentation/0.7.1/#Grammar - // license information can be found in the LEGAL_DETAILS file in - // the root directory of this distribution. - // Thank you zig contributors! - peg::parser! { - grammar tokenparser() for [T] { - - pub rule module() = - header() module_defs()? indented_end() - - pub rule full_expr() = - op_expr() - / [T::OpenIndent] op_expr() close_or_end() - - pub rule op_expr() = pizza_expr() - - rule common_expr() = - closure() - / expect() - / if_expr() - / when() - / backpass() - / list() - / record() - / record_update() - / parens_around() - / [T::Number] - / [T::NumberBase] - / [T::String] - / module_var() - / tag() - / accessor_function() - / defs() - / annotation() - / [T::LowercaseIdent] - pub rule expr() = - access() - / apply() - / common_expr() - - pub rule closure() = - [T::LambdaStart] args() [T::Arrow] closure_body() - - rule closure_body() = - [T::OpenIndent] full_expr() ([T::CloseIndent] / end_of_file() / &[T::CloseParen]) - / [T::SameIndent]? full_expr() - - rule args() = - (arg() [T::Comma])* arg() - - rule arg() = - [T::Underscore] - / ident() - / record_destructure() - - - rule tag() = - [T::UppercaseIdent] - - - rule list() = empty_list() - / [T::OpenSquare] (expr() [T::Comma])* expr()? [T::Comma]? [T::CloseSquare] { } - rule empty_list() = [T::OpenSquare] [T::CloseSquare] - - - rule record() = - empty_record() - / [T::OpenCurly] assigned_fields_i() [T::CloseCurly] - - rule assigned_fields() = - (assigned_field() [T::SameIndent]? [T::Comma] [T::SameIndent]?)* [T::SameIndent]? assigned_field()? [T::Comma]? - - rule assigned_fields_i() = - [T::OpenIndent] assigned_fields() [T::CloseIndent] - / [T::SameIndent]? assigned_fields() [T::SameIndent]? - - - rule assigned_field() = - required_value() - / [T::LowercaseIdent] - - rule required_value() = - [T::LowercaseIdent] [T::Colon] full_expr() - - rule empty_record() = [T::OpenCurly] [T::CloseCurly] - - rule record_update() = [T::OpenCurly] expr() [T::Ampersand] assigned_fields_i() [T::CloseCurly] - - rule record_type() = - empty_record() - / [T::OpenCurly] record_field_types_i() [T::CloseCurly] - - rule record_type_i() = - [T::OpenIndent] record_type() [T::CloseIndent]? - / record_type() - - rule record_field_types_i() = - [T::OpenIndent] record_field_types() [T::CloseIndent] - / record_field_types() - - rule record_field_types() = - ([T::SameIndent]? record_field_type() [T::SameIndent]? [T::Comma])* ([T::SameIndent]? record_field_type() [T::Comma]?)? - - rule record_field_type() = - ident() [T::Colon] type_annotation() - - - pub rule parens_around() = [T::OpenParen] full_expr() [T::CloseParen] - - rule if_expr() = [T::KeywordIf] full_expr() [T::KeywordThen] full_expr() - [T::KeywordElse] full_expr() - - rule expect() = [T::KeywordExpect] expr() - - pub rule backpass() = - single_backpass() ([T::SameIndent] single_backpass())* [T::SameIndent] full_expr() - - pub rule single_backpass() = - backpass_pattern() [T::OpBackpassing] full_expr() - - rule common_pattern() = - [T::LowercaseIdent] - / [T::Underscore] - / module_var() - / concrete_type() - / parens_around() - / tag() - - rule backpass_pattern() = - common_pattern() - / record_destructure() - / [T::Number] - / [T::NumberBase] - / [T::String] - / list() - - // for applies without line breaks between args: Node color rK rV - rule apply_arg_pattern() = - accessor_function() - / access() - / record() - / record_update() - / closure() - / common_pattern() - / [T::Number] - / [T::NumberBase] - / [T::String] - / list() - / parens_around() - - pub rule when_match_pattern() = - record() - / [T::Number] - / [T::NumberBase] - / [T::String] - / list() - / parens_around() - / apply() - / common_pattern() - - - // for applies where the arg is on its own line, for example: - // Effect.after - // transform a - rule apply_arg_line_pattern() = - record() - / closure() - / apply() - / common_pattern() - - rule apply_start_pattern() = - access() - / common_pattern() - - rule record_destructure() = - empty_record() - / [T::OpenCurly] (ident() [T::Comma])* ident() [T::Comma]? [T::CloseCurly] - - rule access() = - access_start() [T::Dot] ident() - - rule access_start() = - [T::LowercaseIdent] - / record() - / parens_around() - - rule accessor_function() = - [T::SpaceDot] ident() - / [T::Dot] ident() - - pub rule header() = - __ almost_header() header_end() - - pub rule almost_header() = - app_header() - / interface_header() - / platform_header() - - rule app_header() = - [T::KeywordApp] [T::String] [T::OpenIndent]? packages() imports() provides()// check String to be non-empty? - - rule interface_header() = - [T::KeywordInterface] module_name() [T::OpenIndent]? exposes() imports() - - rule platform_header() = - [T::KeywordPlatform] [T::String] [T::OpenIndent]? requires() exposes() packages() imports() provides() effects()// check String to be nonempty? - - rule header_end() = - ([T::CloseIndent] - / &[T::SameIndent])? // & to not consume the SameIndent - rule packages() = - __ [T::KeywordPackages] record() - - rule imports() = - __ [T::KeywordImports] imports_list() - - rule imports_list() = - empty_list() - / [T::OpenSquare] (imports_entry() [T::Comma])* imports_entry()? [T::Comma]? [T::CloseSquare] - - rule imports_entry() = - ([T::LowercaseIdent] [T::Dot])? - module_name() - ([T::Dot] exposes_list() )? - - rule exposes_list() = - [T::OpenCurly] (exposes_entry() [T::Comma])* exposes_entry()? [T::Comma]? [T::CloseCurly] - rule exposes_entry() = - ident() - - rule provides() = - __ [T::KeywordProvides] provides_list() ([T::KeywordTo] provides_to())? - - rule provides_to() = - [T::String] - / ident() - - rule provides_list() = - empty_list() - / [T::OpenSquare] exposed_names() [T::CloseSquare] - - rule exposes() = - __ [T::KeywordExposes] [T::OpenSquare] exposed_names() [T::CloseSquare] - - rule exposed_names() = - (ident() [T::Comma])* ident()? [T::Comma]? - - rule requires() = - [T::KeywordRequires] requires_rigids() [T::OpenCurly] typed_ident() [T::CloseCurly] - - rule requires_rigids() = - empty_record() - / [T::OpenCurly] (requires_rigid() [T::Comma])* requires_rigid() [T::Comma]? [T::CloseCurly] - - rule requires_rigid() = - [T::LowercaseIdent] ([T::FatArrow] [T::UppercaseIdent])? - - pub rule typed_ident() = - [T::LowercaseIdent] [T::Colon] type_annotation() - - pub rule effects() = - __ [T::KeywordEffects] effect_name() record_type_i() - - rule effect_name() = - [T::LowercaseIdent] [T::Dot] [T::UppercaseIdent] - - - rule module_name() = - [T::UppercaseIdent] ([T::Dot] [T::UppercaseIdent])* - - rule ident() = - [T::UppercaseIdent] - / [T::LowercaseIdent] - - - // content of type_annotation without Colon(:) - pub rule type_annotation() = - function_type() - / type_annotation_no_fun() - - rule type_annotation_no_fun() = - [T::OpenParen] type_annotation_no_fun() [T::CloseParen] - / [T::OpenIndent] type_annotation_no_fun() close_or_end() - / tag_union() - / apply_type() - / bound_variable() - / record_type() - / inferred() - / wildcard() - // TODO inline type alias - - rule type_annotation_paren_fun() = - type_annotation_no_fun() - / [T::OpenParen] function_type() [T::CloseParen] - - rule tag_union() = - empty_list() - / [T::OpenSquare] tags() [T::CloseSquare] type_variable()? - - rule tags() = - [T::OpenIndent] tags_only() [T::CloseIndent] - / tags_only() - - rule tags_only() = - ([T::SameIndent]? apply_type() [T::SameIndent]? [T::Comma] [T::SameIndent]? )* ([T::SameIndent]? apply_type() [T::Comma]?)? - - rule type_variable() = - [T::Underscore] - / bound_variable() - - rule bound_variable() = - [T::LowercaseIdent] - - // The `*` type variable, e.g. in (List *) - rule wildcard() = - [T::Asterisk] - - // '_', indicating the compiler should infer the type - rule inferred() = - [T::Underscore] - - rule function_type() = - ( type_annotation_paren_fun() ([T::Comma] type_annotation_paren_fun())* [T::Arrow])? type_annotation_paren_fun() - - pub rule apply_type() = - concrete_type() apply_type_args()? - rule concrete_type() = - [T::UppercaseIdent] ([T::Dot] [T::UppercaseIdent])* - rule apply_type_args() = - apply_type_arg() apply_type_arg()* - - rule apply_type_arg() = - type_annotation_no_fun() - / record_destructure() - - rule _() = - ([T::SameIndent])? - - // the rules below allow us to set assoicativity and precedence - rule unary_op() = - [T::OpMinus] - / [T::Bang] - rule unary_expr() = - unary_op()* expr() - - rule mul_level_op() = - [T::Asterisk] - / [T::OpSlash] - / [T::OpDoubleSlash] - / [T::OpPercent] - rule mul_level_expr() = - unary_expr() (mul_level_op() unary_expr())* - - rule add_level_op() = - [T::OpPlus] - / [T::OpMinus] - rule add_level_expr() = - mul_level_expr() (add_level_op() mul_level_expr())* - - rule compare_op() = - [T::OpEquals] // == - / [T::OpNotEquals] - / [T::OpLessThan] - / [T::OpGreaterThan] - / [T::OpLessThanOrEq] - / [T::OpGreaterThanOrEq] - rule compare_expr() = - add_level_expr() (compare_op() add_level_expr())? - - rule bool_and_expr() = - compare_expr() ([T::OpAnd] compare_expr())* - - rule bool_or_expr() = - bool_and_expr() ([T::OpOr] bool_and_expr())* - - - rule pizza_expr() = - bool_or_expr() pizza_end()? - - rule pizza_end() = - [T::SameIndent]? [T::OpPizza] [T::SameIndent]? bool_or_expr() pizza_end()* - / [T::SameIndent]? [T::OpPizza] [T::OpenIndent] bool_or_expr() pizza_end()* close_or_end() - / [T::OpenIndent] [T::OpPizza] [T::SameIndent]? bool_or_expr() pizza_end()* close_or_end() - / [T::OpenIndent] [T::OpPizza] [T::OpenIndent] bool_or_expr() pizza_end()* close_double_or_end() - - rule close_or_end() = - [T::CloseIndent] - / end_of_file() - - rule close_double_or_end() = - [T::CloseIndent] [T::CloseIndent] - / [T::CloseIndent] end_of_file() - / end_of_file() - - //TODO support right assoicative caret(^), for example: 2^2 - - pub rule defs() = - def() ([T::SameIndent]? def())* [T::SameIndent]? full_expr() - - pub rule def() = - annotated_body() - / annotation() - / body() - / alias() - / expect() - - pub rule module_defs() = - ([T::SameIndent]? def())+ - - rule annotation() = - annotation_pre_colon() [T::Colon] type_annotation() - - rule annotation_pre_colon() = - apply() - / tag() - / ident() - - rule body() = - ident() [T::OpAssignment] [T::OpenIndent] full_expr() ([T::SameIndent]? full_expr())* ([T::CloseIndent] / end_of_file()) - / ident() [T::OpAssignment] full_expr() end_of_file()? - - rule annotated_body() = - annotation() [T::SameIndent] body() - - rule alias() = - apply_type() [T::Colon] type_annotation() - - pub rule when() = - [T::KeywordWhen] expr() [T::KeywordIs] when_branches() - - rule when_branches() = - [T::OpenIndent] when_branch() ([T::SameIndent]? when_branch())* close_or_end() - / when_branch()+ - - pub rule when_branch() = - when_match_pattern() ([T::Pipe] full_expr())* ([T::KeywordIf] full_expr())? [T::Arrow] when_branch_body() - - rule when_branch_body() = - [T::OpenIndent] full_expr() close_or_end() - / full_expr() - - rule var() = - [T::LowercaseIdent] - / module_var() - - rule module_var() = - module_name() [T::Dot] [T::LowercaseIdent] - - pub rule apply() = - apply_start_pattern() apply_args() - - pub rule apply_args() = - [T::OpenIndent] apply_arg_line_pattern() single_line_apply_args()? ([T::CloseIndent]/indented_end()) - / apply_arg_pattern()+ - - rule single_line_apply_args() = - [T::SameIndent] apply_arg_line_pattern() ( (single_line_apply_args()*) / indented_end() ) - / ([T::OpenIndent] apply_arg_line_pattern() single_line_apply_args()* ([T::CloseIndent] / indented_end())) - - rule apply_expr() = - var() - / tag() - - rule end() = - [T::CloseIndent] - / &[T::SameIndent] // & to not consume the SameIndent - / end_of_file() - - rule indented_end() = - ([T::OpenIndent] / [T::CloseIndent] / [T::SameIndent])* end_of_file() - - // for optionalindents - // underscore rules do not require parentheses - rule __() = - ( - [T::OpenIndent] - / [T::CloseIndent] - / [T::SameIndent] - )? - - rule end_of_file() = - ![_] - - } - } - - #[test] - fn test_basic_expr() { - assert_eq!(tokenparser::expr(&[T::OpenSquare, T::CloseSquare]), Ok(())); - assert_eq!(tokenparser::expr(&[T::OpenCurly, T::CloseCurly]), Ok(())); - - assert_eq!( - tokenparser::expr(&[T::OpenParen, T::OpenSquare, T::CloseSquare, T::CloseParen]), - Ok(()) - ); - - assert_eq!(tokenparser::expr(&[T::Number]), Ok(())); - assert_eq!(tokenparser::expr(&[T::String]), Ok(())); - - assert_eq!( - tokenparser::expr(&[ - T::KeywordIf, - T::Number, - T::KeywordThen, - T::Number, - T::KeywordElse, - T::Number - ]), - Ok(()) - ); - - assert_eq!(tokenparser::expr(&[T::KeywordExpect, T::Number]), Ok(())); - } - - #[test] - fn test_app_header_1() { - let tokens = tokenize(r#"app "test-app" packages {} imports [] provides [] to blah"#); - - assert_eq!(tokenparser::header(&tokens), Ok(())); - } - - #[test] - fn test_app_header_2() { - let tokens = tokenize( - r#" - app "test-app" - packages { pf: "platform/main.roc" } - imports [] - provides [ main ] to pf - "#, - ); - - assert_eq!(tokenparser::header(&tokens), Ok(())); - } - - #[test] - fn test_interface_header() { - let tokens = tokenize( - r#" - interface Foo.Bar.Baz exposes [] imports []"#, - ); - - assert_eq!(tokenparser::header(&tokens), Ok(())); - } - - #[test] - fn test_interface_header_2() { - let tokens = tokenize( - r#" - - interface Base64.Encode - exposes [ toBytes ] - imports [ Bytes.Encode.{ Encoder } ]"#, - ); - - assert_eq!(tokenparser::header(&tokens), Ok(())); - } - - #[test] - fn test_platform_header_1() { - let tokens = tokenize( - r#"platform "rtfeldman/blah" requires {} { main : {} } exposes [] packages {} imports [] provides [] effects fx.Blah {}"#, - ); - - assert_eq!(tokenparser::header(&tokens), Ok(())); - } - - #[test] - fn test_platform_header_2() { - let tokens = tokenize( - r#"platform "examples/cli" - requires {}{ main : Task {} [] } # TODO FIXME - exposes [] - packages {} - imports [ Task.{ Task } ] - provides [ mainForHost ] - effects fx.Effect - { - getLine : Effect Str, - putLine : Str -> Effect {}, - twoArguments : Int, Int -> Effect {} - }"#, - ); - - assert_eq!(tokenparser::header(&tokens), Ok(())); - } - - #[test] - fn test_annotated_def() { - let tokens = tokenize( - r#"test1 : Bool -test1 = - example1 == [ 2, 4 ]"#, - ); - - assert_eq!(tokenparser::def(&tokens), Ok(())); - } - - #[test] - fn test_record_def_1() { - let tokens = tokenize(r#"x = { content: 4 }"#); - - assert_eq!(tokenparser::def(&tokens), Ok(())); - } - - #[test] - fn test_record_def_2() { - let tokens = tokenize( - r#"x = - { content: 4 }"#, - ); - - assert_eq!(tokenparser::def(&tokens), Ok(())); - } - - #[test] - fn test_record_def_3() { - let tokens = tokenize( - r#"x = - { - a: 4, - b: 5 - }"#, - ); - - assert_eq!(tokenparser::def(&tokens), Ok(())); - } - - #[test] - fn test_record_def_4() { - let tokens = tokenize( - r#"x = - { - a: 4, - b: 5, - c: 6, - }"#, - ); - - assert_eq!(tokenparser::def(&tokens), Ok(())); - } - - #[test] - fn test_record_def_5() { - let tokens = tokenize( - r#"x = - { - a: 4, - }"#, - ); - - assert_eq!(tokenparser::def(&tokens), Ok(())); - } - - #[test] - fn test_record_def_6() { - let tokens = tokenize( - r#"a = { - b: c, - d: { - e: f, - }, - }"#, - ); - - assert_eq!(tokenparser::def(&tokens), Ok(())); - } - - #[test] - fn test_typed_ident() { - // main : Task {} [] - assert_eq!( - tokenparser::typed_ident(&[ - T::LowercaseIdent, - T::Colon, - T::UppercaseIdent, - T::OpenCurly, - T::CloseCurly, - T::OpenSquare, - T::CloseSquare - ]), - Ok(()) - ); - } - - #[test] - fn test_order_of_ops() { - // True || False && True || False - assert_eq!( - tokenparser::full_expr(&[ - T::UppercaseIdent, - T::OpOr, - T::UppercaseIdent, - T::OpAnd, - T::UppercaseIdent, - T::OpOr, - T::UppercaseIdent - ]), - Ok(()) - ); - } - - fn file_to_string(file_path: &str) -> String { - // it's ok to panic in a test - std::fs::read_to_string(file_path).unwrap() - } - - fn example_path(sub_path: &str) -> String { - let examples_dir = "../../examples/".to_string(); - - let file_path = examples_dir + sub_path; - - file_to_string(&file_path) - } - - fn cli_testing_path(sub_path: &str) -> String { - let examples_dir = "../cli_testing_examples/".to_string(); - - let file_path = examples_dir + sub_path; - - file_to_string(&file_path) - } - - #[test] - fn test_hello() { - let tokens = tokenize(&example_path("helloWorld.roc")); - - assert_eq!(tokenparser::module(&tokens), Ok(())); - } - - #[test] - fn test_fibo() { - let tokens = tokenize(&cli_testing_path("algorithms/fibonacci.roc")); - - assert_eq!(tokenparser::module(&tokens), Ok(())); - } - - #[test] - fn test_annotation() { - let tokens = tokenize(r#"ConsList a : [ Cons a (ConsList a), Nil ]"#); - - assert_eq!(tokenparser::def(&tokens), Ok(())); - } - - #[test] - fn test_apply_type() { - let tokens = tokenize(r#"Cons a (ConsList a)"#); - - assert_eq!(tokenparser::apply_type(&tokens), Ok(())); - } - - #[test] - fn test_apply_expect_fail_1() { - assert!(tokenparser::apply(&[ - T::LowercaseIdent, - T::LowercaseIdent, - T::CloseIndent, - T::UppercaseIdent - ]) - .is_err()); - } - - #[test] - fn test_apply_expect_fail_2() { - let tokens = tokenize( - r#"eval a - b"#, - ); - - assert!(tokenparser::apply(&tokens).is_err()); - } - - #[test] - fn test_when_1() { - let tokens = tokenize( - r#"when list is - Cons _ rest -> - 1 + len rest - - Nil -> - 0"#, - ); - - assert_eq!(tokenparser::when(&tokens), Ok(())); - } - - #[test] - fn test_when_2() { - let tokens = tokenize( - r#"when list is - Nil -> - Cons a - - Nil -> - Nil"#, - ); - - assert_eq!(tokenparser::when(&tokens), Ok(())); - } - - #[test] - fn test_when_3() { - let tokens = tokenize( - r#"when list is - Nil -> Cons a - Nil -> Nil"#, - ); - assert_eq!(tokenparser::when(&tokens), Ok(())); - } - - #[test] - fn test_when_in_defs() { - let tokens = tokenize( - r#"fromBytes = \bytes -> - when bytes is - Ok v -> v - "#, - ); - dbg!(&tokens); - assert_eq!(tokenparser::module_defs(&tokens), Ok(())); - } - - #[test] - fn test_base64() { - let tokens = tokenize(&cli_testing_path("benchmarks/Base64.roc")); - - assert_eq!(tokenparser::module(&tokens), Ok(())); - } - - #[test] - fn test_base64_test() { - let tokens = tokenize(&cli_testing_path("benchmarks/TestBase64.roc")); - - assert_eq!(tokenparser::module(&tokens), Ok(())); - } - - #[test] - fn test_when_branch() { - let tokens = tokenize(r#"Ok path -> path"#); - - assert_eq!(tokenparser::when_branch(&tokens), Ok(())); - } - - #[test] - fn test_def_in_def() { - let tokens = tokenize( - r#"example = - cost = 1 - - cost"#, - ); - assert_eq!(tokenparser::def(&tokens), Ok(())); - } - - #[test] - fn test_backpass_in_def() { - let tokens = tokenize( - r#"main = - lastName <- 4 - Stdout.line "Hi!""#, - ); - - assert_eq!(tokenparser::def(&tokens), Ok(())); - } - - #[test] - fn test_astar_test() { - let tokens = tokenize(&cli_testing_path("benchmarks/TestAStar.roc")); - - assert_eq!(tokenparser::module(&tokens), Ok(())); - } - - #[test] - fn test_cli_echo() { - let tokens = tokenize(&example_path("cli/echo.roc")); - - assert_eq!(tokenparser::module(&tokens), Ok(())); - } - - #[test] - fn test_pizza_1() { - let tokens = tokenize( - r#"closure = \_ -> - Task.succeed {} - |> Task.map (\_ -> x)"#, - ); - - assert_eq!(tokenparser::def(&tokens), Ok(())); - } - - #[test] - fn test_pizza_one_line() { - let tokens = tokenize(r#"5 |> fun"#); - - assert_eq!(tokenparser::op_expr(&tokens), Ok(())); - } - - #[test] - fn test_pizza_same_indent_1() { - let tokens = tokenize( - r#"5 - |> fun"#, - ); - - assert_eq!(tokenparser::op_expr(&tokens), Ok(())); - } - - #[test] - fn test_pizza_same_indent_2() { - let tokens = tokenize( - r#"5 - |> - fun"#, - ); - - assert_eq!(tokenparser::op_expr(&tokens), Ok(())); - } - - #[test] - fn test_pizza_indented_1_a() { - let tokens = tokenize( - r#"5 - |> fun"#, - ); - - assert_eq!(tokenparser::op_expr(&tokens), Ok(())); - } - - #[test] - fn test_pizza_indented_1_b() { - let tokens = tokenize( - r#"5 - |> fun - "#, - ); - - assert_eq!(tokenparser::op_expr(&tokens), Ok(())); - } - - #[test] - fn test_pizza_indented_2_a() { - let tokens = tokenize( - r#"5 - |> - fun"#, - ); - - assert_eq!(tokenparser::op_expr(&tokens), Ok(())); - } - - #[test] - fn test_pizza_indented_2_b() { - let tokens = tokenize( - r#"5 - |> - fun - "#, - ); - - assert_eq!(tokenparser::op_expr(&tokens), Ok(())); - } - - #[test] - fn test_pizza_indented_2_c() { - let tokens = tokenize( - r#"5 - |> - fun - - "#, - ); - - assert_eq!(tokenparser::op_expr(&tokens), Ok(())); - } - - #[test] - fn test_pizza_mixed_indent_1_a() { - let tokens = tokenize( - r#"5 - |> - fun"#, - ); - - assert_eq!(tokenparser::op_expr(&tokens), Ok(())); - } - - #[test] - fn test_pizza_mixed_indent_1_b() { - let tokens = tokenize( - r#"5 - |> - fun - "#, - ); - - assert_eq!(tokenparser::op_expr(&tokens), Ok(())); - } - - #[test] - fn test_pizza_mixed_indent_2_a() { - let tokens = tokenize( - r#"5 - |> - fun"#, - ); - - assert_eq!(tokenparser::op_expr(&tokens), Ok(())); - } - - #[test] - fn test_pizza_mixed_indent_2_b() { - let tokens = tokenize( - r#"5 - |> - fun"#, - ); - - assert_eq!(tokenparser::op_expr(&tokens), Ok(())); - } - - #[test] - fn test_longer_pizza() { - let tokens = tokenize(r#"5 |> fun a |> fun b"#); - - assert_eq!(tokenparser::op_expr(&tokens), Ok(())); - } - - #[test] - fn test_deeper_pizza() { - let tokens = tokenize( - r#"5 - |> fun a - |> fun b"#, - ); - - assert_eq!(tokenparser::op_expr(&tokens), Ok(())); - } - - #[test] - fn test_deeper_indented_pizza_a() { - let tokens = tokenize( - r#"5 - |> fun a - |> fun b"#, - ); - - assert_eq!(tokenparser::op_expr(&tokens), Ok(())); - } - - #[test] - fn test_deeper_indented_pizza_b() { - let tokens = tokenize( - r#"5 - |> fun a - |> fun b - "#, - ); - - assert_eq!(tokenparser::op_expr(&tokens), Ok(())); - } - - #[test] - fn test_deep_mixed_indent_pizza_a() { - let tokens = tokenize( - r#"5 - |> fun a |> fun b - |> fun c d - |> fun "test" - |> List.map Str.toI64 - |> g (1 + 1)"#, - ); - - assert_eq!(tokenparser::op_expr(&tokens), Ok(())); - } - - #[test] - fn test_deep_mixed_indent_pizza_b() { - let tokens = tokenize( - r#"5 - |> fun a |> fun b - |> fun c d - |> fun "test" - |> List.map Str.toI64 - |> g (1 + 1) - "#, - ); - - assert_eq!(tokenparser::op_expr(&tokens), Ok(())); - } - - #[test] - fn test_bool_or() { - let tokens = tokenize(r#"a || True || b || False"#); - - assert_eq!(tokenparser::op_expr(&tokens), Ok(())); - } - - #[test] - fn test_closure_file() { - let tokens = tokenize(&cli_testing_path("benchmarks/Closure.roc")); - - assert_eq!(tokenparser::module(&tokens), Ok(())); - } - - #[test] - fn test_def_with_indents() { - let tokens = tokenize( - r#"main = - Task.after - Task.getInt - \n -> - queens n"#, - ); - - assert_eq!(tokenparser::def(&tokens), Ok(())); - } - - #[test] - fn test_nqueens() { - let tokens = tokenize(&cli_testing_path("benchmarks/NQueens.roc")); - - assert_eq!(tokenparser::module(&tokens), Ok(())); - } - - #[test] - fn test_quicksort_help() { - let tokens = tokenize( - r#"quicksortHelp = \list, low, high -> - if low < high then - when partition low is - Pair -> - partitioned - |> quicksortHelp low - else - list"#, - ); - - assert_eq!(tokenparser::def(&tokens), Ok(())); - } - - #[test] - fn test_quicksort() { - let tokens = tokenize(&cli_testing_path("benchmarks/Quicksort.roc")); - - assert_eq!(tokenparser::module(&tokens), Ok(())); - } - - #[test] - fn test_indented_closure_apply() { - let tokens = tokenize( - r#" - effect - \result -> result"#, - ); - - assert_eq!(tokenparser::apply_args(&tokens), Ok(())); - } - - #[test] - fn test_parens_closure_indent() { - let tokens = tokenize( - r#"(\i -> - i)"#, - ); - assert_eq!(tokenparser::parens_around(&tokens), Ok(())); - } - - #[test] - fn test_task() { - let tokens = tokenize(&cli_testing_path("benchmarks/platform/Task.roc")); - - assert_eq!(tokenparser::module(&tokens), Ok(())); - } - - #[test] - fn test_pizza_line() { - let tokens = tokenize( - r#"unoptimized - |> Num.toStr - |> Task.putLine"#, - ); - - assert_eq!(tokenparser::full_expr(&tokens), Ok(())); - } - - #[test] - fn test_defs_w_apply() { - let tokens = tokenize( - r#"unoptimized = eval e - - 42"#, - ); - - assert_eq!(tokenparser::defs(&tokens), Ok(())); - } - - #[test] - fn test_indented_apply_defs() { - let tokens = tokenize( - r#"main = - after - \n -> - e = 5 - - 4 - - Expr : I64"#, - ); - - assert_eq!(tokenparser::module_defs(&tokens), Ok(())); - } - - #[test] - fn test_cfold() { - let tokens = tokenize(&cli_testing_path("benchmarks/CFold.roc")); - - assert_eq!(tokenparser::module(&tokens), Ok(())); - } - - #[test] - fn test_apply_with_comment() { - let tokens = tokenize( - r#"main = - Task.after - \n -> - e = mkExpr n 1 # comment - unoptimized = eval e - optimized = eval (constFolding (reassoc e)) - - optimized"#, - ); - - assert_eq!(tokenparser::def(&tokens), Ok(())); - } - - #[test] - fn test_multi_defs() { - let tokens = tokenize( - r#"main = - tree : I64 - tree = 0 - - tree"#, - ); - - assert_eq!(tokenparser::def(&tokens), Ok(())); - } - - // TODO fix slow execution; likely a problem with apply - #[test] - fn test_perf_issue() { - let tokens = tokenize( - r#"main = - tree = insert 0 {} Empty - - tree - |> Task.putLine - -nodeInParens : RedBlackTree k v, (k -> Str), (v -> Str) -> Str -nodeInParens = \tree, showKey, showValue -> - when tree is - _ -> - "(\(inner))" - -RedBlackTree k v : [ Node NodeColor k v (RedBlackTree k v) (RedBlackTree k v), Empty ] - -Key k : Num k - -balance = \color -> - when right is - Node Red -> - when left is - _ -> - Node color rK rV (Node Red key value left) - - _ -> - 5"#, - ); - - assert_eq!(tokenparser::module_defs(&tokens), Ok(())); - } - - #[test] - fn test_rbtree_insert() { - let tokens = tokenize(&cli_testing_path("benchmarks/RBTreeInsert.roc")); - - assert_eq!(tokenparser::module(&tokens), Ok(())); - } - - #[test] - fn test_closure_1() { - let tokens = tokenize( - r#"\key -> - when dict is - Empty -> - 4 - - Node -> - 5"#, - ); - - assert_eq!(tokenparser::closure(&tokens), Ok(())); - } - - #[test] - fn test_closure_2() { - let tokens = tokenize( - r#"\key -> - when dict is - Empty -> - Node Red - - Node nColor -> - when key is - GT -> - balance nColor"#, - ); - - assert_eq!(tokenparser::closure(&tokens), Ok(())); - } - - #[test] - fn test_nested_apply() { - let tokens = tokenize( - r#"after = \effect -> - Effect.after - transform a - - map : Str"#, - ); - - assert_eq!(tokenparser::module_defs(&tokens), Ok(())); - } - - #[test] - fn test_deep_indented_defs() { - let tokens = tokenize( - r#"after = \effect -> - after - \result -> - transform a - - map : Str"#, - ); - - assert_eq!(tokenparser::module_defs(&tokens), Ok(())); - } - - #[test] - fn test_rbtree_ck() { - let tokens = tokenize(&cli_testing_path("benchmarks/RBTreeCk.roc")); - - assert_eq!(tokenparser::module(&tokens), Ok(())); - } - - #[test] - fn test_record_type_def() { - let tokens = tokenize( - r#"Model position : - { - evaluated : Set, - }"#, - ); - - assert_eq!(tokenparser::def(&tokens), Ok(())); - } - - #[test] - fn test_apply_with_acces() { - let tokens = tokenize(r#"Dict.get model.costs"#); - - assert_eq!(tokenparser::apply(&tokens), Ok(())); - } - - #[test] - fn test_space_dot() { - let tokens = tokenize(r#"Result.map .position"#); - - assert_eq!(tokenparser::op_expr(&tokens), Ok(())); - } - - #[test] - #[ignore = "Does not yet know about ability syntax"] - fn test_astar() { - let tokens = tokenize(&cli_testing_path("benchmarks/AStar.roc")); - - assert_eq!(tokenparser::module(&tokens), Ok(())); - } - - #[test] - fn test_backpass_in_def_2() { - let tokens = tokenize( - r#"with = \path -> - handle <- withOpen - - 4"#, - ); - - assert_eq!(tokenparser::def(&tokens), Ok(())); - } - - #[test] - fn test_false_interpreter_context() { - let tokens = tokenize(&example_path("cli/false-interpreter/Context.roc")); - - assert_eq!(tokenparser::module(&tokens), Ok(())); - } - - #[test] - fn test_when_match_apply() { - let tokens = tokenize(r#"Pair (Val 0) f"#); - - assert_eq!(tokenparser::when_match_pattern(&tokens), Ok(())); - } - - #[test] - fn test_when_match_apply_2() { - let tokens = tokenize(r#"Pair (Val 0) f"#); - - assert_eq!(tokenparser::when_match_pattern(&tokens), Ok(())); - } - - #[test] - fn test_apply_with_closure() { - let tokens = tokenize(r#"Task.after \w -> nestHelp s"#); - - assert_eq!(tokenparser::apply(&tokens), Ok(())); - } - - #[test] - fn test_deriv() { - let tokens = tokenize(&cli_testing_path("benchmarks/Deriv.roc")); - - assert_eq!(tokenparser::module(&tokens), Ok(())); - } -} diff --git a/crates/linker/Cargo.toml b/crates/linker/Cargo.toml index 8eeb8d2b77..1155b0ddcb 100644 --- a/crates/linker/Cargo.toml +++ b/crates/linker/Cargo.toml @@ -1,32 +1,33 @@ [package] name = "roc_linker" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -repository = "https://github.com/roc-lang/roc" -edition = "2021" description = "A surgical linker for Roc" +authors.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +version.workspace = true + [lib] name = "roc_linker" path = "src/lib.rs" [dependencies] -roc_mono = { path = "../compiler/mono" } -roc_build = { path = "../compiler/build" } roc_collections = { path = "../compiler/collections" } roc_error_macros = { path = "../error_macros" } roc_load = { path = "../compiler/load" } +roc_mono = { path = "../compiler/mono" } roc_packaging = { path = "../packaging" } roc_reporting = { path = "../reporting" } +roc_target = { path = "../compiler/roc_target" } +bincode.workspace = true bumpalo.workspace = true iced-x86.workspace = true +mach_object.workspace = true memmap2.workspace = true object.workspace = true -mach_object.workspace = true serde.workspace = true -bincode.workspace = true target-lexicon.workspace = true tempfile.workspace = true diff --git a/crates/linker/src/elf.rs b/crates/linker/src/elf.rs index bb9bfe1475..8ca990e4ca 100644 --- a/crates/linker/src/elf.rs +++ b/crates/linker/src/elf.rs @@ -1637,8 +1637,8 @@ fn surgery_elf_help( mod tests { use super::*; + use crate::preprocessed_host_filename; use indoc::indoc; - use roc_build::link::preprocessed_host_filename; use target_lexicon::Triple; const ELF64_DYNHOST: &[u8] = include_bytes!("../dynhost_benchmarks_elf64") as &[_]; diff --git a/crates/linker/src/lib.rs b/crates/linker/src/lib.rs index a739993a22..6a53b2b4bb 100644 --- a/crates/linker/src/lib.rs +++ b/crates/linker/src/lib.rs @@ -5,12 +5,11 @@ //! practical to use a regular linker. use memmap2::{Mmap, MmapMut}; use object::Object; -use roc_build::link::{get_target_triple_str, rebuild_host, LinkType}; use roc_error_macros::internal_error; use roc_load::{EntryPoint, ExecutionMode, LoadConfig, Threading}; -use roc_mono::ir::OptLevel; use roc_packaging::cache::RocCacheDir; use roc_reporting::report::{RenderTarget, DEFAULT_PALETTE}; +use roc_target::get_target_triple_str; use std::cmp::Ordering; use std::mem; use std::path::{Path, PathBuf}; @@ -23,6 +22,14 @@ mod pe; mod generate_dylib; mod metadata; +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum LinkType { + // These numbers correspond to the --lib and --no-link flags + Executable = 0, + Dylib = 1, + None = 2, +} + pub fn supported(link_type: LinkType, target: &Triple) -> bool { if let LinkType::Executable = link_type { match target { @@ -54,43 +61,10 @@ pub fn supported(link_type: LinkType, target: &Triple) -> bool { } } -pub fn build_and_preprocess_host( - opt_level: OptLevel, - target: &Triple, - platform_main_roc: &Path, - preprocessed_host_path: &Path, - exposed_to_host: Vec, - exported_closure_types: Vec, -) { - let stub_lib = if let target_lexicon::OperatingSystem::Windows = target.operating_system { - platform_main_roc.with_file_name("libapp.dll") - } else { - platform_main_roc.with_file_name("libapp.so") - }; +pub const PRECOMPILED_HOST_EXT: &str = "rh1"; // Short for "roc host version 1" (so we can change format in the future) - let dynhost = if let target_lexicon::OperatingSystem::Windows = target.operating_system { - platform_main_roc.with_file_name("dynhost.exe") - } else { - platform_main_roc.with_file_name("dynhost") - }; - - let stub_dll_symbols = make_stub_dll_symbols(exposed_to_host, exported_closure_types); - generate_dynamic_lib(target, &stub_dll_symbols, &stub_lib); - rebuild_host(opt_level, target, platform_main_roc, Some(&stub_lib)); - - let metadata = platform_main_roc.with_file_name(metadata_file_name(target)); - // let prehost = host_input_path.with_file_name(preprocessed_host_filename(target).unwrap()); - - preprocess( - target, - &dynhost, - &metadata, - preprocessed_host_path, - &stub_lib, - &stub_dll_symbols, - false, - false, - ) +pub fn preprocessed_host_filename(target: &Triple) -> Option { + roc_target::get_target_triple_str(target).map(|x| format!("{}.{}", x, PRECOMPILED_HOST_EXT)) } fn metadata_file_name(target: &Triple) -> String { @@ -170,6 +144,24 @@ pub fn generate_stub_lib( Ok(0) } +pub fn generate_stub_lib_from_loaded( + target: &Triple, + platform_main_roc: &Path, + exposed_to_host: Vec, + exported_closure_types: Vec, +) -> (PathBuf, Vec) { + let stub_lib = if let target_lexicon::OperatingSystem::Windows = target.operating_system { + platform_main_roc.with_file_name("libapp.dll") + } else { + platform_main_roc.with_file_name("libapp.so") + }; + + let stub_dll_symbols = make_stub_dll_symbols(exposed_to_host, exported_closure_types); + generate_dynamic_lib(target, &stub_dll_symbols, &stub_lib); + + (stub_lib, stub_dll_symbols) +} + fn make_stub_dll_symbols( exposed_to_host: Vec, exported_closure_types: Vec, @@ -332,6 +324,32 @@ fn stub_lib_is_up_to_date(target: &Triple, stub_lib_path: &Path, custom_names: & it1.eq(it2) } +pub fn preprocess_host( + target: &Triple, + platform_main_roc: &Path, + preprocessed_path: &Path, + shared_lib: &Path, + stub_dll_symbols: &[String], +) { + let metadata_path = platform_main_roc.with_file_name(metadata_file_name(target)); + let host_exe_path = if let target_lexicon::OperatingSystem::Windows = target.operating_system { + platform_main_roc.with_file_name("dynhost.exe") + } else { + platform_main_roc.with_file_name("dynhost") + }; + + preprocess( + target, + &host_exe_path, + &metadata_path, + preprocessed_path, + shared_lib, + stub_dll_symbols, + false, + false, + ) +} + /// Constructs a `metadata::Metadata` from a host executable binary, and writes it to disk #[allow(clippy::too_many_arguments)] fn preprocess( diff --git a/crates/linker/src/pe.rs b/crates/linker/src/pe.rs index 3c42d3b26e..1022ad3329 100644 --- a/crates/linker/src/pe.rs +++ b/crates/linker/src/pe.rs @@ -1357,8 +1357,8 @@ mod test { use object::read::pe::PeFile64; use object::{pe, LittleEndian as LE, Object}; + use crate::preprocessed_host_filename; use indoc::indoc; - use roc_build::link::preprocessed_host_filename; use target_lexicon::Triple; use super::*; diff --git a/crates/packaging/Cargo.toml b/crates/packaging/Cargo.toml index c37ff250a8..f0a894dd9a 100644 --- a/crates/packaging/Cargo.toml +++ b/crates/packaging/Cargo.toml @@ -1,33 +1,29 @@ [package] name = "roc_packaging" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -repository = "https://github.com/roc-lang/roc" -edition = "2021" description = "Functionality for packaging Roc source code - e.g. for distribution over the network" +authors.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +version.workspace = true + [dependencies] -roc_parse = { path = "../compiler/parse" } roc_error_macros = { path = "../error_macros" } +roc_parse = { path = "../compiler/parse" } -tar = "0.4.38" # used for `roc build --tar` -brotli = "3.3.4" # used for decompressing tarballs over HTTPS, if the server supports brotli -flate2 = "1.0.24" -walkdir = "2.3.2" -blake3 = "1.3.1" -base64-url = "1.4.13" - +base64-url.workspace = true +blake3.workspace = true +brotli.workspace = true # used for decompressing tarballs over HTTPS, if the server supports brotli bumpalo.workspace = true +flate2.workspace = true fs_extra.workspace = true +tar.workspace = true # used for `roc build --tar` tempfile.workspace = true +walkdir.workspace = true [target.'cfg(not(target_family = "wasm"))'.dependencies] -# default-features=false removes libopenssl as a dependency on Linux, which might not be available! -reqwest = { version = "0.11.13", default-features = false, features = [ "blocking", "rustls-tls" ] } +reqwest.workspace = true [dev-dependencies] -pretty_assertions = "1.3.0" -indoc = "1.0.7" - -tempfile.workspace = true \ No newline at end of file +tempfile.workspace = true diff --git a/crates/repl_cli/Cargo.toml b/crates/repl_cli/Cargo.toml index 518953831a..34db9dc223 100644 --- a/crates/repl_cli/Cargo.toml +++ b/crates/repl_cli/Cargo.toml @@ -1,11 +1,11 @@ [package] -edition = "2021" name = "roc_repl_cli" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" description = "Command Line Interface(CLI) functionality for the Read-Evaluate-Print-Loop (REPL)." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true [features] # pipe target to roc_build @@ -16,30 +16,30 @@ target-x86 = ["roc_build/target-x86"] target-x86_64 = ["roc_build/target-x86_64"] [dependencies] -inkwell.workspace = true +roc_build = { path = "../compiler/build" } +roc_builtins = { path = "../compiler/builtins" } +roc_collections = { path = "../compiler/collections" } +roc_gen_llvm = { path = "../compiler/gen_llvm" } +roc_load = { path = "../compiler/load" } +roc_module = { path = "../compiler/module" } +roc_mono = { path = "../compiler/mono" } +roc_parse = { path = "../compiler/parse" } +roc_region = { path = "../compiler/region" } +roc_repl_eval = { path = "../repl_eval" } +roc_reporting = { path = "../reporting" } +roc_std = { path = "../roc_std" } +roc_target = { path = "../compiler/roc_target" } +roc_types = { path = "../compiler/types" } + bumpalo.workspace = true const_format.workspace = true +inkwell.workspace = true libloading.workspace = true -rustyline.workspace = true rustyline-derive.workspace = true +rustyline.workspace = true target-lexicon.workspace = true unicode-segmentation.workspace = true -roc_build = {path = "../compiler/build"} -roc_builtins = {path = "../compiler/builtins"} -roc_collections = {path = "../compiler/collections"} -roc_gen_llvm = {path = "../compiler/gen_llvm"} -roc_load = {path = "../compiler/load"} -roc_mono = {path = "../compiler/mono"} -roc_parse = {path = "../compiler/parse"} -roc_repl_eval = {path = "../repl_eval"} -roc_reporting = {path = "../reporting"} -roc_std = {path = "../roc_std"} -roc_target = {path = "../compiler/roc_target"} -roc_types = {path = "../compiler/types"} -roc_region = { path = "../compiler/region" } -roc_module = { path = "../compiler/module" } - [lib] name = "roc_repl_cli" path = "src/lib.rs" diff --git a/crates/repl_eval/Cargo.toml b/crates/repl_eval/Cargo.toml index d1ffdf93a1..eb14b97b7b 100644 --- a/crates/repl_eval/Cargo.toml +++ b/crates/repl_eval/Cargo.toml @@ -1,28 +1,27 @@ [package] -edition = "2021" name = "roc_repl_eval" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" description = "Provides the functionality for the REPL to evaluate Roc expressions." -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true [dependencies] -bumpalo.workspace = true +roc_builtins = { path = "../compiler/builtins" } +roc_can = { path = "../compiler/can" } +roc_collections = { path = "../compiler/collections" } +roc_fmt = { path = "../compiler/fmt" } +roc_load = { path = "../compiler/load" } +roc_module = { path = "../compiler/module" } +roc_mono = { path = "../compiler/mono" } +roc_packaging = { path = "../packaging" } +roc_parse = { path = "../compiler/parse" } +roc_problem = { path = "../compiler/problem" } +roc_region = { path = "../compiler/region" } +roc_reporting = { path = "../reporting" } +roc_std = { path = "../roc_std" } +roc_target = { path = "../compiler/roc_target" } +roc_types = { path = "../compiler/types" } -roc_builtins = {path = "../compiler/builtins"} -roc_can = {path = "../compiler/can"} -roc_collections = {path = "../compiler/collections"} -roc_fmt = {path = "../compiler/fmt"} -roc_load = {path = "../compiler/load"} -roc_module = {path = "../compiler/module"} -roc_mono = {path = "../compiler/mono"} -roc_parse = {path = "../compiler/parse"} -roc_problem = {path = "../compiler/problem"} -roc_region = {path = "../compiler/region"} -roc_packaging = {path = "../packaging"} -roc_reporting = {path = "../reporting"} -roc_std = {path = "../roc_std"} -roc_target = {path = "../compiler/roc_target"} -roc_types = {path = "../compiler/types"} +bumpalo.workspace = true diff --git a/crates/repl_expect/Cargo.toml b/crates/repl_expect/Cargo.toml index bae087b61c..305077f466 100644 --- a/crates/repl_expect/Cargo.toml +++ b/crates/repl_expect/Cargo.toml @@ -1,45 +1,45 @@ [package] name = "roc_repl_expect" -version = "0.0.1" -edition = "2021" -authors = ["The Roc Contributors"] -license = "UPL-1.0" description = "Supports evaluating expect and printing contextual information when they fail." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] +roc_build = { path = "../compiler/build" } +roc_builtins = { path = "../compiler/builtins" } +roc_can = { path = "../compiler/can" } +roc_collections = { path = "../compiler/collections" } +roc_error_macros = { path = "../error_macros" } +roc_gen_llvm = { path = "../compiler/gen_llvm" } +roc_load = { path = "../compiler/load" } +roc_module = { path = "../compiler/module" } +roc_mono = { path = "../compiler/mono" } +roc_packaging = { path = "../packaging" } +roc_parse = { path = "../compiler/parse" } +roc_region = { path = "../compiler/region" } +roc_repl_eval = { path = "../repl_eval" } +roc_reporting = { path = "../reporting" } +roc_std = { path = "../roc_std" } +roc_target = { path = "../compiler/roc_target" } +roc_types = { path = "../compiler/types" } + bumpalo.workspace = true -target-lexicon.workspace = true +inkwell.workspace = true +libc.workspace = true libloading.workspace = true signal-hook.workspace = true -libc.workspace = true -inkwell.workspace = true - -roc_builtins = {path = "../compiler/builtins"} -roc_can = {path = "../compiler/can"} -roc_collections = {path = "../compiler/collections"} -roc_load = {path = "../compiler/load"} -roc_mono = {path = "../compiler/mono"} -roc_parse = {path = "../compiler/parse"} -roc_module = {path = "../compiler/module"} -roc_repl_eval = {path = "../repl_eval"} -roc_packaging = {path = "../packaging"} -roc_reporting = {path = "../reporting"} -roc_std = {path = "../roc_std"} -roc_target = {path = "../compiler/roc_target"} -roc_types = {path = "../compiler/types"} -roc_gen_llvm = {path = "../compiler/gen_llvm"} -roc_region = { path = "../compiler/region" } -roc_build = { path = "../compiler/build" } -roc_error_macros = { path = "../error_macros" } +target-lexicon.workspace = true [dev-dependencies] -test_gen = { path = "../compiler/test_gen" } -roc_build = { path = "../compiler/build", features = ["target-aarch64", "target-x86_64"] } +roc_build = { path = "../compiler/build", features = ["target-aarch64", "target-x86_64"] } -tempfile.workspace = true indoc.workspace = true pretty_assertions.workspace = true strip-ansi-escapes.workspace = true +tempfile.workspace = true [lib] diff --git a/crates/repl_test/Cargo.toml b/crates/repl_test/Cargo.toml index 8b94ebbeb4..4858f695a9 100644 --- a/crates/repl_test/Cargo.toml +++ b/crates/repl_test/Cargo.toml @@ -1,37 +1,35 @@ [package] -edition = "2021" name = "repl_test" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" description = "Tests the roc REPL." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [build-dependencies] -roc_cli = {path = "../cli"} +roc_cli = { path = "../cli" } [dev-dependencies] -indoc = "1.0.7" -strip-ansi-escapes = "0.1.1" -bumpalo.workspace = true - roc_build = { path = "../compiler/build" } -roc_repl_cli = {path = "../repl_cli"} -roc_test_utils = {path = "../test_utils"} -roc_wasm_interp = {path = "../wasm_interp"} +roc_repl_cli = { path = "../repl_cli" } +roc_test_utils = { path = "../test_utils" } +roc_wasm_interp = { path = "../wasm_interp" } + +bumpalo.workspace = true +indoc.workspace = true +strip-ansi-escapes.workspace = true [features] default = ["target-aarch64", "target-x86_64", "target-wasm32"] -wasm = ["target-wasm32"] -target-arm = ["roc_build/target-arm", "roc_repl_cli/target-arm"] target-aarch64 = ["roc_build/target-aarch64", "roc_repl_cli/target-aarch64"] +target-arm = ["roc_build/target-arm", "roc_repl_cli/target-arm"] +target-wasm32 = ["roc_build/target-wasm32", "roc_repl_cli/target-wasm32"] target-x86 = ["roc_build/target-x86", "roc_repl_cli/target-x86"] target-x86_64 = ["roc_build/target-x86_64", "roc_repl_cli/target-x86_64"] -target-wasm32 = ["roc_build/target-wasm32", "roc_repl_cli/target-wasm32"] +wasm = ["target-wasm32"] -target-all = [ - "target-aarch64", - "target-arm", - "target-x86", - "target-x86_64", - "target-wasm32" -] +target-all = ["target-aarch64", "target-arm", "target-x86", "target-x86_64", "target-wasm32"] + +[package.metadata.cargo-udeps.ignore] +development = ["roc_wasm_interp"] \ No newline at end of file diff --git a/crates/repl_test/src/tests.rs b/crates/repl_test/src/tests.rs index 1fb4c4c4f4..df68e53c7b 100644 --- a/crates/repl_test/src/tests.rs +++ b/crates/repl_test/src/tests.rs @@ -990,7 +990,7 @@ fn issue_2343_complete_mono_with_shadowed_vars() { ^ Since these variables have the same name, it's easy to use the wrong - one on accident. Give one of them a new name. + one by accident. Give one of them a new name. "# ), ); diff --git a/crates/repl_test/src/wasm.rs b/crates/repl_test/src/wasm.rs index a11d3abbf1..80c664863a 100644 --- a/crates/repl_test/src/wasm.rs +++ b/crates/repl_test/src/wasm.rs @@ -4,7 +4,7 @@ use roc_wasm_interp::{ }; const COMPILER_BYTES: &[u8] = - include_bytes!("../../../target/wasm32-wasi/release/roc_repl_wasm.wasm"); + include_bytes!("../../../target/wasm32-wasi/release-with-lto/roc_repl_wasm.wasm"); struct CompilerDispatcher<'a> { arena: &'a Bump, diff --git a/crates/repl_test/test_wasm.sh b/crates/repl_test/test_wasm.sh index 1e772d367e..1e36648ac1 100755 --- a/crates/repl_test/test_wasm.sh +++ b/crates/repl_test/test_wasm.sh @@ -7,7 +7,9 @@ set -euxo pipefail # We need to clear RUSTFLAGS for this command, as CI sets normally some flags that are specific to CPU targets. # Tests target wasm32-wasi instead of wasm32-unknown-unknown, so that we can debug with println! and dbg! -RUSTFLAGS="" cargo build --locked --release --target wasm32-wasi -p roc_repl_wasm --no-default-features --features wasi_test +# This has to be built with lto for now. If we do not use lto, it will pull in system calls we don't yet support. +# TODO: Add system calls to our wasi interp so that this can just be built in release without lto. +RUSTFLAGS="" cargo build --locked --profile release-with-lto --target wasm32-wasi -p roc_repl_wasm --no-default-features --features wasi_test # Build & run the test code on *native* target, not WebAssembly cargo test --locked --release -p repl_test --features wasm diff --git a/crates/repl_wasm/Cargo.toml b/crates/repl_wasm/Cargo.toml index d977ff74f1..59e245f0f7 100644 --- a/crates/repl_wasm/Cargo.toml +++ b/crates/repl_wasm/Cargo.toml @@ -1,36 +1,39 @@ [package] -edition = "2021" name = "roc_repl_wasm" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" description = "Provides a build of the REPL for the Roc website using WebAssembly." +authors = ["The Roc Contributors"] +edition = "2021" +license = "UPL-1.0" +version = "0.0.1" + [lib] crate-type = ["cdylib"] [build-dependencies] -roc_builtins = {path = "../compiler/builtins"} -roc_utils = {path = "../utils"} +roc_bitcode = { path = "../compiler/builtins/bitcode" } +roc_builtins = { path = "../compiler/builtins" } wasi_libc_sys = { path = "../wasi-libc-sys" } + tempfile.workspace = true [dependencies] bumpalo.workspace = true -console_error_panic_hook = {version = "0.1.7", optional = true} -futures = {version = "0.3.24", optional = true} -js-sys = "0.3.60" -wasm-bindgen = "0.2.79" -wasm-bindgen-futures = "0.4.33" +console_error_panic_hook = { workspace = true, optional = true } +futures = { workspace = true, optional = true } +getrandom = { version = "0.2", features = ["js"] } # not a direct dependency, needed because of https://docs.rs/getrandom/latest/getrandom/#webassembly-support +js-sys.workspace = true +wasm-bindgen-futures.workspace = true +wasm-bindgen.workspace = true -roc_collections = {path = "../compiler/collections"} -roc_gen_wasm = {path = "../compiler/gen_wasm"} -roc_load = {path = "../compiler/load"} -roc_parse = {path = "../compiler/parse"} -roc_repl_eval = {path = "../repl_eval"} -roc_reporting = {path = "../reporting"} -roc_target = {path = "../compiler/roc_target"} -roc_types = {path = "../compiler/types"} +roc_collections = { path = "../compiler/collections" } +roc_gen_wasm = { path = "../compiler/gen_wasm" } +roc_load = { path = "../compiler/load" } +roc_parse = { path = "../compiler/parse" } +roc_repl_eval = { path = "../repl_eval" } +roc_reporting = { path = "../reporting" } +roc_target = { path = "../compiler/roc_target" } +roc_types = { path = "../compiler/types" } [features] wasi_test = ["futures"] diff --git a/crates/repl_wasm/build.rs b/crates/repl_wasm/build.rs index 12dfbf449d..0ed3b1b4dd 100644 --- a/crates/repl_wasm/build.rs +++ b/crates/repl_wasm/build.rs @@ -2,7 +2,6 @@ use std::env; use std::path::PathBuf; use std::process::Command; -use roc_builtins::bitcode; use wasi_libc_sys::{WASI_COMPILER_RT_PATH, WASI_LIBC_PATH}; const PLATFORM_FILENAME: &str = "repl_platform"; @@ -29,8 +28,8 @@ fn main() { pre_linked_binary_path.extend(["pre_linked_binary"]); pre_linked_binary_path.set_extension(OBJECT_EXTENSION); - let builtins_host_tempfile = - bitcode::host_wasm_tempfile().expect("failed to write host builtins object to tempfile"); + let builtins_host_tempfile = roc_bitcode::host_wasm_tempfile() + .expect("failed to write host builtins object to tempfile"); let output = Command::new(&zig_executable()) .args([ diff --git a/crates/reporting/Cargo.toml b/crates/reporting/Cargo.toml index df2ac5dd73..ad4c0e9de3 100644 --- a/crates/reporting/Cargo.toml +++ b/crates/reporting/Cargo.toml @@ -1,40 +1,42 @@ [package] name = "roc_reporting" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Responsible for generating warning and error messages." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] +roc_can = { path = "../compiler/can" } roc_collections = { path = "../compiler/collections" } roc_error_macros = { path = "../error_macros" } roc_exhaustive = { path = "../compiler/exhaustive" } -roc_region = { path = "../compiler/region" } +roc_fmt = { path = "../compiler/fmt" } roc_module = { path = "../compiler/module" } roc_parse = { path = "../compiler/parse" } roc_problem = { path = "../compiler/problem" } -roc_types = { path = "../compiler/types" } -roc_can = { path = "../compiler/can" } -roc_fmt = { path = "../compiler/fmt" } +roc_region = { path = "../compiler/region" } roc_solve_problem = { path = "../compiler/solve_problem" } roc_std = { path = "../roc_std" } +roc_types = { path = "../compiler/types" } ven_pretty = { path = "../vendor/pretty" } -distance.workspace = true + bumpalo.workspace = true +distance.workspace = true [dev-dependencies] +roc_builtins = { path = "../compiler/builtins" } roc_constrain = { path = "../compiler/constrain" } roc_derive = { path = "../compiler/derive" } -roc_builtins = { path = "../compiler/builtins" } roc_load = { path = "../compiler/load" } -roc_problem = { path = "../compiler/problem" } +roc_packaging = { path = "../packaging" } roc_parse = { path = "../compiler/parse" } +roc_problem = { path = "../compiler/problem" } +roc_solve = { path = "../compiler/solve" } roc_target = { path = "../compiler/roc_target" } roc_test_utils = { path = "../test_utils" } -roc_solve = { path = "../compiler/solve" } -roc_packaging = { path = "../packaging" } -pretty_assertions.workspace = true indoc.workspace = true insta.workspace = true +pretty_assertions.workspace = true diff --git a/crates/reporting/src/error/canonicalize.rs b/crates/reporting/src/error/canonicalize.rs index 037235172a..7468e1d93e 100644 --- a/crates/reporting/src/error/canonicalize.rs +++ b/crates/reporting/src/error/canonicalize.rs @@ -1539,7 +1539,7 @@ fn report_shadowing<'b>( alloc.concat([ alloc.reflow("Since these "), alloc.reflow(what_plural), - alloc.reflow(" have the same name, it's easy to use the wrong one on accident. Give one of them a new name."), + alloc.reflow(" have the same name, it's easy to use the wrong one by accident. Give one of them a new name."), ]), ]) }; diff --git a/crates/reporting/tests/test_reporting.rs b/crates/reporting/tests/test_reporting.rs index 77612096b0..a50debc07c 100644 --- a/crates/reporting/tests/test_reporting.rs +++ b/crates/reporting/tests/test_reporting.rs @@ -543,7 +543,7 @@ mod test_reporting { ^ Since these variables have the same name, it's easy to use the wrong - one on accident. Give one of them a new name. + one by accident. Give one of them a new name. "### ); @@ -575,7 +575,7 @@ mod test_reporting { ^^^^^^^^^^^^^^^^^^^^^^^^ Since these aliases have the same name, it's easy to use the wrong one - on accident. Give one of them a new name. + by accident. Give one of them a new name. "### ); @@ -8425,7 +8425,7 @@ In roc, functions are always written as a lambda, like{} ^^^^^^^^^ Since these variables have the same name, it's easy to use the wrong - one on accident. Give one of them a new name. + one by accident. Give one of them a new name. "# ); @@ -8454,7 +8454,7 @@ In roc, functions are always written as a lambda, like{} ^^^^^^^ Since these abilities have the same name, it's easy to use the wrong - one on accident. Give one of them a new name. + one by accident. Give one of them a new name. "# ); @@ -9739,7 +9739,7 @@ In roc, functions are always written as a lambda, like{} ^^^^ Since these variables have the same name, it's easy to use the wrong - one on accident. Give one of them a new name. + one by accident. Give one of them a new name. ── UNNECESSARY DEFINITION ──────────────────────────────── /code/proj/Main.roc ─ diff --git a/crates/roc_std/Cargo.lock b/crates/roc_std/Cargo.lock deleted file mode 100644 index a0df90bf30..0000000000 --- a/crates/roc_std/Cargo.lock +++ /dev/null @@ -1,297 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "aho-corasick" -version = "0.7.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" -dependencies = [ - "memchr", -] - -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi", -] - -[[package]] -name = "arrayvec" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "ctor" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "diff" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499" - -[[package]] -name = "env_logger" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "getrandom" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "indoc" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7906a9fababaeacb774f72410e497a1d18de916322e33797bb2cd29baa23c9e" -dependencies = [ - "unindent", -] - -[[package]] -name = "itoa" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" - -[[package]] -name = "libc" -version = "0.2.139" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" - -[[package]] -name = "log" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "memchr" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" - -[[package]] -name = "output_vt100" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66" -dependencies = [ - "winapi", -] - -[[package]] -name = "pretty_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d5b548b725018ab5496482b45cb8bef21e9fed1858a6d674e3a8a0f0bb5d50" -dependencies = [ - "ansi_term", - "ctor", - "diff", - "output_vt100", -] - -[[package]] -name = "proc-macro2" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "quickcheck" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" -dependencies = [ - "env_logger", - "log", - "rand", -] - -[[package]] -name = "quickcheck_macros" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b22a693222d716a9587786f37ac3f6b4faedb5b80c23914e7303ff5a1d8016e9" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "quote" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" -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.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom", -] - -[[package]] -name = "regex" -version = "1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.6.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" - -[[package]] -name = "roc_std" -version = "0.0.1" -dependencies = [ - "arrayvec", - "indoc", - "libc", - "pretty_assertions", - "quickcheck", - "quickcheck_macros", - "serde", - "serde_json", - "static_assertions", -] - -[[package]] -name = "ryu" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" - -[[package]] -name = "serde" -version = "1.0.143" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553" - -[[package]] -name = "serde_json" -version = "1.0.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "syn" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - -[[package]] -name = "unindent" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514672a55d7380da379785a4d70ca8386c8883ff7eaae877be4d2081cebe73d8" - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - -[[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-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/crates/roc_std/Cargo.toml b/crates/roc_std/Cargo.toml index 5f0161caa8..8c7b41cb9d 100644 --- a/crates/roc_std/Cargo.toml +++ b/crates/roc_std/Cargo.toml @@ -1,26 +1,29 @@ [package] -authors = ["The Roc Contributors"] +name = "roc_std" description = "Rust representations of Roc data structures" +readme = "README.md" + +authors = ["The Roc Contributors"] edition = "2021" license = "UPL-1.0" -name = "roc_std" -readme = "README.md" repository = "https://github.com/roc-lang/roc" version = "0.0.1" [dependencies] -static_assertions = "1.1.0" arrayvec = "0.7.2" -serde = { version = "1", optional = true } +serde = { version = "1.0.153", optional = true } +static_assertions = "1.1.0" [dev-dependencies] -indoc = "1.0.3" -libc = "0.2.135" -pretty_assertions = "1.0.0" +libc = "0.2.139" +pretty_assertions = "1.3.0" quickcheck = "1.0.3" quickcheck_macros = "1.0.0" -serde_json = "1.0.83" +serde_json = "1.0.94" [features] -std = [] serde = ["dep:serde"] +std = [] + +[package.metadata.cargo-udeps.ignore] +development = ["quickcheck_macros", "serde_json"] \ No newline at end of file diff --git a/crates/roc_std/src/roc_dict.rs b/crates/roc_std/src/roc_dict.rs index 96d17aac58..6c960884d0 100644 --- a/crates/roc_std/src/roc_dict.rs +++ b/crates/roc_std/src/roc_dict.rs @@ -46,7 +46,14 @@ impl RocDict { } impl RocDict { - pub fn from_iter>(src: I) -> Self { + unsafe fn insert_unchecked(&mut self, _key: K, _val: V) { + todo!(); + } +} + +impl FromIterator<(K, V)> for RocDict { + fn from_iter>(into_iter: T) -> Self { + let src = into_iter.into_iter(); let mut ret = Self::with_capacity(src.size_hint().0); for (key, val) in src { @@ -57,16 +64,6 @@ impl RocDict { ret } - - unsafe fn insert_unchecked(&mut self, _key: K, _val: V) { - todo!(); - } -} - -impl<'a, K: Hash, V> FromIterator<(K, V)> for RocDict { - fn from_iter>(into_iter: T) -> Self { - RocDict::from_iter(into_iter.into_iter()) - } } impl<'a, K, V> IntoIterator for &'a RocDict { diff --git a/crates/roc_std/src/roc_list.rs b/crates/roc_std/src/roc_list.rs index 1f6ba03bae..94b9387e40 100644 --- a/crates/roc_std/src/roc_list.rs +++ b/crates/roc_std/src/roc_list.rs @@ -151,7 +151,7 @@ impl RocList { /// bytes over - in other words, calling this `as_slice` method and then calling `to_vec` /// on that. pub fn as_slice(&self) -> &[T] { - &*self + self } #[inline(always)] diff --git a/crates/roc_std/src/roc_set.rs b/crates/roc_std/src/roc_set.rs index d268c63643..683045b8a4 100644 --- a/crates/roc_std/src/roc_set.rs +++ b/crates/roc_std/src/roc_set.rs @@ -27,10 +27,11 @@ impl RocSet { } } -impl RocSet { - #[allow(unused)] - pub fn from_iter>(src: I) -> Self { - Self(RocDict::from_iter(src.map(|elem| (elem, ())))) +impl FromIterator for RocSet { + fn from_iter>(into_iter: I) -> Self { + Self(RocDict::from_iter( + into_iter.into_iter().map(|elem| (elem, ())), + )) } } diff --git a/crates/roc_std/src/roc_str.rs b/crates/roc_std/src/roc_str.rs index 0face1fe2c..4463b6f34d 100644 --- a/crates/roc_std/src/roc_str.rs +++ b/crates/roc_std/src/roc_str.rs @@ -154,7 +154,7 @@ impl RocStr { /// bytes over - in other words, calling this `as_str` method and then calling `to_string` /// on that. pub fn as_str(&self) -> &str { - &*self + self } /// Create an empty RocStr with enough space preallocated to store @@ -562,8 +562,8 @@ impl Deref for RocStr { fn deref(&self) -> &Self::Target { match self.as_enum_ref() { - RocStrInnerRef::HeapAllocated(h) => unsafe { core::str::from_utf8_unchecked(&*h) }, - RocStrInnerRef::SmallString(s) => &*s, + RocStrInnerRef::HeapAllocated(h) => unsafe { core::str::from_utf8_unchecked(h) }, + RocStrInnerRef::SmallString(s) => s, } } } diff --git a/crates/roc_std/tests/test_roc_std.rs b/crates/roc_std/tests/test_roc_std.rs index 4de4e543fe..63aec446a9 100644 --- a/crates/roc_std/tests/test_roc_std.rs +++ b/crates/roc_std/tests/test_roc_std.rs @@ -1,7 +1,7 @@ +#![allow(clippy::missing_safety_doc)] + #[macro_use] extern crate pretty_assertions; -// #[macro_use] -// extern crate indoc; extern crate quickcheck; extern crate roc_std; diff --git a/crates/test_utils/Cargo.toml b/crates/test_utils/Cargo.toml index fa8caad1ad..1d70df053d 100644 --- a/crates/test_utils/Cargo.toml +++ b/crates/test_utils/Cargo.toml @@ -1,13 +1,14 @@ [package] name = "roc_test_utils" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Utility functions used all over the code base." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] -pretty_assertions = "1.3.0" -remove_dir_all = "0.7.0" +pretty_assertions.workspace = true +remove_dir_all.workspace = true [dev-dependencies] diff --git a/crates/tracing/Cargo.toml b/crates/tracing/Cargo.toml index ee153b5aa8..07eb67cb78 100644 --- a/crates/tracing/Cargo.toml +++ b/crates/tracing/Cargo.toml @@ -1,12 +1,13 @@ [package] name = "roc_tracing" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" description = "Utilities for setting up tracing at various executable entry points." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] -tracing = { version = "0.1.36", features = ["release_max_level_off"] } -tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } -tracing-appender = "0.2.2" +tracing-appender.workspace = true +tracing-subscriber.workspace = true +tracing.workspace = true diff --git a/crates/utils/Cargo.toml b/crates/utils/Cargo.toml deleted file mode 100644 index 02445e2963..0000000000 --- a/crates/utils/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "roc_utils" -version = "0.0.1" -authors = ["The Roc Contributors"] -license = "UPL-1.0" -edition = "2021" -description = "Utility functions used all over the code base." - -[dependencies] -snafu = { version = "0.7.1", features = ["backtraces"] } - -[dev-dependencies] diff --git a/crates/utils/command/Cargo.toml b/crates/utils/command/Cargo.toml new file mode 100644 index 0000000000..132b228fb3 --- /dev/null +++ b/crates/utils/command/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "roc_command_utils" +description = "Utility functions used all over the code base to call eternal apps like zig." + +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + +[dependencies] + +[dev-dependencies] diff --git a/crates/utils/src/lib.rs b/crates/utils/command/src/lib.rs similarity index 66% rename from crates/utils/src/lib.rs rename to crates/utils/command/src/lib.rs index b49eede385..ed76330655 100644 --- a/crates/utils/src/lib.rs +++ b/crates/utils/command/src/lib.rs @@ -1,105 +1,8 @@ -//! Provides utility functions used all over the code base. -use snafu::OptionExt; use std::{ - collections::HashMap, env::{self, VarError}, path::PathBuf, process::Command, - slice::SliceIndex, }; -use util_error::{IndexOfFailedSnafu, KeyNotFoundSnafu, OutOfBoundsSnafu, UtilResult}; - -pub mod util_error; - -// replace HashMap method that returns Option with one that returns Result and proper Error -pub fn map_get<'a, K: ::std::fmt::Debug + std::hash::Hash + std::cmp::Eq, V>( - hash_map: &'a HashMap, - key: &K, -) -> UtilResult<&'a V> { - let value = hash_map.get(key).context(KeyNotFoundSnafu { - key_str: format!("{:?}", key), - })?; - - Ok(value) -} - -pub fn index_of(elt: T, slice: &[T]) -> UtilResult { - let index = slice - .iter() - .position(|slice_elt| *slice_elt == elt) - .with_context(|| { - let elt_str = format!("{:?}", elt); - let collection_str = format!("{:?}", slice); - - IndexOfFailedSnafu { - elt_str, - collection_str, - } - })?; - - Ok(index) -} - -// replaces slice method that return Option with one that return Result and proper Error -pub fn slice_get(index: usize, slice: &[T]) -> UtilResult<&>::Output> { - let elt_ref = slice.get(index).context(OutOfBoundsSnafu { - index, - collection_name: "Slice", - len: slice.len(), - })?; - - Ok(elt_ref) -} - -pub fn slice_get_mut( - index: usize, - slice: &mut [T], -) -> UtilResult<&mut >::Output> { - let slice_len = slice.len(); - - let elt_ref = slice.get_mut(index).context(OutOfBoundsSnafu { - index, - collection_name: "Slice", - len: slice_len, - })?; - - Ok(elt_ref) -} - -// returns the index of the first occurrence of element and index of the last occurrence -pub fn first_last_index_of( - elt: T, - slice: &[T], -) -> UtilResult<(usize, usize)> { - let mut first_index_opt = None; - let mut last_index_opt = None; - - for (index, list_elt) in slice.iter().enumerate() { - if *list_elt == elt { - if first_index_opt.is_none() { - first_index_opt = Some(index); - last_index_opt = Some(index); - } else { - last_index_opt = Some(index) - } - } else if last_index_opt.is_some() { - break; - } - } - - if let (Some(first_index), Some(last_index)) = (first_index_opt, last_index_opt) { - Ok((first_index, last_index)) - } else { - let elt_str = format!("{:?}", elt); - let collection_str = format!("{:?}", slice); - - IndexOfFailedSnafu { - elt_str, - collection_str, - } - .fail() - } -} // get the path of the lib folder // runtime dependencies like zig files, Windows dylib builds, are put in the lib folder diff --git a/crates/utils/error/Cargo.toml b/crates/utils/error/Cargo.toml new file mode 100644 index 0000000000..85b4635dc8 --- /dev/null +++ b/crates/utils/error/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "roc_error_utils" +description = "Utility functions used all over the code base adding better errors to calls." + +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + +[dependencies] +snafu.workspace = true + +[dev-dependencies] diff --git a/crates/utils/error/src/lib.rs b/crates/utils/error/src/lib.rs new file mode 100644 index 0000000000..9b63f1307c --- /dev/null +++ b/crates/utils/error/src/lib.rs @@ -0,0 +1,127 @@ +//! Provides utility functions used all over the code base. +use snafu::{Backtrace, OptionExt, Snafu}; +use std::{collections::HashMap, slice::SliceIndex}; + +#[derive(Debug, Snafu)] +#[snafu(visibility(pub))] +pub enum UtilError { + #[snafu(display( + "IndexOfFailed: Element {} was not found in collection {}.", + elt_str, + collection_str + ))] + IndexOfFailed { + elt_str: String, + collection_str: String, + backtrace: Backtrace, + }, + #[snafu(display("KeyNotFound: key {} was not found in HashMap.", key_str,))] + KeyNotFound { + key_str: String, + backtrace: Backtrace, + }, + #[snafu(display( + "OutOfBounds: index {} was out of bounds for {} with length {}.", + index, + collection_name, + len + ))] + OutOfBounds { + index: usize, + collection_name: String, + len: usize, + backtrace: Backtrace, + }, +} + +pub type UtilResult = std::result::Result; + +// replace HashMap method that returns Option with one that returns Result and proper Error +pub fn map_get<'a, K: ::std::fmt::Debug + std::hash::Hash + std::cmp::Eq, V>( + hash_map: &'a HashMap, + key: &K, +) -> UtilResult<&'a V> { + let value = hash_map.get(key).context(KeyNotFoundSnafu { + key_str: format!("{:?}", key), + })?; + + Ok(value) +} + +pub fn index_of(elt: T, slice: &[T]) -> UtilResult { + let index = slice + .iter() + .position(|slice_elt| *slice_elt == elt) + .with_context(|| { + let elt_str = format!("{:?}", elt); + let collection_str = format!("{:?}", slice); + + IndexOfFailedSnafu { + elt_str, + collection_str, + } + })?; + + Ok(index) +} + +// replaces slice method that return Option with one that return Result and proper Error +pub fn slice_get(index: usize, slice: &[T]) -> UtilResult<&>::Output> { + let elt_ref = slice.get(index).context(OutOfBoundsSnafu { + index, + collection_name: "Slice", + len: slice.len(), + })?; + + Ok(elt_ref) +} + +pub fn slice_get_mut( + index: usize, + slice: &mut [T], +) -> UtilResult<&mut >::Output> { + let slice_len = slice.len(); + + let elt_ref = slice.get_mut(index).context(OutOfBoundsSnafu { + index, + collection_name: "Slice", + len: slice_len, + })?; + + Ok(elt_ref) +} + +// returns the index of the first occurrence of element and index of the last occurrence +pub fn first_last_index_of( + elt: T, + slice: &[T], +) -> UtilResult<(usize, usize)> { + let mut first_index_opt = None; + let mut last_index_opt = None; + + for (index, list_elt) in slice.iter().enumerate() { + if *list_elt == elt { + if first_index_opt.is_none() { + first_index_opt = Some(index); + last_index_opt = Some(index); + } else { + last_index_opt = Some(index) + } + } else if last_index_opt.is_some() { + break; + } + } + + if let (Some(first_index), Some(last_index)) = (first_index_opt, last_index_opt) { + Ok((first_index, last_index)) + } else { + let elt_str = format!("{:?}", elt); + let collection_str = format!("{:?}", slice); + + IndexOfFailedSnafu { + elt_str, + collection_str, + } + .fail() + } +} diff --git a/crates/utils/src/util_error.rs b/crates/utils/src/util_error.rs deleted file mode 100644 index d19c230f11..0000000000 --- a/crates/utils/src/util_error.rs +++ /dev/null @@ -1,35 +0,0 @@ -use snafu::{Backtrace, Snafu}; - -#[derive(Debug, Snafu)] -#[snafu(visibility(pub))] -pub enum UtilError { - #[snafu(display( - "IndexOfFailed: Element {} was not found in collection {}.", - elt_str, - collection_str - ))] - IndexOfFailed { - elt_str: String, - collection_str: String, - backtrace: Backtrace, - }, - #[snafu(display("KeyNotFound: key {} was not found in HashMap.", key_str,))] - KeyNotFound { - key_str: String, - backtrace: Backtrace, - }, - #[snafu(display( - "OutOfBounds: index {} was out of bounds for {} with length {}.", - index, - collection_name, - len - ))] - OutOfBounds { - index: usize, - collection_name: String, - len: usize, - backtrace: Backtrace, - }, -} - -pub type UtilResult = std::result::Result; diff --git a/crates/valgrind/Cargo.toml b/crates/valgrind/Cargo.toml index eb5271ab46..11799d3d20 100644 --- a/crates/valgrind/Cargo.toml +++ b/crates/valgrind/Cargo.toml @@ -1,20 +1,24 @@ [package] name = "valgrind" -version = "0.1.0" -edition = "2021" -authors = ["The Roc Contributors"] -license = "UPL-1.0" + +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true [dev-dependencies] -roc_cli = { path = "../cli" } cli_utils = { path = "../cli_utils" } roc_build = { path = "../compiler/build" } -roc_mono = { path = "../compiler/mono" } -roc_load = { path = "../compiler/load" } -roc_reporting = { path = "../reporting" } roc_linker = { path = "../linker" } +roc_load = { path = "../compiler/load" } +roc_mono = { path = "../compiler/mono" } roc_packaging = { path = "../packaging" } +roc_reporting = { path = "../reporting" } + bumpalo.workspace = true +indoc.workspace = true target-lexicon.workspace = true tempfile.workspace = true -indoc.workspace = true + +[package.metadata.cargo-udeps.ignore] +development = ["roc_build", "roc_linker"] \ No newline at end of file diff --git a/crates/valgrind/src/lib.rs b/crates/valgrind/src/lib.rs index f90b769b7c..b510dbd953 100644 --- a/crates/valgrind/src/lib.rs +++ b/crates/valgrind/src/lib.rs @@ -7,8 +7,8 @@ static BUILD_ONCE: std::sync::Once = std::sync::Once::new(); #[cfg(all(target_os = "linux"))] fn build_host() { - use roc_build::link::preprocessed_host_filename; - use roc_linker::build_and_preprocess_host; + use roc_build::program::build_and_preprocess_host; + use roc_linker::preprocessed_host_filename; let platform_main_roc = std::env::current_dir() .unwrap() @@ -45,7 +45,7 @@ fn valgrind_test(source: &str) { #[cfg(target_os = "linux")] fn valgrind_test_linux(source: &str) { - use roc_cli::build::BuiltFile; + use roc_build::program::BuiltFile; // the host is identical for all tests so we only want to build it once BUILD_ONCE.call_once(build_host); @@ -81,7 +81,7 @@ fn valgrind_test_linux(source: &str) { let arena = bumpalo::Bump::new(); let assume_prebuilt = true; - let res_binary_path = roc_cli::build::build_str_test( + let res_binary_path = roc_build::program::build_str_test( &arena, &app_module_path, &app_module_source, @@ -101,7 +101,7 @@ fn valgrind_test_linux(source: &str) { run_with_valgrind(&binary_path); } - Err(roc_cli::build::BuildFileError::LoadingProblem( + Err(roc_build::program::BuildFileError::LoadingProblem( roc_load::LoadingProblem::FormattedReport(report), )) => { eprintln!("{}", report); diff --git a/crates/vendor/morphic_lib/Cargo.toml b/crates/vendor/morphic_lib/Cargo.toml index 5c950e0799..eb87e12ac3 100644 --- a/crates/vendor/morphic_lib/Cargo.toml +++ b/crates/vendor/morphic_lib/Cargo.toml @@ -5,7 +5,7 @@ authors = ["William Brandon", "Wilson Berkow", "Frank Dai", "Benjamin Driscoll"] edition = "2018" [dependencies] -thiserror = "1.0.30" -sha2 = "0.10.2" -smallvec = "1.7.0" -typed-arena = "2.0.1" +thiserror = "1.0.39" +sha2 = "0.10.6" +smallvec = "1.10.0" +typed-arena = "2.0.2" diff --git a/crates/vendor/pretty/Cargo.toml b/crates/vendor/pretty/Cargo.toml index 7df7a3b737..78bf73d5b6 100644 --- a/crates/vendor/pretty/Cargo.toml +++ b/crates/vendor/pretty/Cargo.toml @@ -15,5 +15,5 @@ features = ["termcolor"] [dependencies] arrayvec = "0.7.2" -typed-arena = "2.0.1" -termcolor = { version = "1.1.2", optional = true } +typed-arena = "2.0.2" +termcolor = { version = "1.2.0", optional = true } diff --git a/crates/wasi-libc-sys/Cargo.toml b/crates/wasi-libc-sys/Cargo.toml index f7faff97fd..7bc52198fc 100644 --- a/crates/wasi-libc-sys/Cargo.toml +++ b/crates/wasi-libc-sys/Cargo.toml @@ -1,11 +1,12 @@ [package] -authors = ["The Roc Contributors"] description = "Rust wrapper for a WebAssembly test platform built on libc" -edition = "2021" -license = "UPL-1.0" name = "wasi_libc_sys" -repository = "https://github.com/roc-lang/roc" -version = "0.0.1" + +authors.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +version.workspace = true [build-dependencies] -roc_utils = {path = "../utils"} \ No newline at end of file +roc_command_utils = { path = "../utils/command" } diff --git a/crates/wasi-libc-sys/build.rs b/crates/wasi-libc-sys/build.rs index 2aca3eadd2..1ef3bda1ea 100644 --- a/crates/wasi-libc-sys/build.rs +++ b/crates/wasi-libc-sys/build.rs @@ -1,4 +1,4 @@ -use roc_utils::zig; +use roc_command_utils::zig; use std::env; use std::ffi::OsString; use std::fs; diff --git a/crates/wasm_interp/Cargo.toml b/crates/wasm_interp/Cargo.toml index fa49a8a07d..c4a6c84dd5 100644 --- a/crates/wasm_interp/Cargo.toml +++ b/crates/wasm_interp/Cargo.toml @@ -1,18 +1,20 @@ [package] name = "roc_wasm_interp" -version = "0.1.0" -edition = "2021" -authors = ["The Roc Contributors"] -license = "UPL-1.0" description = "A WebAssembly interpreter for testing the compiler." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [[bin]] name = "roc_wasm_interp" path = "src/main.rs" [dependencies] roc_wasm_module = { path = "../wasm_module" } -rand = "0.8.4" + bitvec.workspace = true bumpalo.workspace = true clap.workspace = true +rand.workspace = true diff --git a/crates/wasm_module/Cargo.toml b/crates/wasm_module/Cargo.toml index 315b9950d2..0ff4298cdd 100644 --- a/crates/wasm_module/Cargo.toml +++ b/crates/wasm_module/Cargo.toml @@ -1,11 +1,12 @@ [package] name = "roc_wasm_module" -version = "0.0.1" -edition = "2021" -authors = ["The Roc Contributors"] -license = "UPL-1.0" description = "Parse, manipulate, and serialize WebAssembly modules." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + [dependencies] roc_error_macros = { path = "../error_macros" } diff --git a/default.nix b/default.nix index 31c84f5bfe..d1b8a7c621 100644 --- a/default.nix +++ b/default.nix @@ -22,7 +22,7 @@ rustPlatform.buildRustPackage { cargoLock = { lockFile = ./Cargo.lock; outputHashes = { - "confy-0.5.0" = "sha256-BVTczVbURL1Id/k/5ArlDQTZxLuI3XxQl7BdIx230U4="; + "confy-0.5.1" = "sha256-3PQdz9W/uJd4CaUZdwAd2u3JJ100SFAoKLCFE6THRZI="; "criterion-0.3.5" = "sha256-7REd3phV6PBzqWwKF8hwttw4FTq2tKGxxAAJDpLC50A="; "inkwell-0.1.0" = "sha256-1kpvY3naS33B99nuu5ZYhb7mdddAyG+DkbUl/RG1Ptg="; "plotters-0.3.1" = "sha256-noy/RSjoEPZZbOJTZw1yxGcX5S+2q/7mxnUrzDyxOFw="; @@ -65,7 +65,6 @@ rustPlatform.buildRustPackage { cargo makeWrapper # necessary for postBuild wrapProgram ] ++ lib.optionals pkgs.stdenv.isLinux [ - alsa-lib valgrind vulkan-headers vulkan-loader diff --git a/examples/cli/cli-platform/Cargo.lock b/examples/cli/cli-platform/Cargo.lock deleted file mode 100644 index 94e74cf1db..0000000000 --- a/examples/cli/cli-platform/Cargo.lock +++ /dev/null @@ -1,963 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "arrayvec" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" - -[[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.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "base64" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" - -[[package]] -name = "bumpalo" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" - -[[package]] -name = "bytes" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" - -[[package]] -name = "cc" -version = "1.0.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "encoding_rs" -version = "0.8.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "form_urlencoded" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "futures-channel" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050" -dependencies = [ - "futures-core", -] - -[[package]] -name = "futures-core" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf" - -[[package]] -name = "futures-io" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68" - -[[package]] -name = "futures-sink" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56" - -[[package]] -name = "futures-task" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1" - -[[package]] -name = "futures-util" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90" -dependencies = [ - "futures-core", - "futures-io", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "gimli" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" - -[[package]] -name = "h2" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "host" -version = "0.0.1" -dependencies = [ - "backtrace", - "libc", - "reqwest", - "roc_std", -] - -[[package]] -name = "http" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" -dependencies = [ - "bytes", - "http", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "httpdate" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" - -[[package]] -name = "hyper" -version = "0.14.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac" -dependencies = [ - "http", - "hyper", - "rustls", - "tokio", - "tokio-rustls", -] - -[[package]] -name = "idna" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "indexmap" -version = "1.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "ipnet" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" - -[[package]] -name = "itoa" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" - -[[package]] -name = "js-sys" -version = "0.3.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "libc" -version = "0.2.134" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb" - -[[package]] -name = "log" -version = "0.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "memchr" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "mime" -version = "0.3.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" - -[[package]] -name = "miniz_oxide" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" -dependencies = [ - "libc", - "log", - "wasi", - "windows-sys 0.36.1", -] - -[[package]] -name = "num_cpus" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "object" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" - -[[package]] -name = "percent-encoding" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" - -[[package]] -name = "pin-project-lite" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "proc-macro2" -version = "1.0.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "reqwest" -version = "0.11.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "431949c384f4e2ae07605ccaa56d1d9d2ecdb5cadd4f9577ccfab29f2e5149fc" -dependencies = [ - "base64", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-rustls", - "ipnet", - "js-sys", - "log", - "mime", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "tokio", - "tokio-rustls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webpki-roots", - "winreg", -] - -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin", - "untrusted", - "web-sys", - "winapi", -] - -[[package]] -name = "roc_std" -version = "0.0.1" -dependencies = [ - "arrayvec", - "static_assertions", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" - -[[package]] -name = "rustls" -version = "0.20.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033" -dependencies = [ - "log", - "ring", - "sct", - "webpki", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0864aeff53f8c05aa08d86e5ef839d3dfcf07aeba2db32f12db0ef716e87bd55" -dependencies = [ - "base64", -] - -[[package]] -name = "ryu" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" - -[[package]] -name = "sct" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "serde" -version = "1.0.145" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b" - -[[package]] -name = "serde_json" -version = "1.0.85" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "slab" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" -dependencies = [ - "autocfg", -] - -[[package]] -name = "socket2" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "syn" -version = "1.0.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[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.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" - -[[package]] -name = "tokio" -version = "1.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d9f76183f91ecfb55e1d7d5602bd1d979e38a3a522fe900241cf195624d67ae" -dependencies = [ - "autocfg", - "bytes", - "libc", - "memchr", - "mio", - "num_cpus", - "pin-project-lite", - "socket2", - "windows-sys 0.42.0", -] - -[[package]] -name = "tokio-rustls" -version = "0.23.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" -dependencies = [ - "rustls", - "tokio", - "webpki", -] - -[[package]] -name = "tokio-util" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", - "tracing", -] - -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - -[[package]] -name = "tracing" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" -dependencies = [ - "cfg-if", - "pin-project-lite", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" -dependencies = [ - "once_cell", -] - -[[package]] -name = "try-lock" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" - -[[package]] -name = "unicode-bidi" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" - -[[package]] -name = "unicode-ident" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" - -[[package]] -name = "unicode-normalization" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - -[[package]] -name = "url" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - -[[package]] -name = "want" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" -dependencies = [ - "log", - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" - -[[package]] -name = "web-sys" -version = "0.3.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "webpki-roots" -version = "0.22.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368bfe657969fb01238bb756d351dcade285e0f6fcbd36dcb23359a5169975be" -dependencies = [ - "webpki", -] - -[[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-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.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" -dependencies = [ - "windows_aarch64_msvc 0.36.1", - "windows_i686_gnu 0.36.1", - "windows_i686_msvc 0.36.1", - "windows_x86_64_gnu 0.36.1", - "windows_x86_64_msvc 0.36.1", -] - -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc 0.42.0", - "windows_i686_gnu 0.42.0", - "windows_i686_msvc 0.42.0", - "windows_x86_64_gnu 0.42.0", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.42.0", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" - -[[package]] -name = "windows_i686_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" - -[[package]] -name = "windows_i686_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" - -[[package]] -name = "winreg" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" -dependencies = [ - "winapi", -] diff --git a/examples/cli/cli-platform/Cargo.toml b/examples/cli/cli-platform/Cargo.toml index 294b712a9c..56bd77a63a 100644 --- a/examples/cli/cli-platform/Cargo.toml +++ b/examples/cli/cli-platform/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "host" -version = "0.0.1" authors = ["The Roc Contributors"] -license = "UPL-1.0" edition = "2021" +license = "UPL-1.0" +version = "0.0.1" links = "app" @@ -17,9 +17,9 @@ name = "host" path = "src/main.rs" [dependencies] -roc_std = { path = "../../../crates/roc_std" } -libc = "0.2" backtrace = "0.3" -reqwest = { version="0.11.11", default-features=false, features=["blocking", "rustls-tls"] } +libc = "0.2" +reqwest = { version = "0.11.11", default-features = false, features = ["blocking", "rustls-tls"] } +roc_std = { path = "../../../crates/roc_std" } [workspace] diff --git a/examples/cli/false-interpreter/platform/Cargo.lock b/examples/cli/false-interpreter/platform/Cargo.lock deleted file mode 100644 index 3c874e3e30..0000000000 --- a/examples/cli/false-interpreter/platform/Cargo.lock +++ /dev/null @@ -1,37 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "arrayvec" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" - -[[package]] -name = "host" -version = "0.0.1" -dependencies = [ - "libc", - "roc_std", -] - -[[package]] -name = "libc" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1fa8cddc8fbbee11227ef194b5317ed014b8acbf15139bd716a18ad3fe99ec5" - -[[package]] -name = "roc_std" -version = "0.0.1" -dependencies = [ - "arrayvec", - "static_assertions", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" diff --git a/examples/cli/false-interpreter/platform/Cargo.toml b/examples/cli/false-interpreter/platform/Cargo.toml index eeeb74f517..1cce894c1d 100644 --- a/examples/cli/false-interpreter/platform/Cargo.toml +++ b/examples/cli/false-interpreter/platform/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "host" -version = "0.0.1" authors = ["The Roc Contributors"] -license = "UPL-1.0" edition = "2021" +license = "UPL-1.0" +version = "0.0.1" links = "app" @@ -17,7 +17,7 @@ name = "host" path = "src/main.rs" [dependencies] -roc_std = { path = "../../../../crates/roc_std" } libc = "0.2" +roc_std = { path = "../../../../crates/roc_std" } [workspace] diff --git a/examples/gui/breakout/platform/Cargo.lock b/examples/gui/breakout/platform/Cargo.lock deleted file mode 100644 index cc44dde1c7..0000000000 --- a/examples/gui/breakout/platform/Cargo.lock +++ /dev/null @@ -1,2799 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "ab_glyph" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61caed9aec6daeee1ea38ccf5fb225e4f96c1eeead1b4a5c267324a63cf02326" -dependencies = [ - "ab_glyph_rasterizer", - "owned_ttf_parser", -] - -[[package]] -name = "ab_glyph_rasterizer" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a13739d7177fbd22bb0ed28badfff9f372f8bef46c863db4e1c6248f6b223b6e" - -[[package]] -name = "addr2line" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "ahash" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - -[[package]] -name = "alsa" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75c4da790adcb2ce5e758c064b4f3ec17a30349f9961d3e5e6c9688b052a9e18" -dependencies = [ - "alsa-sys", - "bitflags", - "libc", - "nix 0.20.2", -] - -[[package]] -name = "alsa-sys" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" -dependencies = [ - "libc", - "pkg-config", -] - -[[package]] -name = "approx" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f2a05fd1bd10b2527e20a2cd32d8873d115b8b39fe219ee25f42a8aca6ba278" -dependencies = [ - "num-traits", -] - -[[package]] -name = "approx" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "072df7202e63b127ab55acfe16ce97013d5b97bf160489336d3f1840fd78e99e" -dependencies = [ - "num-traits", -] - -[[package]] -name = "arrayvec" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" - -[[package]] -name = "ash" -version = "0.35.1+1.2.203" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7fd04def1c9101b5fb488c131022d2d6f87753ef4b1b11b279e2af404fae6b9" -dependencies = [ - "libloading", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - -[[package]] -name = "backtrace" -version = "0.3.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321629d8ba6513061f26707241fa9bc89524ff1cd7a915a97ef0c62c666ce1b6" -dependencies = [ - "addr2line", - "cc", - "cfg-if 1.0.0", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "bindgen" -version = "0.56.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da379dbebc0b76ef63ca68d8fc6e71c0f13e59432e0987e508c1820e6ab5239" -dependencies = [ - "bitflags", - "cexpr", - "clang-sys", - "lazy_static", - "lazycell", - "peeking_take_while", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", -] - -[[package]] -name = "bit-set" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de" -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.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" - -[[package]] -name = "block" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" - -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -dependencies = [ - "block-padding", - "byte-tools", - "byteorder", - "generic-array", -] - -[[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -dependencies = [ - "byte-tools", -] - -[[package]] -name = "bumpalo" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" - -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" - -[[package]] -name = "bytemuck" -version = "1.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439989e6b8c38d1b6570a384ef1e49c8848128f5a97f3914baef02920842712f" -dependencies = [ - "bytemuck_derive", -] - -[[package]] -name = "bytemuck_derive" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e215f8c2f9f79cb53c8335e687ffd07d5bfcb6fe5fc80723762d0be46e7cc54" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "bytes" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" - -[[package]] -name = "calloop" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf2eec61efe56aa1e813f5126959296933cf0700030e4314786c48779a66ab82" -dependencies = [ - "log", - "nix 0.22.0", -] - -[[package]] -name = "cc" -version = "1.0.72" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" -dependencies = [ - "jobserver", -] - -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - -[[package]] -name = "cexpr" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27" -dependencies = [ - "nom 5.1.2", -] - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cfg_aliases" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" - -[[package]] -name = "cgmath" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a98d30140e3296250832bbaaff83b27dcd6fa3cc70fb6f1f3e5c9c0023b5317" -dependencies = [ - "approx 0.4.0", - "num-traits", -] - -[[package]] -name = "clang-sys" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa66045b9cb23c2e9c1520732030608b02ee07e5cfaa5a521ec15ded7fa24c90" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "claxon" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688" - -[[package]] -name = "clipboard-win" -version = "3.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fdf5e01086b6be750428ba4a40619f847eb2e95756eee84b18e06e5f0b50342" -dependencies = [ - "lazy-bytes-cast", - "winapi", -] - -[[package]] -name = "cocoa" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63902e9223530efb4e26ccd0cf55ec30d592d3b42e21a28defc42a9586e832" -dependencies = [ - "bitflags", - "block", - "cocoa-foundation", - "core-foundation 0.9.2", - "core-graphics 0.22.3", - "foreign-types", - "libc", - "objc", -] - -[[package]] -name = "cocoa-foundation" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318" -dependencies = [ - "bitflags", - "block", - "core-foundation 0.9.2", - "core-graphics-types", - "foreign-types", - "libc", - "objc", -] - -[[package]] -name = "codespan-reporting" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] - -[[package]] -name = "colored" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" -dependencies = [ - "atty", - "lazy_static", - "winapi", -] - -[[package]] -name = "combine" -version = "4.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50b727aacc797f9fc28e355d21f34709ac4fc9adecfe470ad07b8f4464f53062" -dependencies = [ - "bytes", - "memchr", -] - -[[package]] -name = "confy" -version = "0.4.0" -source = "git+https://github.com/rust-cli/confy#664992aecd97b4af0eda8d9d2825885662e1c6b4" -dependencies = [ - "directories-next", - "serde", - "serde_yaml", -] - -[[package]] -name = "copyless" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536" - -[[package]] -name = "copypasta" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4423d79fed83ebd9ab81ec21fa97144300a961782158287dc9bf7eddac37ff0b" -dependencies = [ - "clipboard-win", - "objc", - "objc-foundation", - "objc_id", - "smithay-clipboard", - "x11-clipboard", -] - -[[package]] -name = "core-foundation" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" -dependencies = [ - "core-foundation-sys 0.7.0", - "libc", -] - -[[package]] -name = "core-foundation" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3" -dependencies = [ - "core-foundation-sys 0.8.3", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" - -[[package]] -name = "core-foundation-sys" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" - -[[package]] -name = "core-graphics" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3889374e6ea6ab25dba90bb5d96202f61108058361f6dc72e8b03e6f8bbe923" -dependencies = [ - "bitflags", - "core-foundation 0.7.0", - "foreign-types", - "libc", -] - -[[package]] -name = "core-graphics" -version = "0.22.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" -dependencies = [ - "bitflags", - "core-foundation 0.9.2", - "core-graphics-types", - "foreign-types", - "libc", -] - -[[package]] -name = "core-graphics-types" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" -dependencies = [ - "bitflags", - "core-foundation 0.9.2", - "foreign-types", - "libc", -] - -[[package]] -name = "core-video-sys" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ecad23610ad9757664d644e369246edde1803fcb43ed72876565098a5d3828" -dependencies = [ - "cfg-if 0.1.10", - "core-foundation-sys 0.7.0", - "core-graphics 0.19.2", - "libc", - "objc", -] - -[[package]] -name = "coreaudio-rs" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11894b20ebfe1ff903cbdc52259693389eea03b94918a2def2c30c3bf227ad88" -dependencies = [ - "bitflags", - "coreaudio-sys", -] - -[[package]] -name = "coreaudio-sys" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b7e3347be6a09b46aba228d6608386739fb70beff4f61e07422da87b0bb31fa" -dependencies = [ - "bindgen", -] - -[[package]] -name = "cpal" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98f45f0a21f617cd2c788889ef710b63f075c949259593ea09c826f1e47a2418" -dependencies = [ - "alsa", - "core-foundation-sys 0.8.3", - "coreaudio-rs", - "jni", - "js-sys", - "lazy_static", - "libc", - "mach", - "ndk 0.3.0", - "ndk-glue 0.3.0", - "nix 0.20.2", - "oboe", - "parking_lot", - "stdweb", - "thiserror", - "web-sys", - "winapi", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97242a70df9b89a65d0b6df3c4bf5b9ce03c5b7309019777fbde37e7537f8762" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils", - "lazy_static", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "cty" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" - -[[package]] -name = "d3d12" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2daefd788d1e96e0a9d66dee4b828b883509bc3ea9ce30665f04c3246372690c" -dependencies = [ - "bitflags", - "libloading", - "winapi", -] - -[[package]] -name = "darling" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" -dependencies = [ - "darling_core 0.10.2", - "darling_macro 0.10.2", -] - -[[package]] -name = "darling" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4" -dependencies = [ - "darling_core 0.13.1", - "darling_macro 0.13.1", -] - -[[package]] -name = "darling_core" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim 0.9.3", - "syn", -] - -[[package]] -name = "darling_core" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim 0.10.0", - "syn", -] - -[[package]] -name = "darling_macro" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" -dependencies = [ - "darling_core 0.10.2", - "quote", - "syn", -] - -[[package]] -name = "darling_macro" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b" -dependencies = [ - "darling_core 0.13.1", - "quote", - "syn", -] - -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -dependencies = [ - "generic-array", -] - -[[package]] -name = "directories-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc" -dependencies = [ - "cfg-if 1.0.0", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "dispatch" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" - -[[package]] -name = "dlib" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794" -dependencies = [ - "libloading", -] - -[[package]] -name = "doc-comment" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" - -[[package]] -name = "downcast-rs" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" - -[[package]] -name = "either" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" - -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" - -[[package]] -name = "find-crate" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a98bbaacea1c0eb6a0876280051b892eb73594fd90cf3b20e9c817029c57d2" -dependencies = [ - "toml", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "fs_extra" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" - -[[package]] -name = "futures" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28560757fe2bb34e79f907794bb6b22ae8b0e5c669b638a1132f2592b19035b4" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7" - -[[package]] -name = "futures-executor" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29d6d2ff5bb10fb95c85b8ce46538a2e5f5e7fdc755623a7d4529ab8a4ed9d2a" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2" - -[[package]] -name = "futures-macro" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508" - -[[package]] -name = "futures-task" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" - -[[package]] -name = "futures-util" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - -[[package]] -name = "generic-array" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" -dependencies = [ - "typenum", -] - -[[package]] -name = "getrandom" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "wasi", -] - -[[package]] -name = "gimli" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" - -[[package]] -name = "glob" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" - -[[package]] -name = "glow" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8bd5877156a19b8ac83a29b2306fe20537429d318f3ff0a1a2119f8d9c61919" -dependencies = [ - "js-sys", - "slotmap", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "glyph_brush" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21932fbf719272848eec4583740d978203c6e7da4c4e203358f5b95946c97409" -dependencies = [ - "glyph_brush_draw_cache", - "glyph_brush_layout", - "log", - "ordered-float", - "rustc-hash", - "twox-hash", -] - -[[package]] -name = "glyph_brush_draw_cache" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6010675390f6889e09a21e2c8b575b3ee25667ea8237a8d59423f73cb8c28610" -dependencies = [ - "ab_glyph", - "crossbeam-channel", - "crossbeam-deque", - "linked-hash-map", - "rayon", - "rustc-hash", -] - -[[package]] -name = "glyph_brush_layout" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc32c2334f00ca5ac3695c5009ae35da21da8c62d255b5b96d56e2597a637a38" -dependencies = [ - "ab_glyph", - "approx 0.5.0", - "xi-unicode", -] - -[[package]] -name = "gpu-alloc" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fc59e5f710e310e76e6707f86c561dd646f69a8876da9131703b2f717de818d" -dependencies = [ - "bitflags", - "gpu-alloc-types", -] - -[[package]] -name = "gpu-alloc-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54804d0d6bc9d7f26db4eaec1ad10def69b599315f487d32c334a80d1efe67a5" -dependencies = [ - "bitflags", -] - -[[package]] -name = "gpu-descriptor" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a538f217be4d405ff4719a283ca68323cc2384003eca5baaa87501e821c81dda" -dependencies = [ - "bitflags", - "gpu-descriptor-types", - "hashbrown", -] - -[[package]] -name = "gpu-descriptor-types" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "363e3677e55ad168fef68cf9de3a4a310b53124c5e784c53a1d70e92d23f2126" -dependencies = [ - "bitflags", -] - -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash", -] - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hexf-parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" - -[[package]] -name = "host" -version = "0.0.1" -dependencies = [ - "arrayvec", - "bytemuck", - "cgmath", - "colored", - "confy", - "copypasta", - "fs_extra", - "futures", - "glyph_brush", - "libc", - "log", - "nonempty", - "page_size", - "palette", - "pest", - "pest_derive", - "roc_std", - "rodio", - "serde", - "snafu", - "threadpool", - "wgpu", - "wgpu_glyph", - "winit", -] - -[[package]] -name = "hound" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a164bb2ceaeff4f42542bdb847c41517c78a60f5649671b2a07312b6e117549" - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "indexmap" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "inplace_it" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90953f308a79fe6d62a4643e51f848fbfddcd05975a38e69fdf4ab86a7baf7ca" - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if 1.0.0", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "jni" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" -dependencies = [ - "cesu8", - "combine", - "jni-sys", - "log", - "thiserror", - "walkdir", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - -[[package]] -name = "jobserver" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" -dependencies = [ - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "khronos-egl" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" -dependencies = [ - "libc", - "libloading", - "pkg-config", -] - -[[package]] -name = "lazy-bytes-cast" -version = "5.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10257499f089cd156ad82d0a9cd57d9501fa2c989068992a97eb3c27836f206b" - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[package]] -name = "lewton" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030" -dependencies = [ - "byteorder", - "ogg", - "tinyvec", -] - -[[package]] -name = "libc" -version = "0.2.113" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eef78b64d87775463c549fbd80e19249ef436ea3bf1de2a1eb7e717ec7fab1e9" - -[[package]] -name = "libloading" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" -dependencies = [ - "cfg-if 1.0.0", - "winapi", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" - -[[package]] -name = "lock_api" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "mach" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" -dependencies = [ - "libc", -] - -[[package]] -name = "malloc_buf" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -dependencies = [ - "libc", -] - -[[package]] -name = "maplit" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" - -[[package]] -name = "memchr" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" - -[[package]] -name = "memmap2" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b6c2ebff6180198788f5db08d7ce3bc1d0b617176678831a7510825973e357" -dependencies = [ - "libc", -] - -[[package]] -name = "memoffset" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -dependencies = [ - "autocfg", -] - -[[package]] -name = "metal" -version = "0.23.1" -source = "git+https://github.com/gfx-rs/metal-rs?rev=44af5cc#44af5cca340617d42d701264f9bf71d1f3e68096" -dependencies = [ - "bitflags", - "block", - "core-graphics-types", - "foreign-types", - "log", - "objc", -] - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "minimp3" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "985438f75febf74c392071a975a29641b420dd84431135a6e6db721de4b74372" -dependencies = [ - "minimp3-sys", - "slice-deque", - "thiserror", -] - -[[package]] -name = "minimp3-sys" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e21c73734c69dc95696c9ed8926a2b393171d98b3f5f5935686a26a487ab9b90" -dependencies = [ - "cc", -] - -[[package]] -name = "miniz_oxide" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" -dependencies = [ - "adler", - "autocfg", -] - -[[package]] -name = "mio" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2" -dependencies = [ - "libc", - "log", - "miow", - "ntapi", - "winapi", -] - -[[package]] -name = "miow" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" -dependencies = [ - "winapi", -] - -[[package]] -name = "naga" -version = "0.8.0" -source = "git+https://github.com/gfx-rs/naga?rev=8e2e39e#8e2e39e4d8fa5bbb657c3b170b4f6607d703e284" -dependencies = [ - "bit-set", - "bitflags", - "codespan-reporting", - "hexf-parse", - "indexmap", - "log", - "num-traits", - "rustc-hash", - "spirv", - "thiserror", -] - -[[package]] -name = "ndk" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8794322172319b972f528bf90c6b467be0079f1fa82780ffb431088e741a73ab" -dependencies = [ - "jni-sys", - "ndk-sys 0.2.2", - "num_enum", - "thiserror", -] - -[[package]] -name = "ndk" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d868f654c72e75f8687572699cdabe755f03effbb62542768e995d5b8d699d" -dependencies = [ - "bitflags", - "jni-sys", - "ndk-sys 0.2.2", - "num_enum", - "thiserror", -] - -[[package]] -name = "ndk" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2032c77e030ddee34a6787a64166008da93f6a352b629261d0fee232b8742dd4" -dependencies = [ - "bitflags", - "jni-sys", - "ndk-sys 0.3.0", - "num_enum", - "thiserror", -] - -[[package]] -name = "ndk-glue" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5caf0c24d51ac1c905c27d4eda4fa0635bbe0de596b8f79235e0b17a4d29385" -dependencies = [ - "lazy_static", - "libc", - "log", - "ndk 0.3.0", - "ndk-macro 0.2.0", - "ndk-sys 0.2.2", -] - -[[package]] -name = "ndk-glue" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc291b8de2095cba8dab7cf381bf582ff4c17a09acf854c32e46545b08085d28" -dependencies = [ - "lazy_static", - "libc", - "log", - "ndk 0.5.0", - "ndk-macro 0.3.0", - "ndk-sys 0.2.2", -] - -[[package]] -name = "ndk-glue" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04c0d14b0858eb9962a5dac30b809b19f19da7e4547d64af2b0bb051d2e55d79" -dependencies = [ - "lazy_static", - "libc", - "log", - "ndk 0.6.0", - "ndk-macro 0.3.0", - "ndk-sys 0.3.0", -] - -[[package]] -name = "ndk-macro" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d1c6307dc424d0f65b9b06e94f88248e6305726b14729fd67a5e47b2dc481d" -dependencies = [ - "darling 0.10.2", - "proc-macro-crate 0.1.5", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "ndk-macro" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c" -dependencies = [ - "darling 0.13.1", - "proc-macro-crate 1.1.0", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "ndk-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121" - -[[package]] -name = "ndk-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e5a6ae77c8ee183dcbbba6150e2e6b9f3f4196a7666c02a715a95692ec1fa97" -dependencies = [ - "jni-sys", -] - -[[package]] -name = "nix" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5e06129fb611568ef4e868c14b326274959aa70ff7776e9d55323531c374945" -dependencies = [ - "bitflags", - "cc", - "cfg-if 1.0.0", - "libc", - "memoffset", -] - -[[package]] -name = "nix" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1e25ee6b412c2a1e3fcb6a4499a5c1bfe7f43e014bdce9a6b6666e5aa2d187" -dependencies = [ - "bitflags", - "cc", - "cfg-if 1.0.0", - "libc", - "memoffset", -] - -[[package]] -name = "nom" -version = "5.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" -dependencies = [ - "memchr", - "version_check", -] - -[[package]] -name = "nom" -version = "7.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109" -dependencies = [ - "memchr", - "minimal-lexical", - "version_check", -] - -[[package]] -name = "nonempty" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7" - -[[package]] -name = "ntapi" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" -dependencies = [ - "winapi", -] - -[[package]] -name = "num-derive" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "num-traits" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "num_enum" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "720d3ea1055e4e4574c0c0b0f8c3fd4f24c4cdaf465948206dea090b57b526ad" -dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d992b768490d7fe0d8586d9b5745f6c49f557da6d81dc982b1d167ad4edbb21" -dependencies = [ - "proc-macro-crate 1.1.0", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "objc" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" -dependencies = [ - "malloc_buf", - "objc_exception", -] - -[[package]] -name = "objc-foundation" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" -dependencies = [ - "block", - "objc", - "objc_id", -] - -[[package]] -name = "objc_exception" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" -dependencies = [ - "cc", -] - -[[package]] -name = "objc_id" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" -dependencies = [ - "objc", -] - -[[package]] -name = "object" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" -dependencies = [ - "memchr", -] - -[[package]] -name = "oboe" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2463c8f2e19b4e0d0710a21f8e4011501ff28db1c95d7a5482a553b2100502d2" -dependencies = [ - "jni", - "ndk 0.6.0", - "ndk-glue 0.6.0", - "num-derive", - "num-traits", - "oboe-sys", -] - -[[package]] -name = "oboe-sys" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3370abb7372ed744232c12954d920d1a40f1c4686de9e79e800021ef492294bd" -dependencies = [ - "cc", -] - -[[package]] -name = "ogg" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e" -dependencies = [ - "byteorder", -] - -[[package]] -name = "once_cell" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" - -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" - -[[package]] -name = "ordered-float" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87" -dependencies = [ - "num-traits", -] - -[[package]] -name = "owned_ttf_parser" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ef05f2882a8b3e7acc10c153ade2631f7bfc8ce00d2bf3fb8f4e9d2ae6ea5c3" -dependencies = [ - "ttf-parser", -] - -[[package]] -name = "page_size" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eebde548fbbf1ea81a99b128872779c437752fb99f217c45245e1a61dcd9edcd" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "palette" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9735f7e1e51a3f740bacd5dc2724b61a7806f23597a8736e679f38ee3435d18" -dependencies = [ - "approx 0.5.0", - "num-traits", - "palette_derive", - "phf", -] - -[[package]] -name = "palette_derive" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7799c3053ea8a6d8a1193c7ba42f534e7863cf52e378a7f90406f4a645d33bad" -dependencies = [ - "find-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" -dependencies = [ - "cfg-if 1.0.0", - "instant", - "libc", - "redox_syscall", - "smallvec", - "winapi", -] - -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" - -[[package]] -name = "percent-encoding" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" - -[[package]] -name = "pest" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" -dependencies = [ - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pest_meta" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" -dependencies = [ - "maplit", - "pest", - "sha-1", -] - -[[package]] -name = "phf" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ac8b67553a7ca9457ce0e526948cad581819238f4a9d1ea74545851fa24f37" -dependencies = [ - "phf_macros", - "phf_shared", - "proc-macro-hack", -] - -[[package]] -name = "phf_generator" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d43f3220d96e0080cc9ea234978ccd80d904eafb17be31bb0f76daaea6493082" -dependencies = [ - "phf_shared", - "rand", -] - -[[package]] -name = "phf_macros" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b706f5936eb50ed880ae3009395b43ed19db5bff2ebd459c95e7bf013a89ab86" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro-hack", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "phf_shared" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a68318426de33640f02be62b4ae8eb1261be2efbc337b60c54d845bf4484e0d9" -dependencies = [ - "siphasher", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkg-config" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" - -[[package]] -name = "ppv-lite86" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" - -[[package]] -name = "proc-macro-crate" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" -dependencies = [ - "toml", -] - -[[package]] -name = "proc-macro-crate" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83" -dependencies = [ - "thiserror", - "toml", -] - -[[package]] -name = "proc-macro-hack" -version = "0.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" - -[[package]] -name = "proc-macro2" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "profiling" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9145ac0af1d93c638c98c40cf7d25665f427b2a44ad0a99b1dccf3e2f25bb987" - -[[package]] -name = "quick-xml" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8533f14c8382aaad0d592c812ac3b826162128b65662331e1127b45c3d18536b" -dependencies = [ - "memchr", -] - -[[package]] -name = "quote" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core", -] - -[[package]] -name = "range-alloc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e935c45e09cc6dcf00d2f0b2d630a58f4095320223d47fc68918722f0538b6" - -[[package]] -name = "raw-window-handle" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fba75eee94a9d5273a68c9e1e105d9cffe1ef700532325788389e5a83e2522b7" -dependencies = [ - "cty", -] - -[[package]] -name = "rayon" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" -dependencies = [ - "autocfg", - "crossbeam-deque", - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-utils", - "lazy_static", - "num_cpus", -] - -[[package]] -name = "redox_syscall" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" -dependencies = [ - "bitflags", -] - -[[package]] -name = "redox_users" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" -dependencies = [ - "getrandom", - "redox_syscall", -] - -[[package]] -name = "regex" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" -dependencies = [ - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.6.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" - -[[package]] -name = "renderdoc-sys" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1382d1f0a252c4bf97dc20d979a2fdd05b024acd7c2ed0f7595d7817666a157" - -[[package]] -name = "roc_std" -version = "0.0.1" -dependencies = [ - "arrayvec", - "static_assertions", -] - -[[package]] -name = "rodio" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d98f5e557b61525057e2bc142c8cd7f0e70d75dc32852309bec440e6e046bf9" -dependencies = [ - "claxon", - "cpal", - "hound", - "lewton", - "minimp3", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "ryu" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" - -[[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 = "scoped-tls" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "serde" -version = "1.0.135" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cf9235533494ea2ddcdb794665461814781c53f19d87b76e571a1c35acbad2b" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.135" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dcde03d87d4c973c04be249e7d8f0b35db1c848c487bd43032808e59dd8328d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_yaml" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a521f2940385c165a24ee286aa8599633d162077a54bdcae2a6fd5a7bfa7a0" -dependencies = [ - "indexmap", - "ryu", - "serde", - "yaml-rust", -] - -[[package]] -name = "sha-1" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" -dependencies = [ - "block-buffer", - "digest", - "fake-simd", - "opaque-debug", -] - -[[package]] -name = "shlex" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" - -[[package]] -name = "siphasher" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a86232ab60fa71287d7f2ddae4a7073f6b7aac33631c3015abb556f08c6d0a3e" - -[[package]] -name = "slab" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" - -[[package]] -name = "slice-deque" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31ef6ee280cdefba6d2d0b4b78a84a1c1a3f3a4cec98c2d4231c8bc225de0f25" -dependencies = [ - "libc", - "mach", - "winapi", -] - -[[package]] -name = "slotmap" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e08e261d0e8f5c43123b7adf3e4ca1690d655377ac93a03b2c9d3e98de1342" -dependencies = [ - "version_check", -] - -[[package]] -name = "smallvec" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" - -[[package]] -name = "smithay-client-toolkit" -version = "0.15.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1325f292209cee78d5035530932422a30aa4c8fda1a16593ac083c1de211e68a" -dependencies = [ - "bitflags", - "calloop", - "dlib", - "lazy_static", - "log", - "memmap2", - "nix 0.22.0", - "pkg-config", - "wayland-client", - "wayland-cursor", - "wayland-protocols", -] - -[[package]] -name = "smithay-clipboard" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "610b551bd25378bfd2b8e7a0fcbd83d427e8f2f6a40c47ae0f70688e9949dd55" -dependencies = [ - "smithay-client-toolkit", - "wayland-client", -] - -[[package]] -name = "snafu" -version = "0.6.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eab12d3c261b2308b0d80c26fffb58d17eba81a4be97890101f416b478c79ca7" -dependencies = [ - "backtrace", - "doc-comment", - "snafu-derive", -] - -[[package]] -name = "snafu-derive" -version = "0.6.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1508efa03c362e23817f96cde18abed596a25219a8b2c66e8db33c03543d315b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "spirv" -version = "0.2.0+1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "246bfa38fe3db3f1dfc8ca5a2cdeb7348c78be2112740cc0ec8ef18b6d94f830" -dependencies = [ - "bitflags", - "num-traits", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "stdweb" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e" - -[[package]] -name = "strsim" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "syn" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "termcolor" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "thiserror" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "threadpool" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" -dependencies = [ - "num_cpus", -] - -[[package]] -name = "tinyvec" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" - -[[package]] -name = "toml" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" -dependencies = [ - "serde", -] - -[[package]] -name = "ttf-parser" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ccbe8381883510b6a2d8f1e32905bddd178c11caef8083086d0c0c9ab0ac281" - -[[package]] -name = "twox-hash" -version = "1.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee73e6e4924fe940354b8d4d98cad5231175d615cd855b758adc658c0aac6a0" -dependencies = [ - "cfg-if 0.1.10", - "rand", - "static_assertions", -] - -[[package]] -name = "typenum" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" - -[[package]] -name = "ucd-trie" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" - -[[package]] -name = "unicode-width" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" - -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "walkdir" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" -dependencies = [ - "same-file", - "winapi", - "winapi-util", -] - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - -[[package]] -name = "wasm-bindgen" -version = "0.2.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" -dependencies = [ - "cfg-if 1.0.0", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" -dependencies = [ - "bumpalo", - "lazy_static", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395" -dependencies = [ - "cfg-if 1.0.0", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" - -[[package]] -name = "wayland-client" -version = "0.29.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91223460e73257f697d9e23d401279123d36039a3f7a449e983f123292d4458f" -dependencies = [ - "bitflags", - "downcast-rs", - "libc", - "nix 0.22.0", - "scoped-tls", - "wayland-commons", - "wayland-scanner", - "wayland-sys", -] - -[[package]] -name = "wayland-commons" -version = "0.29.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94f6e5e340d7c13490eca867898c4cec5af56c27a5ffe5c80c6fc4708e22d33e" -dependencies = [ - "nix 0.22.0", - "once_cell", - "smallvec", - "wayland-sys", -] - -[[package]] -name = "wayland-cursor" -version = "0.29.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c52758f13d5e7861fc83d942d3d99bf270c83269575e52ac29e5b73cb956a6bd" -dependencies = [ - "nix 0.22.0", - "wayland-client", - "xcursor", -] - -[[package]] -name = "wayland-protocols" -version = "0.29.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60147ae23303402e41fe034f74fb2c35ad0780ee88a1c40ac09a3be1e7465741" -dependencies = [ - "bitflags", - "wayland-client", - "wayland-commons", - "wayland-scanner", -] - -[[package]] -name = "wayland-scanner" -version = "0.29.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39a1ed3143f7a143187156a2ab52742e89dac33245ba505c17224df48939f9e0" -dependencies = [ - "proc-macro2", - "quote", - "xml-rs", -] - -[[package]] -name = "wayland-sys" -version = "0.29.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9341df79a8975679188e37dab3889bfa57c44ac2cb6da166f519a81cbe452d4" -dependencies = [ - "dlib", - "lazy_static", - "pkg-config", -] - -[[package]] -name = "web-sys" -version = "0.3.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "wgpu" -version = "0.12.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=0545e36#0545e36aa82709cca78c14eb3813f10eea7a9275" -dependencies = [ - "arrayvec", - "js-sys", - "log", - "naga", - "parking_lot", - "raw-window-handle", - "smallvec", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "wgpu-core", - "wgpu-hal", - "wgpu-types", -] - -[[package]] -name = "wgpu-core" -version = "0.12.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=0545e36#0545e36aa82709cca78c14eb3813f10eea7a9275" -dependencies = [ - "arrayvec", - "bitflags", - "cfg_aliases", - "codespan-reporting", - "copyless", - "fxhash", - "log", - "naga", - "parking_lot", - "profiling", - "raw-window-handle", - "smallvec", - "thiserror", - "wgpu-hal", - "wgpu-types", -] - -[[package]] -name = "wgpu-hal" -version = "0.12.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=0545e36#0545e36aa82709cca78c14eb3813f10eea7a9275" -dependencies = [ - "arrayvec", - "ash", - "bit-set", - "bitflags", - "block", - "core-graphics-types", - "d3d12", - "foreign-types", - "fxhash", - "glow", - "gpu-alloc", - "gpu-descriptor", - "inplace_it", - "js-sys", - "khronos-egl", - "libloading", - "log", - "metal", - "naga", - "objc", - "parking_lot", - "profiling", - "range-alloc", - "raw-window-handle", - "renderdoc-sys", - "thiserror", - "wasm-bindgen", - "web-sys", - "wgpu-types", - "winapi", -] - -[[package]] -name = "wgpu-types" -version = "0.12.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=0545e36#0545e36aa82709cca78c14eb3813f10eea7a9275" -dependencies = [ - "bitflags", -] - -[[package]] -name = "wgpu_glyph" -version = "0.16.0" -source = "git+https://github.com/Anton-4/wgpu_glyph?rev=257d109#257d1098cbafa3c8a0a2465937b06fc730fc6ffb" -dependencies = [ - "bytemuck", - "glyph_brush", - "log", - "wgpu", -] - -[[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.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -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 = "winit" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b43cc931d58b99461188607efd7acb2a093e65fc621f54cad78517a6063e73a" -dependencies = [ - "bitflags", - "cocoa", - "core-foundation 0.9.2", - "core-graphics 0.22.3", - "core-video-sys", - "dispatch", - "instant", - "lazy_static", - "libc", - "log", - "mio", - "ndk 0.5.0", - "ndk-glue 0.5.0", - "ndk-sys 0.2.2", - "objc", - "parking_lot", - "percent-encoding", - "raw-window-handle", - "smithay-client-toolkit", - "wasm-bindgen", - "wayland-client", - "wayland-protocols", - "web-sys", - "winapi", - "x11-dl", -] - -[[package]] -name = "x11-clipboard" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "473068b7b80ac86a18328824f1054e5e007898c47b5bbc281bd7abe32bc3653c" -dependencies = [ - "xcb", -] - -[[package]] -name = "x11-dl" -version = "2.19.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea26926b4ce81a6f5d9d0f3a0bc401e5a37c6ae14a1bfaa8ff6099ca80038c59" -dependencies = [ - "lazy_static", - "libc", - "pkg-config", -] - -[[package]] -name = "xcb" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771e2b996df720cd1c6dd9ff90f62d91698fd3610cc078388d0564bdd6622a9c" -dependencies = [ - "libc", - "log", - "quick-xml", -] - -[[package]] -name = "xcursor" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "463705a63313cd4301184381c5e8042f0a7e9b4bb63653f216311d4ae74690b7" -dependencies = [ - "nom 7.1.0", -] - -[[package]] -name = "xi-unicode" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a67300977d3dc3f8034dae89778f502b6ba20b269527b3223ba59c0cf393bb8a" - -[[package]] -name = "xml-rs" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" - -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] diff --git a/examples/gui/breakout/platform/Cargo.toml b/examples/gui/breakout/platform/Cargo.toml index 5b612df452..8590583a5b 100644 --- a/examples/gui/breakout/platform/Cargo.toml +++ b/examples/gui/breakout/platform/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "host" -version = "0.0.1" authors = ["The Roc Contributors"] -license = "UPL-1.0" edition = "2021" +license = "UPL-1.0" +version = "0.0.1" [lib] name = "host" @@ -15,32 +15,28 @@ name = "host" path = "src/main.rs" [dependencies] -roc_std = { path = "../../../../crates/roc_std" } -libc = "0.2" arrayvec = "0.7.2" +libc = "0.2" page_size = "0.4.2" -# when changing winit version, check if copypasta can be updated simultaneously so they use the same versions for their dependencies. This will save build time. -winit = "0.26.1" -wgpu = { git = "https://github.com/gfx-rs/wgpu", rev = "0545e36" } -wgpu_glyph = { git = "https://github.com/Anton-4/wgpu_glyph", rev = "257d109" } +roc_std = { path = "../../../../crates/roc_std" } +cgmath = "0.18.0" +colored = "2.0.0" +confy = { git = 'https://github.com/rust-cli/confy', features = ["yaml_conf"], default-features = false } +copypasta = "0.7.1" +fs_extra = "1.2.0" +futures = "0.3.17" glyph_brush = "0.7.2" log = "0.4.14" -futures = "0.3.17" -cgmath = "0.18.0" -snafu = { version = "0.6.10", features = ["backtraces"] } -colored = "2.0.0" +nonempty = "0.7.0" +palette = "0.6.0" pest = "2.1.3" pest_derive = "2.1.0" -copypasta = "0.7.1" -palette = "0.6.0" -confy = { git = 'https://github.com/rust-cli/confy', features = [ - "yaml_conf" -], default-features = false } serde = { version = "1.0.130", features = ["derive"] } -nonempty = "0.7.0" -fs_extra = "1.2.0" -rodio = { version = "0.14.0", optional = true } # to play sounds +snafu = { version = "0.6.10", features = ["backtraces"] } threadpool = "1.8.1" +wgpu = { git = "https://github.com/gfx-rs/wgpu", rev = "0545e36" } +wgpu_glyph = { git = "https://github.com/Anton-4/wgpu_glyph", rev = "257d109" } +winit = "0.26.1" [package.metadata.cargo-udeps.ignore] # confy is currently unused but should not be removed @@ -50,7 +46,6 @@ normal = ["confy"] [features] default = [] -with_sound = ["rodio"] [dependencies.bytemuck] version = "1.7.2" diff --git a/examples/gui/platform/Cargo.lock b/examples/gui/platform/Cargo.lock deleted file mode 100644 index 453ced75e3..0000000000 --- a/examples/gui/platform/Cargo.lock +++ /dev/null @@ -1,2800 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "ab_glyph" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61caed9aec6daeee1ea38ccf5fb225e4f96c1eeead1b4a5c267324a63cf02326" -dependencies = [ - "ab_glyph_rasterizer", - "owned_ttf_parser", -] - -[[package]] -name = "ab_glyph_rasterizer" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a13739d7177fbd22bb0ed28badfff9f372f8bef46c863db4e1c6248f6b223b6e" - -[[package]] -name = "addr2line" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "ahash" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - -[[package]] -name = "alsa" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75c4da790adcb2ce5e758c064b4f3ec17a30349f9961d3e5e6c9688b052a9e18" -dependencies = [ - "alsa-sys", - "bitflags", - "libc", - "nix 0.20.2", -] - -[[package]] -name = "alsa-sys" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" -dependencies = [ - "libc", - "pkg-config", -] - -[[package]] -name = "approx" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f2a05fd1bd10b2527e20a2cd32d8873d115b8b39fe219ee25f42a8aca6ba278" -dependencies = [ - "num-traits", -] - -[[package]] -name = "approx" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "072df7202e63b127ab55acfe16ce97013d5b97bf160489336d3f1840fd78e99e" -dependencies = [ - "num-traits", -] - -[[package]] -name = "arrayvec" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" - -[[package]] -name = "ash" -version = "0.35.1+1.2.203" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7fd04def1c9101b5fb488c131022d2d6f87753ef4b1b11b279e2af404fae6b9" -dependencies = [ - "libloading", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - -[[package]] -name = "backtrace" -version = "0.3.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321629d8ba6513061f26707241fa9bc89524ff1cd7a915a97ef0c62c666ce1b6" -dependencies = [ - "addr2line", - "cc", - "cfg-if 1.0.0", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "bindgen" -version = "0.56.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da379dbebc0b76ef63ca68d8fc6e71c0f13e59432e0987e508c1820e6ab5239" -dependencies = [ - "bitflags", - "cexpr", - "clang-sys", - "lazy_static", - "lazycell", - "peeking_take_while", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", -] - -[[package]] -name = "bit-set" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de" -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.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" - -[[package]] -name = "block" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" - -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -dependencies = [ - "block-padding", - "byte-tools", - "byteorder", - "generic-array", -] - -[[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -dependencies = [ - "byte-tools", -] - -[[package]] -name = "bumpalo" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" - -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" - -[[package]] -name = "bytemuck" -version = "1.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439989e6b8c38d1b6570a384ef1e49c8848128f5a97f3914baef02920842712f" -dependencies = [ - "bytemuck_derive", -] - -[[package]] -name = "bytemuck_derive" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e215f8c2f9f79cb53c8335e687ffd07d5bfcb6fe5fc80723762d0be46e7cc54" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "bytes" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" - -[[package]] -name = "calloop" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf2eec61efe56aa1e813f5126959296933cf0700030e4314786c48779a66ab82" -dependencies = [ - "log", - "nix 0.22.0", -] - -[[package]] -name = "cc" -version = "1.0.72" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" -dependencies = [ - "jobserver", -] - -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - -[[package]] -name = "cexpr" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27" -dependencies = [ - "nom 5.1.2", -] - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cfg_aliases" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" - -[[package]] -name = "cgmath" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a98d30140e3296250832bbaaff83b27dcd6fa3cc70fb6f1f3e5c9c0023b5317" -dependencies = [ - "approx 0.4.0", - "num-traits", -] - -[[package]] -name = "clang-sys" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa66045b9cb23c2e9c1520732030608b02ee07e5cfaa5a521ec15ded7fa24c90" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "claxon" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688" - -[[package]] -name = "clipboard-win" -version = "3.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fdf5e01086b6be750428ba4a40619f847eb2e95756eee84b18e06e5f0b50342" -dependencies = [ - "lazy-bytes-cast", - "winapi", -] - -[[package]] -name = "cocoa" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63902e9223530efb4e26ccd0cf55ec30d592d3b42e21a28defc42a9586e832" -dependencies = [ - "bitflags", - "block", - "cocoa-foundation", - "core-foundation 0.9.2", - "core-graphics 0.22.3", - "foreign-types", - "libc", - "objc", -] - -[[package]] -name = "cocoa-foundation" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318" -dependencies = [ - "bitflags", - "block", - "core-foundation 0.9.2", - "core-graphics-types", - "foreign-types", - "libc", - "objc", -] - -[[package]] -name = "codespan-reporting" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] - -[[package]] -name = "colored" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" -dependencies = [ - "atty", - "lazy_static", - "winapi", -] - -[[package]] -name = "combine" -version = "4.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50b727aacc797f9fc28e355d21f34709ac4fc9adecfe470ad07b8f4464f53062" -dependencies = [ - "bytes", - "memchr", -] - -[[package]] -name = "confy" -version = "0.4.0" -source = "git+https://github.com/rust-cli/confy#664992aecd97b4af0eda8d9d2825885662e1c6b4" -dependencies = [ - "directories-next", - "serde", - "serde_yaml", -] - -[[package]] -name = "copyless" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536" - -[[package]] -name = "copypasta" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4423d79fed83ebd9ab81ec21fa97144300a961782158287dc9bf7eddac37ff0b" -dependencies = [ - "clipboard-win", - "objc", - "objc-foundation", - "objc_id", - "smithay-clipboard", - "x11-clipboard", -] - -[[package]] -name = "core-foundation" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" -dependencies = [ - "core-foundation-sys 0.7.0", - "libc", -] - -[[package]] -name = "core-foundation" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3" -dependencies = [ - "core-foundation-sys 0.8.3", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" - -[[package]] -name = "core-foundation-sys" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" - -[[package]] -name = "core-graphics" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3889374e6ea6ab25dba90bb5d96202f61108058361f6dc72e8b03e6f8bbe923" -dependencies = [ - "bitflags", - "core-foundation 0.7.0", - "foreign-types", - "libc", -] - -[[package]] -name = "core-graphics" -version = "0.22.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" -dependencies = [ - "bitflags", - "core-foundation 0.9.2", - "core-graphics-types", - "foreign-types", - "libc", -] - -[[package]] -name = "core-graphics-types" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" -dependencies = [ - "bitflags", - "core-foundation 0.9.2", - "foreign-types", - "libc", -] - -[[package]] -name = "core-video-sys" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ecad23610ad9757664d644e369246edde1803fcb43ed72876565098a5d3828" -dependencies = [ - "cfg-if 0.1.10", - "core-foundation-sys 0.7.0", - "core-graphics 0.19.2", - "libc", - "objc", -] - -[[package]] -name = "coreaudio-rs" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11894b20ebfe1ff903cbdc52259693389eea03b94918a2def2c30c3bf227ad88" -dependencies = [ - "bitflags", - "coreaudio-sys", -] - -[[package]] -name = "coreaudio-sys" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b7e3347be6a09b46aba228d6608386739fb70beff4f61e07422da87b0bb31fa" -dependencies = [ - "bindgen", -] - -[[package]] -name = "cpal" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98f45f0a21f617cd2c788889ef710b63f075c949259593ea09c826f1e47a2418" -dependencies = [ - "alsa", - "core-foundation-sys 0.8.3", - "coreaudio-rs", - "jni", - "js-sys", - "lazy_static", - "libc", - "mach", - "ndk 0.3.0", - "ndk-glue 0.3.0", - "nix 0.20.2", - "oboe", - "parking_lot", - "stdweb", - "thiserror", - "web-sys", - "winapi", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97242a70df9b89a65d0b6df3c4bf5b9ce03c5b7309019777fbde37e7537f8762" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils", - "lazy_static", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcae03edb34f947e64acdb1c33ec169824e20657e9ecb61cef6c8c74dcb8120" -dependencies = [ - "cfg-if 1.0.0", - "lazy_static", -] - -[[package]] -name = "cty" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" - -[[package]] -name = "d3d12" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2daefd788d1e96e0a9d66dee4b828b883509bc3ea9ce30665f04c3246372690c" -dependencies = [ - "bitflags", - "libloading", - "winapi", -] - -[[package]] -name = "darling" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" -dependencies = [ - "darling_core 0.10.2", - "darling_macro 0.10.2", -] - -[[package]] -name = "darling" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4" -dependencies = [ - "darling_core 0.13.1", - "darling_macro 0.13.1", -] - -[[package]] -name = "darling_core" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim 0.9.3", - "syn", -] - -[[package]] -name = "darling_core" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim 0.10.0", - "syn", -] - -[[package]] -name = "darling_macro" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" -dependencies = [ - "darling_core 0.10.2", - "quote", - "syn", -] - -[[package]] -name = "darling_macro" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b" -dependencies = [ - "darling_core 0.13.1", - "quote", - "syn", -] - -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -dependencies = [ - "generic-array", -] - -[[package]] -name = "directories-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc" -dependencies = [ - "cfg-if 1.0.0", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "dispatch" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" - -[[package]] -name = "dlib" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794" -dependencies = [ - "libloading", -] - -[[package]] -name = "doc-comment" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" - -[[package]] -name = "downcast-rs" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" - -[[package]] -name = "either" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" - -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" - -[[package]] -name = "find-crate" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a98bbaacea1c0eb6a0876280051b892eb73594fd90cf3b20e9c817029c57d2" -dependencies = [ - "toml", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "fs_extra" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" - -[[package]] -name = "futures" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28560757fe2bb34e79f907794bb6b22ae8b0e5c669b638a1132f2592b19035b4" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7" - -[[package]] -name = "futures-executor" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29d6d2ff5bb10fb95c85b8ce46538a2e5f5e7fdc755623a7d4529ab8a4ed9d2a" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2" - -[[package]] -name = "futures-macro" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508" - -[[package]] -name = "futures-task" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" - -[[package]] -name = "futures-util" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - -[[package]] -name = "generic-array" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" -dependencies = [ - "typenum", -] - -[[package]] -name = "getrandom" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "wasi", -] - -[[package]] -name = "gimli" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" - -[[package]] -name = "glob" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" - -[[package]] -name = "glow" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8bd5877156a19b8ac83a29b2306fe20537429d318f3ff0a1a2119f8d9c61919" -dependencies = [ - "js-sys", - "slotmap", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "glyph_brush" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21932fbf719272848eec4583740d978203c6e7da4c4e203358f5b95946c97409" -dependencies = [ - "glyph_brush_draw_cache", - "glyph_brush_layout", - "log", - "ordered-float", - "rustc-hash", - "twox-hash", -] - -[[package]] -name = "glyph_brush_draw_cache" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6010675390f6889e09a21e2c8b575b3ee25667ea8237a8d59423f73cb8c28610" -dependencies = [ - "ab_glyph", - "crossbeam-channel", - "crossbeam-deque", - "linked-hash-map", - "rayon", - "rustc-hash", -] - -[[package]] -name = "glyph_brush_layout" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc32c2334f00ca5ac3695c5009ae35da21da8c62d255b5b96d56e2597a637a38" -dependencies = [ - "ab_glyph", - "approx 0.5.0", - "xi-unicode", -] - -[[package]] -name = "gpu-alloc" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fc59e5f710e310e76e6707f86c561dd646f69a8876da9131703b2f717de818d" -dependencies = [ - "bitflags", - "gpu-alloc-types", -] - -[[package]] -name = "gpu-alloc-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54804d0d6bc9d7f26db4eaec1ad10def69b599315f487d32c334a80d1efe67a5" -dependencies = [ - "bitflags", -] - -[[package]] -name = "gpu-descriptor" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a538f217be4d405ff4719a283ca68323cc2384003eca5baaa87501e821c81dda" -dependencies = [ - "bitflags", - "gpu-descriptor-types", - "hashbrown", -] - -[[package]] -name = "gpu-descriptor-types" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "363e3677e55ad168fef68cf9de3a4a310b53124c5e784c53a1d70e92d23f2126" -dependencies = [ - "bitflags", -] - -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash", -] - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hexf-parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" - -[[package]] -name = "host" -version = "0.0.1" -dependencies = [ - "arrayvec", - "bytemuck", - "cgmath", - "colored", - "confy", - "copypasta", - "fs_extra", - "futures", - "glyph_brush", - "libc", - "log", - "nonempty", - "page_size", - "palette", - "pest", - "pest_derive", - "roc_std", - "rodio", - "serde", - "snafu", - "threadpool", - "wgpu", - "wgpu_glyph", - "winit", -] - -[[package]] -name = "hound" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a164bb2ceaeff4f42542bdb847c41517c78a60f5649671b2a07312b6e117549" - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "indexmap" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "inplace_it" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90953f308a79fe6d62a4643e51f848fbfddcd05975a38e69fdf4ab86a7baf7ca" - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if 1.0.0", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "jni" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" -dependencies = [ - "cesu8", - "combine", - "jni-sys", - "log", - "thiserror", - "walkdir", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - -[[package]] -name = "jobserver" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" -dependencies = [ - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "khronos-egl" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" -dependencies = [ - "libc", - "libloading", - "pkg-config", -] - -[[package]] -name = "lazy-bytes-cast" -version = "5.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10257499f089cd156ad82d0a9cd57d9501fa2c989068992a97eb3c27836f206b" - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[package]] -name = "lewton" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030" -dependencies = [ - "byteorder", - "ogg", - "tinyvec", -] - -[[package]] -name = "libc" -version = "0.2.113" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eef78b64d87775463c549fbd80e19249ef436ea3bf1de2a1eb7e717ec7fab1e9" - -[[package]] -name = "libloading" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" -dependencies = [ - "cfg-if 1.0.0", - "winapi", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" - -[[package]] -name = "lock_api" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "mach" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" -dependencies = [ - "libc", -] - -[[package]] -name = "malloc_buf" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -dependencies = [ - "libc", -] - -[[package]] -name = "maplit" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" - -[[package]] -name = "memchr" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" - -[[package]] -name = "memmap2" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b6c2ebff6180198788f5db08d7ce3bc1d0b617176678831a7510825973e357" -dependencies = [ - "libc", -] - -[[package]] -name = "memoffset" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -dependencies = [ - "autocfg", -] - -[[package]] -name = "metal" -version = "0.23.1" -source = "git+https://github.com/gfx-rs/metal-rs?rev=44af5cc#44af5cca340617d42d701264f9bf71d1f3e68096" -dependencies = [ - "bitflags", - "block", - "core-graphics-types", - "foreign-types", - "log", - "objc", -] - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "minimp3" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "985438f75febf74c392071a975a29641b420dd84431135a6e6db721de4b74372" -dependencies = [ - "minimp3-sys", - "slice-deque", - "thiserror", -] - -[[package]] -name = "minimp3-sys" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e21c73734c69dc95696c9ed8926a2b393171d98b3f5f5935686a26a487ab9b90" -dependencies = [ - "cc", -] - -[[package]] -name = "miniz_oxide" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" -dependencies = [ - "adler", - "autocfg", -] - -[[package]] -name = "mio" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2" -dependencies = [ - "libc", - "log", - "miow", - "ntapi", - "winapi", -] - -[[package]] -name = "miow" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" -dependencies = [ - "winapi", -] - -[[package]] -name = "naga" -version = "0.8.0" -source = "git+https://github.com/gfx-rs/naga?rev=8e2e39e#8e2e39e4d8fa5bbb657c3b170b4f6607d703e284" -dependencies = [ - "bit-set", - "bitflags", - "codespan-reporting", - "hexf-parse", - "indexmap", - "log", - "num-traits", - "rustc-hash", - "spirv", - "thiserror", -] - -[[package]] -name = "ndk" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8794322172319b972f528bf90c6b467be0079f1fa82780ffb431088e741a73ab" -dependencies = [ - "jni-sys", - "ndk-sys 0.2.2", - "num_enum", - "thiserror", -] - -[[package]] -name = "ndk" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d868f654c72e75f8687572699cdabe755f03effbb62542768e995d5b8d699d" -dependencies = [ - "bitflags", - "jni-sys", - "ndk-sys 0.2.2", - "num_enum", - "thiserror", -] - -[[package]] -name = "ndk" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2032c77e030ddee34a6787a64166008da93f6a352b629261d0fee232b8742dd4" -dependencies = [ - "bitflags", - "jni-sys", - "ndk-sys 0.3.0", - "num_enum", - "thiserror", -] - -[[package]] -name = "ndk-glue" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5caf0c24d51ac1c905c27d4eda4fa0635bbe0de596b8f79235e0b17a4d29385" -dependencies = [ - "lazy_static", - "libc", - "log", - "ndk 0.3.0", - "ndk-macro 0.2.0", - "ndk-sys 0.2.2", -] - -[[package]] -name = "ndk-glue" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc291b8de2095cba8dab7cf381bf582ff4c17a09acf854c32e46545b08085d28" -dependencies = [ - "lazy_static", - "libc", - "log", - "ndk 0.5.0", - "ndk-macro 0.3.0", - "ndk-sys 0.2.2", -] - -[[package]] -name = "ndk-glue" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04c0d14b0858eb9962a5dac30b809b19f19da7e4547d64af2b0bb051d2e55d79" -dependencies = [ - "lazy_static", - "libc", - "log", - "ndk 0.6.0", - "ndk-macro 0.3.0", - "ndk-sys 0.3.0", -] - -[[package]] -name = "ndk-macro" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d1c6307dc424d0f65b9b06e94f88248e6305726b14729fd67a5e47b2dc481d" -dependencies = [ - "darling 0.10.2", - "proc-macro-crate 0.1.5", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "ndk-macro" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c" -dependencies = [ - "darling 0.13.1", - "proc-macro-crate 1.1.0", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "ndk-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121" - -[[package]] -name = "ndk-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e5a6ae77c8ee183dcbbba6150e2e6b9f3f4196a7666c02a715a95692ec1fa97" -dependencies = [ - "jni-sys", -] - -[[package]] -name = "nix" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5e06129fb611568ef4e868c14b326274959aa70ff7776e9d55323531c374945" -dependencies = [ - "bitflags", - "cc", - "cfg-if 1.0.0", - "libc", - "memoffset", -] - -[[package]] -name = "nix" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1e25ee6b412c2a1e3fcb6a4499a5c1bfe7f43e014bdce9a6b6666e5aa2d187" -dependencies = [ - "bitflags", - "cc", - "cfg-if 1.0.0", - "libc", - "memoffset", -] - -[[package]] -name = "nom" -version = "5.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" -dependencies = [ - "memchr", - "version_check", -] - -[[package]] -name = "nom" -version = "7.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109" -dependencies = [ - "memchr", - "minimal-lexical", - "version_check", -] - -[[package]] -name = "nonempty" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7" - -[[package]] -name = "ntapi" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" -dependencies = [ - "winapi", -] - -[[package]] -name = "num-derive" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "num-traits" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "num_enum" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "720d3ea1055e4e4574c0c0b0f8c3fd4f24c4cdaf465948206dea090b57b526ad" -dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d992b768490d7fe0d8586d9b5745f6c49f557da6d81dc982b1d167ad4edbb21" -dependencies = [ - "proc-macro-crate 1.1.0", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "objc" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" -dependencies = [ - "malloc_buf", - "objc_exception", -] - -[[package]] -name = "objc-foundation" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" -dependencies = [ - "block", - "objc", - "objc_id", -] - -[[package]] -name = "objc_exception" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" -dependencies = [ - "cc", -] - -[[package]] -name = "objc_id" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" -dependencies = [ - "objc", -] - -[[package]] -name = "object" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" -dependencies = [ - "memchr", -] - -[[package]] -name = "oboe" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2463c8f2e19b4e0d0710a21f8e4011501ff28db1c95d7a5482a553b2100502d2" -dependencies = [ - "jni", - "ndk 0.6.0", - "ndk-glue 0.6.0", - "num-derive", - "num-traits", - "oboe-sys", -] - -[[package]] -name = "oboe-sys" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3370abb7372ed744232c12954d920d1a40f1c4686de9e79e800021ef492294bd" -dependencies = [ - "cc", -] - -[[package]] -name = "ogg" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e" -dependencies = [ - "byteorder", -] - -[[package]] -name = "once_cell" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" - -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" - -[[package]] -name = "ordered-float" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87" -dependencies = [ - "num-traits", -] - -[[package]] -name = "owned_ttf_parser" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ef05f2882a8b3e7acc10c153ade2631f7bfc8ce00d2bf3fb8f4e9d2ae6ea5c3" -dependencies = [ - "ttf-parser", -] - -[[package]] -name = "page_size" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eebde548fbbf1ea81a99b128872779c437752fb99f217c45245e1a61dcd9edcd" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "palette" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9735f7e1e51a3f740bacd5dc2724b61a7806f23597a8736e679f38ee3435d18" -dependencies = [ - "approx 0.5.0", - "num-traits", - "palette_derive", - "phf", -] - -[[package]] -name = "palette_derive" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7799c3053ea8a6d8a1193c7ba42f534e7863cf52e378a7f90406f4a645d33bad" -dependencies = [ - "find-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" -dependencies = [ - "cfg-if 1.0.0", - "instant", - "libc", - "redox_syscall", - "smallvec", - "winapi", -] - -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" - -[[package]] -name = "percent-encoding" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" - -[[package]] -name = "pest" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" -dependencies = [ - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pest_meta" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" -dependencies = [ - "maplit", - "pest", - "sha-1", -] - -[[package]] -name = "phf" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ac8b67553a7ca9457ce0e526948cad581819238f4a9d1ea74545851fa24f37" -dependencies = [ - "phf_macros", - "phf_shared", - "proc-macro-hack", -] - -[[package]] -name = "phf_generator" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d43f3220d96e0080cc9ea234978ccd80d904eafb17be31bb0f76daaea6493082" -dependencies = [ - "phf_shared", - "rand", -] - -[[package]] -name = "phf_macros" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b706f5936eb50ed880ae3009395b43ed19db5bff2ebd459c95e7bf013a89ab86" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro-hack", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "phf_shared" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a68318426de33640f02be62b4ae8eb1261be2efbc337b60c54d845bf4484e0d9" -dependencies = [ - "siphasher", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkg-config" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" - -[[package]] -name = "ppv-lite86" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" - -[[package]] -name = "proc-macro-crate" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" -dependencies = [ - "toml", -] - -[[package]] -name = "proc-macro-crate" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83" -dependencies = [ - "thiserror", - "toml", -] - -[[package]] -name = "proc-macro-hack" -version = "0.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" - -[[package]] -name = "proc-macro2" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "profiling" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9145ac0af1d93c638c98c40cf7d25665f427b2a44ad0a99b1dccf3e2f25bb987" - -[[package]] -name = "quick-xml" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8533f14c8382aaad0d592c812ac3b826162128b65662331e1127b45c3d18536b" -dependencies = [ - "memchr", -] - -[[package]] -name = "quote" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core", -] - -[[package]] -name = "range-alloc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e935c45e09cc6dcf00d2f0b2d630a58f4095320223d47fc68918722f0538b6" - -[[package]] -name = "raw-window-handle" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fba75eee94a9d5273a68c9e1e105d9cffe1ef700532325788389e5a83e2522b7" -dependencies = [ - "cty", -] - -[[package]] -name = "rayon" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" -dependencies = [ - "autocfg", - "crossbeam-deque", - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-utils", - "lazy_static", - "num_cpus", -] - -[[package]] -name = "redox_syscall" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" -dependencies = [ - "bitflags", -] - -[[package]] -name = "redox_users" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" -dependencies = [ - "getrandom", - "redox_syscall", -] - -[[package]] -name = "regex" -version = "1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" -dependencies = [ - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.6.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" - -[[package]] -name = "renderdoc-sys" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1382d1f0a252c4bf97dc20d979a2fdd05b024acd7c2ed0f7595d7817666a157" - -[[package]] -name = "roc_std" -version = "0.0.1" -dependencies = [ - "arrayvec", - "static_assertions", -] - -[[package]] -name = "rodio" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d98f5e557b61525057e2bc142c8cd7f0e70d75dc32852309bec440e6e046bf9" -dependencies = [ - "claxon", - "cpal", - "hound", - "lewton", - "minimp3", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "ryu" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" - -[[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 = "scoped-tls" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "serde" -version = "1.0.135" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cf9235533494ea2ddcdb794665461814781c53f19d87b76e571a1c35acbad2b" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.135" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dcde03d87d4c973c04be249e7d8f0b35db1c848c487bd43032808e59dd8328d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_yaml" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a521f2940385c165a24ee286aa8599633d162077a54bdcae2a6fd5a7bfa7a0" -dependencies = [ - "indexmap", - "ryu", - "serde", - "yaml-rust", -] - -[[package]] -name = "sha-1" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" -dependencies = [ - "block-buffer", - "digest", - "fake-simd", - "opaque-debug", -] - -[[package]] -name = "shlex" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" - -[[package]] -name = "siphasher" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a86232ab60fa71287d7f2ddae4a7073f6b7aac33631c3015abb556f08c6d0a3e" - -[[package]] -name = "slab" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" - -[[package]] -name = "slice-deque" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31ef6ee280cdefba6d2d0b4b78a84a1c1a3f3a4cec98c2d4231c8bc225de0f25" -dependencies = [ - "libc", - "mach", - "winapi", -] - -[[package]] -name = "slotmap" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e08e261d0e8f5c43123b7adf3e4ca1690d655377ac93a03b2c9d3e98de1342" -dependencies = [ - "version_check", -] - -[[package]] -name = "smallvec" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" - -[[package]] -name = "smithay-client-toolkit" -version = "0.15.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1325f292209cee78d5035530932422a30aa4c8fda1a16593ac083c1de211e68a" -dependencies = [ - "bitflags", - "calloop", - "dlib", - "lazy_static", - "log", - "memmap2", - "nix 0.22.0", - "pkg-config", - "wayland-client", - "wayland-cursor", - "wayland-protocols", -] - -[[package]] -name = "smithay-clipboard" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "610b551bd25378bfd2b8e7a0fcbd83d427e8f2f6a40c47ae0f70688e9949dd55" -dependencies = [ - "smithay-client-toolkit", - "wayland-client", -] - -[[package]] -name = "snafu" -version = "0.6.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eab12d3c261b2308b0d80c26fffb58d17eba81a4be97890101f416b478c79ca7" -dependencies = [ - "backtrace", - "doc-comment", - "snafu-derive", -] - -[[package]] -name = "snafu-derive" -version = "0.6.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1508efa03c362e23817f96cde18abed596a25219a8b2c66e8db33c03543d315b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "spirv" -version = "0.2.0+1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "246bfa38fe3db3f1dfc8ca5a2cdeb7348c78be2112740cc0ec8ef18b6d94f830" -dependencies = [ - "bitflags", - "num-traits", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "stdweb" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e" - -[[package]] -name = "strsim" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "syn" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "termcolor" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "thiserror" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "threadpool" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" -dependencies = [ - "num_cpus", -] - -[[package]] -name = "tinyvec" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" - -[[package]] -name = "toml" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" -dependencies = [ - "serde", -] - -[[package]] -name = "ttf-parser" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ccbe8381883510b6a2d8f1e32905bddd178c11caef8083086d0c0c9ab0ac281" - -[[package]] -name = "twox-hash" -version = "1.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee73e6e4924fe940354b8d4d98cad5231175d615cd855b758adc658c0aac6a0" -dependencies = [ - "cfg-if 0.1.10", - "rand", - "static_assertions", -] - -[[package]] -name = "typenum" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" - -[[package]] -name = "ucd-trie" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" - -[[package]] -name = "unicode-width" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" - -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "walkdir" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" -dependencies = [ - "same-file", - "winapi", - "winapi-util", -] - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - -[[package]] -name = "wasm-bindgen" -version = "0.2.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" -dependencies = [ - "cfg-if 1.0.0", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" -dependencies = [ - "bumpalo", - "lazy_static", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395" -dependencies = [ - "cfg-if 1.0.0", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" - -[[package]] -name = "wayland-client" -version = "0.29.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91223460e73257f697d9e23d401279123d36039a3f7a449e983f123292d4458f" -dependencies = [ - "bitflags", - "downcast-rs", - "libc", - "nix 0.22.0", - "scoped-tls", - "wayland-commons", - "wayland-scanner", - "wayland-sys", -] - -[[package]] -name = "wayland-commons" -version = "0.29.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94f6e5e340d7c13490eca867898c4cec5af56c27a5ffe5c80c6fc4708e22d33e" -dependencies = [ - "nix 0.22.0", - "once_cell", - "smallvec", - "wayland-sys", -] - -[[package]] -name = "wayland-cursor" -version = "0.29.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c52758f13d5e7861fc83d942d3d99bf270c83269575e52ac29e5b73cb956a6bd" -dependencies = [ - "nix 0.22.0", - "wayland-client", - "xcursor", -] - -[[package]] -name = "wayland-protocols" -version = "0.29.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60147ae23303402e41fe034f74fb2c35ad0780ee88a1c40ac09a3be1e7465741" -dependencies = [ - "bitflags", - "wayland-client", - "wayland-commons", - "wayland-scanner", -] - -[[package]] -name = "wayland-scanner" -version = "0.29.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39a1ed3143f7a143187156a2ab52742e89dac33245ba505c17224df48939f9e0" -dependencies = [ - "proc-macro2", - "quote", - "xml-rs", -] - -[[package]] -name = "wayland-sys" -version = "0.29.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9341df79a8975679188e37dab3889bfa57c44ac2cb6da166f519a81cbe452d4" -dependencies = [ - "dlib", - "lazy_static", - "pkg-config", -] - -[[package]] -name = "web-sys" -version = "0.3.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "wgpu" -version = "0.12.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=0545e36#0545e36aa82709cca78c14eb3813f10eea7a9275" -dependencies = [ - "arrayvec", - "js-sys", - "log", - "naga", - "parking_lot", - "raw-window-handle", - "smallvec", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "wgpu-core", - "wgpu-hal", - "wgpu-types", -] - -[[package]] -name = "wgpu-core" -version = "0.12.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=0545e36#0545e36aa82709cca78c14eb3813f10eea7a9275" -dependencies = [ - "arrayvec", - "bitflags", - "cfg_aliases", - "codespan-reporting", - "copyless", - "fxhash", - "log", - "naga", - "parking_lot", - "profiling", - "raw-window-handle", - "smallvec", - "thiserror", - "wgpu-hal", - "wgpu-types", -] - -[[package]] -name = "wgpu-hal" -version = "0.12.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=0545e36#0545e36aa82709cca78c14eb3813f10eea7a9275" -dependencies = [ - "arrayvec", - "ash", - "bit-set", - "bitflags", - "block", - "core-graphics-types", - "d3d12", - "foreign-types", - "fxhash", - "glow", - "gpu-alloc", - "gpu-descriptor", - "inplace_it", - "js-sys", - "khronos-egl", - "libloading", - "log", - "metal", - "naga", - "objc", - "parking_lot", - "profiling", - "range-alloc", - "raw-window-handle", - "renderdoc-sys", - "thiserror", - "wasm-bindgen", - "web-sys", - "wgpu-types", - "winapi", -] - -[[package]] -name = "wgpu-types" -version = "0.12.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=0545e36#0545e36aa82709cca78c14eb3813f10eea7a9275" -dependencies = [ - "bitflags", -] - -[[package]] -name = "wgpu_glyph" -version = "0.16.0" -source = "git+https://github.com/Anton-4/wgpu_glyph?rev=257d109#257d1098cbafa3c8a0a2465937b06fc730fc6ffb" -dependencies = [ - "bytemuck", - "glyph_brush", - "log", - "wgpu", -] - -[[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.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -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 = "winit" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b43cc931d58b99461188607efd7acb2a093e65fc621f54cad78517a6063e73a" -dependencies = [ - "bitflags", - "cocoa", - "core-foundation 0.9.2", - "core-graphics 0.22.3", - "core-video-sys", - "dispatch", - "instant", - "lazy_static", - "libc", - "log", - "mio", - "ndk 0.5.0", - "ndk-glue 0.5.0", - "ndk-sys 0.2.2", - "objc", - "parking_lot", - "percent-encoding", - "raw-window-handle", - "smithay-client-toolkit", - "wasm-bindgen", - "wayland-client", - "wayland-protocols", - "web-sys", - "winapi", - "x11-dl", -] - -[[package]] -name = "x11-clipboard" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "473068b7b80ac86a18328824f1054e5e007898c47b5bbc281bd7abe32bc3653c" -dependencies = [ - "xcb", -] - -[[package]] -name = "x11-dl" -version = "2.19.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea26926b4ce81a6f5d9d0f3a0bc401e5a37c6ae14a1bfaa8ff6099ca80038c59" -dependencies = [ - "lazy_static", - "libc", - "pkg-config", -] - -[[package]] -name = "xcb" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771e2b996df720cd1c6dd9ff90f62d91698fd3610cc078388d0564bdd6622a9c" -dependencies = [ - "libc", - "log", - "quick-xml", -] - -[[package]] -name = "xcursor" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "463705a63313cd4301184381c5e8042f0a7e9b4bb63653f216311d4ae74690b7" -dependencies = [ - "nom 7.1.0", -] - -[[package]] -name = "xi-unicode" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a67300977d3dc3f8034dae89778f502b6ba20b269527b3223ba59c0cf393bb8a" - -[[package]] -name = "xml-rs" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" - -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] diff --git a/examples/gui/platform/Cargo.toml b/examples/gui/platform/Cargo.toml index ec1ec5fad1..0ac7d2812e 100644 --- a/examples/gui/platform/Cargo.toml +++ b/examples/gui/platform/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "host" -version = "0.0.1" authors = ["The Roc Contributors"] -license = "UPL-1.0" edition = "2021" +license = "UPL-1.0" links = "app" +version = "0.0.1" [lib] name = "host" @@ -16,32 +16,28 @@ name = "host" path = "src/main.rs" [dependencies] -roc_std = { path = "../../../crates/roc_std" } -libc = "0.2" arrayvec = "0.7.2" +libc = "0.2" page_size = "0.4.2" -# when changing winit version, check if copypasta can be updated simultaneously so they use the same versions for their dependencies. This will save build time. -winit = "0.26.1" -wgpu = { git = "https://github.com/gfx-rs/wgpu", rev = "0545e36" } -wgpu_glyph = { git = "https://github.com/Anton-4/wgpu_glyph", rev = "257d109" } +roc_std = { path = "../../../crates/roc_std" } +cgmath = "0.18.0" +colored = "2.0.0" +confy = { git = 'https://github.com/rust-cli/confy', features = ["yaml_conf"], default-features = false } +copypasta = "0.7.1" +fs_extra = "1.2.0" +futures = "0.3.17" glyph_brush = "0.7.2" log = "0.4.14" -futures = "0.3.17" -cgmath = "0.18.0" -snafu = { version = "0.6.10", features = ["backtraces"] } -colored = "2.0.0" +nonempty = "0.7.0" +palette = "0.6.0" pest = "2.1.3" pest_derive = "2.1.0" -copypasta = "0.7.1" -palette = "0.6.0" -confy = { git = 'https://github.com/rust-cli/confy', features = [ - "yaml_conf" -], default-features = false } serde = { version = "1.0.130", features = ["derive"] } -nonempty = "0.7.0" -fs_extra = "1.2.0" -rodio = { version = "0.14.0", optional = true } # to play sounds +snafu = { version = "0.6.10", features = ["backtraces"] } threadpool = "1.8.1" +wgpu = { git = "https://github.com/gfx-rs/wgpu", rev = "0545e36" } +wgpu_glyph = { git = "https://github.com/Anton-4/wgpu_glyph", rev = "257d109" } +winit = "0.26.1" [package.metadata.cargo-udeps.ignore] # confy is currently unused but should not be removed @@ -51,20 +47,19 @@ normal = ["confy"] [features] default = [] -with_sound = ["rodio"] [dependencies.bytemuck] -version = "1.7.2" features = ["derive"] +version = "1.7.2" [workspace] # Optimizations based on https://deterministic.space/high-performance-rust.html [profile.release] -lto = "thin" codegen-units = 1 +lto = "thin" # debug = true # enable when profiling [profile.bench] -lto = "thin" codegen-units = 1 +lto = "thin" diff --git a/examples/parser/parse-movies-csv.roc b/examples/parser/parse-movies-csv.roc deleted file mode 100644 index 46dd00b964..0000000000 --- a/examples/parser/parse-movies-csv.roc +++ /dev/null @@ -1,58 +0,0 @@ -app "parse-movies-csv" - packages { pf: "platform/main.roc" } - imports [Parser.Core.{ Parser, map, keep }, Parser.Str.{ RawStr }, Parser.CSV.{ CSV, record, field, string, nat }] - provides [main] to pf - -input : Str -input = "Airplane!,1980,\"Robert Hays,Julie Hagerty\"\r\nCaddyshack,1980,\"Chevy Chase,Rodney Dangerfield,Ted Knight,Michael O'Keefe,Bill Murray\"" - -main : Str -main = - when Parser.CSV.parseStr movieInfoParser input is - Ok movies -> - moviesString = - movies - |> List.map movieInfoExplanation - |> Str.joinWith ("\n") - nMovies = List.len movies |> Num.toStr - - "\(nMovies) movies were found:\n\n\(moviesString)\n\nParse success!\n" - - Err problem -> - when problem is - ParsingFailure failure -> - "Parsing failure: \(failure)\n" - - ParsingIncomplete leftover -> - leftoverStr = leftover |> List.map Parser.Str.strFromRaw |> List.map (\val -> "\"\(val)\"") |> Str.joinWith ", " - - "Parsing incomplete. Following leftover fields while parsing a record: \(leftoverStr)\n" - - SyntaxError error -> - "Parsing failure. Syntax error in the CSV: \(error)" - -MovieInfo := { title : Str, releaseYear : Nat, actors : List Str } - -movieInfoParser = - record (\title -> \releaseYear -> \actors -> @MovieInfo { title, releaseYear, actors }) - |> keep (field string) - |> keep (field nat) - |> keep (field actorsParser) - -actorsParser = - string - |> map (\val -> Str.split val ",") - -movieInfoExplanation = \@MovieInfo { title, releaseYear, actors } -> - enumeratedActors = enumerate actors - releaseYearStr = Num.toStr releaseYear - - "The movie '\(title)' was released in \(releaseYearStr) and stars \(enumeratedActors)" - -enumerate : List Str -> Str -enumerate = \elements -> - { before: inits, others: last } = List.split elements (List.len elements - 1) - - last - |> List.prepend (inits |> Str.joinWith ", ") - |> Str.joinWith " and " diff --git a/examples/parser/platform/host.zig b/examples/parser/platform/host.zig deleted file mode 100755 index b84d428034..0000000000 --- a/examples/parser/platform/host.zig +++ /dev/null @@ -1,125 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const str = @import("str"); -const RocStr = str.RocStr; -const testing = std.testing; -const expectEqual = testing.expectEqual; -const expect = testing.expect; - -extern fn roc__mainForHost_1_exposed_generic(*RocStr) void; - -pub fn main() u8 { - const stdout = std.io.getStdOut().writer(); - - // actually call roc to populate the callresult - var callresult = RocStr.empty(); - roc__mainForHost_1_exposed_generic(&callresult); - - // stdout the result - stdout.print("{s}", .{callresult.asSlice()}) catch unreachable; - - callresult.deinit(); - - return 0; -} - -comptime { - // This is a workaround for https://github.com/ziglang/zig/issues/8218 - // which is only necessary on macOS. - // - // Once that issue is fixed, we can undo the changes in - // 177cf12e0555147faa4d436e52fc15175c2c4ff0 and go back to passing - // -fcompiler-rt in link.rs instead of doing this. Note that this - // workaround is present in many host.zig files, so make sure to undo - // it everywhere! - if (builtin.os.tag == .macos) { - _ = @import("compiler_rt"); - } -} - -const Align = 2 * @alignOf(usize); -extern fn malloc(size: usize) callconv(.C) ?*align(Align) anyopaque; -extern fn realloc(c_ptr: [*]align(Align) u8, size: usize) callconv(.C) ?*anyopaque; -extern fn free(c_ptr: [*]align(Align) u8) callconv(.C) void; -extern fn memcpy(dst: [*]u8, src: [*]u8, size: usize) callconv(.C) void; -extern fn memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void; - -const DEBUG: bool = false; - -export fn roc_alloc(size: usize, alignment: u32) callconv(.C) ?*anyopaque { - if (DEBUG) { - var ptr = malloc(size); - const stdout = std.io.getStdOut().writer(); - stdout.print("alloc: {d} (alignment {d}, size {d})\n", .{ ptr, alignment, size }) catch unreachable; - return ptr; - } else { - return malloc(size); - } -} - -export fn roc_realloc(c_ptr: *anyopaque, new_size: usize, old_size: usize, alignment: u32) callconv(.C) ?*anyopaque { - if (DEBUG) { - const stdout = std.io.getStdOut().writer(); - stdout.print("realloc: {d} (alignment {d}, old_size {d})\n", .{ c_ptr, alignment, old_size }) catch unreachable; - } - - return realloc(@alignCast(Align, @ptrCast([*]u8, c_ptr)), new_size); -} - -export fn roc_dealloc(c_ptr: *anyopaque, alignment: u32) callconv(.C) void { - if (DEBUG) { - const stdout = std.io.getStdOut().writer(); - stdout.print("dealloc: {d} (alignment {d})\n", .{ c_ptr, alignment }) catch unreachable; - } - - free(@alignCast(Align, @ptrCast([*]u8, c_ptr))); -} - -export fn roc_panic(c_ptr: *anyopaque, tag_id: u32) callconv(.C) void { - _ = tag_id; - - const stderr = std.io.getStdErr().writer(); - const msg = @ptrCast([*:0]const u8, c_ptr); - stderr.print("Application crashed with message\n\n {s}\n\nShutting down\n", .{msg}) catch unreachable; - std.process.exit(0); -} - -export fn roc_memcpy(dst: [*]u8, src: [*]u8, size: usize) callconv(.C) void { - return memcpy(dst, src, size); -} - -export fn roc_memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void { - return memset(dst, value, size); -} - -extern fn kill(pid: c_int, sig: c_int) c_int; -extern fn shm_open(name: *const i8, oflag: c_int, mode: c_uint) c_int; -extern fn mmap(addr: ?*anyopaque, length: c_uint, prot: c_int, flags: c_int, fd: c_int, offset: c_uint) *anyopaque; -extern fn getppid() c_int; - -fn roc_getppid() callconv(.C) c_int { - return getppid(); -} - -fn roc_getppid_windows_stub() callconv(.C) c_int { - return 0; -} - -fn roc_shm_open(name: *const i8, oflag: c_int, mode: c_uint) callconv(.C) c_int { - return shm_open(name, oflag, mode); -} -fn roc_mmap(addr: ?*anyopaque, length: c_uint, prot: c_int, flags: c_int, fd: c_int, offset: c_uint) callconv(.C) *anyopaque { - return mmap(addr, length, prot, flags, fd, offset); -} - -comptime { - if (builtin.os.tag == .macos or builtin.os.tag == .linux) { - @export(roc_getppid, .{ .name = "roc_getppid", .linkage = .Strong }); - @export(roc_mmap, .{ .name = "roc_mmap", .linkage = .Strong }); - @export(roc_shm_open, .{ .name = "roc_shm_open", .linkage = .Strong }); - } - - if (builtin.os.tag == .windows) { - @export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .Strong }); - } -} diff --git a/examples/parser/platform/main.roc b/examples/parser/platform/main.roc deleted file mode 100644 index 175f7070d5..0000000000 --- a/examples/parser/platform/main.roc +++ /dev/null @@ -1,9 +0,0 @@ -platform "hello-world" - requires {} { main : Str } - exposes [] - packages {} - imports [] - provides [mainForHost] - -mainForHost : Str -mainForHost = main diff --git a/examples/platform-switching/rust-platform/Cargo.lock b/examples/platform-switching/rust-platform/Cargo.lock deleted file mode 100644 index e338549811..0000000000 --- a/examples/platform-switching/rust-platform/Cargo.lock +++ /dev/null @@ -1,37 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "arrayvec" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" - -[[package]] -name = "host" -version = "0.0.1" -dependencies = [ - "libc", - "roc_std", -] - -[[package]] -name = "libc" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56d855069fafbb9b344c0f962150cd2c1187975cb1c22c1522c240d8c4986714" - -[[package]] -name = "roc_std" -version = "0.0.1" -dependencies = [ - "arrayvec", - "static_assertions", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" diff --git a/examples/platform-switching/rust-platform/Cargo.toml b/examples/platform-switching/rust-platform/Cargo.toml index 8d10ce6eea..b329e6472b 100644 --- a/examples/platform-switching/rust-platform/Cargo.toml +++ b/examples/platform-switching/rust-platform/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "host" -version = "0.0.1" authors = ["The Roc Contributors"] -license = "UPL-1.0" edition = "2021" +license = "UPL-1.0" links = "app" +version = "0.0.1" [lib] name = "host" @@ -16,7 +16,7 @@ name = "host" path = "src/main.rs" [dependencies] -roc_std = { path = "../../../crates/roc_std" } libc = "0.2" +roc_std = { path = "../../../crates/roc_std" } [workspace] diff --git a/examples/ruby-interop/platform/host.c b/examples/ruby-interop/platform/host.c index abd7d96680..cfd449e7a7 100644 --- a/examples/ruby-interop/platform/host.c +++ b/examples/ruby-interop/platform/host.c @@ -28,6 +28,10 @@ void* roc_memcpy(void* dest, const void* src, size_t n) { return memcpy(dest, src, n); } +void* roc_memmove(void* dest, const void* src, size_t n){ + return memmove(dest, src, n); +} + void* roc_memset(void* str, int c, size_t n) { return memset(str, c, n); } int roc_shm_open(char* name, int oflag, int mode) { diff --git a/examples/static-site-gen/README.md b/examples/static-site-gen/README.md index af96a62bfa..f8dd72ab56 100644 --- a/examples/static-site-gen/README.md +++ b/examples/static-site-gen/README.md @@ -9,7 +9,7 @@ To run, `cd` into this directory and run this in your terminal: If `roc` is on your PATH: ```bash -roc run static-site.roc input/ output/ +roc run static-site.roc -- input/ output/ ``` If not, and you're building Roc from source: diff --git a/examples/static-site-gen/input/apple.md b/examples/static-site-gen/input/apple.md index f4e28c985d..f5102a8eb7 100644 --- a/examples/static-site-gen/input/apple.md +++ b/examples/static-site-gen/input/apple.md @@ -44,24 +44,92 @@ ingeniis in pugna quadripedis glandes superos. Tanta quam, illo es prole est telis **unus verba** quisquis iuvenci annis. Nec velox sed sacra gaudia vacuos, Herculei undae calcata inmeriti quercus ignes parabant iam. - digitize(undoDhcp(card_record, cad_flash_dot)); - supercomputer(2 - load_type, yobibyteTraceroute - installHibernate, 1); - burnPci.pop_wrap.usbEmulation(hostESmm, processor_impression(4, lanNntp), - -5); - map_camera -= 73; - if (53) { - dacRootkitDrive(publicActivex.bmpNumWhite.wins_pci_firmware(scroll_cell, - 4, tShortcut)); - horse_algorithm_eide -= 51; - flatbed_blob(flat); - } else { - surge.pci -= open_flash_dv(4, 4, usbStation); - led.memory_fsb.matrixBinaryUrl(umlEngineOsd.agp_thick_thin.t(58)); - kindle_cookie(formulaLedVpn, digital_meme); - } +### Example Table -Foret inpendere, haec ipse ossa, dolentes das Caystro miscuit iunctoque -spoliantis illae, ex! Bello istis nunc Aegides? Animo caelestia melior, -furoribus optat maior invecta quid harenis [est](http://example.org) sollemnia modo -Phineu. Suarum pectora. Relinquam in labore Medusae sororem Herculis [simillima -corpora](http://example.org) plus regi ignibus, totum domus! +| Tables | Are | Cool | +| :------------ | :-----------: | ----: | +| col 3 is | right-aligned | $1600 | +| col 2 is | centered | $12 | +| zebra stripes | are neat | $1 | + +### Example Code Blocks + +```sh +# This isn't fenced roc code so its not formatted +# Use a fence like ```roc to format code blocks +``` + +```roc +## This is a documentation comment + +# This is a comment +app "static-site" + packages { pf: "platform/main.roc" } + imports [ + pf.Html.{ html, head, body, div, text, a, ul, li, link, meta }, + pf.Html.Attributes.{ httpEquiv, content, href, rel, lang, class, title }, + ] + provides [transformFileContent] to pf + +NavLink : { + # this is another comment + url : Str, + title : Str, + text : Str, +} + +navLinks : List NavLink +navLinks = [ + { url: "apple.html", title: "Exempli Gratia Pagina Pomi", text: "Apple" }, + { url: "banana.html", title: "Exempli Gratia Pagina Musa", text: "Banana" }, + { url: "cherry.html", title: "Exempli Pagina Cerasus", text: "Cherry" }, +] + +transformFileContent : Str, Str -> Str +transformFileContent = \currentUrl, htmlContent -> + List.findFirst navLinks (\{ url } -> url == currentUrl) + |> Result.map (\currentNavLink -> view currentNavLink htmlContent) + |> Result.map Html.render + |> Result.withDefault "" + +view : NavLink, Str -> Html.Node +view = \currentNavLink, htmlContent -> + html [lang "en"] [ + head [] [ + meta [httpEquiv "content-type", content "text/html; charset=utf-8"] [], + Html.title [] [text currentNavLink.title], + link [rel "stylesheet", href "style.css"] [], + ], + body [] [ + div [class "main"] [ + div [class "navbar"] [ + viewNavbar currentNavLink, + ], + div [class "article"] [ + # For now `text` is not escaped so we can use it to insert HTML + # We'll probably want something more explicit in the long term though! + text htmlContent, + ], + ], + ], + ] + +viewNavbar : NavLink -> Html.Node +viewNavbar = \currentNavLink -> + ul + [] + (List.map navLinks \nl -> viewNavLink (nl == currentNavLink) nl) + +viewNavLink : Bool, NavLink -> Html.Node +viewNavLink = \isCurrent, navlink -> + if isCurrent then + li [class "nav-link nav-link--current"] [ + text navlink.text, + ] + else + li [class "nav-link"] [ + a + [href navlink.url, title navlink.title] + [text navlink.text], + ] +``` \ No newline at end of file diff --git a/examples/static-site-gen/output/style.css b/examples/static-site-gen/output/style.css index cdc5bf0e97..ba6aa4fa21 100644 --- a/examples/static-site-gen/output/style.css +++ b/examples/static-site-gen/output/style.css @@ -39,7 +39,98 @@ color: #444; } .article pre { - background-color: #222; - color: yellow; + background-color: rgb(241, 241, 241); + color: rgb(27, 27, 27); padding: 16px; } + +pre { + white-space: pre-wrap; +} + +samp .ann { + /* type annotation - purple in the repl */ + color: #f384fd; +} + +samp .autovar .comment { + /* automatic variable names in the repl, e.g. # val1 */ + color: #338545; +} + +samp .kw { + color: #004cc2; +} + +samp .arrow, samp .backslash, samp .bar { + color: #0600c2; +} + +samp .pipe { + color: #0600c2; +} + +samp .op { + color: #0600c2; +} + +samp .assign { + color: #48fd00; +} + +samp .paren, samp .bracket, samp .brace { + color: #ff0000; +} + +samp .comma { + color: #ff00fb; +} + +samp .colon { + color: #9b0098; +} + +samp .number { +/* number literals */ +color: #9669ff; +} + +samp .str { + /* string literals */ + color: #1dbf00; +} + +samp .str-esc, samp .str-interp { + /* escapes inside string literals, e.g. \t */ + color: #3474db; +} + +samp .dim { + opacity: 0.55; +} + +samp .comment { + color: #005a13; +} + + +table { + table-layout: fixed; + width: 100%; + border-collapse: collapse; + border: 3px solid rgb(161, 64, 0); +} + +tbody tr:nth-child(even) { + background-color: #c6f4ff; +} + +th { + background-color: #ffabab; +} + +th, +td { + + padding: 2px; +} \ No newline at end of file diff --git a/examples/static-site-gen/platform/Cargo.lock b/examples/static-site-gen/platform/Cargo.lock deleted file mode 100644 index 0e81055120..0000000000 --- a/examples/static-site-gen/platform/Cargo.lock +++ /dev/null @@ -1,76 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "arrayvec" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "host" -version = "0.0.1" -dependencies = [ - "libc", - "pulldown-cmark", - "roc_std", -] - -[[package]] -name = "libc" -version = "0.2.132" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" - -[[package]] -name = "memchr" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "pulldown-cmark" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d9cc634bc78768157b5cbfe988ffcd1dcba95cd2b2f03a88316c08c6d00ed63" -dependencies = [ - "bitflags", - "memchr", - "unicase", -] - -[[package]] -name = "roc_std" -version = "0.0.1" -dependencies = [ - "arrayvec", - "static_assertions", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "unicase" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" -dependencies = [ - "version_check", -] - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" diff --git a/examples/static-site-gen/platform/Cargo.toml b/examples/static-site-gen/platform/Cargo.toml index 9b5becea49..7475e40815 100644 --- a/examples/static-site-gen/platform/Cargo.toml +++ b/examples/static-site-gen/platform/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "host" -version = "0.0.1" authors = ["The Roc Contributors"] -license = "UPL-1.0" edition = "2021" +license = "UPL-1.0" +version = "0.0.1" links = "app" @@ -17,8 +17,11 @@ name = "host" path = "src/main.rs" [dependencies] -roc_std = { path = "../../../crates/roc_std" } libc = "0.2" +roc_highlight = { path = "../../../crates/highlight" } +roc_std = { path = "../../../crates/roc_std" } + + # Default features include building a binary that we don't need pulldown-cmark = { version = "0.9.2", default-features = false } diff --git a/examples/static-site-gen/platform/src/lib.rs b/examples/static-site-gen/platform/src/lib.rs index 7db426008e..42614e3ac0 100644 --- a/examples/static-site-gen/platform/src/lib.rs +++ b/examples/static-site-gen/platform/src/lib.rs @@ -116,7 +116,7 @@ fn run(input_dirname: &str, output_dirname: &str) -> Result<(), String> { let output_dir = { let dir = PathBuf::from(output_dirname); if !dir.exists() { - fs::create_dir(&dir).unwrap(); + fs::create_dir_all(&dir).unwrap(); } strip_windows_prefix( dir.canonicalize() @@ -143,18 +143,23 @@ fn run(input_dirname: &str, output_dirname: &str) -> Result<(), String> { let mut num_errors = 0; let mut num_successes = 0; for input_file in input_files { - match process_file(&input_dir, &output_dir, &input_file) { - Ok(()) => { - num_successes += 1; + match input_file.extension() { + Some(s) if s.eq("md".into()) => { + match process_file(&input_dir, &output_dir, &input_file) { + Ok(()) => { + num_successes += 1; + } + Err(e) => { + eprintln!( + "Failed to process file:\n\n ({:?})with error:\n\n {}", + &input_file, e + ); + num_errors += 1; + } + } } - Err(e) => { - eprintln!( - "Failed to process file:\n\n ({:?})with error:\n\n {}", - &input_file, e - ); - num_errors += 1; - } - } + _ => {} + }; } println!( @@ -170,11 +175,6 @@ fn run(input_dirname: &str, output_dirname: &str) -> Result<(), String> { } fn process_file(input_dir: &Path, output_dir: &Path, input_file: &Path) -> Result<(), String> { - match input_file.extension() { - Some(s) if s.eq("md".into()) => {} - _ => return Err("Only .md files are supported".into()), - }; - let input_relpath = input_file .strip_prefix(input_dir) .map_err(|e| e.to_string())? @@ -202,7 +202,61 @@ fn process_file(input_dir: &Path, output_dir: &Path, input_file: &Path) -> Resul options.remove(Options::ENABLE_SMART_PUNCTUATION); let parser = Parser::new_ext(&content_md, options); - html::push_html(&mut content_html, parser); + + // We'll build a new vector of events since we can only consume the parser once + let mut parser_with_highlighting = Vec::new(); + // As we go along, we'll want to highlight code in bundles, not lines + let mut to_highlight = String::new(); + // And track a little bit of state + let mut in_code_block = false; + let mut is_roc_code = false; + + for event in parser { + match event { + pulldown_cmark::Event::Code(cow_str) => { + let highlighted_html = + roc_highlight::highlight_roc_code_inline(cow_str.to_string().as_str()); + parser_with_highlighting.push(pulldown_cmark::Event::Html( + pulldown_cmark::CowStr::from(highlighted_html), + )); + } + pulldown_cmark::Event::Start(pulldown_cmark::Tag::CodeBlock(cbk)) => { + in_code_block = true; + is_roc_code = is_roc_code_block(&cbk); + } + pulldown_cmark::Event::End(pulldown_cmark::Tag::CodeBlock(_)) => { + if in_code_block { + // Format the whole multi-line code block as HTML all at once + let highlighted_html: String; + if is_roc_code { + highlighted_html = roc_highlight::highlight_roc_code(&to_highlight) + } else { + highlighted_html = format!("
{}
", &to_highlight) + } + + // And put it into the vector + parser_with_highlighting.push(pulldown_cmark::Event::Html( + pulldown_cmark::CowStr::from(highlighted_html), + )); + to_highlight = String::new(); + in_code_block = false; + } + } + pulldown_cmark::Event::Text(t) => { + if in_code_block { + // If we're in a code block, build up the string of text + to_highlight.push_str(&t); + } else { + parser_with_highlighting.push(pulldown_cmark::Event::Text(t)) + } + } + e => { + parser_with_highlighting.push(e); + } + } + } + + html::push_html(&mut content_html, parser_with_highlighting.into_iter()); let roc_relpath = RocStr::from(output_relpath.to_str().unwrap()); let roc_content_html = RocStr::from(content_html.as_str()); @@ -214,6 +268,12 @@ fn process_file(input_dir: &Path, output_dir: &Path, input_file: &Path) -> Resul println!("{} -> {}", input_file.display(), output_file.display()); + // Create parent directory if it doesn't exist + let parent_dir = output_file.parent().unwrap(); + if !parent_dir.exists() { + fs::create_dir_all(&parent_dir).unwrap(); + } + fs::write(output_file, rust_output_str).map_err(|e| format!("{}", e)) } @@ -240,3 +300,16 @@ pub fn strip_windows_prefix(path_buf: PathBuf) -> std::path::PathBuf { std::path::Path::new(path_str.trim_start_matches(r"\\?\")).to_path_buf() } + +fn is_roc_code_block(cbk: &pulldown_cmark::CodeBlockKind) -> bool { + match cbk { + pulldown_cmark::CodeBlockKind::Indented => false, + pulldown_cmark::CodeBlockKind::Fenced(cow_str) => { + if cow_str.contains("roc") { + true + } else { + false + } + } + } +} diff --git a/flake.nix b/flake.nix index f7a59ceb5c..8f201c739e 100644 --- a/flake.nix +++ b/flake.nix @@ -44,7 +44,6 @@ xorg.libXrandr xorg.libXi xorg.libxcb - alsa-lib ]; darwinInputs = with pkgs; diff --git a/nightly_benches/Cargo.toml b/nightly_benches/Cargo.toml index a79266821d..7bdb94afa6 100644 --- a/nightly_benches/Cargo.toml +++ b/nightly_benches/Cargo.toml @@ -1,17 +1,19 @@ [package] name = "nightly_benches" -version = "0.0.1" -edition = "2021" -authors = ["The Roc Contributors"] -license = "UPL-1.0" + +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true [dependencies] [dev-dependencies] -criterion = { git = "https://github.com/Anton-4/criterion.rs"} cli_utils = { path = "../cli/cli_utils" } -criterion-perf-events ={ git = "https://github.com/Anton-4/criterion-perf-events" } -perfcnt = "0.7.1" + +criterion-perf-events.workspace = true +criterion.workspace = true +perfcnt.workspace = true [[bench]] name = "events_bench" diff --git a/www/generate_tutorial/src/input/tutorial.md b/www/generate_tutorial/src/input/tutorial.md index ebd021ae66..322e0ad772 100644 --- a/www/generate_tutorial/src/input/tutorial.md +++ b/www/generate_tutorial/src/input/tutorial.md @@ -20,7 +20,7 @@ Try typing this in the REPL and pressing Enter: The REPL should cheerfully display the following: -
"Hello, World!" : Str                # val1
+
"Hello, World!" : Str                # val1
Congratulations! You've just written your first Roc code. @@ -38,8 +38,8 @@ You should see the same `"Hello, World!"` line as before. You can also assign specific names to expressions. Try entering these lines: -
greeting = "Hi"
-
audience = "World"
+
greeting = "Hi"
+
audience = "World"
From now until you exit the REPL, you can refer to either `greeting` or `audience` by those names! @@ -47,11 +47,11 @@ From now until you exit the REPL, you can refer to either `greeting` or `audienc You can combine named strings together using _string interpolation_, like so: -
"\(greeting) there, \(audience)!"
+
"\(greeting) there, \(audience)!"
If you put this into the REPL, you should see this output: -
"Hi there, World!" : Str                # val2
+
"Hi there, World!" : Str                # val2
Notice that the REPL printed `# val2` here. This works just like `# val1` did before, but it chose the name `val2` for this expression because `val1` was already taken. As we continue entering more expressions into the REPL, you'll see more and more of these generated names—but they won't be mentioned again in this tutorial, since they're just a convenience. @@ -83,7 +83,7 @@ Remember back in the [string interpolation](#string-interpolation) section when
Str.concat "Hi " "there!"
 
-"Hi there!" : Str
+"Hi there!" : Str
 
Here we're calling the `Str.concat` function and passing two arguments: the string `"Hi "` and the string `"there!"`. This _concatenates_ the two strings together (that is, it puts one after the other) and returns the resulting combined string of `"Hi there!"`. @@ -94,7 +94,7 @@ That said, just like in the arithmetic example above, we can use parentheses to
Str.concat "Birds: " (Num.toStr 42)
 
-"Birds: 42" : Str
+"Birds: 42" : Str
 
This calls `Num.toStr` on the number `42`, which converts it into the string `"42"`, and then passes that string as the second argument to `Str.concat`. @@ -124,14 +124,15 @@ Let's move out of the REPL and create our first Roc application! Make a file named `main.roc` and put this in it: -
app "hello"
-    packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.1/wx1N6qhU3kKva-4YqsVJde3fho34NqiLD3m620zZ-OI.tar.br" }
-    imports [pf.Stdout]
-    provides [main] to pf
+```roc
+app "hello"
+    packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.1/wx1N6qhU3kKva-4YqsVJde3fho34NqiLD3m620zZ-OI.tar.br" }
+    imports [pf.Stdout]
+    provides [main] to pf
 
-main =
-    Stdout.line "I'm a Roc application!"
-
+main = + Stdout.line "I'm a Roc application!" +``` Try running this with: @@ -147,17 +148,18 @@ Congratulations, you've written your first Roc application! We'll go over what t Try replacing the `main` line with this: -
birds = 3
+```roc
+birds = 3
 
-iguanas = 2
+iguanas = 2
 
-total = Num.toStr (birds + iguanas)
+total = Num.toStr (birds + iguanas)
 
-main =
-    Stdout.line "There are \(total) animals."
-
+main = + Stdout.line "There are \(total) animals." +``` -Now run `roc dev` again. This time the "Downloading …" message won't appear; the file has been cached from last time, and won't need to be downloaded again. +Now run `roc dev` again. This time the "Downloading ..." message won't appear; the file has been cached from last time, and won't need to be downloaded again. You should see this: @@ -175,28 +177,30 @@ Once we have a def, we can use its name in other expressions. For example, the ` You can name a def using any combination of letters and numbers, but they have to start with a letter. - +**Note:** Defs are constant; they can't be reassigned. We'd get an error if we wrote these two defs in the same scope: + +```roc +birds = 3 +birds = 2 +``` ### [Defining Functions](#defining-functions) {#defining-functions} So far we've called functions like `Num.toStr`, `Str.concat`, and `Stdout.line`. Next let's try defining a function of our own. -
birds = 3
+```roc
+birds = 3
 
-iguanas = 2
+iguanas = 2
 
-total = Num.toStr (birds + iguanas)
+total = addAndStringify birds iguanas
 
-main =
-    Stdout.line "There are \(total) animals."
+main =
+    Stdout.line "There are \(total) animals."
 
-addAndStringify = \num1, num2 ->
-    Num.toStr (num1 + num2)
-
+addAndStringify = \num1, num2 -> + Num.toStr (num1 + num2) +``` This new `addAndStringify` function we've defined accepts two numbers, adds them, calls `Num.toStr` on the result, and returns that. @@ -206,14 +210,15 @@ The `\num1, num2 ->` syntax defines a function's arguments, and the expression a Let's modify this function to return an empty string if the numbers add to zero. -
addAndStringify = \num1, num2 ->
-    sum = num1 + num2
+```roc
+addAndStringify = \num1, num2 ->
+    sum = num1 + num2
 
-    if sum == 0 then
-        ""
-    else
-        Num.toStr (num1 + num2)
-
+ if sum == 0 then + "" + else + Num.toStr (num1 + num2) +``` We did two things here: @@ -226,30 +231,32 @@ Every `if` must be accompanied by both `then` and also `else`. Having an `if` wi We can combine `if` and `else` to get `else if`, like so: -
addAndStringify = \num1, num2 ->
-    sum = num1 + num2
+```roc
+addAndStringify = \num1, num2 ->
+    sum = num1 + num2
 
-    if sum == 0 then
-        ""
-    else if sum < 0 then
-        "negative"
-    else
-        Num.toStr (num1 + num2)
-
+ if sum == 0 then + "" + else if sum < 0 then + "negative" + else + Num.toStr (num1 + num2) +``` Note that `else if` is not a separate language keyword! It's just an `if`/`else` where the `else` branch contains another `if`/`else`. This is easier to see with different indentation: -
addAndStringify = \num1, num2 ->
-    sum = num1 + num2
+```roc
+addAndStringify = \num1, num2 ->
+    sum = num1 + num2
 
-    if sum == 0 then
-        ""
-    else
-        if sum < 0 then
-            "negative"
-        else
-            Num.toStr (num1 + num2)
-
+ if sum == 0 then + "" + else + if sum < 0 then + "negative" + else + Num.toStr (num1 + num2) +``` This differently-indented version is equivalent to writing `else if sum < 0 then` on the same line, although the convention is to use the original version's style. @@ -257,7 +264,9 @@ This differently-indented version is equivalent to writing `else if sum < 0 then This is a comment in Roc: -# The 'name' field is unused by addAndStringify +```roc +# The 'name' field is unused by addAndStringify +``` Whenever you write `#` it means that the rest of the line is a comment, and will not affect the running program. Roc does not have multiline comment syntax. @@ -266,11 +275,12 @@ running program. Roc does not have multiline comment syntax. Comments that begin with `##` are "doc comments" which will be included in generated documentation (`roc docs`). They can include code blocks by adding five spaces after `##`. -
## This is a comment for documentation, and includes a code block.
+```roc
+## This is a comment for documentation, and includes a code block.
 ##
 ##     x = 2
-##     expect x == 2
-
+## expect x == 2 +``` Like other comments, doc comments do not affect the running program. @@ -278,14 +288,15 @@ Like other comments, doc comments do not affect the running program. [Print debugging](https://en.wikipedia.org/wiki/Debugging#Techniques) is the most common debugging technique in the history of programming, and Roc has a `dbg` keyword to facilitate it. Here's an example of how to use `dbg`: -
pluralize = \singular, plural, count ->
-    dbg count
+```roc
+pluralize = \singular, plural, count ->
+    dbg count
 
-    if count == 1 then
+    if count == 1 then
         singular
-    else
+    else
         plural
-
+``` Whenever this `dbg` line of code is reached, the value of `count` will be printed to [stderr](), along with the source code file and line number where the `dbg` itself was written: @@ -295,11 +306,15 @@ Here, `[pluralize.roc 6:8]` tells us that this `dbg` was written in the file `pl You can give `dbg` any expression you like, for example: -dbg Str.concat singular plural +```roc +dbg Str.concat singular plural +``` An easy way to print multiple values at a time is to wrap them in a tag, for example a concise tag like `T`: -dbg T "the value of `count` is:" count +```roc +dbg T "the value of count is:" count +``` > **Note:** `dbg` is a debugging tool, and is only available when running your program via a `roc` subcommand (for example using `roc dev`, `roc run`, or `roc test`). When you build a standalone application with `roc build`, any uses of `dbg` won't be included! @@ -307,11 +322,12 @@ An easy way to print multiple values at a time is to wrap them in a tag, for exa Currently our `addAndStringify` function takes two arguments. We can instead make it take one argument like so: -
total = addAndStringify { birds: 5, iguanas: 7 }
+```roc
+total = addAndStringify { birds: 5, iguanas: 7 }
 
-addAndStringify = \counts ->
-    Num.toStr (counts.birds + counts.iguanas)
-
+addAndStringify = \counts -> + Num.toStr (counts.birds + counts.iguanas) +``` The function now takes a _record_, which is a group of named values. Records are not [objects](https://en.wikipedia.org/wiki/Object_(computer_science)); they don't have methods or inheritance, they just store information. @@ -327,13 +343,15 @@ When we use [`==`](/builtins/Bool#isEq) on records, it compares all the fields i The `addAndStringify` function will accept any record with at least the fields `birds` and `iguanas`, but it will also accept records with more fields. For example: -
total = addAndStringify { birds: 5, iguanas: 7 }
-
-# The `name` field is unused by addAndStringify
-totalWithNote = addAndStringify { birds: 4, iguanas: 3, name: "Whee!" }
+```roc
+total = addAndStringify { birds: 5, iguanas: 7 }
 
-addAndStringify = \counts ->
-    Num.toStr (counts.birds + counts.iguanas)
+# The `name` field is unused by addAndStringify +totalWithNote = addAndStringify { birds: 4, iguanas: 3, name: "Whee!" } + +addAndStringify = \counts -> + Num.toStr (counts.birds + counts.iguanas) +``` This works because `addAndStringify` only uses `counts.birds` and `counts.iguanas`. If we were to use `counts.note` inside `addAndStringify`, then we would get an error because `total` is calling `addAndStringify` passing a record that doesn't have a `note` field. @@ -343,13 +361,14 @@ Roc has a couple of shorthands you can use to express some record-related operat Instead of writing `\record -> record.x` we can write `.x` and it will evaluate to the same thing: a function that takes a record and returns its `x` field. You can do this with any field you want. For example: -
# returnFoo is a function that takes a record
-# and returns the `foo` field of that record.
-returnFoo = .foo
+```roc
+# returnFoo is a function that takes a record
+# and returns the `foo` field of that record.
+returnFoo = .foo
 
-returnFoo { foo: "hi!", bar: "blah" }
-# returns "hi!"
-
+returnFoo { foo: "hi!", bar: "blah" } +# returns "hi!" +``` Sometimes we assign a def to a field that happens to have the same name—for example, `{ x: x }`. In these cases, we shorten it to writing the name of the def alone—for example, `{ x }`. We can do this with as many fields as we like; here are several different ways to define the same record: @@ -363,30 +382,35 @@ In these cases, we shorten it to writing the name of the def alone—for example We can use _destructuring_ to avoid naming a record in a function argument, instead giving names to its individual fields: -
addAndStringify = \{ birds, iguanas } ->
-    Num.toStr (birds + iguanas)
-
+```roc +addAndStringify = \{ birds, iguanas } -> + Num.toStr (birds + iguanas) +``` Here, we've _destructured_ the record to create a `birds` def that's assigned to its `birds` field, and an `iguanas` def that's assigned to its `iguanas` field. We can customize this if we like: -
addAndStringify = \{ birds, iguanas: lizards } ->
-    Num.toStr (birds + lizards)
-
+```roc +addAndStringify = \{ birds, iguanas: lizards } -> + Num.toStr (birds + lizards) +``` In this version, we created a `lizards` def that's assigned to the record's `iguanas` field. (We could also do something similar with the `birds` field if we like.) Finally, destructuring can be used in defs too: -
{ x, y } = { x: 5, y: 10 }
+```roc +{ x, y } = { x: 5, y: 10 } +``` ### [Making records from other records](#making-records-from-other-records) {#making-records-from-other-records} So far we've only constructed records from scratch, by specifying all of their fields. We can also construct new records by using another record to use as a starting point, and then specifying only the fields we want to be different. For example, here are two ways to get the same record: -
original = { birds: 5, zebras: 2, iguanas: 7, goats: 1 }
-fromScratch = { birds: 4, zebras: 2, iguanas: 3, goats: 1 }
-fromOriginal = { original & birds: 4, iguanas: 3 }
-
+```roc +original = { birds: 5, zebras: 2, iguanas: 7, goats: 1 } +fromScratch = { birds: 4, zebras: 2, iguanas: 3, goats: 1 } +fromOriginal = { original & birds: 4, iguanas: 3 } +``` The `fromScratch` and `fromOriginal` records are equal, although they're defined in different ways. @@ -402,29 +426,31 @@ Roc supports optional record fields using the `?` operator. This can be a useful In Roc you can write a function like: -
table = \{ 
+```roc
+table = \{ 
         height, 
         width, 
-        title? "oak", 
-        description? "a wooden table" 
-    }
-    ->
-
+ title? "oak", + description? "a wooden table" + } + -> +``` This is using *optional field destructuring* to destructure a record while also providing default values for any fields that might be missing. Here's the type of `table`: -
table :
-    {
-        height : Pixels,
-        width : Pixels,
-        title ? Str,
-        description ? Str,
-    }
-    -> Table
-
+```roc +table : + { + height: Pixels, + width: Pixels, + title? Str, + description? Str, + } + -> Table +``` This says that `table` takes a record with two *required* fields, `height` and `width`, and two *optional* fields, `title` and `description`. It also says that @@ -449,14 +475,15 @@ ergonomics of destructuring mean this wouldn't be a good fit for data modeling, Sometimes we want to represent that something can have one of several values. For example: -
stoplightColor =
-    if something > 0 then
+```roc
+stoplightColor =
+    if something > 0 then
         Red
-    else if something == 0 then
+    else if something == 0 then
         Yellow
-    else
+    else
         Green
-
+``` Here, `stoplightColor` can have one of three values: `Red`, `Yellow`, or `Green`. The capitalization is very important! If these were lowercase (`red`, `yellow`, `green`), then they would refer to defs. However, because they are capitalized, they instead refer to _tags_. @@ -464,74 +491,80 @@ A tag is a literal value just like a number or a string. Similarly to how I can Let's say we wanted to turn `stoplightColor` from a `Red`, `Green`, or `Yellow` into a string. Here's one way we could do that: -
stoplightStr =
-    if stoplightColor == Red then
-        "red"
-    else if stoplightColor == Green then
-        "green"
-    else
-        "yellow"
-
+```roc +stoplightStr = + if stoplightColor == Red then + "red" + else if stoplightColor == Green then + "green" + else + "yellow" +``` We can express this logic more concisely using `when`/`is` instead of `if`/`then`: -
stoplightStr =
-    when stoplightColor is
-        Red -> "red"
-        Green -> "green"
-        Yellow -> "yellow"
-
+```roc +stoplightStr = + when stoplightColor is + Red -> "red" + Green -> "green" + Yellow -> "yellow" +``` This results in the same value for `stoplightStr`. In both the `when` version and the `if` version, we have three conditional branches, and each of them evaluates to a string. The difference is how the conditions are specified; here, we specify between `when` and `is` that we're making comparisons against `stoplightColor`, and then we specify the different things we're comparing it to: `Red`, `Green`, and `Yellow`. Besides being more concise, there are other advantages to using `when` here. 1. We don't have to specify an `else` branch, so the code can be more self-documenting about exactly what all the options are. -2. We get more compiler help. If we try deleting any of these branches, we'll get a compile-time error saying that we forgot to cover a case that could come up. For example, if we delete the `Green ->` branch, the compiler will say that we didn't handle the possibility that `stoplightColor` could be `Green`. It knows this because `Green` is one of the possibilities in our `stoplightColor = if …` definition. +2. We get more compiler help. If we try deleting any of these branches, we'll get a compile-time error saying that we forgot to cover a case that could come up. For example, if we delete the `Green ->` branch, the compiler will say that we didn't handle the possibility that `stoplightColor` could be `Green`. It knows this because `Green` is one of the possibilities in our `stoplightColor = if ...` definition. We can still have the equivalent of an `else` branch in our `when` if we like. Instead of writing `else`, we write `_ ->` like so: -
stoplightStr =
-    when stoplightColor is
-        Red -> "red"
-        _ -> "not red"
-
+```roc +stoplightStr = + when stoplightColor is + Red -> "red" + _ -> "not red" +``` This lets us more concisely handle multiple cases. However, it has the downside that if we add a new case - for example, if we introduce the possibility of `stoplightColor` being `Orange`, the compiler can no longer tell us we forgot to handle that possibility in our `when`. After all, we are handling it - just maybe not in the way we'd decide to if the compiler had drawn our attention to it! We can make this `when` _exhaustive_ (that is, covering all possibilities) without using `_ ->` by using `|` to specify multiple matching conditions for the same branch: -
stoplightStr =
-    when stoplightColor is
-        Red -> "red"
-        Green | Yellow -> "not red"
-
+```roc +stoplightStr = + when stoplightColor is + Red -> "red" + Green | Yellow -> "not red" +``` You can read `Green | Yellow` as "either `Green` or `Yellow`". By writing it this way, if we introduce the possibility that `stoplightColor` can be `Orange`, we'll get a compiler error telling us we forgot to cover that case in this `when`, and then we can handle it however we think is best. We can also combine `if` and `when` to make branches more specific: -
stoplightStr =
-    when stoplightColor is
-        Red -> "red"
-        Green | Yellow if contrast > 75 -> "not red, but very high contrast"
-        Green | Yellow if contrast > 50 -> "not red, but high contrast"
-        Green | Yellow -> "not red"
-
+```roc +stoplightStr = + when stoplightColor is + Red -> "red" + Green | Yellow if contrast > 75 -> "not red, but very high contrast" + Green | Yellow if contrast > 50 -> "not red, but high contrast" + Green | Yellow -> "not red" +``` This will give the same answer for `stoplightStr` as if we had written the following: -
stoplightStr =
-    when stoplightColor is
-        Red -> "red"
-        Green | Yellow ->
-            if contrast > 75 then
-                "not red, but very high contrast"
-            else if contrast > 50 then
-                "not red, but high contrast"
-            else
-                "not red"
-
+```roc +stoplightStr = + when stoplightColor is + Red -> "red" + Green | Yellow -> + if contrast > 75 then + "not red, but very high contrast" + else if contrast > 50 then + "not red, but high contrast" + else + "not red" +``` Either style can be a reasonable choice depending on the circumstances. @@ -539,22 +572,23 @@ Either style can be a reasonable choice depending on the circumstances. Tags can have _payloads_—that is, values inside them. For example: -
stoplightColor =
-    if something > 100 then
+```roc
+stoplightColor =
+    if something > 100 then
         Red
-    else if something > 0 then
+    else if something > 0 then
         Yellow
-    else if something == 0 then
+    else if something == 0 then
         Green
-    else
-        Custom "some other color"
+    else
+        Custom "some other color"
 
-stoplightStr =
-    when stoplightColor is
-        Red -> "red"
-        Green | Yellow -> "not red"
-        Custom description -> description
-
+stoplightStr = + when stoplightColor is + Red -> "red" + Green | Yellow -> "not red" + Custom description -> description +``` This makes two changes to our earlier `stoplightColor` / `stoplightStr` example. @@ -571,17 +605,18 @@ We refer to whatever comes before a `->` in a `when` expression as a _pattern_ You can also pattern match on lists, like so: -
when myList is
-    [] -> 0 # the list is empty
-    [Foo, ..] -> 1 # it starts with a Foo tag
-    [_, ..] -> 2 # it contains at least one element, which we ignore
-    [Foo, Bar, ..] -> 3 # it starts with a Foo tag followed by a Bar tag
-    [Foo, Bar, Baz] -> 4 # it has exactly 3 elements: Foo, Bar, and Baz
-    [Foo, a, ..] -> 5 # its first element is Foo, and its second we name `a`
-    [Ok a, ..] -> 6 # it starts with an Ok containing a payload named `a`
-    [.., Foo] -> 7 # it ends with a Foo tag
-    [A, B, .., C, D] -> 8 # it has certain elements at the beginning and end
-
+```roc +when myList is + [] -> 0 # the list is empty + [Foo, ..] -> 1 # it starts with a Foo tag + [_, ..] -> 2 # it contains at least one element, which we ignore + [Foo, Bar, ..] -> 3 # it starts with a Foo tag followed by a Bar tag + [Foo, Bar, Baz] -> 4 # it has exactly 3 elements: Foo, Bar, and Baz + [Foo, a, ..] -> 5 # its first element is Foo, and its second we name `a` + [Ok a, ..] -> 6 # it starts with an Ok containing a payload named `a` + [.., Foo] -> 7 # it ends with a Foo tag + [A, B, .., C, D] -> 8 # it has certain elements at the beginning and end +``` This can be both more concise and more efficient (at runtime) than calling [`List.get`](https://www.roc-lang.org/builtins/List#get) multiple times, since each call to `get` requires a separate conditional to handle the different `Result`s they return. @@ -599,11 +634,15 @@ As an example of why tags are encouraged for data modeling, in many languages it Another thing we can do in Roc is to make a _list_ of values. Here's an example: -names = ["Sam", "Lee", "Ari"] +```roc +names = ["Sam", "Lee", "Ari"] +``` This is a list with three elements in it, all strings. We can add a fourth element using `List.append` like so: -List.append names "Jess" +```roc +List.append names "Jess" +``` This returns a **new** list with `"Jess"` after `"Ari"`, and doesn't modify the original list at all. All values in Roc (including lists, but also records, strings, numbers, and so on) are immutable, meaning whenever we want to "change" them, we want to instead pass them to a function which returns some variation of what was passed in. @@ -611,8 +650,9 @@ This returns a **new** list with `"Jess"` after `"Ari"`, and doesn't modify the A common way to transform one list into another is to use `List.map`. Here's an example of how to use it: -List.map [1, 2, 3] \num -> num * 2 - +```roc +List.map [1, 2, 3] \num -> num * 2 +``` This returns `[2, 4, 6]`. @@ -625,9 +665,11 @@ It then returns a list which it creates by calling the given function on each el We can also give `List.map` a named function, instead of an anonymous one: -List.map [1, 2, 3] Num.isOdd +```roc +List.map [1, 2, 3] Num.isOdd +``` -This `Num.isOdd` function returns `Bool.true` if it's given an odd number, and `Bool.false` otherwise. So `Num.isOdd 5` returns true and `Num.isOdd 2` returns false. +This `Num.isOdd` function returns `Bool.true` if it's given an odd number, and `Bool.false` otherwise. So `Num.isOdd 5` returns `Bool.true` and `Num.isOdd 2` returns `Bool.false`. As such, calling `List.map [1, 2, 3] Num.isOdd` returns a new list of `[Bool.true, Bool.false, Bool.true]`. @@ -635,22 +677,25 @@ As such, calling `List.map [1, 2, 3] Num.isOdd` returns a new list of `[Bool.tru If we tried to give `List.map` a function that didn't work on the elements in the list, then we'd get an error at compile time. Here's a valid, and then an invalid example: -
# working example
-List.map [-1, 2, 3, -4] Num.isNegative
-# returns [Bool.true, Bool.false, Bool.false, Bool.true]
-
+```roc +# working example +List.map [-1, 2, 3, -4] Num.isNegative +# returns [Bool.true, Bool.false, Bool.false, Bool.true] +``` -
# invalid example
-List.map ["A", "B", "C"] Num.isNegative
-# error: isNegative doesn't work on strings!
-
+```roc +# invalid example +List.map ["A", "B", "C"] Num.isNegative +# error: isNegative doesn't work on strings! +``` Because `Num.isNegative` works on numbers and not strings, calling `List.map` with `Num.isNegative` and a list of numbers works, but doing the same with a list of strings doesn't work. This wouldn't work either: -
List.map ["A", "B", "C", 1, 2, 3] Num.isNegative
-
+```roc +List.map ["A", "B", "C", 1, 2, 3] Num.isNegative +``` Every element in a Roc list has to share the same type. For example, we can have a list of strings like `["Sam", "Lee", "Ari"]`, or a list of numbers like `[1, 2, 3, 4, 5]` but we can't have a list which mixes strings and numbers like `["Sam", 1, "Lee", 2, 3]`, that would be a compile-time error. @@ -660,17 +705,19 @@ Ensuring that all elements in a list share a type eliminates entire categories o We can use tags with payloads to make a list that contains a mixture of different types. For example: -
List.map [StrElem "A", StrElem "b", NumElem 1, StrElem "c", NumElem -3] \elem ->
-    when elem is
-        NumElem num -> Num.isNegative num
-        StrElem str -> Str.isCapitalized str
-# returns [Bool.true, Bool.false, Bool.false, Bool.false, Bool.true]
-
+```roc +List.map [StrElem "A", StrElem "b", NumElem 1, StrElem "c", NumElem -3] \elem -> + when elem is + NumElem num -> Num.isNegative num + StrElem str -> Str.isCapitalized str +# returns [Bool.true, Bool.false, Bool.false, Bool.false, Bool.true] +``` Compare this with the example from earlier, which caused a compile-time error: -
List.map ["A", "B", "C", 1, 2, 3] Num.isNegative
-
+```roc +List.map ["A", "B", "C", 1, 2, 3] Num.isNegative +``` The version that uses tags works because we aren't trying to call `Num.isNegative` on each element. Instead, we're using a `when` to tell when we've got a string or a number, and then calling either `Num.isNegative` or `Str.isCapitalized` depending on which type we have. @@ -680,57 +727,66 @@ We could take this as far as we like, adding more different tags (e.g. `BoolElem Let's say I want to apply a tag to a bunch of elements in a list. For example: -
List.map ["a", "b", "c"] \str -> Foo str
-
+```roc +List.map ["a", "b", "c"] \str -> Foo str +``` This is a perfectly reasonable way to write it, but I can also write it like this: -
List.map ["a", "b", "c"] Foo
-
+```roc +List.map ["a", "b", "c"] Foo +``` These two versions compile to the same thing. As a convenience, Roc lets you specify a tag name where a function is expected; when you do this, the compiler infers that you want a function which uses all of its arguments as the payload to the given tag. -### [`List.any` and `List.all`](#list-any-and-list-all) {#list-any-and-list-all} +### [List.any and List.all](#list-any-and-list-all) {#list-any-and-list-all} -There are several functions that work like `List.map`, they walk through each element of a list and do something with it. Another is `List.any`, which returns `Bool.true` if calling the given function on any element in the list returns `true`: +There are several functions that work like `List.map`, they walk through each element of a list and do something with it. Another is `List.any`, which returns `Bool.true` if calling the given function on any element in the list returns `Bool.true`: -
List.any [1, 2, 3] Num.isOdd
-# returns `Bool.true` because 1 and 3 are odd
-
+```roc +List.any [1, 2, 3] Num.isOdd +# returns `Bool.true` because 1 and 3 are odd +``` -
List.any [1, 2, 3] Num.isNegative
-# returns `Bool.false` because none of these is negative
-
+```roc +List.any [1, 2, 3] Num.isNegative +# returns `Bool.false` because none of these is negative +``` -There's also `List.all` which only returns `true` if all the elements in the list pass the test: +There's also `List.all` which only returns `Bool.true` if all the elements in the list pass the test: -
List.all [1, 2, 3] Num.isOdd
-# returns `Bool.false` because 2 is not odd
-
+```roc +List.all [1, 2, 3] Num.isOdd +# returns `Bool.false` because 2 is not odd +``` -
List.all [1, 2, 3] Num.isPositive
-# returns `Bool.true` because all of these are positive
-
+```roc +List.all [1, 2, 3] Num.isPositive +# returns `Bool.true` because all of these are positive +``` ### [Removing elements from a list](#removing-elements-from-a-list) {#removing-elements-from-a-list} You can also drop elements from a list. One way is `List.dropAt` - for example: -
List.dropAt ["Sam", "Lee", "Ari"] 1
-# drops the element at offset 1 ("Lee") and returns ["Sam", "Ari"]
-
+```roc +List.dropAt ["Sam", "Lee", "Ari"] 1 +# drops the element at offset 1 ("Lee") and returns ["Sam", "Ari"] +``` -Another way is to use `List.keepIf`, which passes each of the list's elements to the given function, and then keeps them only if that function returns `true`. +Another way is to use `List.keepIf`, which passes each of the list's elements to the given function, and then keeps them only if that function returns `Bool.true`. -
List.keepIf [1, 2, 3, 4, 5] Num.isEven
-# returns [2, 4]
-
+```roc +List.keepIf [1, 2, 3, 4, 5] Num.isEven +# returns [2, 4] +``` There's also `List.dropIf`, which does the opposite: -
List.dropIf [1, 2, 3, 4, 5] Num.isEven
-# returns [1, 3, 5]
-
+```roc +List.dropIf [1, 2, 3, 4, 5] Num.isEven +# returns [1, 3, 5] +``` ### [Getting an individual element from a list](#getting-an-individual-element-from-a-list) {#getting-an-individual-element-from-a-list} @@ -738,32 +794,38 @@ Another thing we can do with a list is to get an individual element out of it. ` For example, what do each of these return? -
List.get ["a", "b", "c"] 1
-
-List.get ["a", "b", "c"] 100
-
+```roc +List.get ["a", "b", "c"] 1 +``` + +```roc +List.get ["a", "b", "c"] 100 +``` The answer is that the first one returns `Ok "b"` and the second one returns `Err OutOfBounds`. They both return tags! This is done so that the caller becomes responsible for handling the possibility that the index is outside the bounds of that particular list. Here's how calling `List.get` can look in practice: -
when List.get ["a", "b", "c"] index is
-    Ok str -> "I got this string: \(str)"
-    Err OutOfBounds -> "That index was out of bounds, sorry!"
-
+```roc +when List.get ["a", "b", "c"] index is + Ok str -> "I got this string: \(str)" + Err OutOfBounds -> "That index was out of bounds, sorry!" +``` There's also `List.first`, which always gets the first element, and `List.last` which always gets the last. They return `Err ListWasEmpty` instead of `Err OutOfBounds`, because the only way they can fail is if you pass them an empty list! These functions demonstrate a common pattern in Roc: operations that can fail returning either an `Ok` tag with the answer (if successful), or an `Err` tag with another tag describing what went wrong (if unsuccessful). In fact, it's such a common pattern that there's a whole module called `Result` which deals with these two tags. Here are some examples of `Result` functions: -
Result.withDefault (List.get ["a", "b", "c"] 100) ""
-# returns "" because that's the default we said to use if List.get returned an Err
-
-Result.isOk (List.get ["a", "b", "c"] 1)
-# returns `Bool.true` because `List.get` returned an `Ok` tag. (The payload gets ignored.)
+```roc
+Result.withDefault (List.get ["a", "b", "c"] 100) ""
+# returns "" because that's the default we said to use if List.get returned an Err
+```
+```roc
+Result.isOk (List.get ["a", "b", "c"] 1)
+# returns `Bool.true` because `List.get` returned an `Ok` tag. (The payload gets ignored.)
 
-# Note: There's a Result.isErr function that works similarly.
-
+# Note: There's a Result.isErr function that works similarly. +``` ### [Walking the elements in a list](#walking-the-elements-in-a-list) {#walking-the-elements-in-a-list} @@ -782,14 +844,15 @@ because it's more concise, runs faster, and doesn't give you any `Result`s to de Here's an example: -
List.walk [1, 2, 3, 4, 5] { evens: [], odds: [] } \state, elem ->
-    if Num.isEven elem then
-        { state & evens: List.append state.evens elem }
-    else
-        { state & odds: List.append state.odds elem }
+```roc
+List.walk [1, 2, 3, 4, 5] { evens: [], odds: [] } \state, elem ->
+    if Num.isEven elem then
+        { state & evens: List.append state.evens elem }
+    else
+        { state & odds: List.append state.odds elem }
 
-# returns { evens: [2, 4], odds: [1, 3, 5] }
-
+# returns { evens: [2, 4], odds: [1, 3, 5] } +``` In this example, we walk over the list `[1, 2, 3, 4, 5]` and add each element to either the `evens` or `odds` field of a `state` record: `{ evens, odds }`. By the end, that record has a list of all the even numbers in the list and a list of all the odd numbers. @@ -797,48 +860,17 @@ In this example, we walk over the list `[1, 2, 3, 4, 5]` and add each element to 1. A list. (`[1, 2, 3, 4, 5]`) 2. An initial `state` value. (`{ evens: [], odds: [] }`) -3. A function which takes the current `state` and element, and returns a new `state`. (`\state, elem -> …`) +3. A function which takes the current `state` and element, and returns a new `state`. (`\state, elem -> ...`) It then proceeds to walk over each element in the list and call that function. Each time, the state that function returns becomes the argument to the next function call. Here are the arguments the function will receive, and what it will return, as `List.walk` walks over the list `[1, 2, 3, 4, 5]`: -
-
-
-
-    
-    
-    
-
-
-
-
-    
-    
-    
-
-
-    
-    
-    
-
-
-    
-    
-    
-
-
-    
-    
-    
-
-
-    
-    
-    
-
-
-
stateelementreturn value
{ evens: [], odds: [] }1{ evens: [], odds: [1] }
{ evens: [], odds: [1] }2{ evens: [2], odds: [1] }
{ evens: [2], odds: [1] }3{ evens: [2], odds: [1, 3] }
{ evens: [2], odds: [1, 3] }4{ evens: [2, 4], odds: [1, 3] }
{ evens: [2, 4], odds: [1, 3] }4{ evens: [2, 4], odds: [1, 3, 5] }
-
+| State | Element | Return Value | +| --------------------------------- | ------- | ------------------------------------ | +| `{ evens: [], odds: [] }` | `1` | `{ evens: [], odds: [1] }` | +| `{ evens: [], odds: [1] }` | `2` | `{ evens: [2], odds: [1] }` | +| `{ evens: [2], odds: [1] }` | `3` | `{ evens: [2], odds: [1, 3] }` | +| `{ evens: [2], odds: [1, 3] }` | `4` | `{ evens: [2, 4], odds: [1, 3] }` | +| `{ evens: [2, 4], odds: [1, 3] }` | `4` | `{ evens: [2, 4], odds: [1, 3, 5] }` | Note that the initial `state` argument is `{ evens: [], odds: [] }` because that's the argument we passed `List.walk` for its initial state. From then on, each `state` argument is whatever the @@ -850,46 +882,50 @@ Note that the state doesn't have to be a record; it can be anything you want. Fo A helpful way to remember the argument order for `List.walk` is that that its arguments follow the same pattern as what we've seen with `List.map`, `List.any`, `List.keepIf`, and `List.dropIf`: the first argument is a list, and the last argument is a function. The difference here is that `List.walk` has one more argument than those other functions; the only place it could go while preserving that pattern is in the middle! -> **Note:** Other languages give this operation different names, such as `fold`, `reduce`, `accumulate`, `aggregate`, `compress`, and `inject`. Some languages also have operations like `forEach` or `for…in` syntax, which walk across every element and perform potentially side-effecting operations on them; `List.walk` can be used to replace these too, if you include a `Task` in the state. We'll talk about tasks, and how to use them with `List.walk`, later on. +> **Note:** Other languages give this operation different names, such as `fold`, `reduce`, `accumulate`, `aggregate`, `compress`, and `inject`. Some languages also have operations like `forEach` or `for...in` syntax, which walk across every element and perform potentially side-effecting operations on them; `List.walk` can be used to replace these too, if you include a `Task` in the state. We'll talk about tasks, and how to use them with `List.walk`, later on. ### [The pipe operator](#the-pipe-operator) {#the-pipe-operator} When you have nested function calls, sometimes it can be clearer to write them in a "pipelined" style using the `|>` operator. Here are three examples of writing the same expression; they all compile to exactly the same thing, but two of them use the `|>` operator to change how the calls look. -
Result.withDefault (List.get ["a", "b", "c"] 1) ""
-
-List.get ["a", "b", "c"] 1
-|> Result.withDefault ""
-
+```roc +Result.withDefault (List.get ["a", "b", "c"] 1) "" +``` +```roc +List.get ["a", "b", "c"] 1 +|> Result.withDefault "" +``` The `|>` operator takes the value that comes before the `|>` and passes it as the first argument to whatever comes after the `|>`. So in the example above, the `|>` takes `List.get ["a", "b", "c"] 1` and passes that value as the first argument to `Result.withDefault`, making `""` the second argument to `Result.withDefault`. We can take this a step further like so: -
["a", "b", "c"]
-|> List.get 1
-|> Result.withDefault ""
-
+```roc +["a", "b", "c"] +|> List.get 1 +|> Result.withDefault "" +``` This is still equivalent to the first expression. Since `|>` is known as the "pipe operator," we can read this as "start with `["a", "b", "c"]`, then pipe it to `List.get`, then pipe it to `Result.withDefault`." One reason the `|>` operator injects the value as the first argument is to make it work better with functions where argument order matters. For example, these two uses of `List.append` are equivalent: -
List.append ["a", "b", "c"] "d"
-
-["a", "b", "c"]
-|> List.append "d"
-
+```roc +List.append ["a", "b", "c"] "d" +``` +```roc +["a", "b", "c"] +|> List.append "d" +``` Another example is `Num.div`. All three of the following do the same thing, because `a / b` in Roc is syntax sugar for `Num.div a b`: -
first / second
-
-Num.div first second
-
-first
-|> Num.div second
-
+```roc +first / second +``` +```roc +Num.div first second +``` All operators in Roc are syntax sugar for normal function calls. See the [Operator Desugaring Table](https://www.roc-lang.org/tutorial#operator-desugaring-table) at the end of this tutorial for a complete list of them. @@ -897,10 +933,11 @@ All operators in Roc are syntax sugar for normal function calls. See the [Operat Sometimes you may want to document the type of a definition. For example, you might write: -
# Takes a firstName string and a lastName string, and returns a string
-fullName = \firstName, lastName ->
-    "\(firstName) \(lastName)"
-
+```roc +# Takes a firstName string and a lastName string, and returns a string +fullName = \firstName, lastName -> + "\(firstName) \(lastName)" +``` Comments can be valuable documentation, but they can also get out of date and become misleading. If someone changes this function and forgets to update the comment, it will no longer be accurate. @@ -908,10 +945,11 @@ Comments can be valuable documentation, but they can also get out of date and be Here's another way to document this function's type, which doesn't have that problem: -
fullName : Str, Str -> Str
-fullName = \firstName, lastName ->
-    "\(firstName) \(lastName)"
-
+```roc +fullName : Str, Str -> Str +fullName = \firstName, lastName -> + "\(firstName) \(lastName)" +``` The `fullName :` line is a _type annotation_. It's a strictly optional piece of metadata we can add above a def to describe its type. Unlike a comment, the Roc compiler will check type annotations for accuracy. If the annotation ever doesn't fit with the implementation, we'll get a compile-time error. @@ -919,36 +957,39 @@ The annotation `fullName : Str, Str -> Str` says "`fullName` is a function that We can give type annotations to any value, not just functions. For example: -
firstName : Str
-firstName = "Amy"
+```roc
+firstName : Str
+firstName = "Amy"
 
-lastName : Str
-lastName = "Lee"
-
+lastName : Str +lastName = "Lee" +``` These annotations say that both `firstName` and `lastName` have the type `Str`. We can annotate records similarly. For example, we could move `firstName` and `lastName` into a record like so: -
amy : { firstName : Str, lastName : Str }
-amy = { firstName: "Amy", lastName: "Lee" }
+```roc
+amy : { firstName : Str, lastName : Str }
+amy = { firstName: "Amy", lastName: "Lee" }
 
-jen : { firstName : Str, lastName : Str }
-jen = { firstName: "Jen", lastName: "Majura" }
-
+jen : { firstName : Str, lastName : Str } +jen = { firstName: "Jen", lastName: "Majura" } +``` ### [Type Aliases](#type-aliases) {#type-aliases} When we have a recurring type annotation like this, it can be nice to give it its own name. We do this like so: -
Musician : { firstName : Str, lastName : Str }
+```roc
+Musician : { firstName : Str, lastName : Str }
 
-amy : Musician
-amy = { firstName: "Amy", lastName: "Lee" }
+amy : Musician
+amy = { firstName: "Amy", lastName: "Lee" }
 
-simone : Musician
-simone = { firstName: "Simone", lastName: "Simons" }
-
+simone : Musician +simone = { firstName: "Simone", lastName: "Simons" } +``` Here, `Musician` is a _type alias_. A type alias is like a def, except it gives a name to a type instead of to a value. Just like how you can read `name : Str` as "`name` has the type `Str`," you can also read `Musician : { firstName : Str, lastName : Str }` as "`Musician` has the type `{ firstName : Str, lastName : Str }`." @@ -956,9 +997,10 @@ Here, `Musician` is a _type alias_. A type alias is like a def, except it gives Annotations for lists must specify what type the list's elements have: -
names : List Str
-names = ["Amy", "Simone", "Tarja"]
-
+```roc +names : List Str +names = ["Amy", "Simone", "Tarja"] +``` You can read `List Str` as "a list of strings." Here, `Str` is a _type parameter_ that tells us what type of `List` we're dealing with. `List` is a _parameterized type_, which means it's a type that requires a type parameter. There's no way to give something a type of `List` without a type parameter. You have to specify what type of list it is, such as `List Str` or `List Bool` or `List { firstName : Str, lastName : Str }`. @@ -966,8 +1008,9 @@ You can read `List Str` as "a list of strings." Here, `Str` is a _type parameter There are some functions that work on any list, regardless of its type parameter. For example, `List.isEmpty` has this type: -
isEmpty : List * -> Bool
-
+```roc +isEmpty : List * -> Bool +``` The `*` is a _wildcard type_; a type that's compatible with any other type. `List *` is compatible with any type of `List` like `List Str`, `List Bool`, and so on. So you can call `List.isEmpty ["I am a List Str"]` as well as `List.isEmpty [Bool.true]`, and they will both work fine. @@ -977,12 +1020,13 @@ The wildcard type also comes up with empty lists. Suppose we have one function t `List.reverse` works similarly to `List.isEmpty`, but with an important distinction. As with `isEmpty`, we can call `List.reverse` on any list, regardless of its type parameter. However, consider these calls: -
strings : List Str
-strings = List.reverse ["a", "b"]
+```roc
+strings : List Str
+strings = List.reverse ["a", "b"]
 
-bools : List Bool
-bools = List.reverse [Bool.true, Bool.false]
-
+bools : List Bool +bools = List.reverse [Bool.true, Bool.false] +``` In the `strings` example, we have `List.reverse` returning a `List Str`. In the `bools` example, it's returning a `List Bool`. So what's the type of `List.reverse`? @@ -990,12 +1034,17 @@ We saw that `List.isEmpty` has the type `List * -> Bool`, so we might think the What we want is something like one of these: -
reverse : List elem -> List elem
-
-reverse : List value -> List value
-
-reverse : List a -> List a
-
+```roc +reverse : List elem -> List elem +``` + +```roc +reverse : List value -> List value +``` + +```roc +reverse : List a -> List a +``` Any of these will work, because `elem`, `value`, and `a` are all _type variables_. A type variable connects two or more types in the same annotation. So you can read `List elem -> List elem` as "takes a list and returns a list that has **the same element type**." Just like `List.reverse` does! @@ -1009,47 +1058,52 @@ Similarly, the only way to have a function whose type is `a -> a` is if the func We can also annotate types that include tags: -
colorFromStr : Str -> [Red, Green, Yellow]
-colorFromStr = \string ->
-    when string is
-        "red" -> Red
-        "green" -> Green
-        _ -> Yellow
-
+```roc +colorFromStr : Str -> [Red, Green, Yellow] +colorFromStr = \string -> + when string is + "red" -> Red + "green" -> Green + _ -> Yellow +``` You can read the type `[Red, Green, Yellow]` as "a tag union of the tags `Red`, `Green`, and `Yellow`." Some tag unions have only one tag in them. For example: -
redTag : [Red]
-redTag = Red
-
+```roc +redTag : [Red] +redTag = Red +``` ### [Accumulating Tag Types](#accumulating-tag-types) {#accumulating-tag-types} Tag union types can accumulate more tags based on how they're used. Consider this `if` expression: -
\str ->
-    if Str.isEmpty str then
-        Ok "it was empty"
-    else
-        Err ["it was not empty"]
-
+```roc +\str -> + if Str.isEmpty str then + Ok "it was empty" + else + Err ["it was not empty"] +``` Here, Roc sees that the first branch has the type `[Ok Str]` and that the `else` branch has the type `[Err (List Str)]`, so it concludes that the whole `if` expression evaluates to the combination of those two tag unions: `[Ok Str, Err (List Str)]`. -This means this entire `\str -> …` function has the type `Str -> [Ok Str, Err (List Str)]`. However, it would be most common to annotate it as `Result Str (List Str)` instead, because the `Result` type (for operations like `Result.withDefault`, which we saw earlier) is a type alias for a tag union with `Ok` and `Err` tags that each have one payload: +This means this entire `\str -> ...` function has the type `Str -> [Ok Str, Err (List Str)]`. However, it would be most common to annotate it as `Result Str (List Str)` instead, because the `Result` type (for operations like `Result.withDefault`, which we saw earlier) is a type alias for a tag union with `Ok` and `Err` tags that each have one payload: -
Result ok err : [Ok ok, Err err]
-
+```roc +Result ok err : [Ok ok, Err err] +``` We just saw how tag unions get combined when different branches of a conditional return different tags. Another way tag unions can get combined is through pattern matching. For example: -
when color is
-    Red -> "red"
-    Yellow -> "yellow"
-    Green -> "green"
-
+```roc +when color is + Red -> "red" + Yellow -> "yellow" + Green -> "green" +``` Here, Roc's compiler will infer that `color`'s type is `[Red, Yellow, Green]`, because those are the three possibilities this `when` handles. @@ -1062,16 +1116,17 @@ A type can be defined to be opaque to hide its internal structure. This is a lot You can create an opaque type with the `:=` operator. Let's make one called `Username`: -
Username := Str
+```roc
+Username := Str
 
-fromStr : Str -> Username
-fromStr = \str ->
+fromStr : Str -> Username
+fromStr = \str ->
     @Username str
 
-toStr : Username -> Str
-toStr = \@Username str ->
+toStr : Username -> Str
+toStr = \@Username str ->
     str
-
+``` The `fromStr` function turns a string into a `Username` by calling `@Username` on that string. The `toStr` function turns a `Username` back into a string by pattern matching `@Username str` to unwrap the string from the `Username` opaque type. @@ -1105,57 +1160,18 @@ Choosing a size depends on your performance needs and the range of numbers you w Here are the different fixed-size integer types that Roc supports: -

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
RangeType
-128
127
I8
0
255
U8
-32_768
32_767
I16
0
65_535
U16
-2_147_483_648
2_147_483_647
I32
0
(over 4 billion) 4_294_967_295
U32
-9_223_372_036_854_775_808
9_223_372_036_854_775_807
I64
0
(over 18 quintillion)18_446_744_073_709_551_615
U64
-170_141_183_460_469_231_731_687_303_715_884_105_728
170_141_183_460_469_231_731_687_303_715_884_105_727
I128
0
(over 340 undecillion)340_282_366_920_938_463_463_374_607_431_768_211_455
U128
- +| Range | Type | +|-------------------------------------------------------------------------------------------------------------------|--------| +| `-128`
`127` | `I8` | +| `0`
`255` | `U8` | +| `-32_768`
`32_767` | `I16` | +| `0`
`65_535` | `U16` | +| `-2_147_483_648`
`2_147_483_647` | `I32` | +| `0`
(over 4 billion) `4_294_967_295` | `U32` | +| `-9_223_372_036_854_775_808`
`9_223_372_036_854_775_807` | `I64` | +| `0`
_(over 18 quintillion)_`18_446_744_073_709_551_615` | `U64` | +| `-170_141_183_460_469_231_731_687_303_715_884_105_728`
`170_141_183_460_469_231_731_687_303_715_884_105_727` | `I128` | +| `0`
_(over 340 undecillion)_`340_282_366_920_938_463_463_374_607_431_768_211_455` | `U128` | Roc also has one variable-size integer type: `Nat` (short for "natural number"). The size of `Nat` is equal to the size of a memory address, which varies by system. For example, when compiling for a 64-bit system, `Nat` works the same way as `U64`. When compiling for a 32-bit system, it works the same way as `U32`. Most popular computing devices today are 64-bit, so `Nat` is usually the same as `U64`, but Web Assembly is typically 32-bit - so when running a Roc program built for Web Assembly, `Nat` will work like a `U32` in that program. @@ -1189,18 +1205,20 @@ There are some use cases where `F64` and `F32` can be better choices than `Dec` Some operations work on specific numeric types - such as `I64` or `Dec` - but operations support multiple numeric types. For example, the `Num.abs` function works on any number, since you can take the [absolute value](https://en.wikipedia.org/wiki/Absolute_value) of integers and fractions alike. Its type is: -
abs : Num a -> Num a
-
+```roc +abs : Num a -> Num a +``` This type says `abs` takes a number and then returns a number of the same type. Remember that we can see the type of number is the same because the [type variable](#type-variables) `a` is used on both sides. That's because the `Num` type is compatible with both integers and fractions. There's also an `Int` type which is only compatible with integers, and a `Frac` type which is only compatible with fractions. For example: -
Num.xor : Int a, Int a -> Int a
-
-Num.cos : Frac a -> Frac a
-
- +```roc +Num.xor : Int a, Int a -> Int a +``` +```roc +Num.cos : Frac a -> Frac a +``` When you write a number literal in Roc, it has the type `Num *`. So you could call `Num.xor 1 1` and also `Num.cos 1` and have them all work as expected; the number literal `1` has the type `Num *`, which is compatible with the more constrained types `Int` and `Frac`. For the same reason, you can pass number literals to functions expecting even more constrained types, like `I32` or `F64`. ### [Number Literals](#number-literals) {#number-literals} @@ -1229,12 +1247,13 @@ Crashes in Roc are not like [try/catch exceptions](https://en.wikipedia.org/wiki You can intentionally crash a Roc program, for example inside a conditional branch that you believe is unreachable. Suppose you're certain that a particular `List U8` contains valid UTF-8 bytes, which means when you call `Str.fromUtf8` on it, the `Result` it returns will always be `Ok`. In that scenario, you can use the `crash` keyword to handle the `Err` case like so: -
answer : Str
-answer =
-    when Str.fromUtf8 definitelyValidUtf8 is
-        Ok str -> str
-        Err _ -> crash "This should never happen!"
-
+```roc +answer : Str +answer = + when Str.fromUtf8 definitelyValidUtf8 is + Ok str -> str + Err _ -> crash "This should never happen!" +``` If the unthinkable happens, and somehow the program reaches this `Err` branch even though that was thought to be impossible, then it will crash - just like if the system had run out of memory. The string passed to `crash` will be provided to the platform as context; each platform may do something different with it. @@ -1244,11 +1263,12 @@ If the unthinkable happens, and somehow the program reaches this `Err` branch ev Another use for `crash` is as a TODO marker when you're in the middle of building something: -
if x > y then
-    transmogrify (x * 2)
-else
-    crash "TODO handle the x <= y case"
-
+```roc +if x > y then + transmogrify (x * 2) +else + crash "TODO handle the x <= y case" +``` This lets you do things like write tests for the non-`crash` branch, and then come back and finish the other branch later. @@ -1264,43 +1284,46 @@ Errors that are recoverable should be represented using normal Roc types (like [ You can write automated tests for your Roc code like so: -
pluralize = \singular, plural, count ->
-    countStr = Num.toStr count
+```roc
+pluralize = \singular, plural, count ->
+    countStr = Num.toStr count
 
-    if count == 1 then
-        "\(countStr) \(singular)"
-    else
-        "\(countStr) \(plural)"
+    if count == 1 then
+        "\(countStr) \(singular)"
+    else
+        "\(countStr) \(plural)"
 
-expect pluralize "cactus" "cacti" 1 == "1 cactus"
+expect pluralize "cactus" "cacti" 1 == "1 cactus"
 
-expect pluralize "cactus" "cacti" 2 == "2 cacti"
-
+expect pluralize "cactus" "cacti" 2 == "2 cacti" +``` -If you put this in a file named `main.roc` and run `roc test`, Roc will execute the two `expect` expressions (that is, the two `pluralize` calls) and report any that returned `false`. +If you put this in a file named `main.roc` and run `roc test`, Roc will execute the two `expect` expressions (that is, the two `pluralize` calls) and report any that returned `Bool.false`. If a test fails, it will not show the actual value that differs from the expected value. To show the actual value, you can write the expect like this: -
expect
-    funcOut = pluralize "cactus" "cacti" 1
+```roc
+expect
+    funcOut = pluralize "cactus" "cacti" 1
 
-    funcOut == "2 cactus"
-
+ funcOut == "2 cactus" +``` ### [Inline Expectations](#inline-expects) {#inline-expects} Expects do not have to be at the top level: -
pluralize = \singular, plural, count ->
-    countStr = Num.toStr count
+```roc
+pluralize = \singular, plural, count ->
+    countStr = Num.toStr count
 
-    if count == 1 then
-        "\(countStr) \(singular)"
-    else
-        expect count > 0
+    if count == 1 then
+        "\(countStr) \(singular)"
+    else
+        expect count > 0
 
-        "\(countStr) \(plural)"
-
+ "\(countStr) \(plural)" +``` This `expect` will fail if you call `pluralize` passing a count of 0. @@ -1343,11 +1366,12 @@ Besides being built into the compiler, the builtin modules are different from ot Let's take a closer look at the part of `main.roc` above the `main` def: -
app "hello"
-    packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.1/wx1N6qhU3kKva-4YqsVJde3fho34NqiLD3m620zZ-OI.tar.br" }
-    imports [pf.Stdout]
-    provides main to pf
-
+```roc +app "hello" + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.1/wx1N6qhU3kKva-4YqsVJde3fho34NqiLD3m620zZ-OI.tar.br" } + imports [pf.Stdout] + provides main to pf +``` This is known as a _module header_. Every `.roc` file is a _module_, and there are different types of modules. We know this particular one is an _application module_ because it begins with the `app` keyword. @@ -1355,14 +1379,15 @@ The line `app "hello"` states that this module defines a Roc application, and th The remaining lines all involve the [platform](https://github.com/roc-lang/roc/wiki/Roc-concepts-explained#platform) this application is built on: -
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.1/wx1N6qhU3kKva-4YqsVJde3fho34NqiLD3m620zZ-OI.tar.br" }
-    imports [pf.Stdout]
-    provides [main] to pf
-
+```roc +packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.1/wx1N6qhU3kKva-4YqsVJde3fho34NqiLD3m620zZ-OI.tar.br" } + imports [pf.Stdout] + provides [main] to pf +``` -The `packages { pf: "https://…tar.br" }` part says three things: +The `packages { pf: "https://...tar.br" }` part says three things: -- We're going to be using a _package_ (a collection of modules) that can be downloaded from the URL `"https://…tar.br"` +- We're going to be using a _package_ (a collection of modules) that can be downloaded from the URL `"https://...tar.br"` - That package's [base64](https://en.wikipedia.org/wiki/Base64#URL_applications)\-encoded [BLAKE3]() cryptographic hash is the long string at the end (before the `.tar.br` file extension). Once the file has been downloaded, its contents will be verified against this hash, and it will only be installed if they match. This way, you can be confident the download was neither corrupted nor changed since it was originally published. - We're going to name that package `pf` so we can refer to it more concisely in the future. @@ -1370,26 +1395,48 @@ The `imports [pf.Stdout]` line says that we want to import the `Stdout` module f This import has a direct interaction with our definition of `main`. Let's look at that again: -
main = Stdout.line "I'm a Roc application!"
-
+```roc +main = Stdout.line "I'm a Roc application!" +``` Here, `main` is calling a function called `Stdout.line`. More specifically, it's calling a function named `line` which is exposed by a module named `Stdout`. -When we write `imports [pf.Stdout]`, it specifies that the `Stdout` module comes from the package we named `pf` in the `packages { pf: … }` section. +When we write `imports [pf.Stdout]`, it specifies that the `Stdout` module comes from the package we named `pf` in the `packages { pf: ... }` section. If we would like to include other modules in our application, say `AdditionalModule.roc` and `AnotherModule.roc`, then they can be imported directly in `imports` like this: -
imports [pf.Stdout, AdditionalModule, AnotherModule]
-
+```roc +imports [pf.Stdout, AdditionalModule, AnotherModule] +``` You can find documentation for the `Stdout.line` function in the [Stdout](https://www.roc-lang.org/packages/basic-cli/Stdout#line) module documentation. ### [Package Modules](#interface-modules) {#interface-modules} -\[This part of the tutorial has not been written yet. Coming soon!\] +Package modules enable Roc code to be easily re-used and shared. This is achieved by organizing code into different Interface modules and then including these in the `exposes` field of the package file structure, `package "name" exposes [ MyInterface ] packages {}`. The modules that are listed in the `exposes` field are then available for use in applications, platforms, or other packages. Internal modules that are not listed will be unavailable for use outside of the package. See [Parser Package](https://github.com/roc-lang/roc/tree/main/examples/parser/package) for an example. +Package documentation can be generated using the Roc cli with `roc docs /package/*.roc`. + +Build a package for distribution with `roc build --bundle .tar.br /package/main.roc`. This will create a single tarball that can then be easily shared online using a URL. + +You can import a package that is available either locally, or from a URL into a Roc application or platform. This is achieved by specifying the package in the `packages` section of the application or platform file structure. For example, `packages { .., parser: "" }` is an example that imports a parser module from a URL. + +How does the Roc cli import and download a package from a URL? + +1. First it checks to see whether the relevant folder already exists in the local filesystem and if not, creates it. If there is a package already downloaded then there is no need to download or extract anything. Packages are cached in a directory, typically `~/.cache/roc` on UNIX, and `%APPDATA%\\Roc` on Windows. +2. It then downloads the file at that URL and verifies that the hash of the file matches the hash at the end of the URL. +3. If the hash of the file matches the hash in the URL, then decompress and extract its contents into the cache folder so that it can be used. + +Why is a Roc package URL so long? + +Including the hash solves a number of problems: + +1. The package at the URL can not suddenly change and cause different behavior. +2. Because of 1. there is no need to check the URL on every compilation to see if we have the latest version. +3. If the domain of the URL expires, a malicious actor can change the package but the hash will not match so the roc cli will reject it. + ### [Interface Modules](#interface-modules) {#interface-modules} \[This part of the tutorial has not been written yet. Coming soon!\] @@ -1417,19 +1464,21 @@ We'll use these four operations to learn about tasks. Let's start with a basic "Hello World" program. -
app "cli-tutorial"
-    packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.1/wx1N6qhU3kKva-4YqsVJde3fho34NqiLD3m620zZ-OI.tar.br" }
-    imports [pf.Stdout]
-    provides [main] to pf
+```roc
+app "cli-tutorial"
+    packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.1/wx1N6qhU3kKva-4YqsVJde3fho34NqiLD3m620zZ-OI.tar.br" }
+    imports [pf.Stdout]
+    provides [main] to pf
 
-main =
-    Stdout.line "Hello, World!"
-
+main = + Stdout.line "Hello, World!" +``` The `Stdout.line` function takes a `Str` and writes it to [standard output](). It has this type: -
Stdout.line : Str -> Task {} *
-
+```roc +Stdout.line : Str -> Task {} * +``` A `Task` represents an _effect_; an interaction with state outside your Roc program, such as the terminal's standard output, or a file. @@ -1439,20 +1488,22 @@ When we set `main` to be a `Task`, the task will get run when we run our program In contrast, `Stdin.line` produces a `Str` when it finishes reading from [standard input](). That `Str` is reflected in its type: -
Stdin.line : Task Str *
-
+```roc +Stdin.line : Task Str * +``` Let's change `main` to read a line from `stdin`, and then print it back out again: -
app "cli-tutorial"
-    packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.1/wx1N6qhU3kKva-4YqsVJde3fho34NqiLD3m620zZ-OI.tar.br" }
-    imports [pf.Stdout, pf.Stdin, pf.Task]
-    provides [main] to pf
+```roc
+app "cli-tutorial"
+    packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.1/wx1N6qhU3kKva-4YqsVJde3fho34NqiLD3m620zZ-OI.tar.br" }
+    imports [pf.Stdout, pf.Stdin, pf.Task]
+    provides [main] to pf
 
-main =
-    Task.await Stdin.line \text ->
-        Stdout.line "You just entered: \(text)"
-
+main = + Task.await Stdin.line \text -> + Stdout.line "You just entered: \(text)" +``` If you run this program, at first it won't do anything. It's waiting for you to type something in and press Enter! Once you do, it should print back out what you entered. @@ -1460,37 +1511,41 @@ The `Task.await` function combines two tasks into one bigger `Task` which first The type of `Task.await` is: -
Task.await : Task a err, (a -> Task b err) -> Task b err
-
+```roc +Task.await : Task a err, (a -> Task b err) -> Task b err +``` -The second argument to `Task.await` is a "callback function" which runs after the first task completes. This callback function receives the output of that first task, and then returns the second task. This means the second task can make use of output from the first task, like we did in our `\text -> …` callback function here: +The second argument to `Task.await` is a "callback function" which runs after the first task completes. This callback function receives the output of that first task, and then returns the second task. This means the second task can make use of output from the first task, like we did in our `\text -> ...` callback function here: -
\text ->
-    Stdout.line "You just entered: \(text)"
-
+```roc +\text -> + Stdout.line "You just entered: \(text)" +``` Notice that, just like before, we're still building `main` from a single `Task`. This is how we'll always do it! We'll keep building up bigger and bigger `Task`s out of smaller tasks, and then setting `main` to be that one big `Task`. For example, we can print a prompt before we pause to read from `stdin`, so it no longer looks like the program isn't doing anything when we start it up: -
task =
-    Task.await (Stdout.line "Type something press Enter:") \_ ->
-        Task.await Stdin.line \text ->
-            Stdout.line "You just entered: \(text)"
-
+```roc +task = + Task.await (Stdout.line "Type something press Enter:") \_ -> + Task.await Stdin.line \text -> + Stdout.line "You just entered: \(text)" +``` This works, but we can make it a little nicer to read. Let's change it to the following: -
app "cli-tutorial"
-    packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.1/wx1N6qhU3kKva-4YqsVJde3fho34NqiLD3m620zZ-OI.tar.br" }
-    imports [pf.Stdout, pf.Stdin, pf.Task.{ await }]
-    provides [main] to pf
+```roc
+app "cli-tutorial"
+    packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.1/wx1N6qhU3kKva-4YqsVJde3fho34NqiLD3m620zZ-OI.tar.br" }
+    imports [pf.Stdout, pf.Stdin, pf.Task.{ await }]
+    provides [main] to pf
 
-main =
-    await (Stdout.line "Type something press Enter:") \_ ->
-        await Stdin.line \text ->
-            Stdout.line "You just entered: \(text)"
-
+main = + await (Stdout.line "Type something press Enter:") \_ -> + await Stdin.line \text -> + Stdout.line "You just entered: \(text)" +``` Here we've changed how we're importing the `Task` module. Before it was `pf.Task` and now it's `pf.Task.{ await }`. The difference is that we're importing `await` in an _unqualified_ way, meaning that whenever we write `await` in this module, it will refer to `Task.await`. Now we no longer need to write `Task.` every time we want to use `await`. @@ -1498,27 +1553,30 @@ It's most common in Roc to call functions from other modules in a _qualified_ wa Speaking of calling `await` repeatedly, if we keep calling it more and more on this code, we'll end up doing a lot of indenting. If we'd rather not indent so much, we can rewrite `task` into this style which looks different but does the same thing: -
task =
-    _ <- await (Stdout.line "Type something press Enter:")
-    text <- await Stdin.line
+```roc
+task =
+    _ <- await (Stdout.line "Type something press Enter:")
+    text <- await Stdin.line
 
-    Stdout.line "You just entered: \(text)"
-
+ Stdout.line "You just entered: \(text)" +``` -This `<-` syntax is called _backpassing_. The `<-` is a way to define an anonymous function, just like `\ … ->` is. +This `<-` syntax is called _backpassing_. The `<-` is a way to define an anonymous function, just like `\ ... ->` is. Here, we're using backpassing to define two anonymous functions. Here's one of them: -
text <-
+```roc
+text <-
 
-Stdout.line "You just entered: \(text)"
-
+Stdout.line "You just entered: \(text)" +``` It may not look like it, but this code is defining an anonymous function! You might remember it as the anonymous function we previously defined like this: -
\text ->
-    Stdout.line "You just entered: \(text)"
-
+```roc +\text -> + Stdout.line "You just entered: \(text)" +``` These two anonymous functions are the same, just defined using different syntax. @@ -1528,43 +1586,48 @@ Let's look at these two complete expressions side by side. They are both saying Here's the original: -
await Stdin.line \text ->
-    Stdout.line "You just entered: \(text)"
-
+```roc +await Stdin.line \text -> + Stdout.line "You just entered: \(text)" +``` And here's the equivalent expression with backpassing syntax: -
text <- await Stdin.line
+```roc
+text <- await Stdin.line
 
-Stdout.line "You just entered: \(text)"
-
+Stdout.line "You just entered: \(text)" +``` Here's the other function we're defining with backpassing: -
_ <-
-text <- await Stdin.line
+```roc
+_ <-
+text <- await Stdin.line
 
-Stdout.line "You just entered: \(text)"
-
+Stdout.line "You just entered: \(text)" +``` We could also have written that function this way if we preferred: -
_ <-
+```roc
+_ <-
 
-await Stdin.line \text ->
-    Stdout.line "You just entered: \(text)"
-
+await Stdin.line \text -> + Stdout.line "You just entered: \(text)" +``` This is using a mix of a backpassing function `_ <-` and a normal function `\text ->`, which is totally allowed! Since backpassing is nothing more than syntax sugar for defining a function and passing back as an argument to another function, there's no reason we can't mix and match if we like. That said, the typical style in which this `task` would be written in Roc is using backpassing for all the `await` calls, like we had above: -
task =
-    _ <- await (Stdout.line "Type something press Enter:")
-    text <- await Stdin.line
+```roc
+task =
+    _ <- await (Stdout.line "Type something press Enter:")
+    text <- await Stdin.line
 
-    Stdout.line "You just entered: \(text)"
-
+ Stdout.line "You just entered: \(text)" +``` This way, it reads like a series of instructions: @@ -1590,9 +1653,10 @@ Here are some concepts you likely won't need as a beginner, but may want to know Let's say I write a function which takes a record with a `firstName` and `lastName` field, and puts them together with a space in between: -
fullName = \user ->
-    "\(user.firstName) \(user.lastName)"
-
+```roc +fullName = \user -> + "\(user.firstName) \(user.lastName)" +``` I can pass this function a record that has more fields than just `firstName` and `lastName`, as long as it has _at least_ both of those fields (and both of them are strings). So any of these calls would work: @@ -1606,16 +1670,19 @@ In contrast, a _closed record_ is one that requires an exact set of fields (and If we add a type annotation to this `fullName` function, we can choose to have it accept either an open record or a closed record: -
# Closed record
-fullName : { firstName : Str, lastName : Str } -> Str
-fullName = \user ->
-    "\(user.firstName) \(user.lastName)"
-
-# Open record (because of the `*`)
-fullName : { firstName : Str, lastName : Str }* -> Str
-fullName = \user ->
-    "\(user.firstName) \(user.lastName)"
-
+```roc +# Closed record +fullName : { firstName : Str, lastName : Str } -> Str +fullName = \user -> + "\(user.firstName) \(user.lastName)" +``` + +```roc +# Open record (because of the `*`) +fullName : { firstName : Str, lastName : Str }* -> Str +fullName = \user -> + "\(user.firstName) \(user.lastName)" +``` The `*` in the type `{ firstName : Str, lastName : Str }*` is what makes it an open record type. This `*` is the _wildcard type_ we saw earlier with empty lists. (An empty list has the type `List *`, in contrast to something like `List Str` which is a list of strings.) @@ -1627,10 +1694,11 @@ If the type variable in a record type is a `*` (such as in `{ first : Str, last The type variable can also be a named type variable, like so: -
addHttps : { url : Str }a -> { url : Str }a
-addHttps = \record ->
-    { record & url: "https://\(record.url)" }
-
+```roc +addHttps : { url : Str }a -> { url : Str }a +addHttps = \record -> + { record & url: "https://\(record.url)" } +``` This function uses _constrained records_ in its type. The annotation is saying: @@ -1658,53 +1726,61 @@ You can add type annotations to make record types less flexible than what the co If you like, you can always annotate your functions as accepting open records. However, in practice this may not always be the nicest choice. For example, let's say you have a `User` type alias, like so: -
User : {
-    email : Str,
-    firstName : Str,
-    lastName : Str,
+```roc
+User : {
+    email : Str,
+    firstName : Str,
+    lastName : Str,
 }
-
+``` This defines `User` to be a closed record, which in practice is the most common way records named `User` tend to be defined. If you want to have a function take a `User`, you might write its type like so: -
isValid : User -> Bool
+```roc +isValid : User -> Bool +``` If you want to have a function return a `User`, you might write its type like so: -
userFromEmail : Str -> User
-
+```roc +userFromEmail : Str -> User +``` A function which takes a user and returns a user might look like this: -
capitalizeNames : User -> User
-
+```roc +capitalizeNames : User -> User +``` This is a perfectly reasonable way to write all of these functions. However, I might decide that I really want the `isValid` function to take an open record; a record with _at least_ the fields of this `User` record, but possibly others as well. -Since open records have a type variable (like `*` in `{ email: Str }*` or `a` in `{ email: Str }a -> { email: Str }a`), in order to do this I'd need to add a type variable to the `User` type alias: +Since open records have a type variable (like `*` in `{ email : Str }*` or `a` in `{ email : Str }a -> { email : Str }a`), in order to do this I'd need to add a type variable to the `User` type alias: -
User a : {
-    email : Str
-    firstName : Str
-    lastName : Str
+```roc
+User a : {
+    email : Str
+    firstName : Str
+    lastName : Str
 }a
-
+``` Notice that the `a` type variable appears not only in `User a` but also in `}a` at the end of the record type! Using `User a` type alias, I can still write the same three functions, but now their types need to look different. This is what the first one would look like: -
isValid : User * -> Bool
-
+```roc +isValid : User * -> Bool +``` -Here, the `User *` type alias substitutes `*` for the type variable `a` in the type alias, which takes it from `{ email : Str, … }a` to `{ email : Str, … }*`. Now I can pass it any record that has at least the fields in `User`, and possibly others as well, which was my goal. +Here, the `User *` type alias substitutes `*` for the type variable `a` in the type alias, which takes it from `{ email : Str, ... }a` to `{ email : Str, ... }*`. Now I can pass it any record that has at least the fields in `User`, and possibly others as well, which was my goal. -
userFromEmail : Str -> User {}
-
+```roc +userFromEmail : Str -> User {} +``` -Here, the `User {}` type alias substitutes `{}` for the type variable `a` in the type alias, which takes it from `{ email : Str, … }a` to `{ email : Str, … }{}`. As noted earlier, this is another way to specify a closed record: putting a `{}` after it, in the same place that you'd find a `*` in an open record. +Here, the `User {}` type alias substitutes `{}` for the type variable `a` in the type alias, which takes it from `{ email : Str, ... }a` to `{ email : Str, ... }{}`. As noted earlier, this is another way to specify a closed record: putting a `{}` after it, in the same place that you'd find a `*` in an open record. > **Aside:** This works because you can form new record types by replacing the type variable with other record types. For example, `{ a : Str, b : Str }` can also be written `{ a : Str }{ b : Str }`. You can chain these more than once, e.g. `{ a : Str }{ b : Str }{ c : Str, d : Str }`. This is more useful when used with type annotations; for example, `{ a : Str, b : Str }User` describes a closed record consisting of all the fields in the closed record `User`, plus `a : Str` and `b : Str`. @@ -1712,15 +1788,17 @@ This function still returns the same record as it always did, it just needs to b The third function might need to use a named type variable: -
capitalizeNames : User a -> User a
-
+```roc +capitalizeNames : User a -> User a +``` If this function does a record update on the given user, and returns that - for example, if its definition were `capitalizeNames = \user -> { user & email: "blah" }` - then it needs to use the same named type variable for both the argument and return value. However, if returns a new `User` that it created from scratch, then its type could instead be: -
capitalizeNames : User * -> User {}
-
+```roc +capitalizeNames : User * -> User {} +``` This says that it takes a record with at least the fields specified in the `User` type alias, and possibly others...and then returns a record with exactly the fields specified in the `User` type alias, and no others. @@ -1736,22 +1814,24 @@ The _open tag union_ (or _open union_ for short) `[Foo Str, Bar Bool]*` represen Because an open union represents possibilities that are impossible to know ahead of time, any `when` I use on a `[Foo Str, Bar Bool]*` value must include a catch-all `_ ->` branch. Otherwise, if one of those unknown tags were to come up, the `when` would not know what to do with it! For example: -
example : [Foo Str, Bar Bool]* -> Bool
-example = \tag ->
-    when tag is
-        Foo str -> Str.isEmpty str
-        Bar bool -> bool
-        _ -> Bool.false
-
+```roc +example : [Foo Str, Bar Bool]* -> Bool +example = \tag -> + when tag is + Foo str -> Str.isEmpty str + Bar bool -> bool + _ -> Bool.false +``` In contrast, a _closed tag union_ (or _closed union_) like `[Foo Str, Bar Bool]` (without the `*`) represents the set of all possible tags. If I use a `when` on one of these, I can match on `Foo` only and then on `Bar` only, with no need for a catch-all branch. For example: -
example : [Foo Str, Bar Bool] -> Bool
-example = \tag ->
-    when tag is
-        Foo str -> Str.isEmpty str
-        Bar bool -> bool
-
+```roc +example : [Foo Str, Bar Bool] -> Bool +example = \tag -> + when tag is + Foo str -> Str.isEmpty str + Bar bool -> bool +``` If we were to remove the type annotations from the previous two code examples, Roc would infer the same types for them anyway. @@ -1769,19 +1849,21 @@ When we make a new record, it's inferred to be a closed record. For example, in This is because open unions can accumulate additional tags based on how they're used in the program, whereas closed unions cannot. For example, let's look at this conditional: -
if x > 5 then
-    "foo"
-else
-    7
-
+```roc +if x > 5 then + "foo" +else + 7 +``` This will be a type mismatch because the two branches have incompatible types. Strings and numbers are not type-compatible! Now let's look at another example: -
if x > 5 then
-    Ok "foo"
-else
-    Err "bar"
-
+```roc +if x > 5 then + Ok "foo" +else + Err "bar" +``` This shouldn't be a type mismatch, because we can see that the two branches are compatible; they are both tags that could easily coexist in the same tag union. But if the compiler inferred the type of `Ok "foo"` to be the closed union `[Ok Str]`, and likewise for `Err "bar"` and `[Err Str]`, then this would have to be a type mismatch - because those two closed unions are incompatible. @@ -1791,14 +1873,16 @@ Earlier we saw how a function which accepts an open union must account for more So if I have an `[Ok Str]*` value, I can pass it to functions with any of these types (among others): -- `[Ok Str]* -> Bool` -- `[Ok Str] -> Bool` -- `[Ok Str, Err Bool]* -> Bool` -- `[Ok Str, Err Bool] -> Bool` -- `[Ok Str, Err Bool, Whatever]* -> Bool` -- `[Ok Str, Err Bool, Whatever] -> Bool` -- `Result Str Bool -> Bool` -- `[Err Bool, Whatever]* -> Bool` +| Function Type | Can it receive `[Ok Str]*`? | +| --------------------------------------- | --------------------------- | +| `[Ok Str]* -> Bool` | Yes | +| `[Ok Str] -> Bool` | Yes | +| `[Ok Str, Err Bool]* -> Bool` | Yes | +| `[Ok Str, Err Bool] -> Bool` | Yes | +| `[Ok Str, Err Bool, Whatever]* -> Bool` | Yes | +| `[Ok Str, Err Bool, Whatever] -> Bool` | Yes | +| `Result Str Bool -> Bool` | Yes | +| `[Err Bool, Whatever]* -> Bool` | Yes | That last one works because a function accepting an open union can accept any unrecognized tag (including `Ok Str`) even though it is not mentioned as one of the tags in `[Err Bool, Whatever]*`! Remember, when a function accepts an open tag union, any `when` branches on that union must include a catch-all `_ ->` branch, which is the branch that will end up handling the `Ok Str` value we pass in. @@ -1819,29 +1903,33 @@ In summary, here's a way to think about the difference between open unions in a Earlier we saw these two examples, one with an open tag union and the other with a closed one: -
example : [Foo Str, Bar Bool]* -> Bool
-example = \tag ->
-    when tag is
-        Foo str -> Str.isEmpty str
-        Bar bool -> bool
-        _ -> Bool.false
-
-example : [Foo Str, Bar Bool] -> Bool
-example = \tag ->
-    when tag is
-        Foo str -> Str.isEmpty str
-        Bar bool -> bool
-
+```roc +example : [Foo Str, Bar Bool]* -> Bool +example = \tag -> + when tag is + Foo str -> Str.isEmpty str + Bar bool -> bool + _ -> Bool.false +``` + +```roc +example : [Foo Str, Bar Bool] -> Bool +example = \tag -> + when tag is + Foo str -> Str.isEmpty str + Bar bool -> bool +``` Similarly to how there are open records with a `*`, closed records with nothing, and constrained records with a named type variable, we can also have _constrained tag unions_ with a named type variable. Here's an example: -
example : [Foo Str, Bar Bool]a -> [Foo Str, Bar Bool]a
-example = \tag ->
-    when tag is
-        Foo str -> Bar (Str.isEmpty str)
-        Bar bool -> Bar Bool.false
-        other -> other
-
+```roc +example : [Foo Str, Bar Bool]a -> [Foo Str, Bar Bool]a +example = \tag -> + when tag is + Foo str -> Bar (Str.isEmpty str) + Bar bool -> Bar Bool.false + other -> other +``` This type says that the `example` function will take either a `Foo Str` tag, or a `Bar Bool` tag, or possibly another tag we don't know about at compile time and it also says that the function's return type is the same as the type of its argument. @@ -1868,91 +1956,25 @@ For this reason, any time you see a function that only runs a `when` on its only Here are various Roc expressions involving operators, and what they desugar to. -
-
-
-
-    
-    
-
-
-
-
-    
-    
-
-
-    
-    
-
-
-    
-    
-
-
-    
-    
-
-
-    
-    
-
-
-    
-    
-
-
-    
-    
-
-
-    
-    
-
-
-    
-    
-
-
-    
-    
-
-
-    
-    
-
-
-    
-    
-
-
-    
-    
-
-
-    
-    
-
-
-    
-    
-
-
-    
-    
-
-
-    
-    
-
-
-    
-
-
-    
-    
-
-
-
ExpressionDesugars to
a + bNum.add a b
a - bNum.sub a b
a * bNum.mul a b
a / bNum.div a b
a // bNum.divTrunc a b
a ^ bNum.pow a b
a % bNum.rem a b
a >> bNum.shr a b
a << bNum.shl a b
-aNum.neg a
-f x yNum.neg (f x y)
a == bBool.isEq a b
a != bBool.isNotEq a b
a && bBool.and a b
a || bBool.or a b
!aBool.not a
!f x yBool.not (f x y)
a |> b - b a
a b c |> f x yf (a b c) x y
-
+| Expression | Desugars To | +| ----------------------------- | ------------------ | +| `a + b` | `Num.add a b` | +| `a - b` | `Num.sub a b` | +| `a * b` | `Num.mul a b` | +| `a / b` | `Num.div a b` | +| `a // b` | `Num.divTrunc a b` | +| `a ^ b` | `Num.pow a b` | +| `a % b` | `Num.rem a b` | +| `a >> b` | `Num.shr a b` | +| `a << b` | `Num.shl a b` | +| `-a` | `Num.neg a` | +| `-f x y` | `Num.neg (f x y)` | +| `a == b` | `Bool.isEq a b` | +| `a != b` | `Bool.isNotEq a b` | +| `a && b` | `Bool.and a b` | +| a \|\| b | `Bool.or a b` | +| `!a` | `Bool.not a` | +| `!f x y` | `Bool.not (f x y)` | +| a \|> b | `b a` | +| a b c \|> f x y | `f (a b c) x y` | + diff --git a/www/generate_tutorial/src/tutorial.roc b/www/generate_tutorial/src/tutorial.roc index f7939210f0..f8bc3117ef 100644 --- a/www/generate_tutorial/src/tutorial.roc +++ b/www/generate_tutorial/src/tutorial.roc @@ -95,7 +95,7 @@ tutorialIntro = label [id "tutorial-toc-toggle-label", for "tutorial-toc-toggle"] [text "contents"], ], p [] [text "Welcome to Roc!"], - p [] [text "This tutorial will teach you how to build Roc applications. Along the way, you'll learn how to write tests, use the REPL, and much more!"], + p [] [text "This tutorial will teach you how to build Roc applications. Along the way, you'll learn how to write tests, use the REPL, and more!"], ], section [] [ h2 [ id "installation" ] [ diff --git a/www/public/site.css b/www/public/site.css index c9f2d9128e..5c4c1a1356 100644 --- a/www/public/site.css +++ b/www/public/site.css @@ -1,23 +1,31 @@ :root { + /* WCAG AAA Compliant colors */ + --code-bg: #f4f8f9; + --gray: #717171; + --orange: #BF5000; + --green: #0B8400; + --cyan: #067C94; + --blue: #05006d; + --magenta: #a20031; + --body-max-width: 900px; --text-color: #121212; --top-bar-bg: #222; --top-bar-fg: #eee; - --top-bar-logo-hover: hsl(258, 73%, 70%); - --header-link-color: #17b9b0; + --top-bar-logo-hover: #8055E4; + --header-link-color: #107F79; --header-link-hover: #222; - --link-color: hsl(258, 73%, 58%); - --h1-color: hsl(258, 73%, 70%); + --link-color: #7546e2; + --h1-color: #8055E4; --repl-prompt: #0064ff; --body-bg: #fff; - --code-bg: #e7e7e7; - --code-snippet-bg: #fcfcfc; - --code-snippet-border: #bbb; + --code-color: #303030; - --toc-background: #f3f3f3; - --toc-border: #ddd; + --toc-background: var(--code-bg); + --toc-border: var(--gray); --toc-search-bg: #fcfcfc; - --toc-search-border: #bbb; + --toc-search-border: var(--gray); + --font-mono: "Source Code Pro", monospace; } html { @@ -26,11 +34,13 @@ html { color: var(--text-color); } -html, #tutorial-toc-toggle-label { - font-family: 'Lato', sans-serif; +html, +#tutorial-toc-toggle-label { + font-family: "Lato", sans-serif; } -html, body { +html, +body { margin: 0; padding: 0; } @@ -104,32 +114,46 @@ main { padding: 0 12px; } -code { - margin: 0 0.2rem; - background: var(--code-bg); - padding: 0.1rem 0.5rem; +code, +samp { + font-family: var(--font-mono); + color: var(--code-color); + background-color: var(--code-bg); + display: inline-block; +} + +p code, +td code, +li code, +th code, +samp { + padding: 0 8px; border-radius: 4px; } -code, samp { - font-family: 'Source Code Pro', monospace; - color: var(--code-color); +code a, +a code { + text-decoration: none; + color: var(--code-link-color); + background: none; + padding: 0; } -.code-snippet, samp { - display: block; - overflow: auto; - white-space: pre; - padding: 10px 16px; - background-color: var(--code-snippet-bg); - margin-bottom: 16px; - font-size: 1.2rem; - line-height: 1.76rem; - border: 1px solid var(--code-snippet-border); +code a:visited, +a:visited code { + color: var(--code-link-color); } pre { - white-space: pre-wrap; + margin-bottom: 16px; + padding: 8px 16px; + box-sizing: border-box; + border-radius: 8px; + background-color: var(--code-bg); + overflow-x: auto; + font-size: 1.2rem; + line-height: 1.76em; + white-space: pre; } .repl-prompt:before { @@ -139,50 +163,7 @@ pre { } .repl-err { - color: #c20000; -} - -samp .ann { - /* type annotation - purple in the repl */ - color: #f384fd; -} - -samp .autovar { - /* automatic variable names in the repl, e.g. # val1 */ - color: #338545; -} - -samp .kw { - /* language keywords, e.g. `if`*/ - color: #004cc2; -} - -samp .op, samp .paren, samp .brace, samp .comma, samp .colon { - /* operators, e.g. `+` */ - color: #c20000; -} - -samp .number { - /* number literals */ - color: #158086; -} - -samp .str { - /* string literals */ - color: #158086; -} - -samp .str-esc, samp .str-interp { - /* escapes inside string literals, e.g. \t */ - color: #3474db; -} - -samp .dim { - opacity: 0.55; -} - -samp .comment { - color: #338545; + color: var(--magenta); } /* Tables */ @@ -217,7 +198,8 @@ td:last-child { width: 100%; } -#integer-types th:first-of-type, #integer-types td:first-of-type { +#integer-types th:first-of-type, +#integer-types td:first-of-type { text-align: right; } @@ -225,16 +207,11 @@ td:last-child { background-color: inherit; } -#integer-types th:last-of-type, #integer-types td:last-of-type { +#integer-types th:last-of-type, +#integer-types td:last-of-type { text-align: left; } -@media (prefers-color-scheme: dark) { - table, tr, th, td { - border-color: #3b3f47; - } -} - /* Tutorial Specific */ #tutorial-start { @@ -248,8 +225,8 @@ td:last-child { #tutorial-toc { margin-top: 18px; - background: var(--toc-background); - border: 1px solid var(--toc-border); + background: var(--code-bg); + border-radius: 8px; padding: 12px 24px; margin-left: 64px; } @@ -270,7 +247,6 @@ td:last-child { } #tutorial-toc h2 { - color: #686868; font-family: inherit; font-size: 2em; text-shadow: none; @@ -290,11 +266,14 @@ td:last-child { font-size: inherit; } -#tutorial-toc-toggle, #tutorial-toc-toggle-label, #close-tutorial-toc { +#tutorial-toc-toggle, +#tutorial-toc-toggle-label, +#close-tutorial-toc { display: none; /* This may be overridden on mobile-friendly screen widths */ } -#tutorial-toc-toggle, #tutorial-toc-toggle-label { +#tutorial-toc-toggle, +#tutorial-toc-toggle-label { font-size: 1.1rem; float: right; } @@ -307,21 +286,38 @@ td:last-child { padding: 12px 24px; } -p, aside, li, footer { +p, +aside, +li, +footer { font-size: 1.2rem; line-height: 1.85rem; } /* Mobile-friendly screen width */ @media only screen and (max-device-width: 480px) and (orientation: portrait) { - p, aside, li, footer, code, samp, .code-snippet { + p, + aside, + li, + footer, + code, + samp, + .code-snippet { font-size: 16px; } - h1 code, h2 code, h3 code, h4 code, h5 code { + h1 code, + h2 code, + h3 code, + h4 code, + h5 code { font-size: inherit; } + code { + white-space: normal; + } + #tutorial-toc-toggle-label, #close-tutorial-toc { display: block; @@ -341,10 +337,21 @@ p, aside, li, footer { padding-right: 120px; border: 0; } - h1, h2, h3, h4, h5, h6, p, code { + h1, + h2, + h3, + h4, + h5, + h6, + p, + code { word-break: break-word !important; } - h1, h2, h3, h4, h5 { + h1, + h2, + h3, + h4, + h5 { line-height: 1.2em !important; font-size: 2rem !important; } @@ -357,12 +364,14 @@ p, aside, li, footer { /* Used on on the different-names page. */ -th, td { +th, +td { text-align: left; padding-right: 24px; } -#different-names-body a, #different-names-body li { +#different-names-body a, +#different-names-body li { font-family: monospace; font-size: 16px; } @@ -381,32 +390,50 @@ th, td { list-style-type: none; } -h1, h2, h3, h4, h5 { - font-family: 'Permanent Marker'; +h1, +h2, +h3, +h4, +h5 { + font-family: "Permanent Marker"; line-height: 1rem; margin-top: 1.75rem; margin-bottom: 0; } -#tutorial-toc-toggle-label, #close-tutorial-toc { +#tutorial-toc-toggle-label, +#close-tutorial-toc { color: var(--header-link-color); } -#tutorial-toc-toggle-label:hover, #close-tutorial-toc:hover { +#tutorial-toc-toggle-label:hover, +#close-tutorial-toc:hover { color: var(--header-link-hover); cursor: pointer; } -h1 a, h2 a, h3 a, h4 a, h5 a { +h1 a, +h2 a, +h3 a, +h4 a, +h5 a { color: var(--header-link-color); } -h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover { +h1 a:hover, +h2 a:hover, +h3 a:hover, +h4 a:hover, +h5 a:hover { text-decoration: none; color: var(--header-link-hover); } -h1 code, h2 code, h3 code, h4 code, h5 code { +h1 code, +h2 code, +h3 code, +h4 code, +h5 code { color: inherit; background-color: inherit; padding: 0; @@ -440,112 +467,154 @@ h4 { } @font-face { - font-family: 'Permanent Marker'; - font-style: normal; - font-weight: 400; - src: url('/fonts/permanent-marker-v16-latin/permanent-marker-v16-latin-regular.woff2') format('woff2'), - url('/fonts/permanent-marker-v16-latin/permanent-marker-v16-latin-regular.woff') format('woff'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; + font-family: "Permanent Marker"; + font-style: normal; + font-weight: 400; + src: url("/fonts/permanent-marker-v16-latin/permanent-marker-v16-latin-regular.woff2") + format("woff2"), + url("/fonts/permanent-marker-v16-latin/permanent-marker-v16-latin-regular.woff") + format("woff"); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, + U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, + U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @font-face { - font-family: 'Merriweather'; - font-style: normal; - font-weight: 400; - src: url('/fonts/merriweather-v30-latin-ext_latin/merriweather-v30-latin-ext_latin-regular.woff2') format('woff2'), - url('/fonts/merriweather-v30-latin-ext_latin/merriweather-v30-latin-ext_latin-regular.woff') format('woff'); - unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; + font-family: "Merriweather"; + font-style: normal; + font-weight: 400; + src: url("/fonts/merriweather-v30-latin-ext_latin/merriweather-v30-latin-ext_latin-regular.woff2") + format("woff2"), + url("/fonts/merriweather-v30-latin-ext_latin/merriweather-v30-latin-ext_latin-regular.woff") + format("woff"); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, + U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { - font-family: 'Merriweather'; - font-style: normal; - font-weight: 400; - src: url('/fonts/merriweather-v30-latin/merriweather-v30-latin-regular.woff2') format('woff2'), - url('/fonts/merriweather-v30-latin/merriweather-v30-latin-regular.woff') format('woff'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; + font-family: "Merriweather"; + font-style: normal; + font-weight: 400; + src: url("/fonts/merriweather-v30-latin/merriweather-v30-latin-regular.woff2") + format("woff2"), + url("/fonts/merriweather-v30-latin/merriweather-v30-latin-regular.woff") + format("woff"); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, + U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, + U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @font-face { - font-family: 'Merriweather Sans'; - font-style: normal; - font-weight: 400; - src: url('/fonts/merriweather-sans-v22-latin-ext_latin/merriweather-sans-v22-latin-ext_latin-regular.woff2') format('woff2'), - url('/fonts/merriweather-sans-v22-latin-ext_latin/merriweather-sans-v22-latin-ext_latin-regular.woff') format('woff'); - unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; + font-family: "Merriweather Sans"; + font-style: normal; + font-weight: 400; + src: url("/fonts/merriweather-sans-v22-latin-ext_latin/merriweather-sans-v22-latin-ext_latin-regular.woff2") + format("woff2"), + url("/fonts/merriweather-sans-v22-latin-ext_latin/merriweather-sans-v22-latin-ext_latin-regular.woff") + format("woff"); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, + U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { - font-family: 'Merriweather Sans'; - font-style: normal; - font-weight: 400; - src: url('/fonts/merriweather-sans-v22-latin/merriweather-sans-v22-latin-regular.woff2') format('woff2'), - url('/fonts/merriweather-sans-v22-latin/merriweather-sans-v22-latin-regular.woff') format('woff'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; + font-family: "Merriweather Sans"; + font-style: normal; + font-weight: 400; + src: url("/fonts/merriweather-sans-v22-latin/merriweather-sans-v22-latin-regular.woff2") + format("woff2"), + url("/fonts/merriweather-sans-v22-latin/merriweather-sans-v22-latin-regular.woff") + format("woff"); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, + U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, + U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @font-face { - font-family: 'Lato'; - font-style: normal; - font-weight: 400; - src: url('/fonts/lato-v23-latin-ext_latin/lato-v23-latin-ext_latin-regular.woff2') format('woff2'), - url('/fonts/lato-v23-latin-ext_latin/lato-v23-latin-ext_latin-regular.woff') format('woff'); - unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; + font-family: "Lato"; + font-style: normal; + font-weight: 400; + src: url("/fonts/lato-v23-latin-ext_latin/lato-v23-latin-ext_latin-regular.woff2") + format("woff2"), + url("/fonts/lato-v23-latin-ext_latin/lato-v23-latin-ext_latin-regular.woff") + format("woff"); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, + U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { - font-family: 'Lato'; - font-style: normal; - font-weight: 400; - src: url('/fonts/lato-v23-latin/lato-v23-latin-regular.woff2') format('woff2'), - url('/fonts/lato-v23-latin/lato-v23-latin-regular.woff') format('woff'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; + font-family: "Lato"; + font-style: normal; + font-weight: 400; + src: url("/fonts/lato-v23-latin/lato-v23-latin-regular.woff2") + format("woff2"), + url("/fonts/lato-v23-latin/lato-v23-latin-regular.woff") format("woff"); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, + U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, + U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @font-face { - font-family: 'Source Code Pro'; - font-style: normal; - font-weight: 400; - src: url('/fonts/source-code-pro-v22-latin-ext_latin/source-code-pro-v22-latin-ext_latin-regular.woff2') format('woff2'), - url('/fonts/source-code-pro-v22-latin-ext_latin/source-code-pro-v22-latin-ext_latin-regular.woff') format('woff'); - unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; + font-family: "Source Code Pro"; + font-style: normal; + font-weight: 400; + src: url("/fonts/source-code-pro-v22-latin-ext_latin/source-code-pro-v22-latin-ext_latin-regular.woff2") + format("woff2"), + url("/fonts/source-code-pro-v22-latin-ext_latin/source-code-pro-v22-latin-ext_latin-regular.woff") + format("woff"); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, + U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { - font-family: 'Source Code Pro'; - font-style: normal; - font-weight: 400; - src: url('/fonts/source-code-pro-v22-latin/source-code-pro-v22-latin-regular.woff2') format('woff2'), - url('/fonts/source-code-pro-v22-latin/source-code-pro-v22-latin-regular.woff') format('woff'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; + font-family: "Source Code Pro"; + font-style: normal; + font-weight: 400; + src: url("/fonts/source-code-pro-v22-latin/source-code-pro-v22-latin-regular.woff2") + format("woff2"), + url("/fonts/source-code-pro-v22-latin/source-code-pro-v22-latin-regular.woff") + format("woff"); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, + U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, + U+2215, U+FEFF, U+FFFD; } @media (prefers-color-scheme: dark) { :root { + /* WCAG AAA Compliant colors */ + --code-bg: #202746; + --gray: #b6b6b6; + --orange: #fd6e08; + --green: #8ecc88; + --cyan: #12c9be; + --blue: #b1afdf; + --magenta: #f39bac; + --text-color: #cdcdcd; --top-bar-bg: #2a2a2a; - --header-link-color: hsl(258, 73%, 70%); + --header-link-color: #9C7CEA; --header-link-hover: #ddd; --h1-color: #1bc6bd; --link-color: #1bc6bd; - --repl-prompt: var(--link-color); + --repl-prompt: #1bc6bd; --body-bg: #0e0e0f; - --code-bg: #303030; - --code-snippet-bg: #1a1a1a; --code-snippet-border: #444; --code-color: #cdcdcd; - --toc-background: var(--code-snippet-bg); + --toc-background: var(--code-bg); --toc-border: var(--code-snippet-border); --toc-search-bg: #333; - --toc-search-border: #555; + --toc-search-border: var(--gray); } - h1, h2, h3, h4, h5 { + h1, + h2, + h3, + h4, + h5 { text-shadow: none; } @@ -553,32 +622,54 @@ h4 { scrollbar-color: #444444 #2f2f2f; } - samp .kw { - /* language keywords, e.g. `if` */ - color: #00c3ff; - } - - samp .colon, samp .op, samp .paren, samp .brace, samp .comma, .repl-err { - /* operators, e.g. `+` */ - color: #ff3966; - } - - samp .str { - /* string literals */ - color: var(--link-color); - } - - code .str { - /* string literals */ - color: var(--link-color); - } - - /* autovar = automatic variable names in the repl, e.g. # val1 */ - samp .comment, samp .autovar { - color: #4ed86c; - } - - samp .number { - color: #00c3ff; + table, + tr, + th, + td { + border-color: var(--gray); } } + +/* Comments `#` and Documentation comments `##` */ +samp .comment, +code .comment { + color: var(--green); +} +/* Number, String, Tag, Type literals */ +samp .literal, +code .literal { + color: var(--cyan); +} +/* Keywords and punctuation */ +samp .kw, +code .kw { + color: var(--magenta); +} +/* Operators */ +samp .op, +code .op { + color: var(--orange); +} + +/* Delimieters */ +samp .delimeter, +code .delimeter { + color: var(--gray); +} + +/* Variables modules and field names */ +samp .lowerident, +code .lowerident { + color: var(--blue); +} + +/* Types, Tags, and Modules */ +samp .upperident, +code .upperident { + color: var(--green); +} + +samp .dim, +code .dim { + opacity: 0.55; +}