diff --git a/.github/workflows/basic_cli_build_release.yml b/.github/workflows/basic_cli_build_release.yml index fa2176db1f..75c885c966 100644 --- a/.github/workflows/basic_cli_build_release.yml +++ b/.github/workflows/basic_cli_build_release.yml @@ -9,15 +9,31 @@ concurrency: env: # use .tar.gz for quick testing - ARCHIVE_FORMAT: .tar.gz - BASIC_CLI_BRANCH: main + ARCHIVE_FORMAT: .tar.br + # Make a new basic-cli git tag and set it here before starting this workflow + RELEASE_TAG: 0.7.1 jobs: - fetch-releases: + prepare: runs-on: [ubuntu-20.04] steps: - uses: actions/checkout@v3 + with: + repository: roc-lang/basic-cli + - name: check if provided RELEASE_TAG is fresh + run: | + git fetch --tags + TAG_DATE=$(git log -1 --format=%ai ${{ env.RELEASE_TAG }}) + CURRENT_DATE=$(date +%Y-%m-%d) + TAG_AGE=$(( ($(date -d $CURRENT_DATE +%s) - $(date -d "$TAG_DATE" +%s) )/(60*60*24) )) + + if [ $TAG_AGE -gt 4 ]; then + echo "The provided RELEASE_TAG (${{ env.RELEASE_TAG }}) seems stale, it is $TAG_AGE days old. Did you set it correctly at the top of this workflow?" + exit 1 + fi + + # get latest nightly releases - run: curl -fOL https://github.com/roc-lang/roc/releases/download/nightly/roc_nightly-linux_x86_64-latest.tar.gz - run: curl -fOL https://github.com/roc-lang/roc/releases/download/nightly/roc_nightly-linux_arm64-latest.tar.gz - run: curl -fOL https://github.com/roc-lang/roc/releases/download/nightly/roc_nightly-macos_x86_64-latest.tar.gz @@ -30,7 +46,7 @@ jobs: build-linux-x86_64-files: runs-on: [ubuntu-20.04] - needs: [fetch-releases] + needs: [prepare] steps: - uses: actions/checkout@v3 @@ -47,14 +63,14 @@ jobs: with: name: linux-x86_64-files path: | - basic-cli/src/metadata_linux-x64.rm - basic-cli/src/linux-x64.rh - basic-cli/src/linux-x64.o + basic-cli/platform/metadata_linux-x64.rm + basic-cli/platform/linux-x64.rh + basic-cli/platform/linux-x64.o build-linux-arm64-files: runs-on: [self-hosted, Linux, ARM64] - needs: [fetch-releases] + needs: [prepare] steps: - uses: actions/checkout@v3 @@ -74,11 +90,11 @@ jobs: with: name: linux-arm64-files path: | - basic-cli/src/linux-arm64.o + basic-cli/platform/linux-arm64.o build-macos-x86_64-files: runs-on: [macos-11] # I expect the generated files to work on macOS 12 and up - needs: [fetch-releases] + needs: [prepare] steps: - uses: actions/checkout@v3 @@ -92,12 +108,12 @@ jobs: with: name: macos-x86_64-files path: | - basic-cli/src/macos-x64.o + basic-cli/platform/macos-x64.o build-macos-apple-silicon-files: name: build apple silicon .o file runs-on: [self-hosted, macOS, ARM64] - needs: [fetch-releases] + needs: [prepare] steps: - uses: actions/checkout@v3 @@ -111,7 +127,7 @@ jobs: with: name: macos-apple-silicon-files path: | - basic-cli/src/macos-arm64.o + basic-cli/platform/macos-arm64.o create-release-archive: needs: [build-linux-x86_64-files, build-linux-arm64-files, build-macos-x86_64-files, build-macos-apple-silicon-files] @@ -140,17 +156,25 @@ jobs: - run: git clone https://github.com/roc-lang/basic-cli.git - - run: cp macos-apple-silicon-files/* ./basic-cli/src + - run: cp macos-apple-silicon-files/* ./basic-cli/platform - - run: cp linux-x86_64-files/* ./basic-cli/src + - run: cp linux-x86_64-files/* ./basic-cli/platform - - run: cp linux-arm64-files/* ./basic-cli/src + - run: cp linux-arm64-files/* ./basic-cli/platform - - run: cp macos-x86_64-files/* ./basic-cli/src + - run: cp macos-x86_64-files/* ./basic-cli/platform - - run: ./roc_nightly/roc build --bundle=${{ env.ARCHIVE_FORMAT }} ./basic-cli/src/main.roc + - name: bundle basic-cli release archive + run: ./roc_nightly/roc build --bundle=${{ env.ARCHIVE_FORMAT }} ./basic-cli/platform/main.roc - - run: echo "TAR_FILENAME=$(ls -d basic-cli/src/* | grep ${{ env.ARCHIVE_FORMAT }})" >> $GITHUB_ENV + - name: build basic-cli docs + env: + ROC_DOCS_URL_ROOT: /packages/basic-cli/${{ env.RELEASE_TAG }} + run: | + ./roc_nightly/roc docs ./basic-cli/platform/main.roc + tar -czvf docs.tar.gz generated-docs/ + + - run: echo "TAR_FILENAME=$(ls -d basic-cli/platform/* | grep ${{ env.ARCHIVE_FORMAT }})" >> $GITHUB_ENV - name: Upload platform archive uses: actions/upload-artifact@v3 @@ -159,6 +183,13 @@ jobs: path: | ${{ env.TAR_FILENAME }} + - name: Upload docs archive + uses: actions/upload-artifact@v3 + with: + name: release-assets-docs + path: | + docs.tar.gz + test-release-ubuntu: needs: [create-release-archive] runs-on: [ubuntu-20.04] @@ -194,18 +225,19 @@ jobs: - name: Install ncat for tests if we dont have it yet run: if ! dpkg -l | grep -qw ncat; then sudo apt install -y ncat; fi - - name: prep testing + - name: prepare testing run: | mv roc_nightly basic-cli-platform/. cd basic-cli-platform - mkdir src - find . -maxdepth 1 -type f -exec mv {} src/ \; + mkdir platform + # move all files to platform dir + find . -maxdepth 1 -type f -exec mv {} platform/ \; mkdir temp-basic-cli cd temp-basic-cli git clone https://github.com/roc-lang/basic-cli.git cd basic-cli - git checkout ${{ env.BASIC_CLI_BRANCH }} + git checkout ${{ env.RELEASE_TAG }} cp -r examples ../.. cp -r ci ../.. cp -r LICENSE ../.. diff --git a/.github/workflows/ci_manager.yml b/.github/workflows/ci_manager.yml index 5a2e0419f0..b152825e3e 100644 --- a/.github/workflows/ci_manager.yml +++ b/.github/workflows/ci_manager.yml @@ -1,6 +1,6 @@ on: pull_request: - + name: CI manager # cancel current runs when a new commit is pushed @@ -21,7 +21,7 @@ jobs: id: filecheck run: | git fetch origin ${{ github.base_ref }} - if git diff --name-only origin/${{ github.base_ref }} HEAD | grep -qvE '(\.md$|\.css$|\.html$)'; then + if git diff --name-only origin/${{ github.base_ref }} HEAD | grep -qvE '(\.md$|\.css$|\.html$|^AUTHORS$)'; then echo "run_tests=full" >> $GITHUB_OUTPUT else echo "run_tests=none" >> $GITHUB_OUTPUT @@ -52,7 +52,7 @@ jobs: start-macos-x86-64-tests: needs: check-changes if: needs.check-changes.outputs.run_tests == 'full' - uses: ./.github/workflows/ubuntu_x86_64.yml + uses: ./.github/workflows/macos_x86_64.yml start-ubuntu-x86-64-tests: needs: check-changes @@ -103,12 +103,16 @@ jobs: needs: [ran-full, ran-none] if: | always() - && contains(needs.*.result, 'success') - && !contains(needs.*.result, 'failure') - && !contains(needs.*.result, 'cancelled') - && !(needs.ran-full.result == 'skipped' && needs.ran-none.result == 'skipped') steps: - - run: echo "Workflow succeeded :)" + - name: Check previous job results + run: | + if [ "${{ needs.ran-full.result }}" != "success" ] && [ "${{ needs.ran-none.result }}" != "success" ]; then + echo "One or more jobs failed." + exit 1 + fi + + - run: echo "Workflow succeeded :)" + + + - - diff --git a/.github/workflows/nightly_linux_arm64.yml b/.github/workflows/nightly_linux_arm64.yml index 96f9d5d958..cecd98cba8 100644 --- a/.github/workflows/nightly_linux_arm64.yml +++ b/.github/workflows/nightly_linux_arm64.yml @@ -25,7 +25,7 @@ jobs: run: ./ci/write_version.sh - name: build release with lto - run: cargo build --profile=release-with-lto --locked --bin roc + run: cargo build --profile=release-with-lto --locked --bin roc --bin roc_ls - name: get commit SHA run: echo "SHA=$(git rev-parse --short "$GITHUB_SHA")" >> $GITHUB_ENV diff --git a/.github/workflows/nightly_linux_x86_64.yml b/.github/workflows/nightly_linux_x86_64.yml index d285e65136..a08befd34f 100644 --- a/.github/workflows/nightly_linux_x86_64.yml +++ b/.github/workflows/nightly_linux_x86_64.yml @@ -25,7 +25,7 @@ jobs: run: ./ci/write_version.sh - name: build release with lto - run: RUSTFLAGS="-C target-cpu=x86-64" cargo build --profile=release-with-lto --locked --bin roc + run: RUSTFLAGS="-C target-cpu=x86-64" cargo build --profile=release-with-lto --locked --bin roc --bin roc_ls # target-cpu=x86-64 -> For maximal compatibility for all CPU's. This was also faster in our tests: https://roc.zulipchat.com/#narrow/stream/231635-compiler-development/topic/.2Ecargo.2Fconfig.2Etoml/near/325726299 - name: get commit SHA diff --git a/.github/workflows/nightly_macos_apple_silicon.yml b/.github/workflows/nightly_macos_apple_silicon.yml index 63340de303..840367c472 100644 --- a/.github/workflows/nightly_macos_apple_silicon.yml +++ b/.github/workflows/nightly_macos_apple_silicon.yml @@ -42,11 +42,7 @@ jobs: run: ./ci/write_version.sh - name: build nightly release - run: cargo build --locked --profile=release-with-lto --bin roc - - # this makes the roc binary a lot smaller - - name: strip debug info - run: strip ./target/release-with-lto/roc + run: cargo build --locked --profile=release-with-lto --bin roc --bin roc_ls - 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 6dd330aa99..7b26a15a8e 100644 --- a/.github/workflows/nightly_macos_x86_64.yml +++ b/.github/workflows/nightly_macos_x86_64.yml @@ -32,7 +32,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 --profile=release-with-lto --locked --bin roc + run: RUSTFLAGS="-C target-cpu=x86-64" cargo build --profile=release-with-lto --locked --bin roc --bin roc_ls # target-cpu=x86-64 -> For maximal compatibility for all CPU's. - name: get commit SHA diff --git a/.github/workflows/nix_linux_x86_64.yml b/.github/workflows/nix_linux_x86_64.yml index f3f957f70d..3637a056eb 100644 --- a/.github/workflows/nix_linux_x86_64.yml +++ b/.github/workflows/nix_linux_x86_64.yml @@ -20,6 +20,9 @@ jobs: - name: execute tests with --release run: nix develop -c cargo test --locked --release + - name: roc test all builtins + run: nix develop -c ./ci/roc_test_builtins.sh + - name: test wasm32 cli_run run: nix develop -c cargo test --locked --release --features="wasm32-cli-run" diff --git a/.github/workflows/nix_macos_apple_silicon.yml b/.github/workflows/nix_macos_apple_silicon.yml index baac08bc4f..2b1ab0dcba 100644 --- a/.github/workflows/nix_macos_apple_silicon.yml +++ b/.github/workflows/nix_macos_apple_silicon.yml @@ -32,8 +32,12 @@ jobs: - name: test building default.nix run: nix-build + # for skipped tests: see issue 6274 - name: execute tests with --release - run: nix develop -c cargo test --locked --release + run: nix develop -c cargo test --locked --release -- --skip cli_run::inspect_gui --skip cli_run::hello_gui + + - name: roc test all builtins + run: nix develop -c ./ci/roc_test_builtins.sh - name: make a libapp.so for the next step run: nix develop -c cargo run -- gen-stub-lib examples/platform-switching/rocLovesRust.roc diff --git a/.github/workflows/nix_macos_x86_64.yml b/.github/workflows/nix_macos_x86_64.yml index 8fde16b746..58a80b5836 100644 --- a/.github/workflows/nix_macos_x86_64.yml +++ b/.github/workflows/nix_macos_x86_64.yml @@ -20,6 +20,9 @@ jobs: run: nix develop -c cargo test --locked --release -p roc_cli -- --skip hello_gui # see 5932 for hello_gui + - name: roc test all builtins + run: nix develop -c ./ci/roc_test_builtins.sh + - name: make a libapp.so for the next step run: nix develop -c cargo run -- gen-stub-lib examples/platform-switching/rocLovesRust.roc diff --git a/.github/workflows/ubuntu_x86_64.yml b/.github/workflows/ubuntu_x86_64.yml index d5c6338e0c..9eff9aeb87 100644 --- a/.github/workflows/ubuntu_x86_64.yml +++ b/.github/workflows/ubuntu_x86_64.yml @@ -47,11 +47,8 @@ jobs: - name: test gen-wasm single threaded # gen-wasm has some multithreading problems to do with the wasmer runtime run: cargo test --locked --release --package test_gen --no-default-features --features gen-wasm -- --test-threads=1 && sccache --show-stats - - name: run `roc test` on Str builtins - run: cargo run --locked --release -- test crates/compiler/builtins/roc/Str.roc && sccache --show-stats - - - name: run `roc test` on Dict builtins - run: cargo run --locked --release -- test crates/compiler/builtins/roc/Dict.roc && sccache --show-stats + - name: roc test all builtins + run: ./ci/roc_test_builtins.sh - name: wasm repl test run: crates/repl_test/test_wasm.sh && sccache --show-stats diff --git a/AUTHORS b/AUTHORS index 40dd984d2d..52980bce83 100644 --- a/AUTHORS +++ b/AUTHORS @@ -123,7 +123,7 @@ Luca Cervello Josh Mak Jakub Kozłowski Travis Staloch -Nick Gravgaard +Nick Gravgaard Keerthana Kasthuril <76804118+keerthanak-tw@users.noreply.github.com> Salman Shaik Austin Clements diff --git a/BUILDING_FROM_SOURCE.md b/BUILDING_FROM_SOURCE.md index b2df065d92..eb5e905811 100644 --- a/BUILDING_FROM_SOURCE.md +++ b/BUILDING_FROM_SOURCE.md @@ -76,7 +76,7 @@ To run the test suite (via `cargo test`), you additionally need to install: - [`valgrind`](https://www.valgrind.org/) (needs special treatment to [install on macOS](https://stackoverflow.com/a/61359781) Alternatively, you can use `cargo test --no-fail-fast` or `cargo test -p specific_tests` to skip over the valgrind failures & tests. -For debugging LLVM IR, we use [DebugIR](https://github.com/vaivaswatha/debugir). This dependency is only required to build with the `--debug` flag, and for normal development you should be fine without it. +For emitting LLVM IR for debugging purposes, the `--emit-llvm-ir` flag can be used. ### libxcb libraries diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2162635633..d794d504bf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,7 +26,7 @@ Check [Building from source](BUILDING_FROM_SOURCE.md) for instructions. Most contributors execute the following commands before pushing their code: ```sh -cargo test +cargo test --release cargo fmt --all -- --check cargo clippy --workspace --tests -- --deny warnings ``` diff --git a/Earthfile b/Earthfile index ae0df6e89c..bb217ad572 100644 --- a/Earthfile +++ b/Earthfile @@ -53,9 +53,7 @@ build-nightly-release: COPY --dir .git LICENSE LEGAL_DETAILS ci ./ # version.txt is used by the CLI: roc --version RUN ./ci/write_version.sh - RUN RUSTFLAGS=$RUSTFLAGS cargo build --profile=release-with-lto --locked --bin roc - # strip debug info - RUN strip ./target/release-with-lto/roc + RUN RUSTFLAGS=$RUSTFLAGS cargo build --profile=release-with-lto --locked --bin roc --bin roc_ls RUN ./ci/package_release.sh $RELEASE_FOLDER_NAME RUN ls SAVE ARTIFACT ./$RELEASE_FOLDER_NAME.tar.gz AS LOCAL $RELEASE_FOLDER_NAME.tar.gz diff --git a/LEGAL_DETAILS b/LEGAL_DETAILS index 0afbff3f94..abea4c63a8 100644 --- a/LEGAL_DETAILS +++ b/LEGAL_DETAILS @@ -277,4 +277,33 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +=========================================================== + +* ankerl::unordered_dense - https://github.com/martinus/unordered_dense + +A rather direct port of the source into Roc is currently the implementation for our Dict type. +Source code is in crates/compiler/builtins/roc/Dict.roc + +MIT License + +Copyright (c) 2022 Martin Leitner-Ankerl + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 315dcbae72..d1ce200105 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ - [**tutorial**](https://roc-lang.org/tutorial) - [**docs** for the standard library](https://www.roc-lang.org/builtins) - [**examples**](https://github.com/roc-lang/examples/tree/main/examples) -- [**faq**: frequently asked questions](https://github.com/roc-lang/roc/blob/main/FAQ.md) +- [**faq**: frequently asked questions](https://github.com/roc-lang/roc/blob/main/www/content/faq.md) - [**group chat**](https://roc.zulipchat.com) for help, questions and discussions If you'd like to contribute, check out [good first issues](https://github.com/roc-lang/roc/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22). Don't hesitate to ask for help on our [group chat](https://roc.zulipchat.com), we're friendly! @@ -17,14 +17,17 @@ You can 💜 **sponsor** 💜 Roc on: - [GitHub](https://github.com/sponsors/roc-lang) - [Liberapay](https://liberapay.com/roc_lang) -We are very grateful for our corporate sponsors [Vendr](https://www.vendr.com/), [RWX](https://www.rwx.com), [Tweede golf](https://tweedegolf.nl/en), and [ohne-makler](https://www.ohne-makler.net): +We are very grateful for our corporate sponsors [Vendr](https://www.vendr.com/), [RWX](https://www.rwx.com), [Tweede golf](https://tweedegolf.nl/en), [ohne-makler](https://www.ohne-makler.net), and [Decem](https://www.decem.com.au): [Vendr logo](https://www.vendr.com)      [RWX logo](https://www.rwx.com)      [tweede golf logo](https://tweedegolf.nl/en) +     [ohne-makler logo](https://www.ohne-makler.net) +     +[Decem logo](https://www.decem.com.au) 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)! @@ -39,7 +42,7 @@ We'd also like to express our gratitude to our generous [individual sponsors](ht * [Lucas Rosa](https://github.com/rvcas) * [Jonas Schell](https://github.com/Ocupe) * [Christopher Dolan](https://github.com/cdolan) -* [Nick Gravgaard](https://github.com/nickgravgaard) +* [Nick Gravgaard](https://github.com/nick-gravgaard) * [Zeljko Nesic](https://github.com/popara) * [Shritesh Bhattarai](https://github.com/shritesh) * [Richard Feldman](https://github.com/rtfeldman) diff --git a/ci/build_basic_cli.sh b/ci/build_basic_cli.sh index d4885ee2bd..b9f984a0e1 100755 --- a/ci/build_basic_cli.sh +++ b/ci/build_basic_cli.sh @@ -4,6 +4,9 @@ set -euxo pipefail git clone https://github.com/roc-lang/basic-cli.git +cd basic-cli +git checkout $RELEASE_TAG +cd .. if [ "$(uname -s)" == "Linux" ]; then @@ -13,7 +16,7 @@ if [ "$(uname -s)" == "Linux" ]; then timeout 300s sudo apt-get install -y musl-tools fi - cd basic-cli/src # we cd to install the target for the right rust version + cd basic-cli/platform # we cd to install the target for the right rust version if [ "$(uname -m)" == "x86_64" ]; then rustup target add x86_64-unknown-linux-musl elif [ "$(uname -m)" == "aarch64" ]; then diff --git a/ci/package_release.sh b/ci/package_release.sh index e99680f3e5..131e155b61 100755 --- a/ci/package_release.sh +++ b/ci/package_release.sh @@ -3,15 +3,21 @@ # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/ set -euxo pipefail -cp target/release-with-lto/roc ./roc # to be able to delete "target" later +# this makes the binaries a lot smaller +strip ./target/release-with-lto/roc +strip ./target/release-with-lto/roc_ls + +# to be able to delete "target" later +cp target/release-with-lto/roc ./roc +cp target/release-with-lto/roc_ls ./roc_lang_server # delete unnecessary files and folders -git clean -fdx --exclude roc +git clean -fdx --exclude roc --exclude roc_lang_server mkdir $1 -mv roc LICENSE LEGAL_DETAILS $1 +mv roc roc_lang_server LICENSE LEGAL_DETAILS $1 mkdir $1/examples mv examples/helloWorld.roc examples/platform-switching examples/cli $1/examples diff --git a/ci/roc_test_builtins.sh b/ci/roc_test_builtins.sh new file mode 100755 index 0000000000..79da0db0d9 --- /dev/null +++ b/ci/roc_test_builtins.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +# https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/ +set -euxo pipefail + +for file in crates/compiler/builtins/roc/*.roc; do + if grep -qE '^\s*expect' "$file"; then + cargo run --locked --release -- test "$file" + fi +done \ No newline at end of file diff --git a/ci/update_basic_cli_url.sh b/ci/update_basic_cli_url.sh new file mode 100755 index 0000000000..52ee60910e --- /dev/null +++ b/ci/update_basic_cli_url.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +# https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/ +set -euxo pipefail + +# Check if the correct number of arguments is given +if [ "$#" -ne 2 ]; then + echo "Usage: ./update_basic_cli_url.sh OLD_URL NEW_URL" + exit 1 +fi + +OLD_URL=$1 +NEW_URL=$2 + +# Use git ls-files to list all files tracked by Git, excluding those in .gitignore +files=$(git ls-files) + +# Use perl to replace OLD_URL with NEW_URL in the files +for file in $files; do + perl -pi -e "s|\Q$OLD_URL\E|$NEW_URL|g" $file +done + +echo "Replaced all old basic-cli URLs with the new one." \ No newline at end of file diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index 91d833b792..c59c4c8ed7 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -50,7 +50,8 @@ pub const CMD_GLUE: &str = "glue"; pub const CMD_GEN_STUB_LIB: &str = "gen-stub-lib"; pub const CMD_PREPROCESS_HOST: &str = "preprocess-host"; -pub const FLAG_DEBUG: &str = "debug"; +pub const FLAG_EMIT_LLVM_IR: &str = "emit-llvm-ir"; +pub const FLAG_PROFILING: &str = "profiling"; pub const FLAG_BUNDLE: &str = "bundle"; pub const FLAG_DEV: &str = "dev"; pub const FLAG_OPTIMIZE: &str = "optimize"; @@ -102,9 +103,15 @@ pub fn build_app() -> Command { .action(ArgAction::SetTrue) .required(false); - let flag_debug = Arg::new(FLAG_DEBUG) - .long(FLAG_DEBUG) - .help("Store LLVM debug information in the generated program") + let flag_emit_llvm_ir = Arg::new(FLAG_EMIT_LLVM_IR) + .long(FLAG_EMIT_LLVM_IR) + .help("Emit a `.ll` file containing the LLVM IR of the program") + .action(ArgAction::SetTrue) + .required(false); + + let flag_profiling = Arg::new(FLAG_PROFILING) + .long(FLAG_PROFILING) + .help("Keep debug info in the final generated program even in optmized builds") .action(ArgAction::SetTrue) .required(false); @@ -163,7 +170,8 @@ pub fn build_app() -> Command { .arg(flag_max_threads.clone()) .arg(flag_opt_size.clone()) .arg(flag_dev.clone()) - .arg(flag_debug.clone()) + .arg(flag_emit_llvm_ir.clone()) + .arg(flag_profiling.clone()) .arg(flag_time.clone()) .arg(flag_linker.clone()) .arg(flag_prebuilt.clone()) @@ -212,7 +220,8 @@ pub fn build_app() -> Command { .arg(flag_max_threads.clone()) .arg(flag_opt_size.clone()) .arg(flag_dev.clone()) - .arg(flag_debug.clone()) + .arg(flag_emit_llvm_ir.clone()) + .arg(flag_profiling.clone()) .arg(flag_time.clone()) .arg(flag_linker.clone()) .arg(flag_prebuilt.clone()) @@ -234,7 +243,8 @@ pub fn build_app() -> Command { .arg(flag_max_threads.clone()) .arg(flag_opt_size.clone()) .arg(flag_dev.clone()) - .arg(flag_debug.clone()) + .arg(flag_emit_llvm_ir.clone()) + .arg(flag_profiling.clone()) .arg(flag_time.clone()) .arg(flag_linker.clone()) .arg(flag_prebuilt.clone()) @@ -247,7 +257,8 @@ pub fn build_app() -> Command { .arg(flag_max_threads.clone()) .arg(flag_opt_size.clone()) .arg(flag_dev.clone()) - .arg(flag_debug.clone()) + .arg(flag_emit_llvm_ir.clone()) + .arg(flag_profiling.clone()) .arg(flag_time.clone()) .arg(flag_linker.clone()) .arg(flag_prebuilt.clone()) @@ -376,7 +387,8 @@ pub fn build_app() -> Command { .arg(flag_max_threads) .arg(flag_opt_size) .arg(flag_dev) - .arg(flag_debug) + .arg(flag_emit_llvm_ir) + .arg(flag_profiling) .arg(flag_time) .arg(flag_linker) .arg(flag_prebuilt) @@ -695,7 +707,13 @@ pub fn build( CodeGenBackend::Llvm(backend_mode) }; - let emit_debug_info = matches.get_flag(FLAG_DEBUG); + let emit_llvm_ir = matches.get_flag(FLAG_EMIT_LLVM_IR); + if emit_llvm_ir && !matches!(code_gen_backend, CodeGenBackend::Llvm(_)) { + user_error!("Cannot emit llvm ir while using a dev backend."); + } + + let emit_debug_info = matches.get_flag(FLAG_PROFILING) + || matches!(opt_level, OptLevel::Development | OptLevel::Normal); let emit_timings = matches.get_flag(FLAG_TIME); let threading = match matches.get_one::(FLAG_MAX_THREADS) { @@ -744,6 +762,7 @@ pub fn build( backend: code_gen_backend, opt_level, emit_debug_info, + emit_llvm_ir, }; let load_config = standard_load_config(&triple, build_ordering, threading); diff --git a/crates/cli/tests/cli_run.rs b/crates/cli/tests/cli_run.rs index 8bddb5465f..ce9e640cba 100644 --- a/crates/cli/tests/cli_run.rs +++ b/crates/cli/tests/cli_run.rs @@ -562,11 +562,12 @@ mod cli_run { words : List Str words = ["this", "will", "for", "sure", "be", "a", "large", "string", "so", "when", "we", "split", "it", "it", "will", "use", "seamless", "slices", "which", "affect", "printing"] - [#UserApp] 42 - [#UserApp] "Fjoer en ferdjer frieten oan dyn geve lea" - [#UserApp] "abc" - [#UserApp] 10 - [#UserApp] (A (B C)) + [:22] x = 42 + [:23] "Fjoer en ferdjer frieten oan dyn geve lea" = "Fjoer en ferdjer frieten oan dyn geve lea" + [:24] "this is line 24" = "this is line 24" + [:13] x = "abc" + [:13] x = 10 + [:13] x = (A (B C)) Program finished! "# ), @@ -873,7 +874,7 @@ mod cli_run { This roc file can print it's own source code. The source is: app "ingested-file" - packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.0/bkGby8jb0tmZYsy2hg1E_B2QrCgcSTxdUlHtETwm5m4.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br" } imports [ pf.Stdout, "ingested-file.roc" as ownCode : Str, @@ -900,7 +901,7 @@ mod cli_run { &[], &[], &[], - "30461\n", + "162088\n", UseValgrind::No, TestCliCommands::Run, ) @@ -942,7 +943,7 @@ mod cli_run { test_roc_app_slim( "examples", "inspect-logging.roc", - r#"{friends: [{2}, {2}, {0, 1}], people: [{age: 27, favoriteColor: Blue, firstName: "John", hasBeard: Bool.true, lastName: "Smith"}, {age: 47, favoriteColor: Green, firstName: "Debby", hasBeard: Bool.false, lastName: "Johnson"}, {age: 33, favoriteColor: (RGB (255, 255, 0)), firstName: "Jane", hasBeard: Bool.false, lastName: "Doe"}]} + r#"(@Community {friends: [{2}, {2}, {0, 1}], people: [(@Person {age: 27, favoriteColor: Blue, firstName: "John", hasBeard: Bool.true, lastName: "Smith"}), (@Person {age: 47, favoriteColor: Green, firstName: "Debby", hasBeard: Bool.false, lastName: "Johnson"}), (@Person {age: 33, favoriteColor: (RGB (255, 255, 0)), firstName: "Jane", hasBeard: Bool.false, lastName: "Doe"})]}) "#, UseValgrind::Yes, ) diff --git a/crates/cli/tests/fixtures/multi-dep-str/platform/host.zig b/crates/cli/tests/fixtures/multi-dep-str/platform/host.zig index 6f91e049f8..029a3ea4ed 100644 --- a/crates/cli/tests/fixtures/multi-dep-str/platform/host.zig +++ b/crates/cli/tests/fixtures/multi-dep-str/platform/host.zig @@ -52,9 +52,9 @@ export fn roc_panic(msg: *RocStr, tag_id: u32) callconv(.C) void { std.process.exit(1); } -export fn roc_dbg(loc: *RocStr, msg: *RocStr) callconv(.C) void { +export fn roc_dbg(loc: *RocStr, msg: *RocStr, src: *RocStr) callconv(.C) void { const stderr = std.io.getStdErr().writer(); - stderr.print("[{s}] {s}\n", .{ loc.asSlice(), msg.asSlice() }) catch unreachable; + stderr.print("[{s}] {s} = {s}\n", .{ loc.asSlice(), src.asSlice(), msg.asSlice() }) catch unreachable; } extern fn kill(pid: c_int, sig: c_int) c_int; diff --git a/crates/cli/tests/fixtures/multi-dep-thunk/platform/host.zig b/crates/cli/tests/fixtures/multi-dep-thunk/platform/host.zig index a4a0ff9012..3859fd9015 100644 --- a/crates/cli/tests/fixtures/multi-dep-thunk/platform/host.zig +++ b/crates/cli/tests/fixtures/multi-dep-thunk/platform/host.zig @@ -52,9 +52,9 @@ export fn roc_panic(msg: *RocStr, tag_id: u32) callconv(.C) void { std.process.exit(1); } -export fn roc_dbg(loc: *RocStr, msg: *RocStr) callconv(.C) void { +export fn roc_dbg(loc: *RocStr, msg: *RocStr, src: *RocStr) callconv(.C) void { const stderr = std.io.getStdErr().writer(); - stderr.print("[{s}] {s}\n", .{ loc.asSlice(), msg.asSlice() }) catch unreachable; + stderr.print("[{s}] {s} = {s}\n", .{ loc.asSlice(), src.asSlice(), msg.asSlice() }) catch unreachable; } extern fn kill(pid: c_int, sig: c_int) c_int; diff --git a/crates/cli/tests/fixtures/packages/platform/host.zig b/crates/cli/tests/fixtures/packages/platform/host.zig index 6f91e049f8..029a3ea4ed 100644 --- a/crates/cli/tests/fixtures/packages/platform/host.zig +++ b/crates/cli/tests/fixtures/packages/platform/host.zig @@ -52,9 +52,9 @@ export fn roc_panic(msg: *RocStr, tag_id: u32) callconv(.C) void { std.process.exit(1); } -export fn roc_dbg(loc: *RocStr, msg: *RocStr) callconv(.C) void { +export fn roc_dbg(loc: *RocStr, msg: *RocStr, src: *RocStr) callconv(.C) void { const stderr = std.io.getStdErr().writer(); - stderr.print("[{s}] {s}\n", .{ loc.asSlice(), msg.asSlice() }) catch unreachable; + stderr.print("[{s}] {s} = {s}\n", .{ loc.asSlice(), src.asSlice(), msg.asSlice() }) catch unreachable; } extern fn kill(pid: c_int, sig: c_int) c_int; diff --git a/crates/cli_testing_examples/algorithms/fibonacci-platform/host.zig b/crates/cli_testing_examples/algorithms/fibonacci-platform/host.zig index 8abd265eee..e75b1dd7a0 100644 --- a/crates/cli_testing_examples/algorithms/fibonacci-platform/host.zig +++ b/crates/cli_testing_examples/algorithms/fibonacci-platform/host.zig @@ -66,9 +66,9 @@ export fn roc_panic(msg: *RocStr, tag_id: u32) callconv(.C) void { std.process.exit(1); } -export fn roc_dbg(loc: *RocStr, msg: *RocStr) callconv(.C) void { +export fn roc_dbg(loc: *RocStr, msg: *RocStr, src: *RocStr) callconv(.C) void { const stderr = std.io.getStdErr().writer(); - stderr.print("[{s}] {s}\n", .{ loc.asSlice(), msg.asSlice() }) catch unreachable; + stderr.print("[{s}] {s} = {s}\n", .{ loc.asSlice(), src.asSlice(), msg.asSlice() }) catch unreachable; } export fn roc_memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void { diff --git a/crates/cli_testing_examples/algorithms/quicksort-platform/host.zig b/crates/cli_testing_examples/algorithms/quicksort-platform/host.zig index 138e276e21..50362d5f5c 100644 --- a/crates/cli_testing_examples/algorithms/quicksort-platform/host.zig +++ b/crates/cli_testing_examples/algorithms/quicksort-platform/host.zig @@ -63,9 +63,9 @@ export fn roc_panic(msg: *RocStr, tag_id: u32) callconv(.C) void { std.process.exit(1); } -export fn roc_dbg(loc: *RocStr, msg: *RocStr) callconv(.C) void { +export fn roc_dbg(loc: *RocStr, msg: *RocStr, src: *RocStr) callconv(.C) void { const stderr = std.io.getStdErr().writer(); - stderr.print("[{s}] {s}\n", .{ loc.asSlice(), msg.asSlice() }) catch unreachable; + stderr.print("[{s}] {s} = {s}\n", .{ loc.asSlice(), src.asSlice(), msg.asSlice() }) catch unreachable; } export fn roc_memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void { diff --git a/crates/cli_testing_examples/benchmarks/platform/host.zig b/crates/cli_testing_examples/benchmarks/platform/host.zig index 3362518568..f227605d28 100644 --- a/crates/cli_testing_examples/benchmarks/platform/host.zig +++ b/crates/cli_testing_examples/benchmarks/platform/host.zig @@ -68,9 +68,9 @@ export fn roc_panic(msg: *RocStr, tag_id: u32) callconv(.C) void { std.process.exit(1); } -export fn roc_dbg(loc: *RocStr, msg: *RocStr) callconv(.C) void { +export fn roc_dbg(loc: *RocStr, msg: *RocStr, src: *RocStr) callconv(.C) void { const stderr = std.io.getStdErr().writer(); - stderr.print("[{s}] {s}\n", .{ loc.asSlice(), msg.asSlice() }) catch unreachable; + stderr.print("[{s}] {s} = {s}\n", .{ loc.asSlice(), src.asSlice(), msg.asSlice() }) catch unreachable; } export fn roc_memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void { diff --git a/crates/cli_testing_examples/expects/expects.roc b/crates/cli_testing_examples/expects/expects.roc index c25b73bc68..68f1a433dd 100644 --- a/crates/cli_testing_examples/expects/expects.roc +++ b/crates/cli_testing_examples/expects/expects.roc @@ -21,6 +21,7 @@ main = x = 42 dbg x dbg "Fjoer en ferdjer frieten oan dyn geve lea" + dbg "this is line 24" r = {x : polyDbg "abc", y: polyDbg 10u8, z : polyDbg (A (B C))} diff --git a/crates/cli_testing_examples/expects/zig-platform/host.zig b/crates/cli_testing_examples/expects/zig-platform/host.zig index a830db2cb7..1ac9ce6dbe 100644 --- a/crates/cli_testing_examples/expects/zig-platform/host.zig +++ b/crates/cli_testing_examples/expects/zig-platform/host.zig @@ -52,10 +52,10 @@ export fn roc_panic(msg: *RocStr, tag_id: u32) callconv(.C) void { std.process.exit(1); } -export fn roc_dbg(loc: *RocStr, msg: *RocStr) callconv(.C) void { +export fn roc_dbg(loc: *RocStr, msg: *RocStr, src: *RocStr) callconv(.C) void { // This platform uses stdout for testing purposes instead of the normal stderr. const stdout = std.io.getStdOut().writer(); - stdout.print("[{s}] {s}\n", .{ loc.asSlice(), msg.asSlice() }) catch unreachable; + stdout.print("[{s}] {s} = {s}\n", .{ loc.asSlice(), src.asSlice(), msg.asSlice() }) catch unreachable; } export fn roc_memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void { diff --git a/crates/compiler/build/src/program.rs b/crates/compiler/build/src/program.rs index 664de63332..c749a0c5f0 100644 --- a/crates/compiler/build/src/program.rs +++ b/crates/compiler/build/src/program.rs @@ -85,6 +85,7 @@ pub struct CodeGenOptions { pub backend: CodeGenBackend, pub opt_level: OptLevel, pub emit_debug_info: bool, + pub emit_llvm_ir: bool, } type GenFromMono<'a> = (CodeObject, CodeGenTiming, ExpectMetadata<'a>); @@ -101,6 +102,7 @@ pub fn gen_from_mono_module<'a>( ) -> GenFromMono<'a> { let path = roc_file_path; let debug = code_gen_options.emit_debug_info; + let emit_llvm_ir = code_gen_options.emit_llvm_ir; let opt = code_gen_options.opt_level; match code_gen_options.backend { @@ -120,15 +122,23 @@ pub fn gen_from_mono_module<'a>( wasm_dev_stack_bytes, backend_mode, ), - CodeGenBackend::Llvm(backend_mode) => { - gen_from_mono_module_llvm(arena, loaded, path, target, opt, backend_mode, debug) - } + CodeGenBackend::Llvm(backend_mode) => gen_from_mono_module_llvm( + arena, + loaded, + path, + target, + opt, + backend_mode, + debug, + emit_llvm_ir, + ), } } // TODO how should imported modules factor into this? What if those use builtins too? // TODO this should probably use more helper functions // TODO make this polymorphic in the llvm functions so it can be reused for another backend. +#[allow(clippy::too_many_arguments)] fn gen_from_mono_module_llvm<'a>( arena: &'a bumpalo::Bump, loaded: MonomorphizedModule<'a>, @@ -137,6 +147,7 @@ fn gen_from_mono_module_llvm<'a>( opt_level: OptLevel, backend_mode: LlvmBackendMode, emit_debug_info: bool, + emit_llvm_ir: bool, ) -> GenFromMono<'a> { use crate::target::{self, convert_opt_level}; use inkwell::attributes::{Attribute, AttributeLoc}; @@ -151,9 +162,6 @@ fn gen_from_mono_module_llvm<'a>( let context = Context::create(); let module = arena.alloc(module_from_builtins(target, &context, "app")); - // strip Zig debug stuff - // module.strip_debug_info(); - // mark our zig-defined builtins as internal let app_ll_file = { let mut temp = PathBuf::from(roc_file_path); @@ -245,8 +253,9 @@ fn gen_from_mono_module_llvm<'a>( env.dibuilder.finalize(); - // we don't use the debug info, and it causes weird errors. - module.strip_debug_info(); + if !emit_debug_info { + module.strip_debug_info(); + } // Uncomment this to see the module's optimized LLVM instruction output: // env.module.print_to_stderr(); @@ -265,6 +274,11 @@ fn gen_from_mono_module_llvm<'a>( ); } + if emit_llvm_ir { + eprintln!("Emitting LLVM IR to {}", &app_ll_file.display()); + module.print_to_file(&app_ll_file).unwrap(); + } + // Uncomment this to see the module's optimized LLVM instruction output: // env.module.print_to_stderr(); @@ -359,65 +373,6 @@ fn gen_from_mono_module_llvm<'a>( assert!(bc_to_object.status.success(), "{bc_to_object:#?}"); - MemoryBuffer::create_from_file(&app_o_file).expect("memory buffer creation works") - } else if emit_debug_info { - module.strip_debug_info(); - - let mut app_ll_dbg_file = PathBuf::from(roc_file_path); - app_ll_dbg_file.set_extension("dbg.ll"); - - let mut app_o_file = PathBuf::from(roc_file_path); - app_o_file.set_extension("o"); - - use std::process::Command; - - // write the ll code to a file, so we can modify it - module.print_to_file(&app_ll_file).unwrap(); - - // run the debugir https://github.com/vaivaswatha/debugir tool - match Command::new("debugir") - .args(["-instnamer", app_ll_file.to_str().unwrap()]) - .output() - { - Ok(_) => {} - Err(error) => { - use std::io::ErrorKind; - match error.kind() { - ErrorKind::NotFound => internal_error!( - r"I could not find the `debugir` tool on the PATH, install it from https://github.com/vaivaswatha/debugir" - ), - _ => internal_error!("{:?}", error), - } - } - } - - use target_lexicon::Architecture; - match target.architecture { - Architecture::X86_64 - | Architecture::X86_32(_) - | Architecture::Aarch64(_) - | Architecture::Wasm32 => { - // write the .o file. Note that this builds the .o for the local machine, - // and ignores the `target_machine` entirely. - // - // different systems name this executable differently, so we shotgun for - // the most common ones and then give up. - let ll_to_object = Command::new("llc") - .args([ - "-relocation-model=pic", - "-filetype=obj", - app_ll_dbg_file.to_str().unwrap(), - "-o", - app_o_file.to_str().unwrap(), - ]) - .output() - .unwrap(); - - assert!(ll_to_object.stderr.is_empty(), "{ll_to_object:#?}"); - } - _ => unreachable!(), - } - MemoryBuffer::create_from_file(&app_o_file).expect("memory buffer creation works") } else { // Emit the .o file @@ -1326,6 +1281,7 @@ pub fn build_str_test<'a>( backend: CodeGenBackend::Llvm(LlvmBackendMode::Binary), opt_level: OptLevel::Normal, emit_debug_info: false, + emit_llvm_ir: false, }; let emit_timings = false; diff --git a/crates/compiler/builtins/bitcode/benchmark/dec.zig b/crates/compiler/builtins/bitcode/benchmark/dec.zig index 965d3bdd0c..1793ac2e52 100644 --- a/crates/compiler/builtins/bitcode/benchmark/dec.zig +++ b/crates/compiler/builtins/bitcode/benchmark/dec.zig @@ -11,7 +11,7 @@ fn roc_alloc(_: usize, _: u32) callconv(.C) ?*anyopaque { fn roc_panic(_: *anyopaque, _: u32) callconv(.C) void { @panic("Not needed for dec benchmark"); } -fn roc_dbg(_: *anyopaque, _: *anyopaque) callconv(.C) void { +fn roc_dbg(_: *anyopaque, _: *anyopaque, _: *anyopaque) callconv(.C) void { @panic("Not needed for dec benchmark"); } diff --git a/crates/compiler/builtins/bitcode/build.zig b/crates/compiler/builtins/bitcode/build.zig index c0bd931386..a8836c597d 100644 --- a/crates/compiler/builtins/bitcode/build.zig +++ b/crates/compiler/builtins/bitcode/build.zig @@ -7,7 +7,7 @@ const CrossTarget = std.zig.CrossTarget; const Arch = std.Target.Cpu.Arch; pub fn build(b: *Build) void { - // const mode = b.standardOptimizeOption(.{ .preferred_optimize_mode = .ReleaseFast }); + // const mode = b.standardOptimizeOption(.{ .preferred_optimize_mode = .Debug }); const mode = b.standardOptimizeOption(.{ .preferred_optimize_mode = .ReleaseFast }); // Options @@ -58,6 +58,9 @@ fn generateLlvmIrFile( ) void { const obj = b.addObject(.{ .name = object_name, .root_source_file = main_path, .optimize = mode, .target = target, .use_llvm = true }); obj.strip = true; + obj.disable_stack_probing = true; + if (target.cpu_arch != .wasm32) + obj.bundle_compiler_rt = true; // Generating the bin seems required to get zig to generate the llvm ir. _ = obj.getEmittedBin(); @@ -89,6 +92,9 @@ fn generateObjectFile( obj.strip = true; obj.link_function_sections = true; obj.force_pic = true; + obj.disable_stack_probing = true; + if (target.cpu_arch != .wasm32) + obj.bundle_compiler_rt = true; const obj_file = obj.getEmittedBin(); @@ -110,7 +116,7 @@ fn makeLinux32Target() CrossTarget { target.cpu_arch = std.Target.Cpu.Arch.x86; target.os_tag = std.Target.Os.Tag.linux; - target.abi = std.Target.Abi.musl; + target.abi = std.Target.Abi.none; return target; } @@ -120,7 +126,7 @@ fn makeLinuxAarch64Target() CrossTarget { target.cpu_arch = std.Target.Cpu.Arch.aarch64; target.os_tag = std.Target.Os.Tag.linux; - target.abi = std.Target.Abi.musl; + target.abi = std.Target.Abi.none; return target; } @@ -130,7 +136,7 @@ fn makeLinuxX64Target() CrossTarget { target.cpu_arch = std.Target.Cpu.Arch.x86_64; target.os_tag = std.Target.Os.Tag.linux; - target.abi = std.Target.Abi.musl; + target.abi = std.Target.Abi.none; return target; } @@ -140,7 +146,7 @@ fn makeWindows64Target() CrossTarget { target.cpu_arch = std.Target.Cpu.Arch.x86_64; target.os_tag = std.Target.Os.Tag.windows; - target.abi = std.Target.Abi.gnu; + target.abi = std.Target.Abi.none; return target; } diff --git a/crates/compiler/builtins/bitcode/src/compiler_rt.zig b/crates/compiler/builtins/bitcode/src/compiler_rt.zig deleted file mode 100644 index 9a22da5bd4..0000000000 --- a/crates/compiler/builtins/bitcode/src/compiler_rt.zig +++ /dev/null @@ -1,478 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const math = std.math; - -// Eventually, we need to statically ingest compiler-rt and get it working with the surgical linker, then these should not be needed anymore. -// Until then, we are manually ingesting used parts of compiler-rt here. -// -// Taken from -// https://github.com/ziglang/zig/tree/4976b58ab16069f8d3267b69ed030f29685c1abe/lib/compiler_rt/ -// Thank you Zig Contributors! - -// Libcalls that involve u128 on Windows x86-64 are expected by LLVM to use the -// calling convention of @Vector(2, u64), rather than what's standard. -pub const want_windows_v2u64_abi = builtin.os.tag == .windows and builtin.cpu.arch == .x86_64 and @import("builtin").object_format != .c; - -const v2u64 = @Vector(2, u64); - -// Export it as weak incase it is already linked in by something else. -comptime { - if (!want_windows_v2u64_abi) { - @export(__muloti4, .{ .name = "__muloti4", .linkage = .Weak }); - @export(__lshrti3, .{ .name = "__lshrti3", .linkage = .Weak }); - @export(__divti3, .{ .name = "__divti3", .linkage = .Weak }); - @export(__modti3, .{ .name = "__modti3", .linkage = .Weak }); - @export(__umodti3, .{ .name = "__umodti3", .linkage = .Weak }); - @export(__udivti3, .{ .name = "__udivti3", .linkage = .Weak }); - @export(__fixdfti, .{ .name = "__fixdfti", .linkage = .Weak }); - @export(__fixsfti, .{ .name = "__fixsfti", .linkage = .Weak }); - @export(__fixunsdfti, .{ .name = "__fixunsdfti", .linkage = .Weak }); - @export(__fixunssfti, .{ .name = "__fixunssfti", .linkage = .Weak }); - } -} - -pub fn __muloti4(a: i128, b: i128, overflow: *c_int) callconv(.C) i128 { - if (2 * @bitSizeOf(i128) <= @bitSizeOf(usize)) { - return muloXi4_genericFast(i128, a, b, overflow); - } else { - return muloXi4_genericSmall(i128, a, b, overflow); - } -} - -pub fn __divti3(a: i128, b: i128) callconv(.C) i128 { - return div(a, b); -} - -fn __divti3_windows_x86_64(a: v2u64, b: v2u64) callconv(.C) v2u64 { - return @as(v2u64, @bitCast(div(@as(i128, @bitCast(a)), @as(i128, @bitCast(b))))); -} - -inline fn div(a: i128, b: i128) i128 { - const s_a = a >> (128 - 1); - const s_b = b >> (128 - 1); - - const an = (a ^ s_a) -% s_a; - const bn = (b ^ s_b) -% s_b; - - const r = udivmod(u128, @as(u128, @bitCast(an)), @as(u128, @bitCast(bn)), null); - const s = s_a ^ s_b; - return (@as(i128, @bitCast(r)) ^ s) -% s; -} - -pub fn __udivti3(a: u128, b: u128) callconv(.C) u128 { - return udivmod(u128, a, b, null); -} - -fn __udivti3_windows_x86_64(a: v2u64, b: v2u64) callconv(.C) v2u64 { - return @as(v2u64, @bitCast(udivmod(u128, @as(u128, @bitCast(a)), @as(u128, @bitCast(b)), null))); -} - -pub fn __umodti3(a: u128, b: u128) callconv(.C) u128 { - var r: u128 = undefined; - _ = udivmod(u128, a, b, &r); - return r; -} - -fn __umodti3_windows_x86_64(a: v2u64, b: v2u64) callconv(.C) v2u64 { - var r: u128 = undefined; - _ = udivmod(u128, @as(u128, @bitCast(a)), @as(u128, @bitCast(b)), &r); - return @as(v2u64, @bitCast(r)); -} - -pub fn __modti3(a: i128, b: i128) callconv(.C) i128 { - return mod(a, b); -} - -fn __modti3_windows_x86_64(a: v2u64, b: v2u64) callconv(.C) v2u64 { - return @as(v2u64, @bitCast(mod(@as(i128, @bitCast(a)), @as(i128, @bitCast(b))))); -} - -inline fn mod(a: i128, b: i128) i128 { - const s_a = a >> (128 - 1); // s = a < 0 ? -1 : 0 - const s_b = b >> (128 - 1); // s = b < 0 ? -1 : 0 - - const an = (a ^ s_a) -% s_a; // negate if s == -1 - const bn = (b ^ s_b) -% s_b; // negate if s == -1 - - var r: u128 = undefined; - _ = udivmod(u128, @as(u128, @bitCast(an)), @as(u128, @bitCast(bn)), &r); - return (@as(i128, @bitCast(r)) ^ s_a) -% s_a; // negate if s == -1 -} - -pub fn __fixdfti(a: f64) callconv(.C) i128 { - return floatToInt(i128, a); -} - -fn __fixdfti_windows_x86_64(a: f64) callconv(.C) v2u64 { - return @as(v2u64, @bitCast(floatToInt(i128, a))); -} - -pub fn __fixsfti(a: f32) callconv(.C) i128 { - return floatToInt(i128, a); -} - -fn __fixsfti_windows_x86_64(a: f32) callconv(.C) v2u64 { - return @as(v2u64, @bitCast(floatToInt(i128, a))); -} - -pub fn __fixunsdfti(a: f64) callconv(.C) u128 { - return floatToInt(u128, a); -} - -fn __fixunsdfti_windows_x86_64(a: f64) callconv(.C) v2u64 { - return @as(v2u64, @bitCast(floatToInt(u128, a))); -} - -pub fn __fixunssfti(a: f32) callconv(.C) u128 { - return floatToInt(u128, a); -} - -fn __fixunssfti_windows_x86_64(a: f32) callconv(.C) v2u64 { - return @as(v2u64, @bitCast(floatToInt(u128, a))); -} -// mulo - multiplication overflow -// * return a*%b. -// * return if a*b overflows => 1 else => 0 -// - muloXi4_genericSmall as default -// - muloXi4_genericFast for 2*bitsize <= usize - -inline fn muloXi4_genericSmall(comptime ST: type, a: ST, b: ST, overflow: *c_int) ST { - overflow.* = 0; - const min = math.minInt(ST); - var res: ST = a *% b; - // Hacker's Delight section Overflow subsection Multiplication - // case a=-2^{31}, b=-1 problem, because - // on some machines a*b = -2^{31} with overflow - // Then -2^{31}/-1 overflows and any result is possible. - // => check with a<0 and b=-2^{31} - if ((a < 0 and b == min) or (a != 0 and @divTrunc(res, a) != b)) - overflow.* = 1; - return res; -} - -inline fn muloXi4_genericFast(comptime ST: type, a: ST, b: ST, overflow: *c_int) ST { - overflow.* = 0; - const EST = switch (ST) { - i32 => i64, - i64 => i128, - i128 => i256, - else => unreachable, - }; - const min = math.minInt(ST); - const max = math.maxInt(ST); - var res: EST = @as(EST, a) * @as(EST, b); - //invariant: -2^{bitwidth(EST)} < res < 2^{bitwidth(EST)-1} - if (res < min or max < res) - overflow.* = 1; - return @as(ST, @truncate(res)); -} - -const native_endian = builtin.cpu.arch.endian(); -const low = switch (native_endian) { - .Big => 1, - .Little => 0, -}; -const high = 1 - low; - -pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: ?*DoubleInt) DoubleInt { - // @setRuntimeSafety(builtin.is_test); - - const double_int_bits = @typeInfo(DoubleInt).Int.bits; - const single_int_bits = @divExact(double_int_bits, 2); - const SingleInt = std.meta.Int(.unsigned, single_int_bits); - const SignedDoubleInt = std.meta.Int(.signed, double_int_bits); - const Log2SingleInt = std.math.Log2Int(SingleInt); - - const n = @as([2]SingleInt, @bitCast(a)); - const d = @as([2]SingleInt, @bitCast(b)); - var q: [2]SingleInt = undefined; - var r: [2]SingleInt = undefined; - var sr: c_uint = undefined; - // special cases, X is unknown, K != 0 - if (n[high] == 0) { - if (d[high] == 0) { - // 0 X - // --- - // 0 X - if (maybe_rem) |rem| { - rem.* = n[low] % d[low]; - } - return n[low] / d[low]; - } - // 0 X - // --- - // K X - if (maybe_rem) |rem| { - rem.* = n[low]; - } - return 0; - } - // n[high] != 0 - if (d[low] == 0) { - if (d[high] == 0) { - // K X - // --- - // 0 0 - if (maybe_rem) |rem| { - rem.* = n[high] % d[low]; - } - return n[high] / d[low]; - } - // d[high] != 0 - if (n[low] == 0) { - // K 0 - // --- - // K 0 - if (maybe_rem) |rem| { - r[high] = n[high] % d[high]; - r[low] = 0; - rem.* = @as(DoubleInt, @bitCast(r)); - } - return n[high] / d[high]; - } - // K K - // --- - // K 0 - if ((d[high] & (d[high] - 1)) == 0) { - // d is a power of 2 - if (maybe_rem) |rem| { - r[low] = n[low]; - r[high] = n[high] & (d[high] - 1); - rem.* = @as(DoubleInt, @bitCast(r)); - } - return n[high] >> @as(Log2SingleInt, @intCast(@ctz(d[high]))); - } - // K K - // --- - // K 0 - sr = @as(c_uint, @bitCast(@as(c_int, @clz(d[high])) - @as(c_int, @clz(n[high])))); - // 0 <= sr <= single_int_bits - 2 or sr large - if (sr > single_int_bits - 2) { - if (maybe_rem) |rem| { - rem.* = a; - } - return 0; - } - sr += 1; - // 1 <= sr <= single_int_bits - 1 - // q.all = a << (double_int_bits - sr); - q[low] = 0; - q[high] = n[low] << @as(Log2SingleInt, @intCast(single_int_bits - sr)); - // r.all = a >> sr; - r[high] = n[high] >> @as(Log2SingleInt, @intCast(sr)); - r[low] = (n[high] << @as(Log2SingleInt, @intCast(single_int_bits - sr))) | (n[low] >> @as(Log2SingleInt, @intCast(sr))); - } else { - // d[low] != 0 - if (d[high] == 0) { - // K X - // --- - // 0 K - if ((d[low] & (d[low] - 1)) == 0) { - // d is a power of 2 - if (maybe_rem) |rem| { - rem.* = n[low] & (d[low] - 1); - } - if (d[low] == 1) { - return a; - } - sr = @ctz(d[low]); - q[high] = n[high] >> @as(Log2SingleInt, @intCast(sr)); - q[low] = (n[high] << @as(Log2SingleInt, @intCast(single_int_bits - sr))) | (n[low] >> @as(Log2SingleInt, @intCast(sr))); - return @as(DoubleInt, @bitCast(q)); - } - // K X - // --- - // 0 K - sr = 1 + single_int_bits + @as(c_uint, @clz(d[low])) - @as(c_uint, @clz(n[high])); - // 2 <= sr <= double_int_bits - 1 - // q.all = a << (double_int_bits - sr); - // r.all = a >> sr; - if (sr == single_int_bits) { - q[low] = 0; - q[high] = n[low]; - r[high] = 0; - r[low] = n[high]; - } else if (sr < single_int_bits) { - // 2 <= sr <= single_int_bits - 1 - q[low] = 0; - q[high] = n[low] << @as(Log2SingleInt, @intCast(single_int_bits - sr)); - r[high] = n[high] >> @as(Log2SingleInt, @intCast(sr)); - r[low] = (n[high] << @as(Log2SingleInt, @intCast(single_int_bits - sr))) | (n[low] >> @as(Log2SingleInt, @intCast(sr))); - } else { - // single_int_bits + 1 <= sr <= double_int_bits - 1 - q[low] = n[low] << @as(Log2SingleInt, @intCast(double_int_bits - sr)); - q[high] = (n[high] << @as(Log2SingleInt, @intCast(double_int_bits - sr))) | (n[low] >> @as(Log2SingleInt, @intCast(sr - single_int_bits))); - r[high] = 0; - r[low] = n[high] >> @as(Log2SingleInt, @intCast(sr - single_int_bits)); - } - } else { - // K X - // --- - // K K - sr = @as(c_uint, @bitCast(@as(c_int, @clz(d[high])) - @as(c_int, @clz(n[high])))); - // 0 <= sr <= single_int_bits - 1 or sr large - if (sr > single_int_bits - 1) { - if (maybe_rem) |rem| { - rem.* = a; - } - return 0; - } - sr += 1; - // 1 <= sr <= single_int_bits - // q.all = a << (double_int_bits - sr); - // r.all = a >> sr; - q[low] = 0; - if (sr == single_int_bits) { - q[high] = n[low]; - r[high] = 0; - r[low] = n[high]; - } else { - r[high] = n[high] >> @as(Log2SingleInt, @intCast(sr)); - r[low] = (n[high] << @as(Log2SingleInt, @intCast(single_int_bits - sr))) | (n[low] >> @as(Log2SingleInt, @intCast(sr))); - q[high] = n[low] << @as(Log2SingleInt, @intCast(single_int_bits - sr)); - } - } - } - // Not a special case - // q and r are initialized with: - // q.all = a << (double_int_bits - sr); - // r.all = a >> sr; - // 1 <= sr <= double_int_bits - 1 - var carry: u32 = 0; - var r_all: DoubleInt = undefined; - while (sr > 0) : (sr -= 1) { - // r:q = ((r:q) << 1) | carry - r[high] = (r[high] << 1) | (r[low] >> (single_int_bits - 1)); - r[low] = (r[low] << 1) | (q[high] >> (single_int_bits - 1)); - q[high] = (q[high] << 1) | (q[low] >> (single_int_bits - 1)); - q[low] = (q[low] << 1) | carry; - // carry = 0; - // if (r.all >= b) - // { - // r.all -= b; - // carry = 1; - // } - r_all = @as(DoubleInt, @bitCast(r)); - const s: SignedDoubleInt = @as(SignedDoubleInt, @bitCast(b -% r_all -% 1)) >> (double_int_bits - 1); - carry = @as(u32, @intCast(s & 1)); - r_all -= b & @as(DoubleInt, @bitCast(s)); - r = @as([2]SingleInt, @bitCast(r_all)); - } - const q_all = (@as(DoubleInt, @bitCast(q)) << 1) | carry; - if (maybe_rem) |rem| { - rem.* = r_all; - } - return q_all; -} - -pub inline fn floatToInt(comptime I: type, a: anytype) I { - const Log2Int = math.Log2Int; - const Int = @import("std").meta.Int; - const F = @TypeOf(a); - const float_bits = @typeInfo(F).Float.bits; - const int_bits = @typeInfo(I).Int.bits; - const rep_t = Int(.unsigned, float_bits); - const sig_bits = math.floatMantissaBits(F); - const exp_bits = math.floatExponentBits(F); - const fractional_bits = floatFractionalBits(F); - - // const implicit_bit = if (F != f80) (@as(rep_t, 1) << sig_bits) else 0; - const implicit_bit = @as(rep_t, 1) << sig_bits; - const max_exp = (1 << (exp_bits - 1)); - const exp_bias = max_exp - 1; - const sig_mask = (@as(rep_t, 1) << sig_bits) - 1; - - // Break a into sign, exponent, significand - const a_rep: rep_t = @as(rep_t, @bitCast(a)); - const negative = (a_rep >> (float_bits - 1)) != 0; - const exponent = @as(i32, @intCast((a_rep << 1) >> (sig_bits + 1))) - exp_bias; - const significand: rep_t = (a_rep & sig_mask) | implicit_bit; - - // If the exponent is negative, the result rounds to zero. - if (exponent < 0) return 0; - - // If the value is too large for the integer type, saturate. - switch (@typeInfo(I).Int.signedness) { - .unsigned => { - if (negative) return 0; - if (@as(c_uint, @intCast(exponent)) >= @min(int_bits, max_exp)) return math.maxInt(I); - }, - .signed => if (@as(c_uint, @intCast(exponent)) >= @min(int_bits - 1, max_exp)) { - return if (negative) math.minInt(I) else math.maxInt(I); - }, - } - - // If 0 <= exponent < sig_bits, right shift to get the result. - // Otherwise, shift left. - var result: I = undefined; - if (exponent < fractional_bits) { - result = @as(I, @intCast(significand >> @as(Log2Int(rep_t), @intCast(fractional_bits - exponent)))); - } else { - result = @as(I, @intCast(significand)) << @as(Log2Int(I), @intCast(exponent - fractional_bits)); - } - - if ((@typeInfo(I).Int.signedness == .signed) and negative) - return ~result +% 1; - return result; -} - -/// Returns the number of fractional bits in the mantissa of floating point type T. -pub inline fn floatFractionalBits(comptime T: type) comptime_int { - comptime std.debug.assert(@typeInfo(T) == .Float); - - // standard IEEE floats have an implicit 0.m or 1.m integer part - // f80 is special and has an explicitly stored bit in the MSB - // this function corresponds to `MANT_DIG - 1' from C - return switch (@typeInfo(T).Float.bits) { - 16 => 10, - 32 => 23, - 64 => 52, - 80 => 63, - 128 => 112, - else => @compileError("unknown floating point type " ++ @typeName(T)), - }; -} - -pub fn __lshrti3(a: i128, b: i32) callconv(.C) i128 { - return lshrXi3(i128, a, b); -} - -// Logical shift right: shift in 0 from left to right -// Precondition: 0 <= b < T.bit_count -inline fn lshrXi3(comptime T: type, a: T, b: i32) T { - const word_t = HalveInt(T, false); - const S = std.math.Log2Int(word_t.HalfT); - - const input = word_t{ .all = a }; - var output: word_t = undefined; - - if (b >= word_t.bits) { - output.s.high = 0; - output.s.low = input.s.high >> @as(S, @intCast(b - word_t.bits)); - } else if (b == 0) { - return a; - } else { - output.s.high = input.s.high >> @as(S, @intCast(b)); - output.s.low = input.s.high << @as(S, @intCast(word_t.bits - b)); - output.s.low |= input.s.low >> @as(S, @intCast(b)); - } - - return output.all; -} - -/// Allows to access underlying bits as two equally sized lower and higher -/// signed or unsigned integers. -fn HalveInt(comptime T: type, comptime signed_half: bool) type { - return extern union { - pub const bits = @divExact(@typeInfo(T).Int.bits, 2); - pub const HalfTU = std.meta.Int(.unsigned, bits); - pub const HalfTS = std.meta.Int(.signed, bits); - pub const HalfT = if (signed_half) HalfTS else HalfTU; - - all: T, - s: if (native_endian == .Little) - extern struct { low: HalfT, high: HalfT } - else - extern struct { high: HalfT, low: HalfT }, - }; -} diff --git a/crates/compiler/builtins/bitcode/src/dbg.zig b/crates/compiler/builtins/bitcode/src/dbg.zig new file mode 100644 index 0000000000..29004d7f37 --- /dev/null +++ b/crates/compiler/builtins/bitcode/src/dbg.zig @@ -0,0 +1,11 @@ +const std = @import("std"); +const builtin = @import("builtin"); +const RocStr = @import("str.zig").RocStr; + +// An optional debug impl to be called during `roc test` +pub fn dbg_impl(loc: *const RocStr, msg: *const RocStr, src: *const RocStr) callconv(.C) void { + if (builtin.target.cpu.arch != .wasm32) { + const stderr = std.io.getStdErr().writer(); + stderr.print("[{s}] {s} = {s}\n", .{ loc.asSlice(), src.asSlice(), msg.asSlice() }) catch unreachable; + } +} diff --git a/crates/compiler/builtins/bitcode/src/dec.zig b/crates/compiler/builtins/bitcode/src/dec.zig index d60057843c..cd9a851502 100644 --- a/crates/compiler/builtins/bitcode/src/dec.zig +++ b/crates/compiler/builtins/bitcode/src/dec.zig @@ -252,7 +252,6 @@ pub const RocDec = extern struct { if (answer.has_overflowed) { roc_panic("Decimal addition overflowed!", 0); - unreachable; } else { return answer.value; } @@ -283,7 +282,6 @@ pub const RocDec = extern struct { if (answer.has_overflowed) { roc_panic("Decimal subtraction overflowed!", 0); - unreachable; } else { return answer.value; } @@ -347,7 +345,6 @@ pub const RocDec = extern struct { if (answer.has_overflowed) { roc_panic("Decimal multiplication overflowed!", 0); - unreachable; } else { return answer.value; } @@ -369,7 +366,7 @@ pub const RocDec = extern struct { // (n / 0) is an error if (denominator_i128 == 0) { - @panic("TODO runtime exception for dividing by 0!"); + roc_panic("Decimal division by 0!", 0); } // If they're both negative, or if neither is negative, the final answer @@ -397,7 +394,7 @@ pub const RocDec = extern struct { if (denominator_i128 == one_point_zero_i128) { return self; } else { - @panic("TODO runtime exception for overflow when dividing!"); + roc_panic("Decimal division overflow in numerator!", 0); } }; const numerator_u128 = @as(u128, @intCast(numerator_abs_i128)); @@ -410,7 +407,7 @@ pub const RocDec = extern struct { if (numerator_i128 == one_point_zero_i128) { return other; } else { - @panic("TODO runtime exception for overflow when dividing!"); + roc_panic("Decimal division overflow in denominator!", 0); } }; const denominator_u128 = @as(u128, @intCast(denominator_abs_i128)); @@ -422,7 +419,7 @@ pub const RocDec = extern struct { if (answer.hi == 0 and answer.lo <= math.maxInt(i128)) { unsigned_answer = @as(i128, @intCast(answer.lo)); } else { - @panic("TODO runtime exception for overflow when dividing!"); + roc_panic("Decimal division overflow!", 0); } return RocDec{ .num = if (is_answer_negative) -unsigned_answer else unsigned_answer }; @@ -636,7 +633,7 @@ fn mul_and_decimalize(a: u128, b: u128) i128 { const d = answer[0]; if (overflowed == 1) { - @panic("TODO runtime exception for overflow!"); + roc_panic("Decimal multiplication overflow!", 0); } // Final 512bit value is d, c, b, a @@ -1216,7 +1213,7 @@ pub fn fromF64C(arg: f64) callconv(.C) i128 { if (@call(.always_inline, RocDec.fromF64, .{arg})) |dec| { return dec.num; } else { - @panic("TODO runtime exception failing convert f64 to RocDec"); + roc_panic("Decimal conversion from f64 failed!", 0); } } @@ -1225,7 +1222,7 @@ pub fn fromF32C(arg_f32: f32) callconv(.C) i128 { if (@call(.always_inline, RocDec.fromF64, .{arg_f64})) |dec| { return dec.num; } else { - @panic("TODO runtime exception failing convert f64 to RocDec"); + roc_panic("Decimal conversion from f32!", 0); } } @@ -1240,7 +1237,7 @@ pub fn exportFromInt(comptime T: type, comptime name: []const u8) void { const answer = @mulWithOverflow(this, RocDec.one_point_zero_i128); if (answer[1] == 1) { - @panic("TODO runtime exception failing convert integer to RocDec"); + roc_panic("Decimal conversion from Integer failed!", 0); } else { return answer[0]; } @@ -1266,11 +1263,15 @@ pub fn neqC(arg1: RocDec, arg2: RocDec) callconv(.C) bool { } pub fn negateC(arg: RocDec) callconv(.C) i128 { - return if (@call(.always_inline, RocDec.negate, .{arg})) |dec| dec.num else @panic("TODO overflow for negating RocDec"); + return if (@call(.always_inline, RocDec.negate, .{arg})) |dec| dec.num else { + roc_panic("Decimal negation overflow!", 0); + }; } pub fn absC(arg: RocDec) callconv(.C) i128 { - const result = @call(.always_inline, RocDec.abs, .{arg}) catch @panic("TODO overflow for calling absolute value on RocDec"); + const result = @call(.always_inline, RocDec.abs, .{arg}) catch { + roc_panic("Decimal absolute value overflow!", 0); + }; return result.num; } diff --git a/crates/compiler/builtins/bitcode/src/libc.zig b/crates/compiler/builtins/bitcode/src/libc.zig deleted file mode 100644 index d02467634a..0000000000 --- a/crates/compiler/builtins/bitcode/src/libc.zig +++ /dev/null @@ -1,87 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const arch = builtin.cpu.arch; -const musl = @import("libc/musl.zig"); -const folly = @import("libc/folly.zig"); -const cpuid = @import("libc/cpuid.zig"); - -comptime { - // TODO: remove this workaround. - // Our wasm llvm pipeline always links in memcpy. - // As such, our impl will conflict. - if (builtin.is_test) { - // We don't need memcpy for tests because the tests are built with -lc - } else if (arch != .wasm32) { - @export(memcpy, .{ .name = "memcpy", .linkage = .Strong }); - } -} - -const Memcpy = *const fn (noalias [*]u8, noalias [*]const u8, len: usize) callconv(.C) [*]u8; - -pub var memcpy_target: Memcpy = switch (arch) { - .x86_64 => dispatch_memcpy, - else => unreachable, -}; - -pub fn memcpy(noalias dest: [*]u8, noalias src: [*]const u8, len: usize) callconv(.C) [*]u8 { - switch (builtin.os.tag) { - .windows => { - return musl.memcpy(dest, src, len); - }, - else => switch (arch) { - // x86_64 has a special optimized memcpy that can use avx2. - .x86_64 => { - return memcpy_target(dest, src, len); - }, - else => { - return musl.memcpy(dest, src, len); - }, - }, - } -} - -const MemcpyDecision = enum { - uninitialized, - folly_prefetchw, - folly_prefetcht0, - musl, -}; - -var memcpy_decision: MemcpyDecision = .uninitialized; - -fn dispatch_memcpy(noalias dest: [*]u8, noalias src: [*]const u8, len: usize) callconv(.C) [*]u8 { - switch (arch) { - .x86_64 => { - // TODO: Switch this to overwrite the memcpy_target pointer once the surgical linker can support it. - // Then dispatch will just happen on the first call instead of every call. - // if (cpuid.supports_avx2()) { - // if (cpuid.supports_prefetchw()) { - // memcpy_target = folly.memcpy_prefetchw; - // } else { - // memcpy_target = folly.memcpy_prefetcht0; - // } - // } else { - // memcpy_target = musl.memcpy; - // } - // return memcpy_target(dest, src, len); - switch (memcpy_decision) { - .uninitialized => { - if (cpuid.supports_avx2()) { - if (cpuid.supports_prefetchw()) { - memcpy_decision = .folly_prefetchw; - } else { - memcpy_decision = .folly_prefetcht0; - } - } else { - memcpy_decision = .musl; - } - return dispatch_memcpy(dest, src, len); - }, - .folly_prefetchw => return folly.memcpy_prefetchw(dest, src, len), - .folly_prefetcht0 => return folly.memcpy_prefetcht0(dest, src, len), - .musl => return musl.memcpy(dest, src, len), - } - }, - else => unreachable, - } -} diff --git a/crates/compiler/builtins/bitcode/src/libc/assembly_util.zig b/crates/compiler/builtins/bitcode/src/libc/assembly_util.zig deleted file mode 100644 index 93bbc9f98d..0000000000 --- a/crates/compiler/builtins/bitcode/src/libc/assembly_util.zig +++ /dev/null @@ -1,7 +0,0 @@ -const builtin = @import("builtin"); -const os = builtin.os; - -pub const function_prefix = switch (os.tag) { - .macos => "_", - else => "", -}; diff --git a/crates/compiler/builtins/bitcode/src/libc/cpuid.S b/crates/compiler/builtins/bitcode/src/libc/cpuid.S deleted file mode 100644 index 1ea5eca2e4..0000000000 --- a/crates/compiler/builtins/bitcode/src/libc/cpuid.S +++ /dev/null @@ -1,53 +0,0 @@ -// Check if AVX2 is supported. -// Returns 1 if AVX2 is supported, 0 otherwise. -.global {[function_prefix]s}supports_avx2; -{[function_prefix]s}supports_avx2: - // Save the EBX register. - push %rbx - - // Call the CPUID instruction with the EAX register set to 7 and ECX set to 0. - // This will get the CPUID information for the current CPU. - mov $7, %eax - mov $0, %ecx - cpuid - - // The AVX2 feature flag is located in the EBX register at bit 5. - bt $5, %ebx - jc .avx2_supported - - // AVX2 is not supported. - pop %rbx - mov $0, %eax - ret - - .avx2_supported: - pop %rbx - mov $1, %eax - ret - - // Check if prefetchw is supported. - // Returns 1 if the prefetchw instruction is supported, 0 otherwise. -.global {[function_prefix]s}supports_prefetchw; -{[function_prefix]s}supports_prefetchw: - // Save the EBX register. - push %rbx - - // Call the CPUID instruction with the EAX register set to 0x80000001 and ECX set to 0. - // This will get the CPUID information for the current CPU. - mov $0x80000001, %eax - mov $0, %ecx - cpuid - - // The prefetchw feature flag is located in the ECX register at bit 8. - bt $8, %ecx - jc .prefetchw_supported - - // AVX2 is not supported. - pop %rbx - mov $0, %eax - ret - - .prefetchw_supported: - pop %rbx - mov $1, %eax - ret diff --git a/crates/compiler/builtins/bitcode/src/libc/cpuid.zig b/crates/compiler/builtins/bitcode/src/libc/cpuid.zig deleted file mode 100644 index 6b2dc63af6..0000000000 --- a/crates/compiler/builtins/bitcode/src/libc/cpuid.zig +++ /dev/null @@ -1,18 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const arch = builtin.cpu.arch; -const function_prefix = @import("assembly_util.zig").function_prefix; - -// I couldn't manage to define this in a PIE friendly way with inline assembly. -// Instead, I am defining it as global assembly functions. -comptime { - switch (arch) { - .x86_64 => { - asm (std.fmt.comptimePrint(@embedFile("cpuid.S"), .{ .function_prefix = function_prefix })); - }, - else => unreachable, - } -} - -pub extern fn supports_avx2() bool; -pub extern fn supports_prefetchw() bool; diff --git a/crates/compiler/builtins/bitcode/src/libc/folly.zig b/crates/compiler/builtins/bitcode/src/libc/folly.zig deleted file mode 100644 index f8d0612b61..0000000000 --- a/crates/compiler/builtins/bitcode/src/libc/folly.zig +++ /dev/null @@ -1,2 +0,0 @@ -pub const memcpy_prefetchw = @import("folly/memcpy.zig").__folly_memcpy_prefetchw; -pub const memcpy_prefetcht0 = @import("folly/memcpy.zig").__folly_memcpy_prefetcht0; diff --git a/crates/compiler/builtins/bitcode/src/libc/folly/memcpy-x86_64.S b/crates/compiler/builtins/bitcode/src/libc/folly/memcpy-x86_64.S deleted file mode 100644 index 266e56b0a2..0000000000 --- a/crates/compiler/builtins/bitcode/src/libc/folly/memcpy-x86_64.S +++ /dev/null @@ -1,437 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * __folly_memcpy: An optimized memcpy implementation that uses prefetch and - * AVX2 instructions. - * - * This implementation of memcpy acts as a memmove: while overlapping copies - * are undefined in memcpy, in some implementations they're the same function and - * legacy programs rely on this behavior. - * - * This implementation uses prefetch to avoid dtlb misses. This can - * substantially reduce dtlb store misses in cases where the destination - * location is absent from L1 cache and where the copy size is small enough - * that the hardware prefetcher doesn't have a large impact. - * - * The number of branches is limited by the use of overlapping loads & stores. - * This helps with copies where the source and destination cache lines are already - * present in L1 because there are fewer instructions to execute and fewer - * branches to potentially mispredict. - * e.g. to copy the last 4 <= n <= 7 bytes: copy the first & last 4 bytes (overlapped): - * movl (%rsi), %r8d - * movl -4(%rsi,%rdx), %r9d - * movl %r8d, (%rdi) - * movl %r9d, -4(%rdi,%rdx) - * - * - * For sizes up to 256 all source data is first read into registers and then written: - * - n <= 16: overlapping movs - * - n <= 32: overlapping unaligned 16-byte SSE XMM load/stores - * - n <= 256: overlapping unaligned 32-byte AVX YMM load/stores - * - * Large copies (> 256 bytes) use unaligned loads + aligned stores. - * This is observed to always be faster than rep movsb, so the rep movsb - * instruction is not used. - * - The head & tail may be unaligned => they're always written using unaligned stores. - * - * If the copy size is humongous (> 32 KiB) and the source and destination are both - * aligned, this memcpy will use non-temporal operations (AVX2). This can have - * a substantial speedup for copies where data is absent from L1, but it - * is significantly slower if the source and destination data were already - * in L1. The use of non-temporal operations also has the effect that after - * the copy is complete, the data will be moved out of L1, even if the data was - * present before the copy started. - * - * For n > 256 and overlapping src & dst buffers (memmove): - * - use unaligned loads + aligned stores, but not non-temporal stores - * - for dst < src forward copy in 128 byte batches: - * - unaligned load the first 32 bytes & last 4 x 32 bytes - * - forward copy (unaligned load + aligned stores) 4 x 32 bytes at a time - * - unaligned store the first 32 bytes & last 4 x 32 bytes - * - for dst > src backward copy in 128 byte batches: - * - unaligned load the first 4 x 32 bytes & last 32 bytes - * - backward copy (unaligned load + aligned stores) 4 x 32 bytes at a time - * - unaligned store the first 4 x 32 bytes & last 32 bytes - * - * @author Logan Evans - */ - - - // .type {[function_prefix]s}__folly_memcpy_short_{[prefetch]s}, @function not supported by windows -{[function_prefix]s}__folly_memcpy_short_{[prefetch]s}: - .cfi_startproc - -.L_GE1_LE7_{[prefetch]s}: - cmp $1, %rdx - je .L_EQ1_{[prefetch]s} - - cmp $4, %rdx - jae .L_GE4_LE7_{[prefetch]s} - -.L_GE2_LE3_{[prefetch]s}: - movw (%rsi), %r8w - movw -2(%rsi,%rdx), %r9w - movw %r8w, (%rdi) - movw %r9w, -2(%rdi,%rdx) - ret - - .balign 2 -.L_EQ1_{[prefetch]s}: - movb (%rsi), %r8b - movb %r8b, (%rdi) - ret - - // Aligning the target of a jump to an even address has a measurable - // speedup in microbenchmarks. - .balign 2 -.L_GE4_LE7_{[prefetch]s}: - movl (%rsi), %r8d - movl -4(%rsi,%rdx), %r9d - movl %r8d, (%rdi) - movl %r9d, -4(%rdi,%rdx) - ret - - .cfi_endproc - // .size {[function_prefix]s}__folly_memcpy_short_{[prefetch]s}, .-{[function_prefix]s}__folly_memcpy_short_{[prefetch]s} not supported by windows - -// memcpy is an alternative entrypoint into the function named __folly_memcpy. -// The compiler is able to call memcpy since the name is global while -// stacktraces will show __folly_memcpy since that is the name of the function. -// This is intended to aid in debugging by making it obvious which version of -// memcpy is being used. - .balign 64 - .globl {[function_prefix]s}__folly_memcpy_{[prefetch]s} - // .type {[function_prefix]s}__folly_memcpy_{[prefetch]s}, @function not supported by windows - -{[function_prefix]s}__folly_memcpy_{[prefetch]s}: - .cfi_startproc - - mov %rdi, %rax // return: $rdi - - test %rdx, %rdx - je .L_EQ0_{[prefetch]s} - - {[prefetch]s} (%rdi) - {[prefetch]s} -1(%rdi,%rdx) - - cmp $8, %rdx - jb .L_GE1_LE7_{[prefetch]s} - -.L_GE8_{[prefetch]s}: - cmp $32, %rdx - ja .L_GE33_{[prefetch]s} - -.L_GE8_LE32_{[prefetch]s}: - cmp $16, %rdx - ja .L_GE17_LE32_{[prefetch]s} - -.L_GE8_LE16_{[prefetch]s}: - mov (%rsi), %r8 - mov -8(%rsi,%rdx), %r9 - mov %r8, (%rdi) - mov %r9, -8(%rdi,%rdx) -.L_EQ0_{[prefetch]s}: - ret - - .balign 2 -.L_GE17_LE32_{[prefetch]s}: - movdqu (%rsi), %xmm0 - movdqu -16(%rsi,%rdx), %xmm1 - movdqu %xmm0, (%rdi) - movdqu %xmm1, -16(%rdi,%rdx) - ret - - .balign 2 -.L_GE193_LE256_{[prefetch]s}: - vmovdqu %ymm3, 96(%rdi) - vmovdqu %ymm4, -128(%rdi,%rdx) - -.L_GE129_LE192_{[prefetch]s}: - vmovdqu %ymm2, 64(%rdi) - vmovdqu %ymm5, -96(%rdi,%rdx) - -.L_GE65_LE128_{[prefetch]s}: - vmovdqu %ymm1, 32(%rdi) - vmovdqu %ymm6, -64(%rdi,%rdx) - -.L_GE33_LE64_{[prefetch]s}: - vmovdqu %ymm0, (%rdi) - vmovdqu %ymm7, -32(%rdi,%rdx) - - vzeroupper - ret - - .balign 2 -.L_GE33_{[prefetch]s}: - vmovdqu (%rsi), %ymm0 - vmovdqu -32(%rsi,%rdx), %ymm7 - - cmp $64, %rdx - jbe .L_GE33_LE64_{[prefetch]s} - - {[prefetch]s} 64(%rdi) - - vmovdqu 32(%rsi), %ymm1 - vmovdqu -64(%rsi,%rdx), %ymm6 - - cmp $128, %rdx - jbe .L_GE65_LE128_{[prefetch]s} - - {[prefetch]s} 128(%rdi) - - vmovdqu 64(%rsi), %ymm2 - vmovdqu -96(%rsi,%rdx), %ymm5 - - cmp $192, %rdx - jbe .L_GE129_LE192_{[prefetch]s} - - {[prefetch]s} 192(%rdi) - - vmovdqu 96(%rsi), %ymm3 - vmovdqu -128(%rsi,%rdx), %ymm4 - - cmp $256, %rdx - jbe .L_GE193_LE256_{[prefetch]s} - -.L_GE257_{[prefetch]s}: - {[prefetch]s} 256(%rdi) - - // Check if there is an overlap. If there is an overlap then the caller - // has a bug since this is undefined behavior. However, for legacy - // reasons this behavior is expected by some callers. - // - // All copies through 256 bytes will operate as a memmove since for - // those sizes all reads are performed before any writes. - // - // This check uses the idea that there is an overlap if - // (%rdi < (%rsi + %rdx)) && (%rsi < (%rdi + %rdx)), - // or equivalently, there is no overlap if - // ((%rsi + %rdx) <= %rdi) || ((%rdi + %rdx) <= %rsi). - // - // %r9 will be used after .L_ALIGNED_DST_LOOP to calculate how many - // bytes remain to be copied. - - // (%rsi + %rdx <= %rdi) => no overlap - lea (%rsi,%rdx), %r9 - cmp %rdi, %r9 - jbe .L_NO_OVERLAP_{[prefetch]s} - - // (%rdi + %rdx <= %rsi) => no overlap - lea (%rdi,%rdx), %r8 - cmp %rsi, %r8 - // If no info is available in branch predictor's cache, Intel CPUs assume - // forward jumps are not taken. Use a forward jump as overlapping buffers - // are unlikely. - ja .L_OVERLAP_{[prefetch]s} - - .balign 2 -.L_NO_OVERLAP_{[prefetch]s}: - vmovdqu %ymm0, (%rdi) - vmovdqu %ymm1, 32(%rdi) - vmovdqu %ymm2, 64(%rdi) - vmovdqu %ymm3, 96(%rdi) - - // Align %rdi to a 32 byte boundary. - // %rcx = 128 - 31 & %rdi - mov $128, %rcx - and $31, %rdi - sub %rdi, %rcx - - lea (%rsi,%rcx), %rsi - lea (%rax,%rcx), %rdi - sub %rcx, %rdx - - // %r8 is the end condition for the loop. - lea -128(%rsi,%rdx), %r8 - - // This threshold is half of L1 cache on a Skylake machine, which means that - // potentially all of L1 will be populated by this copy once it is executed - // (dst and src are cached for temporal copies). - // NON_TEMPORAL_STORE_THRESHOLD = $32768 - // cmp NON_TEMPORAL_STORE_THRESHOLD, %rdx - cmp $32768, %rdx - jae .L_NON_TEMPORAL_LOOP_{[prefetch]s} - - .balign 2 -.L_ALIGNED_DST_LOOP_{[prefetch]s}: - {[prefetch]s} 128(%rdi) - {[prefetch]s} 192(%rdi) - - vmovdqu (%rsi), %ymm0 - vmovdqu 32(%rsi), %ymm1 - vmovdqu 64(%rsi), %ymm2 - vmovdqu 96(%rsi), %ymm3 - add $128, %rsi - - vmovdqa %ymm0, (%rdi) - vmovdqa %ymm1, 32(%rdi) - vmovdqa %ymm2, 64(%rdi) - vmovdqa %ymm3, 96(%rdi) - add $128, %rdi - - cmp %r8, %rsi - jb .L_ALIGNED_DST_LOOP_{[prefetch]s} - -.L_ALIGNED_DST_LOOP_END_{[prefetch]s}: - sub %rsi, %r9 - mov %r9, %rdx - - vmovdqu %ymm4, -128(%rdi,%rdx) - vmovdqu %ymm5, -96(%rdi,%rdx) - vmovdqu %ymm6, -64(%rdi,%rdx) - vmovdqu %ymm7, -32(%rdi,%rdx) - - vzeroupper - ret - - .balign 2 -.L_NON_TEMPORAL_LOOP_{[prefetch]s}: - testb $31, %sil - jne .L_ALIGNED_DST_LOOP_{[prefetch]s} - // This is prefetching the source data unlike ALIGNED_DST_LOOP which - // prefetches the destination data. This choice is again informed by - // benchmarks. With a non-temporal store the entirety of the cache line - // is being written so the previous data can be discarded without being - // fetched. - prefetchnta 128(%rsi) - prefetchnta 196(%rsi) - - vmovntdqa (%rsi), %ymm0 - vmovntdqa 32(%rsi), %ymm1 - vmovntdqa 64(%rsi), %ymm2 - vmovntdqa 96(%rsi), %ymm3 - add $128, %rsi - - vmovntdq %ymm0, (%rdi) - vmovntdq %ymm1, 32(%rdi) - vmovntdq %ymm2, 64(%rdi) - vmovntdq %ymm3, 96(%rdi) - add $128, %rdi - - cmp %r8, %rsi - jb .L_NON_TEMPORAL_LOOP_{[prefetch]s} - - sfence - jmp .L_ALIGNED_DST_LOOP_END_{[prefetch]s} - - -.L_OVERLAP_{[prefetch]s}: - .balign 2 - cmp %rdi, %rsi - jb .L_OVERLAP_BWD_{[prefetch]s} // %rsi < %rdi => backward-copy - je .L_RET_{[prefetch]s} // %rsi == %rdi => return, nothing to copy - - // Source & destination buffers overlap. Forward copy. - - vmovdqu (%rsi), %ymm8 - - // Align %rdi to a 32 byte boundary. - // %rcx = 32 - 31 & %rdi - mov $32, %rcx - and $31, %rdi - sub %rdi, %rcx - - lea (%rsi,%rcx), %rsi - lea (%rax,%rcx), %rdi - sub %rcx, %rdx - - // %r8 is the end condition for the loop. - lea -128(%rsi,%rdx), %r8 - - -.L_OVERLAP_FWD_ALIGNED_DST_LOOP_{[prefetch]s}: - {[prefetch]s} 128(%rdi) - {[prefetch]s} 192(%rdi) - - vmovdqu (%rsi), %ymm0 - vmovdqu 32(%rsi), %ymm1 - vmovdqu 64(%rsi), %ymm2 - vmovdqu 96(%rsi), %ymm3 - add $128, %rsi - - vmovdqa %ymm0, (%rdi) - vmovdqa %ymm1, 32(%rdi) - vmovdqa %ymm2, 64(%rdi) - vmovdqa %ymm3, 96(%rdi) - add $128, %rdi - - cmp %r8, %rsi - jb .L_OVERLAP_FWD_ALIGNED_DST_LOOP_{[prefetch]s} - - sub %rsi, %r9 - mov %r9, %rdx - - vmovdqu %ymm4, -128(%rdi,%rdx) - vmovdqu %ymm5, -96(%rdi,%rdx) - vmovdqu %ymm6, -64(%rdi,%rdx) - vmovdqu %ymm7, -32(%rdi,%rdx) - vmovdqu %ymm8, (%rax) // %rax == the original (unaligned) %rdi - - vzeroupper - -.L_RET_{[prefetch]s}: - ret - -.L_OVERLAP_BWD_{[prefetch]s}: - // Save last 32 bytes. - vmovdqu -32(%rsi, %rdx), %ymm8 - lea -32(%rdi, %rdx), %r9 - - - // %r8 is the end condition for the loop. - lea 128(%rsi), %r8 - - // Align %rdi+%rdx (destination end) to a 32 byte boundary. - // %rcx = (%rdi + %rdx - 32) & 31 - mov %r9, %rcx - and $31, %rcx - // Set %rsi & %rdi to the end of the 32 byte aligned range. - sub %rcx, %rdx - add %rdx, %rsi - add %rdx, %rdi - - -.L_OVERLAP_BWD_ALIGNED_DST_LOOP_{[prefetch]s}: - {[prefetch]s} -128(%rdi) - {[prefetch]s} -192(%rdi) - - vmovdqu -32(%rsi), %ymm4 - vmovdqu -64(%rsi), %ymm5 - vmovdqu -96(%rsi), %ymm6 - vmovdqu -128(%rsi), %ymm7 - sub $128, %rsi - - vmovdqa %ymm4, -32(%rdi) - vmovdqa %ymm5, -64(%rdi) - vmovdqa %ymm6, -96(%rdi) - vmovdqa %ymm7, -128(%rdi) - sub $128, %rdi - - cmp %r8, %rsi - ja .L_OVERLAP_BWD_ALIGNED_DST_LOOP_{[prefetch]s} - - vmovdqu %ymm0, (%rax) // %rax == the original unaligned %rdi - vmovdqu %ymm1, 32(%rax) - vmovdqu %ymm2, 64(%rax) - vmovdqu %ymm3, 96(%rax) - vmovdqu %ymm8, (%r9) - - vzeroupper - ret - - .cfi_endproc - // .size {[function_prefix]s}__folly_memcpy_{[prefetch]s}, .-{[function_prefix]s}__folly_memcpy_{[prefetch]s} not supported by windows diff --git a/crates/compiler/builtins/bitcode/src/libc/folly/memcpy.zig b/crates/compiler/builtins/bitcode/src/libc/folly/memcpy.zig deleted file mode 100644 index e7f1b068db..0000000000 --- a/crates/compiler/builtins/bitcode/src/libc/folly/memcpy.zig +++ /dev/null @@ -1,18 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const arch = builtin.cpu.arch; -const function_prefix = @import("../assembly_util.zig").function_prefix; - -comptime { - switch (arch) { - .x86_64 => { - inline for ([_][]const u8{ "prefetchw", "prefetcht0" }) |prefetch| { - asm (std.fmt.comptimePrint(@embedFile("memcpy-x86_64.S"), .{ .prefetch = prefetch, .function_prefix = function_prefix })); - } - }, - else => unreachable, - } -} - -pub extern fn __folly_memcpy_prefetchw(noalias dest: [*]u8, noalias src: [*]const u8, len: usize) callconv(.SysV) [*]u8; -pub extern fn __folly_memcpy_prefetcht0(noalias dest: [*]u8, noalias src: [*]const u8, len: usize) callconv(.SysV) [*]u8; diff --git a/crates/compiler/builtins/bitcode/src/libc/musl.zig b/crates/compiler/builtins/bitcode/src/libc/musl.zig deleted file mode 100644 index 8bff515806..0000000000 --- a/crates/compiler/builtins/bitcode/src/libc/musl.zig +++ /dev/null @@ -1 +0,0 @@ -pub const memcpy = @import("musl/memcpy.zig").memcpy; diff --git a/crates/compiler/builtins/bitcode/src/libc/musl/COPYRIGHT b/crates/compiler/builtins/bitcode/src/libc/musl/COPYRIGHT deleted file mode 100644 index c1628e9ac8..0000000000 --- a/crates/compiler/builtins/bitcode/src/libc/musl/COPYRIGHT +++ /dev/null @@ -1,193 +0,0 @@ -musl as a whole is licensed under the following standard MIT license: - ----------------------------------------------------------------------- -Copyright © 2005-2020 Rich Felker, et al. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ----------------------------------------------------------------------- - -Authors/contributors include: - -A. Wilcox -Ada Worcester -Alex Dowad -Alex Suykov -Alexander Monakov -Andre McCurdy -Andrew Kelley -Anthony G. Basile -Aric Belsito -Arvid Picciani -Bartosz Brachaczek -Benjamin Peterson -Bobby Bingham -Boris Brezillon -Brent Cook -Chris Spiegel -Clément Vasseur -Daniel Micay -Daniel Sabogal -Daurnimator -David Carlier -David Edelsohn -Denys Vlasenko -Dmitry Ivanov -Dmitry V. Levin -Drew DeVault -Emil Renner Berthing -Fangrui Song -Felix Fietkau -Felix Janda -Gianluca Anzolin -Hauke Mehrtens -He X -Hiltjo Posthuma -Isaac Dunham -Jaydeep Patil -Jens Gustedt -Jeremy Huntwork -Jo-Philipp Wich -Joakim Sindholt -John Spencer -Julien Ramseier -Justin Cormack -Kaarle Ritvanen -Khem Raj -Kylie McClain -Leah Neukirchen -Luca Barbato -Luka Perkov -M Farkas-Dyck (Strake) -Mahesh Bodapati -Markus Wichmann -Masanori Ogino -Michael Clark -Michael Forney -Mikhail Kremnyov -Natanael Copa -Nicholas J. Kain -orc -Pascal Cuoq -Patrick Oppenlander -Petr Hosek -Petr Skocik -Pierre Carrier -Reini Urban -Rich Felker -Richard Pennington -Ryan Fairfax -Samuel Holland -Segev Finer -Shiz -sin -Solar Designer -Stefan Kristiansson -Stefan O'Rear -Szabolcs Nagy -Timo Teräs -Trutz Behn -Valentin Ochs -Will Dietz -William Haddon -William Pitcock - -Portions of this software are derived from third-party works licensed -under terms compatible with the above MIT license: - -The TRE regular expression implementation (src/regex/reg* and -src/regex/tre*) is Copyright © 2001-2008 Ville Laurikari and licensed -under a 2-clause BSD license (license text in the source files). The -included version has been heavily modified by Rich Felker in 2012, in -the interests of size, simplicity, and namespace cleanliness. - -Much of the math library code (src/math/* and src/complex/*) is -Copyright © 1993,2004 Sun Microsystems or -Copyright © 2003-2011 David Schultz or -Copyright © 2003-2009 Steven G. Kargl or -Copyright © 2003-2009 Bruce D. Evans or -Copyright © 2008 Stephen L. Moshier or -Copyright © 2017-2018 Arm Limited -and labelled as such in comments in the individual source files. All -have been licensed under extremely permissive terms. - -The ARM memcpy code (src/string/arm/memcpy.S) is Copyright © 2008 -The Android Open Source Project and is licensed under a two-clause BSD -license. It was taken from Bionic libc, used on Android. - -The AArch64 memcpy and memset code (src/string/aarch64/*) are -Copyright © 1999-2019, Arm Limited. - -The implementation of DES for crypt (src/crypt/crypt_des.c) is -Copyright © 1994 David Burren. It is licensed under a BSD license. - -The implementation of blowfish crypt (src/crypt/crypt_blowfish.c) was -originally written by Solar Designer and placed into the public -domain. The code also comes with a fallback permissive license for use -in jurisdictions that may not recognize the public domain. - -The smoothsort implementation (src/stdlib/qsort.c) is Copyright © 2011 -Valentin Ochs and is licensed under an MIT-style license. - -The x86_64 port was written by Nicholas J. Kain and is licensed under -the standard MIT terms. - -The mips and microblaze ports were originally written by Richard -Pennington for use in the ellcc project. The original code was adapted -by Rich Felker for build system and code conventions during upstream -integration. It is licensed under the standard MIT terms. - -The mips64 port was contributed by Imagination Technologies and is -licensed under the standard MIT terms. - -The powerpc port was also originally written by Richard Pennington, -and later supplemented and integrated by John Spencer. It is licensed -under the standard MIT terms. - -All other files which have no copyright comments are original works -produced specifically for use as part of this library, written either -by Rich Felker, the main author of the library, or by one or more -contibutors listed above. Details on authorship of individual files -can be found in the git version control history of the project. The -omission of copyright and license comments in each file is in the -interest of source tree size. - -In addition, permission is hereby granted for all public header files -(include/* and arch/*/bits/*) and crt files intended to be linked into -applications (crt/*, ldso/dlstart.c, and arch/*/crt_arch.h) to omit -the copyright notice and permission notice otherwise required by the -license, and to use these files without any requirement of -attribution. These files include substantial contributions from: - -Bobby Bingham -John Spencer -Nicholas J. Kain -Rich Felker -Richard Pennington -Stefan Kristiansson -Szabolcs Nagy - -all of whom have explicitly granted such permission. - -This file previously contained text expressing a belief that most of -the files covered by the above exception were sufficiently trivial not -to be subject to copyright, resulting in confusion over whether it -negated the permissions granted in the license. In the spirit of -permissive licensing, and of not having licensing issues being an -obstacle to adoption, that text has been removed. diff --git a/crates/compiler/builtins/bitcode/src/libc/musl/README.md b/crates/compiler/builtins/bitcode/src/libc/musl/README.md deleted file mode 100644 index d2d8d90c89..0000000000 --- a/crates/compiler/builtins/bitcode/src/libc/musl/README.md +++ /dev/null @@ -1,2 +0,0 @@ -This set of files all come from [musl libc](https://musl.libc.org/). -Roc just directly uses a few of them instead of depending on musl libc fully. diff --git a/crates/compiler/builtins/bitcode/src/libc/musl/memcpy-x86.S b/crates/compiler/builtins/bitcode/src/libc/musl/memcpy-x86.S deleted file mode 100644 index 83a2d4261d..0000000000 --- a/crates/compiler/builtins/bitcode/src/libc/musl/memcpy-x86.S +++ /dev/null @@ -1,30 +0,0 @@ -.global {[function_prefix]s}musl_memcpy -// Windows does not support the type directive. -// .type {[function_prefix]s}musl_memcpy,@function -{[function_prefix]s}musl_memcpy: - push %esi - push %edi - mov 12(%esp),%edi - mov 16(%esp),%esi - mov 20(%esp),%ecx - mov %edi,%eax - cmp $4,%ecx - jc 1f - test $3,%edi - jz 1f -2: movsb - dec %ecx - test $3,%edi - jnz 2b -1: mov %ecx,%edx - shr $2,%ecx - rep - movsl - and $3,%edx - jz 1f -2: movsb - dec %edx - jnz 2b -1: pop %edi - pop %esi - ret \ No newline at end of file diff --git a/crates/compiler/builtins/bitcode/src/libc/musl/memcpy-x86_64.S b/crates/compiler/builtins/bitcode/src/libc/musl/memcpy-x86_64.S deleted file mode 100644 index 21391b4553..0000000000 --- a/crates/compiler/builtins/bitcode/src/libc/musl/memcpy-x86_64.S +++ /dev/null @@ -1,23 +0,0 @@ -.global {[function_prefix]s}musl_memcpy -// Windows does not support the type directive. -// .type {[function_prefix]s}musl_memcpy,@function -{[function_prefix]s}musl_memcpy: - mov %rdi,%rax - cmp $8,%rdx - jc 1f - test $7,%edi - jz 1f -2: movsb - dec %rdx - test $7,%edi - jnz 2b -1: mov %rdx,%rcx - shr $3,%rcx - rep - movsq - and $7,%edx - jz 1f -2: movsb - dec %edx - jnz 2b -1: ret diff --git a/crates/compiler/builtins/bitcode/src/libc/musl/memcpy.zig b/crates/compiler/builtins/bitcode/src/libc/musl/memcpy.zig deleted file mode 100644 index b301900f21..0000000000 --- a/crates/compiler/builtins/bitcode/src/libc/musl/memcpy.zig +++ /dev/null @@ -1,223 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const arch = builtin.cpu.arch; -const function_prefix = @import("../assembly_util.zig").function_prefix; - -comptime { - switch (arch) { - .x86_64 => { - asm (std.fmt.comptimePrint(@embedFile("memcpy-x86_64.S"), .{ .function_prefix = function_prefix })); - }, - .x86 => { - asm (std.fmt.comptimePrint(@embedFile("memcpy-x86.S"), .{ .function_prefix = function_prefix })); - }, - // TODO: add assembly implementations for other platforms. - else => {}, - } -} - -pub const memcpy = - switch (builtin.os.tag) { - .windows => fallback_memcpy, - else => switch (arch) { - .x86_64, .x86 => musl_memcpy, - else => fallback_memcpy, - }, -}; - -pub extern fn musl_memcpy(noalias dest: [*]u8, noalias src: [*]const u8, len: usize) callconv(.C) [*]u8; - -// Note: this is written to only support little endian targets. -// To support big endian, `<<` and `>>` wold need to be swapped. -pub fn fallback_memcpy(noalias dest: [*]u8, noalias src: [*]const u8, len: usize) callconv(.C) [*]u8 { - var d = dest; - var s = src; - var n = len; - switch (@min(n, @intFromPtr(s) % 4)) { - 1 => { - d[0] = s[0]; - d += 1; - s += 1; - n -= 1; - }, - 2 => { - d[0] = s[0]; - d[1] = s[1]; - d += 2; - s += 2; - n -= 2; - }, - 3 => { - d[0] = s[0]; - d[1] = s[1]; - d[2] = s[2]; - d += 3; - s += 3; - n -= 3; - }, - else => {}, - } - - if (@intFromPtr(d) % 4 == 0) { - var d4 = @as([*]align(4) u8, @alignCast(d)); - var s4 = @as([*]align(4) const u8, @alignCast(s)); - while (n >= 16) : (n -= 16) { - var d_u32 = @as([*]u32, @ptrCast(d4)); - var s_u32 = @as([*]const u32, @ptrCast(s4)); - d_u32[0] = s_u32[0]; - d_u32[1] = s_u32[1]; - d_u32[2] = s_u32[2]; - d_u32[3] = s_u32[3]; - - d4 += 16; - s4 += 16; - } - if (n & 8 != 0) { - var d_u32 = @as([*]u32, @ptrCast(d4)); - var s_u32 = @as([*]const u32, @ptrCast(s4)); - d_u32[0] = s_u32[0]; - d_u32[1] = s_u32[1]; - - d4 += 8; - s4 += 8; - } - if (n & 4 != 0) { - var d_u32 = @as([*]u32, @ptrCast(d4)); - var s_u32 = @as([*]const u32, @ptrCast(s4)); - d_u32[0] = s_u32[0]; - - d4 += 4; - s4 += 4; - } - d = d4; - s = s4; - if (n & 2 != 0) { - d[0] = s[0]; - d += 1; - s += 1; - d[0] = s[0]; - d += 1; - s += 1; - } - if (n & 1 != 0) { - d[0] = s[0]; - } - return dest; - } - if (n >= 32) { - switch (@intFromPtr(d) % 4) { - 1 => { - var w = @as([*]const u32, @ptrCast(@alignCast(s)))[0]; - d[0] = s[0]; - d += 1; - s += 1; - d[0] = s[0]; - d += 1; - s += 1; - d[0] = s[0]; - d += 1; - s += 1; - n -= 3; - while (n >= 17) : (n -= 16) { - var d_u32 = @as([*]u32, @ptrCast(@alignCast(d))); - var s_u32 = @as([*]const u32, @ptrCast(@alignCast(s + 1))); - var x = s_u32[0]; - d_u32[0] = (w >> 24) | (x << 8); - w = s_u32[1]; - d_u32[1] = (x >> 24) | (w << 8); - x = s_u32[2]; - d_u32[2] = (w >> 24) | (x << 8); - w = s_u32[3]; - d_u32[3] = (x >> 24) | (w << 8); - - d += 16; - s += 16; - } - }, - 2 => { - var w = @as([*]const u32, @ptrCast(@alignCast(s)))[0]; - d[0] = s[0]; - d += 1; - s += 1; - d[0] = s[0]; - d += 1; - s += 1; - n -= 2; - while (n >= 18) : (n -= 16) { - var d_u32 = @as([*]u32, @ptrCast(@alignCast(d))); - var s_u32 = @as([*]const u32, @ptrCast(@alignCast(s + 2))); - var x = s_u32[0]; - d_u32[0] = (w >> 16) | (x << 16); - w = s_u32[1]; - d_u32[1] = (x >> 16) | (w << 16); - x = s_u32[2]; - d_u32[2] = (w >> 16) | (x << 16); - w = s_u32[3]; - d_u32[3] = (x >> 16) | (w << 16); - - d += 16; - s += 16; - } - }, - 3 => { - var w = @as([*]const u32, @ptrCast(@alignCast(s)))[0]; - d[0] = s[0]; - d += 1; - s += 1; - n -= 1; - while (n >= 19) : (n -= 16) { - var d_u32 = @as([*]u32, @ptrCast(@alignCast(d))); - var s_u32 = @as([*]const u32, @ptrCast(@alignCast(s + 3))); - var x = s_u32[0]; - d_u32[0] = (w >> 8) | (x << 24); - w = s_u32[1]; - d_u32[1] = (x >> 8) | (w << 24); - x = s_u32[2]; - d_u32[2] = (w >> 8) | (x << 24); - w = s_u32[3]; - d_u32[3] = (x >> 8) | (w << 24); - - d += 16; - s += 16; - } - }, - else => unreachable, - } - } - if (n & 16 != 0) { - comptime var i = 0; - inline while (i < 16) : (i += 1) { - d[0] = s[0]; - d += 1; - s += 1; - } - } - if (n & 8 != 0) { - comptime var i = 0; - inline while (i < 8) : (i += 1) { - d[0] = s[0]; - d += 1; - s += 1; - } - } - if (n & 4 != 0) { - comptime var i = 0; - inline while (i < 4) : (i += 1) { - d[0] = s[0]; - d += 1; - s += 1; - } - } - if (n & 2 != 0) { - d[0] = s[0]; - d += 1; - s += 1; - d[0] = s[0]; - d += 1; - s += 1; - } - if (n & 1 != 0) { - d[0] = s[0]; - } - return dest; -} diff --git a/crates/compiler/builtins/bitcode/src/list.zig b/crates/compiler/builtins/bitcode/src/list.zig index ad0691df60..aea5b21113 100644 --- a/crates/compiler/builtins/bitcode/src/list.zig +++ b/crates/compiler/builtins/bitcode/src/list.zig @@ -21,16 +21,18 @@ const SEAMLESS_SLICE_BIT: usize = pub const RocList = extern struct { bytes: ?[*]u8, length: usize, - // This technically points to directly after the refcount. - // This is an optimization that enables use one code path for regular lists and slices for geting the refcount ptr. - capacity_or_ref_ptr: usize, + // For normal lists, contains the capacity. + // For seamless slices contains the pointer to the original allocation. + // This pointer is to the first element of the original list. + // Note we storing an allocation pointer, the pointer must be right shifted by one. + capacity_or_alloc_ptr: usize, pub inline fn len(self: RocList) usize { return self.length; } pub fn getCapacity(self: RocList) usize { - const list_capacity = self.capacity_or_ref_ptr; + const list_capacity = self.capacity_or_alloc_ptr; const slice_capacity = self.length; const slice_mask = self.seamlessSliceMask(); const capacity = (list_capacity & ~slice_mask) | (slice_capacity & slice_mask); @@ -38,14 +40,14 @@ pub const RocList = extern struct { } pub fn isSeamlessSlice(self: RocList) bool { - return @as(isize, @bitCast(self.capacity_or_ref_ptr)) < 0; + return @as(isize, @bitCast(self.capacity_or_alloc_ptr)) < 0; } // This returns all ones if the list is a seamless slice. // Otherwise, it returns all zeros. // This is done without branching for optimization purposes. pub fn seamlessSliceMask(self: RocList) usize { - return @as(usize, @bitCast(@as(isize, @bitCast(self.capacity_or_ref_ptr)) >> (@bitSizeOf(isize) - 1))); + return @as(usize, @bitCast(@as(isize, @bitCast(self.capacity_or_alloc_ptr)) >> (@bitSizeOf(isize) - 1))); } pub fn isEmpty(self: RocList) bool { @@ -53,7 +55,7 @@ pub const RocList = extern struct { } pub fn empty() RocList { - return RocList{ .bytes = null, .length = 0, .capacity_or_ref_ptr = 0 }; + return RocList{ .bytes = null, .length = 0, .capacity_or_alloc_ptr = 0 }; } pub fn eql(self: RocList, other: RocList) bool { @@ -99,21 +101,22 @@ pub const RocList = extern struct { return list; } - // returns a pointer to just after the refcount. - // It is just after the refcount as an optimization for other shared code paths. - // For regular list, it just returns their bytes pointer. - // For seamless slices, it returns the pointer stored in capacity_or_ref_ptr. - pub fn getRefcountPtr(self: RocList) ?[*]u8 { - const list_ref_ptr = @intFromPtr(self.bytes); - const slice_ref_ptr = self.capacity_or_ref_ptr << 1; + // returns a pointer to the original allocation. + // This pointer points to the first element of the allocation. + // The pointer is to just after the refcount. + // For big lists, it just returns their bytes pointer. + // For seamless slices, it returns the pointer stored in capacity_or_alloc_ptr. + pub fn getAllocationPtr(self: RocList) ?[*]u8 { + const list_alloc_ptr = @intFromPtr(self.bytes); + const slice_alloc_ptr = self.capacity_or_alloc_ptr << 1; const slice_mask = self.seamlessSliceMask(); - const ref_ptr = (list_ref_ptr & ~slice_mask) | (slice_ref_ptr & slice_mask); - return @as(?[*]u8, @ptrFromInt(ref_ptr)); + const alloc_ptr = (list_alloc_ptr & ~slice_mask) | (slice_alloc_ptr & slice_mask); + return @as(?[*]u8, @ptrFromInt(alloc_ptr)); } pub fn decref(self: RocList, alignment: u32) void { // We use the raw capacity to ensure we always decrement the refcount of seamless slices. - utils.decref(self.getRefcountPtr(), self.capacity_or_ref_ptr, alignment); + utils.decref(self.getAllocationPtr(), self.capacity_or_alloc_ptr, alignment); } pub fn elements(self: RocList, comptime T: type) ?[*]T { @@ -187,7 +190,7 @@ pub const RocList = extern struct { return RocList{ .bytes = utils.allocateWithRefcount(data_bytes, alignment), .length = length, - .capacity_or_ref_ptr = capacity, + .capacity_or_alloc_ptr = capacity, }; } @@ -204,7 +207,7 @@ pub const RocList = extern struct { return RocList{ .bytes = utils.allocateWithRefcount(data_bytes, alignment), .length = length, - .capacity_or_ref_ptr = length, + .capacity_or_alloc_ptr = length, }; } @@ -216,13 +219,13 @@ pub const RocList = extern struct { ) RocList { if (self.bytes) |source_ptr| { if (self.isUnique() and !self.isSeamlessSlice()) { - const capacity = self.capacity_or_ref_ptr; + const capacity = self.capacity_or_alloc_ptr; if (capacity >= new_length) { - return RocList{ .bytes = self.bytes, .length = new_length, .capacity_or_ref_ptr = capacity }; + return RocList{ .bytes = self.bytes, .length = new_length, .capacity_or_alloc_ptr = capacity }; } else { const new_capacity = utils.calculateCapacity(capacity, new_length, element_width); const new_source = utils.unsafeReallocate(source_ptr, alignment, capacity, new_capacity, element_width); - return RocList{ .bytes = new_source, .length = new_length, .capacity_or_ref_ptr = new_capacity }; + return RocList{ .bytes = new_source, .length = new_length, .capacity_or_alloc_ptr = new_capacity }; } } return self.reallocateFresh(alignment, new_length, element_width); @@ -500,8 +503,8 @@ pub fn listReleaseExcessCapacity( update_mode: UpdateMode, ) callconv(.C) RocList { const old_length = list.len(); - // We use the direct list.capacity_or_ref_ptr to make sure both that there is no extra capacity and that it isn't a seamless slice. - if ((update_mode == .InPlace or list.isUnique()) and list.capacity_or_ref_ptr == old_length) { + // We use the direct list.capacity_or_alloc_ptr to make sure both that there is no extra capacity and that it isn't a seamless slice. + if ((update_mode == .InPlace or list.isUnique()) and list.capacity_or_alloc_ptr == old_length) { return list; } else if (old_length == 0) { list.decref(alignment); @@ -649,14 +652,14 @@ pub fn listSublist( output.length = keep_len; return output; } else { - const list_ref_ptr = (@intFromPtr(source_ptr) >> 1) | SEAMLESS_SLICE_BIT; - const slice_ref_ptr = list.capacity_or_ref_ptr; + const list_alloc_ptr = (@intFromPtr(source_ptr) >> 1) | SEAMLESS_SLICE_BIT; + const slice_alloc_ptr = list.capacity_or_alloc_ptr; const slice_mask = list.seamlessSliceMask(); - const ref_ptr = (list_ref_ptr & ~slice_mask) | (slice_ref_ptr & slice_mask); + const alloc_ptr = (list_alloc_ptr & ~slice_mask) | (slice_alloc_ptr & slice_mask); return RocList{ .bytes = source_ptr + start * element_width, .length = keep_len, - .capacity_or_ref_ptr = ref_ptr, + .capacity_or_alloc_ptr = alloc_ptr, }; } } @@ -965,10 +968,10 @@ pub fn listCapacity( return list.getCapacity(); } -pub fn listRefcountPtr( +pub fn listAllocationPtr( list: RocList, ) callconv(.C) ?[*]u8 { - return list.getRefcountPtr(); + return list.getAllocationPtr(); } test "listConcat: non-unique with unique overlapping" { diff --git a/crates/compiler/builtins/bitcode/src/main.zig b/crates/compiler/builtins/bitcode/src/main.zig index d631d01c37..742c4afff1 100644 --- a/crates/compiler/builtins/bitcode/src/main.zig +++ b/crates/compiler/builtins/bitcode/src/main.zig @@ -4,11 +4,7 @@ const math = std.math; const utils = @import("utils.zig"); const expect = @import("expect.zig"); const panic_utils = @import("panic.zig"); - -comptime { - _ = @import("compiler_rt.zig"); - _ = @import("libc.zig"); -} +const dbg_utils = @import("dbg.zig"); const ROC_BUILTINS = "roc_builtins"; const NUM = "num"; @@ -17,6 +13,13 @@ const STR = "str"; // Dec Module const dec = @import("dec.zig"); +var FLTUSED: i32 = 0; +comptime { + if (builtin.os.tag == .windows) { + @export(FLTUSED, .{ .name = "_fltused", .linkage = .Weak }); + } +} + comptime { exportDecFn(dec.absC, "abs"); exportDecFn(dec.acosC, "acos"); @@ -73,7 +76,7 @@ comptime { exportListFn(list.listSwap, "swap"); exportListFn(list.listIsUnique, "is_unique"); exportListFn(list.listCapacity, "capacity"); - exportListFn(list.listRefcountPtr, "refcount_ptr"); + exportListFn(list.listAllocationPtr, "allocation_ptr"); exportListFn(list.listReleaseExcessCapacity, "release_excess_capacity"); } @@ -215,7 +218,7 @@ comptime { exportStrFn(str.strCloneTo, "clone_to"); exportStrFn(str.withCapacity, "with_capacity"); exportStrFn(str.strGraphemes, "graphemes"); - exportStrFn(str.strRefcountPtr, "refcount_ptr"); + exportStrFn(str.strAllocationPtr, "allocation_ptr"); exportStrFn(str.strReleaseExcessCapacity, "release_excess_capacity"); inline for (INTEGERS) |T| { @@ -245,6 +248,7 @@ comptime { exportUtilsFn(utils.dictPseudoSeed, "dict_pseudo_seed"); @export(panic_utils.panic, .{ .name = "roc_builtins.utils." ++ "panic", .linkage = .Weak }); + @export(dbg_utils.dbg_impl, .{ .name = "roc_builtins.utils." ++ "dbg_impl", .linkage = .Weak }); if (builtin.target.cpu.arch != .wasm32) { exportUtilsFn(expect.expectFailedStartSharedBuffer, "expect_failed_start_shared_buffer"); diff --git a/crates/compiler/builtins/bitcode/src/num.zig b/crates/compiler/builtins/bitcode/src/num.zig index c978af99e1..d388859554 100644 --- a/crates/compiler/builtins/bitcode/src/num.zig +++ b/crates/compiler/builtins/bitcode/src/num.zig @@ -233,7 +233,9 @@ pub fn exportCeiling(comptime F: type, comptime T: type, comptime name: []const pub fn exportDivCeil(comptime T: type, comptime name: []const u8) void { comptime var f = struct { fn func(a: T, b: T) callconv(.C) T { - return math.divCeil(T, a, b) catch @panic("TODO runtime exception for dividing by 0!"); + return math.divCeil(T, a, b) catch { + roc_panic("Integer division by 0!", 0); + }; } }.func; @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); @@ -379,8 +381,7 @@ pub fn exportAddOrPanic(comptime T: type, comptime name: []const u8) void { fn func(self: T, other: T) callconv(.C) T { const result = addWithOverflow(T, self, other); if (result.has_overflowed) { - roc_panic("integer addition overflowed!", 0); - unreachable; + roc_panic("Integer addition overflowed!", 0); } else { return result.value; } @@ -437,8 +438,7 @@ pub fn exportSubOrPanic(comptime T: type, comptime name: []const u8) void { fn func(self: T, other: T) callconv(.C) T { const result = subWithOverflow(T, self, other); if (result.has_overflowed) { - roc_panic("integer subtraction overflowed!", 0); - unreachable; + roc_panic("Integer subtraction overflowed!", 0); } else { return result.value; } @@ -622,8 +622,7 @@ pub fn exportMulOrPanic(comptime T: type, comptime W: type, comptime name: []con fn func(self: T, other: T) callconv(.C) T { const result = @call(.always_inline, mulWithOverflow, .{ T, W, self, other }); if (result.has_overflowed) { - roc_panic("integer multiplication overflowed!", 0); - unreachable; + roc_panic("Integer multiplication overflowed!", 0); } else { return result.value; } @@ -634,8 +633,8 @@ pub fn exportMulOrPanic(comptime T: type, comptime W: type, comptime name: []con 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(self)); + fn func(self: T) callconv(.C) u8 { + return @as(u8, @clz(self)); } }.func; @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); @@ -643,8 +642,8 @@ pub fn exportCountLeadingZeroBits(comptime T: type, comptime name: []const u8) v 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(self)); + fn func(self: T) callconv(.C) u8 { + return @as(u8, @ctz(self)); } }.func; @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); @@ -652,8 +651,8 @@ pub fn exportCountTrailingZeroBits(comptime T: type, comptime name: []const u8) 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(self)); + fn func(self: T) callconv(.C) u8 { + return @as(u8, @popCount(self)); } }.func; @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); diff --git a/crates/compiler/builtins/bitcode/src/panic.zig b/crates/compiler/builtins/bitcode/src/panic.zig index 76ecd69e12..13224a67df 100644 --- a/crates/compiler/builtins/bitcode/src/panic.zig +++ b/crates/compiler/builtins/bitcode/src/panic.zig @@ -2,14 +2,14 @@ const std = @import("std"); const RocStr = @import("str.zig").RocStr; // Signals to the host that the program has panicked -extern fn roc_panic(msg: *const RocStr, tag_id: u32) callconv(.C) void; +extern fn roc_panic(msg: *const RocStr, tag_id: u32) callconv(.C) noreturn; -pub fn panic_help(msg: []const u8, tag_id: u32) void { +pub fn panic_help(msg: []const u8, tag_id: u32) noreturn { var str = RocStr.init(msg.ptr, msg.len); roc_panic(&str, tag_id); } // must export this explicitly because right now it is not used from zig code -pub fn panic(msg: *const RocStr, alignment: u32) callconv(.C) void { +pub fn panic(msg: *const RocStr, alignment: u32) callconv(.C) noreturn { return roc_panic(msg, alignment); } diff --git a/crates/compiler/builtins/bitcode/src/str.zig b/crates/compiler/builtins/bitcode/src/str.zig index 3c39f5afba..f732b1e8e7 100644 --- a/crates/compiler/builtins/bitcode/src/str.zig +++ b/crates/compiler/builtins/bitcode/src/str.zig @@ -34,17 +34,21 @@ fn init_blank_small_string(comptime n: usize) [n]u8 { } pub const RocStr = extern struct { - str_bytes: ?[*]u8, - str_len: usize, - str_capacity: usize, + bytes: ?[*]u8, + length: usize, + // For big strs, contains the capacity. + // For seamless slices contains the pointer to the original allocation. + // This pointer is to the first character of the original string. + // Note we storing an allocation pointer, the pointer must be right shifted by one. + capacity_or_alloc_ptr: usize, pub const alignment = @alignOf(usize); pub inline fn empty() RocStr { return RocStr{ - .str_len = 0, - .str_bytes = null, - .str_capacity = MASK, + .length = 0, + .bytes = null, + .capacity_or_alloc_ptr = MASK, }; } @@ -63,29 +67,29 @@ pub const RocStr = extern struct { const start_byte = @as([*]u8, @ptrCast(list.bytes)) + start; if (list.isSeamlessSlice()) { return RocStr{ - .str_bytes = start_byte, - .str_len = count | SEAMLESS_SLICE_BIT, - .str_capacity = list.capacity_or_ref_ptr & (~SEAMLESS_SLICE_BIT), + .bytes = start_byte, + .length = count | SEAMLESS_SLICE_BIT, + .capacity_or_alloc_ptr = list.capacity_or_alloc_ptr & (~SEAMLESS_SLICE_BIT), }; } else if (start == 0 and (update_mode == .InPlace or list.isUnique())) { // Rare case, we can take over the original list. return RocStr{ - .str_bytes = start_byte, - .str_len = count, - .str_capacity = list.capacity_or_ref_ptr, // This is guaranteed to be a proper capacity. + .bytes = start_byte, + .length = count, + .capacity_or_alloc_ptr = list.capacity_or_alloc_ptr, // This is guaranteed to be a proper capacity. }; } else { // Create seamless slice pointing to the list. return RocStr{ - .str_bytes = start_byte, - .str_len = count | SEAMLESS_SLICE_BIT, - .str_capacity = @intFromPtr(list.bytes) >> 1, + .bytes = start_byte, + .length = count | SEAMLESS_SLICE_BIT, + .capacity_or_alloc_ptr = @intFromPtr(list.bytes) >> 1, }; } } pub fn isSeamlessSlice(self: RocStr) bool { - return !self.isSmallStr() and @as(isize, @bitCast(self.str_len)) < 0; + return !self.isSmallStr() and @as(isize, @bitCast(self.length)) < 0; } pub fn fromSlice(slice: []const u8) RocStr { @@ -96,9 +100,9 @@ pub const RocStr = extern struct { const first_element = utils.allocateWithRefcount(capacity, @sizeOf(usize)); return RocStr{ - .str_bytes = first_element, - .str_len = length, - .str_capacity = capacity, + .bytes = first_element, + .length = length, + .capacity_or_alloc_ptr = capacity, }; } @@ -140,27 +144,28 @@ pub const RocStr = extern struct { // Otherwise, it returns all zeros. // This is done without branching for optimization purposes. pub fn seamlessSliceMask(self: RocStr) usize { - return @as(usize, @bitCast(@as(isize, @bitCast(self.str_len)) >> (@bitSizeOf(isize) - 1))); + return @as(usize, @bitCast(@as(isize, @bitCast(self.length)) >> (@bitSizeOf(isize) - 1))); } - // returns a pointer to just after the refcount. - // It is just after the refcount as an optimization for other shared code paths. - // For regular list, it just returns their bytes pointer. - // For seamless slices, it returns the pointer stored in capacity_or_ref_ptr. + // returns a pointer to the original allocation. + // This pointer points to the first element of the allocation. + // The pointer is to just after the refcount. + // For big strings, it just returns their bytes pointer. + // For seamless slices, it returns the pointer stored in capacity_or_alloc_ptr. // This does not return a valid value if the input is a small string. - pub fn getRefcountPtr(self: RocStr) ?[*]u8 { - const str_ref_ptr = @intFromPtr(self.str_bytes); - const slice_ref_ptr = self.str_capacity << 1; + pub fn getAllocationPtr(self: RocStr) ?[*]u8 { + const str_alloc_ptr = @intFromPtr(self.bytes); + const slice_alloc_ptr = self.capacity_or_alloc_ptr << 1; const slice_mask = self.seamlessSliceMask(); - const ref_ptr = (str_ref_ptr & ~slice_mask) | (slice_ref_ptr & slice_mask); - return @as(?[*]u8, @ptrFromInt(ref_ptr)); + const alloc_ptr = (str_alloc_ptr & ~slice_mask) | (slice_alloc_ptr & slice_mask); + return @as(?[*]u8, @ptrFromInt(alloc_ptr)); } pub fn incref(self: RocStr, n: usize) void { if (!self.isSmallStr()) { - const ref_ptr = self.getRefcountPtr(); - if (ref_ptr != null) { - const isizes: [*]isize = @as([*]isize, @ptrCast(@alignCast(ref_ptr))); + const alloc_ptr = self.getAllocationPtr(); + if (alloc_ptr != null) { + const isizes: [*]isize = @as([*]isize, @ptrCast(@alignCast(alloc_ptr))); utils.increfRcPtrC(@as(*isize, @ptrCast(isizes - 1)), @as(isize, @intCast(n))); } } @@ -168,13 +173,13 @@ pub const RocStr = extern struct { pub fn decref(self: RocStr) void { if (!self.isSmallStr()) { - utils.decref(self.getRefcountPtr(), self.str_capacity, RocStr.alignment); + utils.decref(self.getAllocationPtr(), self.capacity_or_alloc_ptr, RocStr.alignment); } } pub fn eq(self: RocStr, other: RocStr) bool { // If they are byte-for-byte equal, they're definitely equal! - if (self.str_bytes == other.str_bytes and self.str_len == other.str_len and self.str_capacity == other.str_capacity) { + if (self.bytes == other.bytes and self.length == other.length and self.capacity_or_alloc_ptr == other.capacity_or_alloc_ptr) { return true; } @@ -208,12 +213,12 @@ pub const RocStr = extern struct { // just return the bytes return str; } else { - var new_str = RocStr.allocateBig(str.str_len, str.str_len); + var new_str = RocStr.allocateBig(str.length, str.length); - var old_bytes: [*]u8 = @as([*]u8, @ptrCast(str.str_bytes)); - var new_bytes: [*]u8 = @as([*]u8, @ptrCast(new_str.str_bytes)); + var old_bytes: [*]u8 = @as([*]u8, @ptrCast(str.bytes)); + var new_bytes: [*]u8 = @as([*]u8, @ptrCast(new_str.bytes)); - @memcpy(new_bytes[0..str.str_len], old_bytes[0..str.str_len]); + @memcpy(new_bytes[0..str.length], old_bytes[0..str.length]); return new_str; } @@ -230,7 +235,7 @@ pub const RocStr = extern struct { return self.reallocateFresh(new_length); } - if (self.str_bytes) |source_ptr| { + if (self.bytes) |source_ptr| { if (old_capacity > new_length) { var output = self; output.setLen(new_length); @@ -245,7 +250,7 @@ pub const RocStr = extern struct { element_width, ); - return RocStr{ .str_bytes = new_source, .str_len = new_length, .str_capacity = new_capacity }; + return RocStr{ .bytes = new_source, .length = new_length, .capacity_or_alloc_ptr = new_capacity }; } return self.reallocateFresh(new_length); } @@ -295,7 +300,7 @@ pub const RocStr = extern struct { } pub fn isSmallStr(self: RocStr) bool { - return @as(isize, @bitCast(self.str_capacity)) < 0; + return @as(isize, @bitCast(self.capacity_or_alloc_ptr)) < 0; } test "isSmallStr: returns true for empty string" { @@ -313,7 +318,7 @@ pub const RocStr = extern struct { if (self.isSmallStr()) { return self.asArray()[@sizeOf(RocStr) - 1] ^ 0b1000_0000; } else { - return self.str_len & (~SEAMLESS_SLICE_BIT); + return self.length & (~SEAMLESS_SLICE_BIT); } } @@ -321,7 +326,7 @@ pub const RocStr = extern struct { if (self.isSmallStr()) { self.asU8ptrMut()[@sizeOf(RocStr) - 1] = @as(u8, @intCast(length)) | 0b1000_0000; } else { - self.str_len = length | (SEAMLESS_SLICE_BIT & self.str_len); + self.length = length | (SEAMLESS_SLICE_BIT & self.length); } } @@ -329,9 +334,9 @@ pub const RocStr = extern struct { if (self.isSmallStr()) { return SMALL_STR_MAX_LENGTH; } else if (self.isSeamlessSlice()) { - return self.str_len & (~SEAMLESS_SLICE_BIT); + return self.length & (~SEAMLESS_SLICE_BIT); } else { - return self.str_capacity; + return self.capacity_or_alloc_ptr; } } @@ -340,7 +345,7 @@ pub const RocStr = extern struct { if (self.isSmallStr()) { return self.asArray()[index]; } else { - const bytes = self.str_bytes orelse unreachable; + const bytes = self.bytes orelse unreachable; return bytes[index]; } @@ -369,7 +374,7 @@ pub const RocStr = extern struct { return utils.REFCOUNT_ONE; } - const ptr: [*]usize = @as([*]usize, @ptrCast(@alignCast(self.str_bytes))); + const ptr: [*]usize = @as([*]usize, @ptrCast(@alignCast(self.bytes))); return (ptr - 1)[0]; } @@ -393,7 +398,7 @@ pub const RocStr = extern struct { if (self.isSmallStr()) { return @as([*]const u8, @ptrCast(self)); } else { - return @as([*]const u8, @ptrCast(self.str_bytes)); + return @as([*]const u8, @ptrCast(self.bytes)); } } @@ -401,7 +406,7 @@ pub const RocStr = extern struct { if (self.isSmallStr()) { return @as([*]u8, @ptrCast(self)); } else { - return @as([*]u8, @ptrCast(self.str_bytes)); + return @as([*]u8, @ptrCast(self.bytes)); } } @@ -516,13 +521,13 @@ pub const RocStr = extern struct { const content = "012345678901234567890123456789"; const roc_str1 = RocStr.init(content, content.len); const roc_str2 = RocStr.init(content, content.len); - try expect(roc_str1.str_bytes != roc_str2.str_bytes); + try expect(roc_str1.bytes != roc_str2.bytes); // Insert garbage after the end of each string - roc_str1.str_bytes.?[30] = '!'; - roc_str1.str_bytes.?[31] = '!'; - roc_str2.str_bytes.?[30] = '-'; - roc_str2.str_bytes.?[31] = '-'; + roc_str1.bytes.?[30] = '!'; + roc_str1.bytes.?[31] = '!'; + roc_str2.bytes.?[30] = '-'; + roc_str2.bytes.?[31] = '-'; defer { roc_str1.decref(); @@ -553,13 +558,13 @@ pub fn strToScalarsC(str: RocStr) callconv(.C) RocList { } fn strToScalars(string: RocStr) callconv(.C) RocList { - const str_len = string.len(); + const len = string.len(); - if (str_len == 0) { + if (len == 0) { return RocList.empty(); } - var capacity = str_len; + var capacity = len; if (!string.isSmallStr()) { capacity = string.getCapacity(); @@ -576,7 +581,7 @@ fn strToScalars(string: RocStr) callconv(.C) RocList { var src_index: usize = 0; var answer_index: usize = 0; - while (src_index < str_len) { + while (src_index < len) { src_index += writeNextScalar(string, src_index, answer_elems, answer_index); answer_index += 1; } @@ -846,13 +851,13 @@ fn initFromSmallStr(slice_bytes: [*]u8, len: usize, _: usize) RocStr { return RocStr.init(slice_bytes, len); } -// The ref_ptr must already be shifted to be ready for storing in a seamless slice. -fn initFromBigStr(slice_bytes: [*]u8, len: usize, ref_ptr: usize) RocStr { +// The alloc_ptr must already be shifted to be ready for storing in a seamless slice. +fn initFromBigStr(slice_bytes: [*]u8, len: usize, alloc_ptr: usize) RocStr { // Here we can make seamless slices instead of copying to a new small str. return RocStr{ - .str_bytes = slice_bytes, - .str_len = len | SEAMLESS_SLICE_BIT, - .str_capacity = ref_ptr, + .bytes = slice_bytes, + .length = len | SEAMLESS_SLICE_BIT, + .capacity_or_alloc_ptr = alloc_ptr, }; } @@ -861,9 +866,9 @@ fn strSplitHelp(array: [*]RocStr, string: RocStr, delimiter: RocStr) void { var slice_start_index: usize = 0; var str_index: usize = 0; - const str_bytes = string.asU8ptr(); - const str_len = string.len(); - const ref_ptr = @intFromPtr(string.getRefcountPtr()) >> 1; + const bytes = string.asU8ptr(); + const len = string.len(); + const alloc_ptr = @intFromPtr(string.getAllocationPtr()) >> 1; const init_fn = if (string.isSmallStr()) &initFromSmallStr else @@ -872,8 +877,8 @@ fn strSplitHelp(array: [*]RocStr, string: RocStr, delimiter: RocStr) void { const delimiter_bytes_ptrs = delimiter.asU8ptr(); const delimiter_len = delimiter.len(); - if (str_len >= delimiter_len and delimiter_len > 0) { - const end_index: usize = str_len - delimiter_len + 1; + if (len >= delimiter_len and delimiter_len > 0) { + const end_index: usize = len - delimiter_len + 1; while (str_index <= end_index) { var delimiter_index: usize = 0; var matches_delimiter = true; @@ -881,12 +886,12 @@ fn strSplitHelp(array: [*]RocStr, string: RocStr, delimiter: RocStr) void { while (delimiter_index < delimiter_len) { var delimiterChar = delimiter_bytes_ptrs[delimiter_index]; - if (str_index + delimiter_index >= str_len) { + if (str_index + delimiter_index >= len) { matches_delimiter = false; break; } - var strChar = str_bytes[str_index + delimiter_index]; + var strChar = bytes[str_index + delimiter_index]; if (delimiterChar != strChar) { matches_delimiter = false; @@ -899,7 +904,7 @@ fn strSplitHelp(array: [*]RocStr, string: RocStr, delimiter: RocStr) void { if (matches_delimiter) { const segment_len: usize = str_index - slice_start_index; - array[ret_array_index] = init_fn(@constCast(str_bytes) + slice_start_index, segment_len, ref_ptr); + array[ret_array_index] = init_fn(@constCast(bytes) + slice_start_index, segment_len, alloc_ptr); slice_start_index = str_index + delimiter_len; ret_array_index += 1; str_index += delimiter_len; @@ -909,7 +914,7 @@ fn strSplitHelp(array: [*]RocStr, string: RocStr, delimiter: RocStr) void { } } - array[ret_array_index] = init_fn(@constCast(str_bytes) + slice_start_index, str_len - slice_start_index, ref_ptr); + array[ret_array_index] = init_fn(@constCast(bytes) + slice_start_index, len - slice_start_index, alloc_ptr); if (!string.isSmallStr()) { // Correct refcount for all of the splits made. @@ -1240,17 +1245,17 @@ test "strSplitHelp: overlapping delimiter 2" { // needs to be broken into, so that we can allocate a array // of that size. It always returns at least 1. pub fn countSegments(string: RocStr, delimiter: RocStr) callconv(.C) usize { - const str_bytes = string.asU8ptr(); - const str_len = string.len(); + const bytes = string.asU8ptr(); + const len = string.len(); const delimiter_bytes_ptrs = delimiter.asU8ptr(); const delimiter_len = delimiter.len(); var count: usize = 1; - if (str_len >= delimiter_len and delimiter_len > 0) { + if (len >= delimiter_len and delimiter_len > 0) { var str_index: usize = 0; - const end_cond: usize = str_len - delimiter_len + 1; + const end_cond: usize = len - delimiter_len + 1; while (str_index < end_cond) { var delimiter_index: usize = 0; @@ -1259,7 +1264,7 @@ pub fn countSegments(string: RocStr, delimiter: RocStr) callconv(.C) usize { while (delimiter_index < delimiter_len) { const delimiterChar = delimiter_bytes_ptrs[delimiter_index]; - const strChar = str_bytes[str_index + delimiter_index]; + const strChar = bytes[str_index + delimiter_index]; if (delimiterChar != strChar) { matches_delimiter = false; @@ -1409,7 +1414,7 @@ pub fn strGraphemes(roc_str: RocStr) callconv(.C) RocList { var index: usize = 0; var last_codepoint_len: u8 = 0; - const ref_ptr = @intFromPtr(roc_str.getRefcountPtr()) >> 1; + const alloc_ptr = @intFromPtr(roc_str.getAllocationPtr()) >> 1; const init_fn = if (roc_str.isSmallStr()) &initFromSmallStr else @@ -1425,7 +1430,7 @@ pub fn strGraphemes(roc_str: RocStr) callconv(.C) RocList { if (opt_last_codepoint) |last_codepoint| { var did_break = grapheme.isGraphemeBreak(last_codepoint, cur_codepoint, &break_state); if (did_break) { - graphemes[index] = init_fn(@constCast(slice.ptr), last_codepoint_len, ref_ptr); + graphemes[index] = init_fn(@constCast(slice.ptr), last_codepoint_len, alloc_ptr); slice = slice[last_codepoint_len..]; index += 1; break_state = null; @@ -1436,7 +1441,7 @@ pub fn strGraphemes(roc_str: RocStr) callconv(.C) RocList { opt_last_codepoint = cur_codepoint; } // Append last grapheme - graphemes[index] = init_fn(@constCast(slice.ptr), slice.len, ref_ptr); + graphemes[index] = init_fn(@constCast(slice.ptr), slice.len, alloc_ptr); if (!roc_str.isSmallStr()) { // Correct refcount for all of the splits made. @@ -1498,8 +1503,35 @@ pub fn getCapacity(string: RocStr) callconv(.C) usize { } pub fn substringUnsafe(string: RocStr, start: usize, length: usize) callconv(.C) RocStr { - const slice = string.asSlice()[start .. start + length]; - return RocStr.fromSlice(slice); + if (string.isSmallStr()) { + if (start == 0) { + var output = string; + output.setLen(length); + return output; + } + const slice = string.asSlice()[start .. start + length]; + return RocStr.fromSlice(slice); + } + if (string.bytes) |source_ptr| { + if (start == 0 and string.isUnique()) { + var output = string; + output.setLen(length); + return output; + } else { + // Shifting right by 1 is required to avoid the highest bit of capacity being set. + // If it was set, the slice would get interpreted as a small string. + const str_alloc_ptr = (@intFromPtr(source_ptr) >> 1); + const slice_alloc_ptr = string.capacity_or_alloc_ptr; + const slice_mask = string.seamlessSliceMask(); + const alloc_ptr = (str_alloc_ptr & ~slice_mask) | (slice_alloc_ptr & slice_mask); + return RocStr{ + .bytes = source_ptr + start, + .length = length | SEAMLESS_SLICE_BIT, + .capacity_or_alloc_ptr = alloc_ptr, + }; + } + } + return RocStr.empty(); } pub fn getUnsafe(string: RocStr, index: usize) callconv(.C) u8 { @@ -1584,9 +1616,9 @@ pub fn repeat(string: RocStr, count: usize) callconv(.C) RocStr { // Str.startsWithScalar pub fn startsWithScalar(string: RocStr, prefix: u32) callconv(.C) bool { - const str_len = string.len(); + const len = string.len(); - if (str_len == 0) { + if (len == 0) { return false; } @@ -1750,7 +1782,7 @@ test "RocStr.concat: small concat small" { pub const RocListStr = extern struct { list_elements: ?[*]RocStr, list_length: usize, - list_capacity_or_ref_ptr: usize, + list_capacity_or_alloc_ptr: usize, }; // Str.joinWith @@ -1758,7 +1790,7 @@ pub fn strJoinWithC(list: RocList, separator: RocStr) callconv(.C) RocStr { const roc_list_str = RocListStr{ .list_elements = @as(?[*]RocStr, @ptrCast(@alignCast(list.bytes))), .list_length = list.length, - .list_capacity_or_ref_ptr = list.capacity_or_ref_ptr, + .list_capacity_or_alloc_ptr = list.capacity_or_alloc_ptr, }; return @call(.always_inline, strJoinWith, .{ roc_list_str, separator }); @@ -1820,7 +1852,7 @@ test "RocStr.joinWith: result is big" { var elements: [3]RocStr = .{ roc_elem, roc_elem, roc_elem }; const list = RocListStr{ .list_length = 3, - .list_capacity_or_ref_ptr = 3, + .list_capacity_or_alloc_ptr = 3, .list_elements = @as([*]RocStr, @ptrCast(&elements)), }; @@ -1851,10 +1883,10 @@ inline fn strToBytes(arg: RocStr) RocList { @memcpy(ptr[0..length], arg.asU8ptr()[0..length]); - return RocList{ .length = length, .bytes = ptr, .capacity_or_ref_ptr = length }; + return RocList{ .length = length, .bytes = ptr, .capacity_or_alloc_ptr = length }; } else { - const is_seamless_slice = arg.str_len & SEAMLESS_SLICE_BIT; - return RocList{ .length = length, .bytes = arg.str_bytes, .capacity_or_ref_ptr = arg.str_capacity | is_seamless_slice }; + const is_seamless_slice = arg.length & SEAMLESS_SLICE_BIT; + return RocList{ .length = length, .bytes = arg.bytes, .capacity_or_alloc_ptr = arg.capacity_or_alloc_ptr | is_seamless_slice }; } } @@ -2015,7 +2047,7 @@ pub const Utf8ByteProblem = enum(u8) { }; fn validateUtf8Bytes(bytes: [*]u8, length: usize) FromUtf8Result { - return fromUtf8Range(RocList{ .bytes = bytes, .length = length, .capacity_or_ref_ptr = length }, 0, length, .Immutable); + return fromUtf8Range(RocList{ .bytes = bytes, .length = length, .capacity_or_alloc_ptr = length }, 0, length, .Immutable); } fn validateUtf8BytesX(str: RocList) FromUtf8Result { @@ -2096,10 +2128,10 @@ test "validateUtf8Bytes: unicode ∆ in middle of array" { fn expectErr(list: RocList, index: usize, err: Utf8DecodeError, problem: Utf8ByteProblem) !void { const str_ptr = @as([*]u8, @ptrCast(list.bytes)); - const str_len = list.length; + const len = list.length; - try expectError(err, numberOfNextCodepointBytes(str_ptr, str_len, index)); - try expectEqual(toErrUtf8ByteResponse(index, problem), validateUtf8Bytes(str_ptr, str_len)); + try expectError(err, numberOfNextCodepointBytes(str_ptr, len, index)); + try expectEqual(toErrUtf8ByteResponse(index, problem), validateUtf8Bytes(str_ptr, len)); } test "validateUtf8Bytes: invalid start byte" { @@ -2247,22 +2279,22 @@ pub fn strTrim(input_string: RocStr) callconv(.C) RocStr { // Big and unique with no leading bytes to remove. // Just take ownership and shrink the length. var new_string = string; - new_string.str_len = new_len; + new_string.length = new_len; return new_string; } else if (string.isSeamlessSlice()) { // Already a seamless slice, just update the range. return RocStr{ - .str_bytes = bytes_ptr + leading_bytes, - .str_len = new_len | SEAMLESS_SLICE_BIT, - .str_capacity = string.str_capacity, + .bytes = bytes_ptr + leading_bytes, + .length = new_len | SEAMLESS_SLICE_BIT, + .capacity_or_alloc_ptr = string.capacity_or_alloc_ptr, }; } else { // Not unique or removing leading bytes, just make a slice. return RocStr{ - .str_bytes = bytes_ptr + leading_bytes, - .str_len = new_len | SEAMLESS_SLICE_BIT, - .str_capacity = @intFromPtr(bytes_ptr) >> 1, + .bytes = bytes_ptr + leading_bytes, + .length = new_len | SEAMLESS_SLICE_BIT, + .capacity_or_alloc_ptr = @intFromPtr(bytes_ptr) >> 1, }; } } @@ -2295,22 +2327,22 @@ pub fn strTrimStart(input_string: RocStr) callconv(.C) RocStr { // Big and unique with no leading bytes to remove. // Just take ownership and shrink the length. var new_string = string; - new_string.str_len = new_len; + new_string.length = new_len; return new_string; } else if (string.isSeamlessSlice()) { // Already a seamless slice, just update the range. return RocStr{ - .str_bytes = bytes_ptr + leading_bytes, - .str_len = new_len | SEAMLESS_SLICE_BIT, - .str_capacity = string.str_capacity, + .bytes = bytes_ptr + leading_bytes, + .length = new_len | SEAMLESS_SLICE_BIT, + .capacity_or_alloc_ptr = string.capacity_or_alloc_ptr, }; } else { // Not unique or removing leading bytes, just make a slice. return RocStr{ - .str_bytes = bytes_ptr + leading_bytes, - .str_len = new_len | SEAMLESS_SLICE_BIT, - .str_capacity = @intFromPtr(bytes_ptr) >> 1, + .bytes = bytes_ptr + leading_bytes, + .length = new_len | SEAMLESS_SLICE_BIT, + .capacity_or_alloc_ptr = @intFromPtr(bytes_ptr) >> 1, }; } } @@ -2343,22 +2375,22 @@ pub fn strTrimEnd(input_string: RocStr) callconv(.C) RocStr { // Big and unique with no leading bytes to remove. // Just take ownership and shrink the length. var new_string = string; - new_string.str_len = new_len; + new_string.length = new_len; return new_string; } else if (string.isSeamlessSlice()) { // Already a seamless slice, just update the range. return RocStr{ - .str_bytes = bytes_ptr, - .str_len = new_len | SEAMLESS_SLICE_BIT, - .str_capacity = string.str_capacity, + .bytes = bytes_ptr, + .length = new_len | SEAMLESS_SLICE_BIT, + .capacity_or_alloc_ptr = string.capacity_or_alloc_ptr, }; } else { // Not unique, just make a slice. return RocStr{ - .str_bytes = bytes_ptr, - .str_len = new_len | SEAMLESS_SLICE_BIT, - .str_capacity = @intFromPtr(bytes_ptr) >> 1, + .bytes = bytes_ptr, + .length = new_len | SEAMLESS_SLICE_BIT, + .capacity_or_alloc_ptr = @intFromPtr(bytes_ptr) >> 1, }; } } @@ -2858,7 +2890,7 @@ pub fn strCloneTo( const slice = string.asSlice(); var relative = string; - relative.str_bytes = @as(?[*]u8, @ptrFromInt(extra_offset)); // i.e. just after the string struct + relative.bytes = @as(?[*]u8, @ptrFromInt(extra_offset)); // i.e. just after the string struct // write the string struct const array = relative.asArray(); @@ -2871,17 +2903,17 @@ pub fn strCloneTo( } } -pub fn strRefcountPtr( +pub fn strAllocationPtr( string: RocStr, ) callconv(.C) ?[*]u8 { - return string.getRefcountPtr(); + return string.getAllocationPtr(); } pub fn strReleaseExcessCapacity( string: RocStr, ) callconv(.C) RocStr { const old_length = string.len(); - // We use the direct list.capacity_or_ref_ptr to make sure both that there is no extra capacity and that it isn't a seamless slice. + // We use the direct list.capacity_or_alloc_ptr to make sure both that there is no extra capacity and that it isn't a seamless slice. if (string.isSmallStr()) { // SmallStr has no excess capacity. return string; diff --git a/crates/compiler/builtins/bitcode/src/utils.zig b/crates/compiler/builtins/bitcode/src/utils.zig index 6a77a13d4d..2dd3f1fd2a 100644 --- a/crates/compiler/builtins/bitcode/src/utils.zig +++ b/crates/compiler/builtins/bitcode/src/utils.zig @@ -20,11 +20,11 @@ extern fn roc_realloc(c_ptr: *anyopaque, new_size: usize, old_size: usize, align // This should never be passed a null pointer. extern fn roc_dealloc(c_ptr: *anyopaque, alignment: u32) callconv(.C) void; -extern fn roc_dbg(file_path: *anyopaque, message: *anyopaque) callconv(.C) void; +extern fn roc_dbg(loc: *anyopaque, message: *anyopaque, src: *anyopaque) callconv(.C) void; // Since roc_dbg is never used by the builtins, we need at export a function that uses it to stop DCE. -pub fn test_dbg(file_path: *anyopaque, message: *anyopaque) callconv(.C) void { - roc_dbg(file_path, message); +pub fn test_dbg(loc: *anyopaque, src: *anyopaque, message: *anyopaque) callconv(.C) void { + roc_dbg(loc, message, src); } extern fn kill(pid: c_int, sig: c_int) c_int; @@ -47,9 +47,10 @@ fn testing_roc_mmap(addr: ?*anyopaque, length: c_uint, prot: c_int, flags: c_int return mmap(addr, length, prot, flags, fd, offset); } -fn testing_roc_dbg(file_path: *anyopaque, message: *anyopaque) callconv(.C) void { +fn testing_roc_dbg(loc: *anyopaque, message: *anyopaque, src: *anyopaque) callconv(.C) void { _ = message; - _ = file_path; + _ = src; + _ = loc; } comptime { diff --git a/crates/compiler/builtins/roc/Decode.roc b/crates/compiler/builtins/roc/Decode.roc index af2800eff3..e8ca1f89b9 100644 --- a/crates/compiler/builtins/roc/Decode.roc +++ b/crates/compiler/builtins/roc/Decode.roc @@ -57,7 +57,7 @@ DecodeError : [TooShort] ## Return type of a [Decoder]. ## -## This is can be useful when creating a [custom](#custom) decoder or when +## This can be useful when creating a [custom](#custom) decoder or when ## using [fromBytesPartial](#fromBytesPartial). For example writing unit tests, ## such as; ## ``` diff --git a/crates/compiler/builtins/roc/Dict.roc b/crates/compiler/builtins/roc/Dict.roc index 172c0e501e..7b27df659b 100644 --- a/crates/compiler/builtins/roc/Dict.roc +++ b/crates/compiler/builtins/roc/Dict.roc @@ -6,6 +6,8 @@ interface Dict single, clear, capacity, + reserve, + releaseExcessCapacity, len, isEmpty, get, @@ -15,6 +17,8 @@ interface Dict update, walk, walkUntil, + keepIf, + dropIf, toList, fromList, keys, @@ -30,7 +34,7 @@ interface Dict Result.{ Result }, List, Str, - Num.{ Nat, U64, U8, I8 }, + Num.{ Nat, U64, F32, U32, U8, I8 }, Hash.{ Hasher, Hash }, Inspect.{ Inspect, Inspector, InspectFormatter }, ] @@ -87,20 +91,15 @@ interface Dict ## [constant time complexity](https://en.wikipedia.org/wiki/Time_complexity#Constant_time). ## ## Dict is inspired by [IndexMap](https://docs.rs/indexmap/latest/indexmap/map/struct.IndexMap.html). -## The internal implementation of a dictionary is similar to [absl::flat_hash_map](https://abseil.io/docs/cpp/guides/container). +## The internal implementation of a dictionary is almost identical to [ankerl::unordered_dense](https://github.com/martinus/unordered_dense). ## It has a list of keys value pairs that is ordered based on insertion. ## It uses a list of indices into the data as the backing of a hash map. Dict k v := { - # TODO: Add hashflooding ordered map fall back. - # TODO: Add Groups and SIMD h1 key comparison (initial tests where slower, but with proper SIMD should be fast). - # TODO: As an optimization, we can make all of these lists in one allocation - # TODO: Grow data with the rest of the hashmap. This will require creating a list of garbage data. - # TODO: Change remove to use tombstones. Store the tombstones in a bitmap. - # TODO: define Eq and Hash that are unordered. Only if value implements hash/eq? - metadata : List I8, - dataIndices : List Nat, + buckets : List Bucket, data : List (k, v), - size : Nat, + maxBucketCapacity : U64, + maxLoadFactor : F32, + shifts : U8, } where k implements Hash & Eq implements [ Eq { @@ -114,7 +113,7 @@ Dict k v := { }, ] -isEq : Dict k v, Dict k v -> Bool where k implements Hash & Eq, v implements Eq +isEq : Dict k v, Dict k v -> Bool where v implements Eq isEq = \xs, ys -> if len xs != len ys then Bool.false @@ -127,7 +126,7 @@ isEq = \xs, ys -> _ -> Break Bool.false -hashDict : hasher, Dict k v -> hasher where k implements Hash & Eq, v implements Hash, hasher implements Hasher +hashDict : hasher, Dict k v -> hasher where v implements Hash, hasher implements Hasher hashDict = \hasher, dict -> Hash.hashUnordered hasher (toList dict) List.walk toInspectorDict : Dict k v -> Inspector f where k implements Inspect & Hash & Eq, v implements Inspect, f implements InspectFormatter @@ -142,12 +141,65 @@ toInspectorDict = \dict -> empty : {} -> Dict * * empty = \{} -> @Dict { - metadata: List.repeat emptySlot 8, - dataIndices: List.repeat 0 8, + buckets: [], data: [], - size: 0, + maxBucketCapacity: 0, + maxLoadFactor: defaultMaxLoadFactor, + shifts: initialShifts, } +## Return a dictionary with space allocated for a number of entries. This +## may provide a performance optimization if you know how many entries will be +## inserted. +withCapacity : Nat -> Dict * * +withCapacity = \requested -> + empty {} + |> reserve requested + +## Enlarge the dictionary for at least capacity additional elements +reserve : Dict k v, Nat -> Dict k v +reserve = \@Dict { buckets, data, maxBucketCapacity: originalMaxBucketCapacity, maxLoadFactor, shifts }, requested -> + currentSize = List.len data + requestedSize = currentSize + requested + size = Num.min (Num.toU64 requestedSize) maxSize + + requestedShifts = calcShiftsForSize size maxLoadFactor + if (List.isEmpty buckets) || requestedShifts > shifts then + (buckets0, maxBucketCapacity) = allocBucketsFromShift requestedShifts maxLoadFactor + buckets1 = fillBucketsFromData buckets0 data requestedShifts + sizeNat = Num.toNat size + @Dict { + buckets: buckets1, + data: List.reserve data (Num.subSaturated sizeNat currentSize), + maxBucketCapacity, + maxLoadFactor, + shifts: requestedShifts, + } + else + @Dict { buckets, data, maxBucketCapacity: originalMaxBucketCapacity, maxLoadFactor, shifts } + +## Shrink the memory footprint of a dictionary such that capacity is as small as possible. +## This function will require regenerating the metadata if the size changes. +## There will still be some overhead due to dictionary metadata always being a power of 2. +releaseExcessCapacity : Dict k v -> Dict k v +releaseExcessCapacity = \@Dict { buckets, data, maxBucketCapacity: originalMaxBucketCapacity, maxLoadFactor, shifts } -> + size = List.len data + + # NOTE: If we want, we technically could increase the load factor here to potentially minimize size more. + minShifts = calcShiftsForSize (Num.toU64 size) maxLoadFactor + if minShifts < shifts then + (buckets0, maxBucketCapacity) = allocBucketsFromShift minShifts maxLoadFactor + buckets1 = fillBucketsFromData buckets0 data minShifts + @Dict { + buckets: buckets1, + data: List.releaseExcessCapacity data, + maxBucketCapacity, + maxLoadFactor, + shifts: minShifts, + } + else + @Dict { buckets, data, maxBucketCapacity: originalMaxBucketCapacity, maxLoadFactor, shifts } + ## Returns the max number of elements the dictionary can hold before requiring a rehash. ## ``` ## foodDict = @@ -157,18 +209,8 @@ empty = \{} -> ## capacityOfDict = Dict.capacity foodDict ## ``` capacity : Dict * * -> Nat -capacity = \@Dict { dataIndices } -> - cap = List.len dataIndices - - Num.subWrap cap (Num.shiftRightZfBy cap 3) - -## Return a dictionary with space allocated for a number of entries. This -## may provide a performance optimization if you know how many entries will be -## inserted. -withCapacity : Nat -> Dict * * -withCapacity = \_ -> - # TODO: power of 2 * 8 and actual implementation - empty {} +capacity = \@Dict { maxBucketCapacity } -> + Num.toNat maxBucketCapacity ## Returns a dictionary containing the key and value provided as input. ## ``` @@ -176,7 +218,7 @@ withCapacity = \_ -> ## Dict.single "A" "B" ## |> Bool.isEq (Dict.insert (Dict.empty {}) "A" "B") ## ``` -single : k, v -> Dict k v where k implements Hash & Eq +single : k, v -> Dict k v single = \k, v -> insert (empty {}) k v @@ -189,9 +231,14 @@ single = \k, v -> ## |> Dict.insert 4 "Four" ## |> Bool.isEq (Dict.fromList [(1, "One"), (2, "Two"), (3, "Three"), (4, "Four")]) ## ``` -fromList : List (k, v) -> Dict k v where k implements Hash & Eq +## +## ## Performance Details +## +## This will build up from an empty dictionary to minimize totally memory use. +## If the list has few duplicate keys, it would be faster to allocate a dictionary +## with the same capacity of the list and walk it calling [Dict.insert] +fromList : List (k, v) -> Dict k v fromList = \data -> - # TODO: make this efficient. Should just set data and then set all indicies in the hashmap. List.walk data (empty {}) (\dict, (k, v) -> insert dict k v) ## Returns the number of values in the dictionary. @@ -205,18 +252,18 @@ fromList = \data -> ## |> Bool.isEq 3 ## ``` len : Dict * * -> Nat -len = \@Dict { size } -> - size +len = \@Dict { data } -> + List.len data -## Check if the dictinoary is empty. +## Check if the dictionary is empty. ## ``` ## Dict.isEmpty (Dict.empty {} |> Dict.insert "key" 42) ## ## Dict.isEmpty (Dict.empty {}) ## ``` isEmpty : Dict * * -> Bool -isEmpty = \@Dict { size } -> - size == 0 +isEmpty = \@Dict { data } -> + List.isEmpty data ## Clears all elements from a dictionary keeping around the allocation if it isn't huge. ## ``` @@ -230,27 +277,21 @@ isEmpty = \@Dict { size } -> ## ## expect Dict.len clearSongs == 0 ## ``` -clear : Dict k v -> Dict k v where k implements Hash & Eq -clear = \@Dict { metadata, dataIndices, data } -> - cap = List.len dataIndices - - # Only clear large allocations. - if cap > 128 * 8 then - empty {} - else - @Dict { - metadata: List.map metadata (\_ -> emptySlot), - # just leave data indicies as garbage, no need to clear. - dataIndices, - # use takeFirst to keep around the capacity. - data: List.takeFirst data 0, - size: 0, - } +clear : Dict k v -> Dict k v +clear = \@Dict { buckets, data, maxBucketCapacity, maxLoadFactor, shifts } -> + @Dict { + buckets: List.map buckets \_ -> emptyBucket, + # use takeFirst to keep around the capacity + data: List.takeFirst data 0, + maxBucketCapacity, + maxLoadFactor, + shifts, + } ## Convert each value in the dictionary to something new, by calling a conversion ## function on each of them which receives both the key and the old value. Then return a ## new dictionary containing the same keys and the converted values. -map : Dict k a, (k, a -> b) -> Dict k b where k implements Hash & Eq, b implements Hash & Eq +map : Dict k a, (k, a -> b) -> Dict k b map = \dict, transform -> init = withCapacity (capacity dict) @@ -262,7 +303,7 @@ map = \dict, transform -> ## (using [Dict.insertAll]) into one dictionary. ## ## You may know a similar function named `concatMap` in other languages. -joinMap : Dict a b, (a, b -> Dict x y) -> Dict x y where a implements Hash & Eq, x implements Hash & Eq +joinMap : Dict a b, (a, b -> Dict x y) -> Dict x y joinMap = \dict, transform -> init = withCapacity (capacity dict) # Might be a pessimization @@ -280,7 +321,7 @@ joinMap = \dict, transform -> ## |> Dict.walk 0 (\count, _, qty -> count + qty) ## |> Bool.isEq 36 ## ``` -walk : Dict k v, state, (state, k, v -> state) -> state where k implements Hash & Eq +walk : Dict k v, state, (state, k, v -> state) -> state walk = \@Dict { data }, initialState, transform -> List.walk data initialState (\state, (k, v) -> transform state k v) @@ -312,10 +353,51 @@ walk = \@Dict { data }, initialState, transform -> ## ## expect someoneIsAnAdult == Bool.true ## ``` -walkUntil : Dict k v, state, (state, k, v -> [Continue state, Break state]) -> state where k implements Hash & Eq +walkUntil : Dict k v, state, (state, k, v -> [Continue state, Break state]) -> state walkUntil = \@Dict { data }, initialState, transform -> List.walkUntil data initialState (\state, (k, v) -> transform state k v) +## Run the given function on each key-value pair of a dictionary, and return +## a dictionary with just the pairs for which the function returned `Bool.true`. +## ``` +## expect Dict.empty {} +## |> Dict.insert "Alice" 17 +## |> Dict.insert "Bob" 18 +## |> Dict.insert "Charlie" 19 +## |> Dict.keepIf \(_k, v) -> v >= 18 +## |> Dict.len +## |> Bool.isEq 2 +## ``` +keepIf : Dict k v, ((k, v) -> Bool) -> Dict k v +keepIf = \dict, predicate -> + keepIfHelp dict predicate 0 (Dict.len dict) + +keepIfHelp : Dict k v, ((k, v) -> Bool), Nat, Nat -> Dict k v +keepIfHelp = \@Dict dict, predicate, index, length -> + if index < length then + (key, value) = listGetUnsafe dict.data index + if predicate (key, value) then + keepIfHelp (@Dict dict) predicate (index + 1) length + else + keepIfHelp (Dict.remove (@Dict dict) key) predicate index (length - 1) + else + @Dict dict + +## Run the given function on each key-value pair of a dictionary, and return +## a dictionary with just the pairs for which the function returned `Bool.false`. +## ``` +## expect Dict.empty {} +## |> Dict.insert "Alice" 17 +## |> Dict.insert "Bob" 18 +## |> Dict.insert "Charlie" 19 +## |> Dict.dropIf \(_k, v) -> v >= 18 +## |> Dict.len +## |> Bool.isEq 1 +## ``` +dropIf : Dict k v, ((k, v) -> Bool) -> Dict k v +dropIf = \dict, predicate -> + Dict.keepIf dict (\e -> Bool.not (predicate e)) + ## 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]. ## ``` @@ -327,25 +409,10 @@ walkUntil = \@Dict { data }, initialState, transform -> ## expect Dict.get dictionary 1 == Ok "Apple" ## expect Dict.get dictionary 2000 == Err KeyNotFound ## ``` -get : Dict k v, k -> Result v [KeyNotFound] where k implements Hash & Eq -get = \@Dict { metadata, dataIndices, data }, key -> - hashKey = - createLowLevelHasher PseudoRandSeed - |> Hash.hash key - |> complete - h1Key = h1 hashKey - h2Key = h2 hashKey - probe = newProbe h1Key (div8 (List.len metadata)) - - when findIndexHelper metadata dataIndices data h2Key key probe 0 is - Ok index -> - dataIndex = listGetUnsafe dataIndices index - (_, v) = listGetUnsafe data dataIndex - - Ok v - - Err NotFound -> - Err KeyNotFound +get : Dict k v, k -> Result v [KeyNotFound] +get = \dict, key -> + find dict key + |> .result ## Check if the dictionary has a value for a specified key. ## ``` @@ -355,22 +422,11 @@ get = \@Dict { metadata, dataIndices, data }, key -> ## |> Dict.contains 1234 ## |> Bool.isEq Bool.true ## ``` -contains : Dict k v, k -> Bool where k implements Hash & Eq -contains = \@Dict { metadata, dataIndices, data }, key -> - hashKey = - createLowLevelHasher PseudoRandSeed - |> Hash.hash key - |> complete - h1Key = h1 hashKey - h2Key = h2 hashKey - probe = newProbe h1Key (div8 (List.len metadata)) - - when findIndexHelper metadata dataIndices data h2Key key probe 0 is - Ok _ -> - Bool.true - - Err NotFound -> - Bool.false +contains : Dict k v, k -> Bool +contains = \dict, key -> + find dict key + |> .result + |> Result.isOk ## Insert a value into the dictionary at a specified key. ## ``` @@ -380,42 +436,41 @@ contains = \@Dict { metadata, dataIndices, data }, key -> ## |> Dict.get "Apples" ## |> Bool.isEq (Ok 12) ## ``` -insert : Dict k v, k, v -> Dict k v where k implements Hash & Eq -insert = \@Dict { metadata, dataIndices, data, size }, key, value -> - hashKey = - createLowLevelHasher PseudoRandSeed - |> Hash.hash key - |> complete - h1Key = h1 hashKey - h2Key = h2 hashKey - probe = newProbe h1Key (div8 (List.len metadata)) +insert : Dict k v, k, v -> Dict k v +insert = \dict, key, value -> + (@Dict { buckets, data, maxBucketCapacity, maxLoadFactor, shifts }) = + if len dict < capacity dict then + dict + else + increaseSize dict - when findIndexHelper metadata dataIndices data h2Key key probe 0 is - Ok index -> - dataIndex = listGetUnsafe dataIndices index + hash = hashKey key + distAndFingerprint = distAndFingerprintFromHash hash + bucketIndex = bucketIndexFromHash hash shifts - @Dict { - metadata, - dataIndices, - data: List.set data dataIndex (key, value), - size, - } + insertHelper buckets data bucketIndex distAndFingerprint key value maxBucketCapacity maxLoadFactor shifts - Err NotFound -> - # The dictionary has grown, it might need to rehash. - rehashedDict = - maybeRehash - ( - @Dict { - metadata, - dataIndices, - data, - size: Num.addWrap size 1, - } - ) - - # Need to rescan searching for the first empty or deleted cell. - insertNotFoundHelper rehashedDict key value h1Key h2Key +insertHelper : List Bucket, List (k, v), Nat, U32, k, v, U64, F32, U8 -> Dict k v +insertHelper = \buckets0, data0, bucketIndex0, distAndFingerprint0, key, value, maxBucketCapacity, maxLoadFactor, shifts -> + loaded = listGetUnsafe buckets0 (Num.toNat bucketIndex0) + if distAndFingerprint0 == loaded.distAndFingerprint then + (foundKey, _) = listGetUnsafe data0 (Num.toNat loaded.dataIndex) + if foundKey == key then + data1 = List.set data0 (Num.toNat loaded.dataIndex) (key, value) + @Dict { buckets: buckets0, data: data1, maxBucketCapacity, maxLoadFactor, shifts } + else + bucketIndex1 = nextBucketIndex bucketIndex0 (List.len buckets0) + distAndFingerprint1 = incrementDist distAndFingerprint0 + insertHelper buckets0 data0 bucketIndex1 distAndFingerprint1 key value maxBucketCapacity maxLoadFactor shifts + else if distAndFingerprint0 > loaded.distAndFingerprint then + data1 = List.append data0 (key, value) + dataIndex = (List.len data1) - 1 + buckets1 = placeAndShiftUp buckets0 { distAndFingerprint: distAndFingerprint0, dataIndex: Num.toU32 dataIndex } bucketIndex0 + @Dict { buckets: buckets1, data: data1, maxBucketCapacity, maxLoadFactor, shifts } + else + bucketIndex1 = nextBucketIndex bucketIndex0 (List.len buckets0) + distAndFingerprint1 = incrementDist distAndFingerprint0 + insertHelper buckets0 data0 bucketIndex1 distAndFingerprint1 key value maxBucketCapacity maxLoadFactor shifts ## Remove a value from the dictionary for a specified key. ## ``` @@ -426,34 +481,30 @@ insert = \@Dict { metadata, dataIndices, data, size }, key, value -> ## |> Dict.len ## |> Bool.isEq 0 ## ``` -remove : Dict k v, k -> Dict k v where k implements Hash & Eq -remove = \@Dict { metadata, dataIndices, data, size }, key -> - # TODO: change this from swap remove to tombstone and test is performance is still good. - hashKey = - createLowLevelHasher PseudoRandSeed - |> Hash.hash key - |> complete - h1Key = h1 hashKey - h2Key = h2 hashKey - probe = newProbe h1Key (div8 (List.len metadata)) +remove : Dict k v, k -> Dict k v +remove = \@Dict { buckets, data, maxBucketCapacity, maxLoadFactor, shifts }, key -> + if !(List.isEmpty data) then + (bucketIndex0, distAndFingerprint0) = nextWhileLess buckets key shifts + (bucketIndex1, distAndFingerprint1) = removeHelper buckets bucketIndex0 distAndFingerprint0 data key - when findIndexHelper metadata dataIndices data h2Key key probe 0 is - Ok index -> - last = Num.subWrap (List.len data) 1 - dataIndex = listGetUnsafe dataIndices index + bucket = listGetUnsafe buckets (Num.toNat bucketIndex1) + if distAndFingerprint1 != bucket.distAndFingerprint then + @Dict { buckets, data, maxBucketCapacity, maxLoadFactor, shifts } + else + removeBucket (@Dict { buckets, data, maxBucketCapacity, maxLoadFactor, shifts }) bucketIndex1 + else + @Dict { buckets, data, maxBucketCapacity, maxLoadFactor, shifts } - if dataIndex == last then - @Dict { - metadata: List.set metadata index deletedSlot, - dataIndices, - data: List.dropLast data 1, - size: Num.subWrap size 1, - } - else - swapAndUpdateDataIndex (@Dict { metadata, dataIndices, data, size }) index last - - Err NotFound -> - @Dict { metadata, dataIndices, data, size } +removeHelper = \buckets, bucketIndex, distAndFingerprint, data, key -> + bucket = listGetUnsafe buckets (Num.toNat bucketIndex) + if distAndFingerprint == bucket.distAndFingerprint then + (foundKey, _) = listGetUnsafe data (Num.toNat bucket.dataIndex) + if foundKey == key then + (bucketIndex, distAndFingerprint) + else + removeHelper buckets (nextBucketIndex bucketIndex (List.len buckets)) (incrementDist distAndFingerprint) data key + else + (bucketIndex, distAndFingerprint) ## Insert or remove a value for a specified key. This function enables a ## performance optimization for the use case of providing a default when a value @@ -470,17 +521,55 @@ remove = \@Dict { metadata, dataIndices, data, size }, key -> ## 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 where k implements Hash & Eq -update = \dict, key, alter -> - # TODO: look into optimizing by merging substeps and reducing lookups. - possibleValue = - get dict key - |> Result.map Present - |> Result.withDefault Missing +update : Dict k v, k, ([Present v, Missing] -> [Present v, Missing]) -> Dict k v +update = \@Dict { buckets, data, maxBucketCapacity, maxLoadFactor, shifts }, key, alter -> + { bucketIndex, result } = find (@Dict { buckets, data, maxBucketCapacity, maxLoadFactor, shifts }) key + when result is + Ok value -> + when alter (Present value) is + Present newValue -> + bucket = listGetUnsafe buckets bucketIndex + newData = List.set data (Num.toNat bucket.dataIndex) (key, newValue) + @Dict { buckets, data: newData, maxBucketCapacity, maxLoadFactor, shifts } - when alter possibleValue is - Present value -> insert dict key value - Missing -> remove dict key + Missing -> + removeBucket (@Dict { buckets, data, maxBucketCapacity, maxLoadFactor, shifts }) bucketIndex + + Err KeyNotFound -> + when alter Missing is + Present newValue -> + if List.len data >= (Num.toNat maxBucketCapacity) then + # Need to reallocate let regular insert handle that. + insert (@Dict { buckets, data, maxBucketCapacity, maxLoadFactor, shifts }) key newValue + else + # Can skip work by jumping staight to the found bucket. + # That will be the location we want to insert in. + hash = hashKey key + baseDistAndFingerprint = distAndFingerprintFromHash hash + baseBucketIndex = bucketIndexFromHash hash shifts + + # Due to the unrolling of loops in find along with loop optimizations, + # The bucketIndex is not guaranteed to be correct here. + # It is only correct if we have traversed past the number of find unrolls. + dist = circularDist baseBucketIndex bucketIndex (List.len buckets) + if dist <= findManualUnrolls then + insertHelper buckets data baseBucketIndex baseDistAndFingerprint key newValue maxBucketCapacity maxLoadFactor shifts + else + distAndFingerprint = incrementDistN baseDistAndFingerprint (Num.toU32 dist) + insertHelper buckets data bucketIndex distAndFingerprint key newValue maxBucketCapacity maxLoadFactor shifts + + Missing -> + @Dict { buckets, data, maxBucketCapacity, maxLoadFactor, shifts } + +circularDist = \start, end, size -> + correction = + if start > end then + size + else + 0 + end + |> Num.subWrap start + |> Num.addWrap correction ## 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. @@ -493,7 +582,7 @@ update = \dict, key, alter -> ## |> Dict.toList ## |> Bool.isEq [(1, "One"), (2, "Two"), (3, "Three"), (4, "Four")] ## ``` -toList : Dict k v -> List (k, v) where k implements Hash & Eq +toList : Dict k v -> List (k, v) toList = \@Dict { data } -> data @@ -508,7 +597,7 @@ toList = \@Dict { data } -> ## |> Dict.keys ## |> Bool.isEq [1,2,3,4] ## ``` -keys : Dict k v -> List k where k implements Hash & Eq +keys : Dict k v -> List k keys = \@Dict { data } -> List.map data (\(k, _) -> k) @@ -523,7 +612,7 @@ keys = \@Dict { data } -> ## |> Dict.values ## |> Bool.isEq ["One","Two","Three","Four"] ## ``` -values : Dict k v -> List v where k implements Hash & Eq +values : Dict k v -> List v values = \@Dict { data } -> List.map data (\(_, v) -> v) @@ -551,38 +640,51 @@ values = \@Dict { data } -> ## expect ## Dict.insertAll first second == expected ## ``` -insertAll : Dict k v, Dict k v -> Dict k v where k implements Hash & Eq +insertAll : Dict k v, Dict k v -> Dict k v insertAll = \xs, ys -> - walk ys xs insert + if len ys > len xs then + insertAll ys xs + else + walk ys xs insert ## Combine two dictionaries by keeping the [intersection](https://en.wikipedia.org/wiki/Intersection_(set_theory)) ## of all the key-value pairs. This means that we keep only those pairs -## 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. +## that are in both dictionaries. Both the key and value must match to be kept. ## ``` ## first = ## Dict.single 1 "Keep Me" ## |> Dict.insert 2 "And Me" +## |> Dict.insert 3 "Not this one" ## ## second = ## Dict.single 1 "Keep Me" ## |> Dict.insert 2 "And Me" -## |> Dict.insert 3 "But Not Me" +## |> Dict.insert 3 "This has a different value" ## |> Dict.insert 4 "Or Me" ## -## expect Dict.keepShared first second == first +## expected = +## Dict.single 1 "Keep Me" +## |> Dict.insert 2 "And Me" +## +## expect Dict.keepShared first second == expected ## ``` -keepShared : Dict k v, Dict k v -> Dict k v where k implements Hash & Eq -keepShared = \xs, ys -> +keepShared : Dict k v, Dict k v -> Dict k v where v implements Eq +keepShared = \xs0, ys0 -> + (xs1, ys1) = + if len ys0 < len xs0 then + (ys0, xs0) + else + (xs0, ys0) walk - xs - (empty {}) + xs1 + (withCapacity (len xs1)) (\state, k, v -> - if contains ys k then - insert state k v - else - state + when get ys1 k is + Ok yv if v == yv -> + insert state k v + + _ -> + state ) ## Remove the key-value pairs in the first input that are also in the second @@ -605,205 +707,251 @@ keepShared = \xs, ys -> ## ## expect Dict.removeAll first second == expected ## ``` -removeAll : Dict k v, Dict k v -> Dict k v where k implements Hash & Eq +removeAll : Dict k v, Dict k v -> Dict k v removeAll = \xs, ys -> walk ys xs (\state, k, _ -> remove state k) -swapAndUpdateDataIndex : Dict k v, Nat, Nat -> Dict k v where k implements Hash & Eq -swapAndUpdateDataIndex = \@Dict { metadata, dataIndices, data, size }, removedIndex, lastIndex -> - (key, _) = listGetUnsafe data lastIndex - hashKey = - createLowLevelHasher PseudoRandSeed - |> Hash.hash key - |> complete - h1Key = h1 hashKey - h2Key = h2 hashKey - probe = newProbe h1Key (div8 (List.len metadata)) +# Below here is a list of generic helpers and internal data types for Dict +Bucket : { + distAndFingerprint : U32, # upper 3 byte: distance to original bucket. lower byte: fingerprint from hash + dataIndex : U32, # index into the data list. +} - when findIndexHelper metadata dataIndices data h2Key key probe 0 is - Ok index -> - dataIndex = listGetUnsafe dataIndices removedIndex - # Swap and remove data. - nextData = - data - |> List.swap dataIndex lastIndex - |> List.dropLast 1 +emptyBucket = { distAndFingerprint: 0, dataIndex: 0 } +distInc = Num.shiftLeftBy 1u32 8 # skip 1 byte fingerprint +fingerprintMask = Num.subWrap distInc 1 # mask for 1 byte of fingerprint +defaultMaxLoadFactor = 0.8 +initialShifts = 64 - 3 # 2^(64-shifts) number of buckets +maxSize = Num.shiftLeftBy 1u64 32 +maxBucketCount = maxSize - @Dict { - # Set old metadata as deleted. - metadata: List.set metadata removedIndex deletedSlot, - # Update index of swaped element. - dataIndices: List.set dataIndices index dataIndex, - data: nextData, - size: Num.subWrap size 1, - } +incrementDist = \distAndFingerprint -> + distAndFingerprint + distInc - Err NotFound -> - # This should be impossible. - crash "unreachable state in dict swapAndUpdateDataIndex hit. Definitely a standard library bug." +incrementDistN = \distAndFingerprint, n -> + distAndFingerprint + (n * distInc) -insertNotFoundHelper : Dict k v, k, v, U64, I8 -> Dict k v -insertNotFoundHelper = \@Dict { metadata, dataIndices, data, size }, key, value, h1Key, h2Key -> - probe = newProbe h1Key (div8 (List.len metadata)) - index = nextEmptyOrDeletedHelper metadata probe 0 - dataIndex = List.len data - nextData = List.append data (key, value) +decrementDist = \distAndFingerprint -> + distAndFingerprint - distInc - @Dict { - metadata: List.set metadata index h2Key, - dataIndices: List.set dataIndices index dataIndex, - data: nextData, - size, - } +find : Dict k v, k -> { bucketIndex : Nat, result : Result v [KeyNotFound] } +find = \@Dict { buckets, data, shifts }, key -> + hash = hashKey key + distAndFingerprint = distAndFingerprintFromHash hash + bucketIndex = bucketIndexFromHash hash shifts -nextEmptyOrDeletedHelper : List I8, Probe, Nat -> Nat -nextEmptyOrDeletedHelper = \metadata, probe, offset -> - # For inserting, we can use deleted indices. - index = Num.addWrap (mul8 probe.slotIndex) offset - - md = listGetUnsafe metadata index - - if md < 0 then - # Empty or deleted slot, no possibility of the element. - index - else if offset == 7 then - nextEmptyOrDeletedHelper metadata (nextProbe probe) 0 + if !(List.isEmpty data) then + # TODO: this is true in the C++ code, confirm it in Roc as well. + # unrolled loop. *Always* check a few directly, then enter the loop. This is faster. + findFirstUnroll buckets bucketIndex distAndFingerprint data key else - nextEmptyOrDeletedHelper metadata probe (Num.addWrap offset 1) + { bucketIndex, result: Err KeyNotFound } -# TODO: investigate if this needs to be split into more specific helper functions. -# There is a chance that returning specific sub-info like the value would be faster. -findIndexHelper : List I8, List Nat, List (k, v), I8, k, Probe, Nat -> Result Nat [NotFound] where k implements Hash & Eq -findIndexHelper = \metadata, dataIndices, data, h2Key, key, probe, offset -> - # For finding a value, we must search past all deleted element tombstones. - index = Num.addWrap (mul8 probe.slotIndex) offset +findManualUnrolls = 2 - md = listGetUnsafe metadata index - - if md == emptySlot then - # Empty slot, no possibility of the element. - Err NotFound - else if md == h2Key then - # Potentially matching slot, check if the key is a match. - dataIndex = listGetUnsafe dataIndices index - (k, _) = listGetUnsafe data dataIndex - - if k == key then - # We have a match, return its index. - Ok index - else if offset == 7 then - # No match, keep checking. - findIndexHelper metadata dataIndices data h2Key key (nextProbe probe) 0 +findFirstUnroll : List Bucket, Nat, U32, List (k, v), k -> { bucketIndex : Nat, result : Result v [KeyNotFound] } where k implements Eq +findFirstUnroll = \buckets, bucketIndex, distAndFingerprint, data, key -> + # TODO: once we have short circuit evaluation, use it here and other similar locations in this file. + # Avoid the nested if with else block inconvenience. + bucket = listGetUnsafe buckets bucketIndex + if distAndFingerprint == bucket.distAndFingerprint then + (foundKey, value) = listGetUnsafe data (Num.toNat bucket.dataIndex) + if foundKey == key then + { bucketIndex, result: Ok value } else - findIndexHelper metadata dataIndices data h2Key key probe (Num.addWrap offset 1) - else if offset == 7 then - # Used slot, check next slot. - findIndexHelper metadata dataIndices data h2Key key (nextProbe probe) 0 + findSecondUnroll buckets (nextBucketIndex bucketIndex (List.len buckets)) (incrementDist distAndFingerprint) data key else - findIndexHelper metadata dataIndices data h2Key key probe (Num.addWrap offset 1) + findSecondUnroll buckets (nextBucketIndex bucketIndex (List.len buckets)) (incrementDist distAndFingerprint) data key -# This is how we grow the container. -# If we aren't to the load factor yet, just ignore this. -# The container must have an updated size including any elements about to be inserted. -maybeRehash : Dict k v -> Dict k v where k implements Hash & Eq -maybeRehash = \@Dict { metadata, dataIndices, data, size } -> - cap = List.len dataIndices - maxLoadCap = - # This is 7/8 * capacity, which is the max load factor. - Num.subWrap cap (Num.shiftRightZfBy cap 3) - - if size > maxLoadCap then - rehash (@Dict { metadata, dataIndices, data, size }) +findSecondUnroll : List Bucket, Nat, U32, List (k, v), k -> { bucketIndex : Nat, result : Result v [KeyNotFound] } where k implements Eq +findSecondUnroll = \buckets, bucketIndex, distAndFingerprint, data, key -> + bucket = listGetUnsafe buckets bucketIndex + if distAndFingerprint == bucket.distAndFingerprint then + (foundKey, value) = listGetUnsafe data (Num.toNat bucket.dataIndex) + if foundKey == key then + { bucketIndex, result: Ok value } + else + findHelper buckets (nextBucketIndex bucketIndex (List.len buckets)) (incrementDist distAndFingerprint) data key else - @Dict { metadata, dataIndices, data, size } + findHelper buckets (nextBucketIndex bucketIndex (List.len buckets)) (incrementDist distAndFingerprint) data key -# TODO: switch rehash to iterate data and eventually clear out tombstones as well. -rehash : Dict k v -> Dict k v where k implements Hash & Eq -rehash = \@Dict { metadata, dataIndices, data, size } -> - newLen = 2 * List.len dataIndices - newDict = +findHelper : List Bucket, Nat, U32, List (k, v), k -> { bucketIndex : Nat, result : Result v [KeyNotFound] } where k implements Eq +findHelper = \buckets, bucketIndex, distAndFingerprint, data, key -> + bucket = listGetUnsafe buckets bucketIndex + if distAndFingerprint == bucket.distAndFingerprint then + (foundKey, value) = listGetUnsafe data (Num.toNat bucket.dataIndex) + if foundKey == key then + { bucketIndex, result: Ok value } + else + findHelper buckets (nextBucketIndex bucketIndex (List.len buckets)) (incrementDist distAndFingerprint) data key + else if distAndFingerprint > bucket.distAndFingerprint then + { bucketIndex, result: Err KeyNotFound } + else + findHelper buckets (nextBucketIndex bucketIndex (List.len buckets)) (incrementDist distAndFingerprint) data key + +removeBucket : Dict k v, Nat -> Dict k v +removeBucket = \@Dict { buckets: buckets0, data: data0, maxBucketCapacity, maxLoadFactor, shifts }, bucketIndex0 -> + { dataIndex: dataIndexToRemove } = listGetUnsafe buckets0 bucketIndex0 + + (buckets1, bucketIndex1) = removeBucketHelper buckets0 bucketIndex0 + buckets2 = List.set buckets1 bucketIndex1 emptyBucket + + lastDataIndex = List.len data0 - 1 + if (Num.toNat dataIndexToRemove) != lastDataIndex then + # Swap removed item to the end + data1 = List.swap data0 (Num.toNat dataIndexToRemove) lastDataIndex + (key, _) = listGetUnsafe data1 (Num.toNat dataIndexToRemove) + + # Update the data index of the new value. + hash = hashKey key + bucketIndex2 = bucketIndexFromHash hash shifts + + bucketIndex3 = scanForIndex buckets2 bucketIndex2 (Num.toU32 lastDataIndex) + swapBucket = listGetUnsafe buckets2 bucketIndex3 @Dict { - metadata: List.repeat emptySlot newLen, - dataIndices: List.repeat 0 newLen, - data, - size, + buckets: List.set buckets2 bucketIndex3 { swapBucket & dataIndex: dataIndexToRemove }, + data: List.dropLast data1 1, + maxBucketCapacity, + maxLoadFactor, + shifts, + } + else + @Dict { + buckets: buckets2, + data: List.dropLast data0 1, + maxBucketCapacity, + maxLoadFactor, + shifts, } - rehashHelper newDict metadata dataIndices data 0 +scanForIndex : List Bucket, Nat, U32 -> Nat +scanForIndex = \buckets, bucketIndex, dataIndex -> + bucket = listGetUnsafe buckets bucketIndex + if bucket.dataIndex != dataIndex then + scanForIndex buckets (nextBucketIndex bucketIndex (List.len buckets)) dataIndex + else + bucketIndex -rehashHelper : Dict k v, List I8, List Nat, List (k, v), Nat -> Dict k v where k implements Hash & Eq -rehashHelper = \dict, oldMetadata, oldDataIndices, oldData, index -> - when List.get oldMetadata index is - Ok md -> - nextDict = - if md >= 0 then - # We have an actual element here - dataIndex = listGetUnsafe oldDataIndices index - (k, _) = listGetUnsafe oldData dataIndex +removeBucketHelper : List Bucket, Nat -> (List Bucket, Nat) +removeBucketHelper = \buckets, bucketIndex -> + nextIndex = nextBucketIndex bucketIndex (List.len buckets) + nextBucket = listGetUnsafe buckets nextIndex + # shift down until either empty or an element with correct spot is found + if nextBucket.distAndFingerprint >= distInc * 2 then + List.set buckets bucketIndex { nextBucket & distAndFingerprint: decrementDist nextBucket.distAndFingerprint } + |> removeBucketHelper nextIndex + else + (buckets, bucketIndex) - insertForRehash dict k dataIndex - else - # Empty or deleted data - dict +increaseSize : Dict k v -> Dict k v +increaseSize = \@Dict { data, maxBucketCapacity, maxLoadFactor, shifts } -> + if maxBucketCapacity != maxBucketCount then + newShifts = shifts - 1 + (buckets0, newMaxBucketCapacity) = allocBucketsFromShift newShifts maxLoadFactor + buckets1 = fillBucketsFromData buckets0 data newShifts + @Dict { + buckets: buckets1, + data, + maxBucketCapacity: newMaxBucketCapacity, + maxLoadFactor, + shifts: newShifts, + } + else + crash "Dict hit limit of \(Num.toStr maxBucketCount) elements. Unable to grow more." - rehashHelper nextDict oldMetadata oldDataIndices oldData (Num.addWrap index 1) +allocBucketsFromShift : U8, F32 -> (List Bucket, U64) +allocBucketsFromShift = \shifts, maxLoadFactor -> + bucketCount = calcNumBuckets shifts + if bucketCount == maxBucketCount then + # reached the maximum, make sure we can use each bucket + (List.repeat emptyBucket (Num.toNat maxBucketCount), maxBucketCount) + else + maxBucketCapacity = + bucketCount + |> Num.toF32 + |> Num.mul maxLoadFactor + |> Num.floor + (List.repeat emptyBucket (Num.toNat bucketCount), maxBucketCapacity) - Err OutOfBounds -> - # Walked entire list, complete now. - dict +calcShiftsForSize : U64, F32 -> U8 +calcShiftsForSize = \size, maxLoadFactor -> + calcShiftsForSizeHelper initialShifts size maxLoadFactor -insertForRehash : Dict k v, k, Nat -> Dict k v where k implements Hash & Eq -insertForRehash = \@Dict { metadata, dataIndices, data, size }, key, dataIndex -> - hashKey = - createLowLevelHasher PseudoRandSeed - |> Hash.hash key - |> complete - h1Key = h1 hashKey - h2Key = h2 hashKey - probe = newProbe h1Key (div8 (List.len metadata)) - index = nextEmptyOrDeletedHelper metadata probe 0 +calcShiftsForSizeHelper = \shifts, size, maxLoadFactor -> + maxBucketCapacity = + shifts + |> calcNumBuckets + |> Num.toF32 + |> Num.mul maxLoadFactor + |> Num.floor + if shifts > 0 && maxBucketCapacity < size then + calcShiftsForSizeHelper (shifts - 1) size maxLoadFactor + else + shifts - @Dict { - metadata: List.set metadata index h2Key, - dataIndices: List.set dataIndices index dataIndex, - data, - size, - } +calcNumBuckets = \shifts -> + Num.min + (Num.shiftLeftBy 1 (64 - shifts)) + maxBucketCount -emptySlot : I8 -emptySlot = -128 -deletedSlot : I8 -deletedSlot = -2 +fillBucketsFromData = \buckets0, data, shifts -> + buckets1, (key, _), dataIndex <- List.walkWithIndex data buckets0 + (bucketIndex, distAndFingerprint) = nextWhileLess buckets1 key shifts + placeAndShiftUp buckets1 { distAndFingerprint, dataIndex: Num.toU32 dataIndex } bucketIndex -# Capacity must be a power of 2. -# We still will use slots of 8 even though this version has no true slots. -# We just move an element at a time. -# Thus, the true index is slotIndex * 8 + offset. -Probe : { slotIndex : Nat, probeI : Nat, mask : Nat } +nextWhileLess : List Bucket, k, U8 -> (Nat, U32) where k implements Hash & Eq +nextWhileLess = \buckets, key, shifts -> + hash = hashKey key + distAndFingerprint = distAndFingerprintFromHash hash + bucketIndex = bucketIndexFromHash hash shifts -newProbe : U64, Nat -> Probe -newProbe = \h1Key, slots -> - mask = Num.subSaturated slots 1 - slotIndex = Num.bitwiseAnd (Num.toNat h1Key) mask + nextWhileLessHelper buckets bucketIndex distAndFingerprint - { slotIndex, probeI: 1, mask } +nextWhileLessHelper = \buckets, bucketIndex, distAndFingerprint -> + loaded = listGetUnsafe buckets (Num.toNat bucketIndex) + if distAndFingerprint < loaded.distAndFingerprint then + nextWhileLessHelper buckets (nextBucketIndex bucketIndex (List.len buckets)) (incrementDist distAndFingerprint) + else + (bucketIndex, distAndFingerprint) -nextProbe : Probe -> Probe -nextProbe = \{ slotIndex, probeI, mask } -> - nextSlotIndex = Num.bitwiseAnd (Num.addWrap slotIndex probeI) mask +placeAndShiftUp = \buckets0, bucket, bucketIndex -> + loaded = listGetUnsafe buckets0 (Num.toNat bucketIndex) + if loaded.distAndFingerprint != 0 then + buckets1 = List.set buckets0 (Num.toNat bucketIndex) bucket + placeAndShiftUp + buckets1 + { loaded & distAndFingerprint: incrementDist loaded.distAndFingerprint } + (nextBucketIndex bucketIndex (List.len buckets1)) + else + List.set buckets0 (Num.toNat bucketIndex) bucket - { slotIndex: nextSlotIndex, probeI: Num.addWrap probeI 1, mask } +nextBucketIndex = \bucketIndex, maxBuckets -> + # I just ported this impl directly. + # I am a bit confused why it is using an if over a mask. + # Maybe compilers are smart enough to optimize this well. + # Maybe the unlikely annotation is super important + if Num.addWrap bucketIndex 1 != maxBuckets then + Num.addWrap bucketIndex 1 + else + 0 -mul8 = \val -> Num.shiftLeftBy val 3 -div8 = \val -> Num.shiftRightZfBy val 3 +hashKey = \key -> + createLowLevelHasher PseudoRandSeed + |> Hash.hash key + |> complete -h1 : U64 -> U64 -h1 = \hashKey -> - Num.shiftRightZfBy hashKey 7 +distAndFingerprintFromHash : U64 -> U32 +distAndFingerprintFromHash = \hash -> + hash + |> Num.toU32 + |> Num.bitwiseAnd fingerprintMask + |> Num.bitwiseOr distInc -h2 : U64 -> I8 -h2 = \hashKey -> - Num.toI8 (Num.bitwiseAnd hashKey 0b0111_1111) +bucketIndexFromHash : U64, U8 -> Nat +bucketIndexFromHash = \hash, shifts -> + hash + |> Num.shiftRightZfBy shifts + |> Num.toNat expect val = @@ -938,10 +1086,16 @@ expect |> insert "e" 4 |> insert "f" 5 |> insert "g" 6 + |> insert "h" 7 + |> insert "i" 8 + |> insert "j" 9 + |> insert "k" 10 + |> insert "l" 11 |> capacity - val == 7 + val == 12 +# Reach capacity, all elements still exist expect dict = empty {} @@ -952,6 +1106,11 @@ expect |> insert "e" 4 |> insert "f" 5 |> insert "g" 6 + |> insert "h" 7 + |> insert "i" 8 + |> insert "j" 9 + |> insert "k" 10 + |> insert "l" 11 (get dict "a" == Ok 0) && (get dict "b" == Ok 1) @@ -960,6 +1119,11 @@ expect && (get dict "e" == Ok 4) && (get dict "f" == Ok 5) && (get dict "g" == Ok 6) + && (get dict "h" == Ok 7) + && (get dict "i" == Ok 8) + && (get dict "j" == Ok 9) + && (get dict "k" == Ok 10) + && (get dict "l" == Ok 11) # Force rehash. expect @@ -973,10 +1137,16 @@ expect |> insert "f" 5 |> insert "g" 6 |> insert "h" 7 + |> insert "i" 8 + |> insert "j" 9 + |> insert "k" 10 + |> insert "l" 11 + |> insert "m" 12 |> capacity - val == 14 + val == 25 +# Force rehash, all elements still exist expect dict = empty {} @@ -988,6 +1158,11 @@ expect |> insert "f" 5 |> insert "g" 6 |> insert "h" 7 + |> insert "i" 8 + |> insert "j" 9 + |> insert "k" 10 + |> insert "l" 11 + |> insert "m" 12 (get dict "a" == Ok 0) && (get dict "b" == Ok 1) @@ -997,6 +1172,11 @@ expect && (get dict "f" == Ok 5) && (get dict "g" == Ok 6) && (get dict "h" == Ok 7) + && (get dict "i" == Ok 8) + && (get dict "j" == Ok 9) + && (get dict "k" == Ok 10) + && (get dict "l" == Ok 11) + && (get dict "m" == Ok 12) expect empty {} @@ -1012,6 +1192,52 @@ expect |> get 7 |> Bool.isEq (Ok "Testing") +# All BadKey's hash to the same location. +# This is needed to test some robinhood logic. +BadKey := U64 implements [ + Eq, + Hash { + hash: hashBadKey, + }, + ] + +hashBadKey : hasher, BadKey -> hasher where hasher implements Hasher +hashBadKey = \hasher, _ -> Hash.hash hasher 0 + +expect + badKeys = [ + @BadKey 0, + @BadKey 1, + @BadKey 2, + @BadKey 3, + @BadKey 4, + @BadKey 5, + @BadKey 6, + @BadKey 5, + @BadKey 4, + @BadKey 3, + @BadKey 3, + @BadKey 3, + @BadKey 10, + ] + + dict = + acc, k <- List.walk badKeys (Dict.empty {}) + Dict.update acc k \val -> + when val is + Present p -> Present (p + 1) + Missing -> Present 0 + + allInsertedCorrectly = + acc, k <- List.walk badKeys Bool.true + acc && Dict.contains dict k + + allInsertedCorrectly + +# Note, there are a number of places we should probably use set and replace unsafe. +# unsafe primitive that does not perform a bounds check +listGetUnsafe : List a, Nat -> a + # We have decided not to expose the standard roc hashing algorithm. # This is to avoid external dependence and the need for versioning. # The current implementation is a form of [Wyhash final4](https://github.com/wangyi-fudan/wyhash/blob/77e50f267fbc7b8e2d09f2d455219adb70ad4749/wyhash.h). @@ -1031,10 +1257,6 @@ LowLevelHasher := { initializedSeed : U64, state : U64 } implements [ }, ] -# unsafe primitive that does not perform a bounds check -# TODO hide behind an InternalList.roc module -listGetUnsafe : List a, Nat -> a - # Returns a application specific pseudo random seed for Dict. # This avoids trivial DOS attacks. pseudoSeed : {} -> U64 @@ -1446,3 +1668,71 @@ expect |> Dict.insert "Charlie" 19 |> Dict.walkUntil Bool.false (\_, _, age -> if age >= 18 then Break Bool.true else Continue Bool.false) |> Bool.isEq Bool.true + +expect + d1 = + Dict.empty {} + |> Dict.insert "Alice" 17 + |> Dict.insert "Bob" 18 + |> Dict.insert "Charlie" 19 + |> Dict.keepIf \(_k, v) -> v >= 18 + + d2 = + Dict.empty {} + |> Dict.insert "Bob" 18 + |> Dict.insert "Charlie" 19 + + d1 == d2 + +expect + d1 = + Dict.empty {} + |> Dict.insert "Alice" 17 + |> Dict.insert "Bob" 18 + |> Dict.insert "Charlie" 19 + |> Dict.keepIf \(k, _v) -> Str.endsWith k "e" + + d2 = + Dict.empty {} + |> Dict.insert "Alice" 17 + |> Dict.insert "Charlie" 19 + + d1 == d2 + +expect + keysToDelete = [1, 2] + d1 = + Dict.empty {} + |> Dict.insert 0 0 + |> Dict.insert 1 1 + |> Dict.insert 2 2 + |> Dict.insert 3 3 + |> Dict.insert 4 4 + |> Dict.keepIf (\(k, _v) -> List.contains keysToDelete k |> Bool.not) + + d2 = + Dict.empty {} + |> Dict.insert 0 0 + |> Dict.insert 3 3 + |> Dict.insert 4 4 + + d1 == d2 + +expect + keysToDelete = [2, 4] + d1 = + Dict.empty {} + |> Dict.insert 0 0 + |> Dict.insert 1 1 + |> Dict.insert 2 2 + |> Dict.insert 3 3 + |> Dict.insert 4 4 + |> Dict.keepIf (\(k, _v) -> List.contains keysToDelete k |> Bool.not) + + d2 = + Dict.empty {} + |> Dict.insert 0 0 + |> Dict.insert 1 1 + |> Dict.insert 3 3 + + d1 == d2 diff --git a/crates/compiler/builtins/roc/Inspect.roc b/crates/compiler/builtins/roc/Inspect.roc index a86b83a247..e9235c9adf 100644 --- a/crates/compiler/builtins/roc/Inspect.roc +++ b/crates/compiler/builtins/roc/Inspect.roc @@ -34,8 +34,7 @@ interface Inspect custom, apply, toInspector, - DbgFormatter, - toDbgStr, + toStr, ] imports [ Bool.{ Bool }, @@ -99,6 +98,12 @@ inspect = \val -> (@Inspector valFn) = toInspector val valFn (init {}) +toStr : val -> Str where val implements Inspect +toStr = \val -> + val + |> inspect + |> toDbgStr + # The current default formatter for inspect. # This just returns a simple string for debugging. # More powerful formatters will likely be wanted in the future. diff --git a/crates/compiler/builtins/roc/List.roc b/crates/compiler/builtins/roc/List.roc index bcfa47366e..0565e0128b 100644 --- a/crates/compiler/builtins/roc/List.roc +++ b/crates/compiler/builtins/roc/List.roc @@ -32,6 +32,7 @@ interface List product, walkWithIndex, walkUntil, + walkWithIndexUntil, walkFrom, walkFromUntil, range, @@ -520,6 +521,25 @@ walkWithIndexHelp = \list, state, f, index, length -> else state +## Like [walkUntil], but at each step the function also receives the index of the current element. +walkWithIndexUntil : List elem, state, (state, elem, Nat -> [Continue state, Break state]) -> state +walkWithIndexUntil = \list, state, f -> + when walkWithIndexUntilHelp list state f 0 (List.len list) is + Continue new -> new + Break new -> new + +## internal helper +walkWithIndexUntilHelp : List elem, s, (s, elem, Nat -> [Continue s, Break b]), Nat, Nat -> [Continue s, Break b] +walkWithIndexUntilHelp = \list, state, f, index, length -> + if index < length then + when f state (List.getUnsafe list index) index is + Continue nextState -> + walkWithIndexUntilHelp list nextState f (Num.addWrap index 1) length + + Break b -> Break b + else + Continue state + ## Note that in other languages, `walkBackwards` is sometimes called `reduceRight`, ## `fold`, `foldRight`, or `foldr`. walkBackwards : List elem, state, (state, elem -> state) -> state diff --git a/crates/compiler/builtins/roc/Num.roc b/crates/compiler/builtins/roc/Num.roc index 7897de6126..2b1e3782b1 100644 --- a/crates/compiler/builtins/roc/Num.roc +++ b/crates/compiler/builtins/roc/Num.roc @@ -560,8 +560,6 @@ tau = 2 * pi # ------- Functions ## Convert a number to a [Str]. ## -## This is the same as calling `Num.format {}` - so for more details on -## exact formatting, see `Num.format`. ## ``` ## Num.toStr 42 ## ``` @@ -573,7 +571,6 @@ tau = 2 * pi ## When this function is given a non-[finite](Num.isFinite) ## [F64] or [F32] value, the returned string will be `"NaN"`, `"∞"`, or `"-∞"`. ## -## To get strings in hexadecimal, octal, or binary format, use `Num.format`. toStr : Num * -> Str intCast : Int a -> Int b @@ -1054,7 +1051,7 @@ shiftLeftBy : Int a, U8 -> Int a ## ## The most significant bits are copied from the current. ## ``` -## shiftRightBy 0b0000_0011 2 == 0b0000_1100 +## shiftRightBy 0b0000_1100 2 == 0b0000_0011 ## ## 0b0001_0100 |> shiftRightBy 2 == 0b0000_0101 ## @@ -1065,16 +1062,16 @@ shiftRightBy : Int a, U8 -> Int a ## Bitwise logical right shift of a number by another ## -## The most significant bits always become 0. This means that shifting left is +## The most significant bits always become 0. This means that shifting right is ## like dividing by factors of two for unsigned integers. ## ``` -## shiftRightBy 0b0010_1000 2 == 0b0000_1010 +## shiftRightZfBy 0b0010_1000 2 == 0b0000_1010 ## -## 0b0010_1000 |> shiftRightBy 2 == 0b0000_1010 +## 0b0010_1000 |> shiftRightZfBy 2 == 0b0000_1010 ## -## 0b1001_0000 |> shiftRightBy 2 == 0b0010_0100 +## 0b1001_0000 |> shiftRightZfBy 2 == 0b0010_0100 ## ``` -## In some languages `shiftRightBy` is implemented as a binary operator `>>`. +## In some languages `shiftRightZfBy` is implemented as a binary operator `>>`. shiftRightZfBy : Int a, U8 -> Int a ## Round off the given fraction to the nearest integer. @@ -1112,7 +1109,7 @@ powInt : Int a, Int a -> Int a ## ## 8 ## ``` -countLeadingZeroBits : Int a -> Nat +countLeadingZeroBits : Int a -> U8 ## Counts the number of least-significant (trailing in a big-Endian sense) zeroes in an integer. ## @@ -1125,7 +1122,7 @@ countLeadingZeroBits : Int a -> Nat ## ## 8 ## ``` -countTrailingZeroBits : Int a -> Nat +countTrailingZeroBits : Int a -> U8 ## Counts the number of set bits in an integer. ## @@ -1138,7 +1135,7 @@ countTrailingZeroBits : Int a -> Nat ## ## 0 ## ``` -countOneBits : Int a -> Nat +countOneBits : Int a -> U8 addWrap : Int range, Int range -> Int range @@ -1433,12 +1430,11 @@ toU32 : Int * -> U32 toU64 : Int * -> U64 toU128 : Int * -> U128 -## Converts an [Int] to a [Nat]. If the given number doesn't fit in [Nat], it will be truncated. +## Converts an [Int] to a [Nat]. If the given number doesn't fit in [Nat], it will be truncated! ## Since [Nat] has a different maximum number depending on the system you're building ## for, this may give a different answer on different systems. ## -## For example, on a 32-bit system, `Num.maxNat` will return the same answer as -## `Num.maxU32`. This means that calling `Num.toNat 9_000_000_000` on a 32-bit +## For example, on a 32-bit system, calling `Num.toNat 9_000_000_000` on a 32-bit ## system will return `Num.maxU32` instead of 9 billion, because 9 billion is ## higher than `Num.maxU32` and will not fit in a [Nat] on a 32-bit system. ## diff --git a/crates/compiler/builtins/roc/Set.roc b/crates/compiler/builtins/roc/Set.roc index b942461f31..43a1b4e466 100644 --- a/crates/compiler/builtins/roc/Set.roc +++ b/crates/compiler/builtins/roc/Set.roc @@ -2,9 +2,14 @@ interface Set exposes [ Set, empty, + withCapacity, + reserve, + releaseExcessCapacity, single, walk, walkUntil, + keepIf, + dropIf, insert, len, isEmpty, @@ -43,7 +48,7 @@ Set k := Dict.Dict k {} where k implements Hash & Eq }, ] -isEq : Set k, Set k -> Bool where k implements Hash & Eq +isEq : Set k, Set k -> Bool isEq = \xs, ys -> if len xs != len ys then Bool.false @@ -54,7 +59,7 @@ isEq = \xs, ys -> else Break Bool.false -hashSet : hasher, Set k -> hasher where k implements Hash & Eq, hasher implements Hasher +hashSet : hasher, Set k -> hasher where hasher implements Hasher hashSet = \hasher, @Set inner -> Hash.hash hasher inner toInspectorSet : Set k -> Inspector f where k implements Inspect & Hash & Eq, f implements InspectFormatter @@ -72,13 +77,25 @@ toInspectorSet = \set -> empty : {} -> Set * empty = \{} -> @Set (Dict.empty {}) -## Return a dictionary with space allocated for a number of entries. This +## Return a set with space allocated for a number of entries. This ## may provide a performance optimization if you know how many entries will be ## inserted. withCapacity : Nat -> Set * withCapacity = \cap -> @Set (Dict.withCapacity cap) +## Enlarge the set for at least capacity additional elements +reserve : Set k, Nat -> Set k +reserve = \@Set dict, requested -> + @Set (Dict.reserve dict requested) + +## Shrink the memory footprint of a set such that capacity is as small as possible. +## This function will require regenerating the metadata if the size changes. +## There will still be some overhead due to dictionary metadata always being a power of 2. +releaseExcessCapacity : Set k -> Set k +releaseExcessCapacity = \@Set dict -> + @Set (Dict.releaseExcessCapacity dict) + ## Creates a new `Set` with a single value. ## ``` ## singleItemSet = Set.single "Apple" @@ -86,7 +103,7 @@ withCapacity = \cap -> ## ## expect countValues == 1 ## ``` -single : k -> Set k where k implements Hash & Eq +single : k -> Set k single = \key -> Dict.single key {} |> @Set @@ -102,7 +119,7 @@ single = \key -> ## ## expect countValues == 3 ## ``` -insert : Set k, k -> Set k where k implements Hash & Eq +insert : Set k, k -> Set k insert = \@Set dict, key -> Dict.insert dict key {} |> @Set @@ -187,7 +204,7 @@ expect ## expect has10 == Bool.false ## expect has20 == Bool.true ## ``` -remove : Set k, k -> Set k where k implements Hash & Eq +remove : Set k, k -> Set k remove = \@Set dict, key -> Dict.remove dict key |> @Set @@ -206,7 +223,7 @@ remove = \@Set dict, key -> ## expect hasApple == Bool.true ## expect hasBanana == Bool.false ## ``` -contains : Set k, k -> Bool where k implements Hash & Eq +contains : Set k, k -> Bool contains = \@Set dict, key -> Dict.contains dict key @@ -219,7 +236,7 @@ contains = \@Set dict, key -> ## ## expect Set.toList numbers == values ## ``` -toList : Set k -> List k where k implements Hash & Eq +toList : Set k -> List k toList = \@Set dict -> Dict.keys dict @@ -233,11 +250,12 @@ toList = \@Set dict -> ## ## expect Set.fromList [Pear, Apple, Banana] == values ## ``` -fromList : List k -> Set k where k implements Hash & Eq +fromList : List k -> Set k fromList = \list -> - initial = @Set (Dict.withCapacity (List.len list)) - - List.walk list initial insert + list + |> List.map \k -> (k, {}) + |> Dict.fromList + |> @Set ## Combine two `Set` collection by keeping the ## [union](https://en.wikipedia.org/wiki/Union_(set_theory)) @@ -249,7 +267,7 @@ fromList = \list -> ## ## expect Set.union set1 set2 == Set.fromList [Left, Right] ## ``` -union : Set k, Set k -> Set k where k implements Hash & Eq +union : Set k, Set k -> Set k union = \@Set dict1, @Set dict2 -> Dict.insertAll dict1 dict2 |> @Set @@ -262,7 +280,7 @@ union = \@Set dict1, @Set dict2 -> ## ## expect Set.intersection set1 set2 == Set.single Left ## ``` -intersection : Set k, Set k -> Set k where k implements Hash & Eq +intersection : Set k, Set k -> Set k intersection = \@Set dict1, @Set dict2 -> Dict.keepShared dict1 dict2 |> @Set @@ -276,7 +294,7 @@ intersection = \@Set dict1, @Set dict2 -> ## ## expect Set.difference first second == Set.fromList [Up, Down] ## ``` -difference : Set k, Set k -> Set k where k implements Hash & Eq +difference : Set k, Set k -> Set k difference = \@Set dict1, @Set dict2 -> Dict.removeAll dict1 dict2 |> @Set @@ -299,14 +317,14 @@ difference = \@Set dict1, @Set dict2 -> ## ## expect result == 2 ## ``` -walk : Set k, state, (state, k -> state) -> state where k implements Hash & Eq +walk : Set k, state, (state, k -> state) -> state walk = \@Set dict, state, step -> Dict.walk dict state (\s, k, _ -> step s k) ## Convert each value in the set to something new, by calling a conversion ## function on each of them which receives the old value. Then return a ## new set containing the converted values. -map : Set a, (a -> b) -> Set b where a implements Hash & Eq, b implements Hash & Eq +map : Set a, (a -> b) -> Set b map = \set, transform -> init = withCapacity (capacity set) @@ -318,7 +336,7 @@ map = \set, transform -> ## (using [Set.union]) into one set. ## ## You may know a similar function named `concatMap` in other languages. -joinMap : Set a, (a -> Set b) -> Set b where a implements Hash & Eq, b implements Hash & Eq +joinMap : Set a, (a -> Set b) -> Set b joinMap = \set, transform -> init = withCapacity (capacity set) # Might be a pessimization @@ -340,10 +358,32 @@ joinMap = \set, transform -> ## ## expect result == FoundTheAnswer ## ``` -walkUntil : Set k, state, (state, k -> [Continue state, Break state]) -> state where k implements Hash & Eq +walkUntil : Set k, state, (state, k -> [Continue state, Break state]) -> state walkUntil = \@Set dict, state, step -> Dict.walkUntil dict state (\s, k, _ -> step s k) +## Run the given function on each element in the `Set`, and return +## a `Set` with just the elements for which the function returned `Bool.true`. +## ``` +## expect Set.fromList [1,2,3,4,5] +## |> Set.keepIf \k -> k >= 3 +## |> Bool.isEq (Set.fromList [3,4,5]) +## ``` +keepIf : Set k, (k -> Bool) -> Set k +keepIf = \@Set dict, predicate -> + @Set (Dict.keepIf dict (\(k, _v) -> predicate k)) + +## Run the given function on each element in the `Set`, and return +## a `Set` with just the elements for which the function returned `Bool.false`. +## ``` +## expect Set.fromList [1,2,3,4,5] +## |> Set.dropIf \k -> k >= 3 +## |> Bool.isEq (Set.fromList [1,2]) +## ``` +dropIf : Set k, (k -> Bool) -> Set k +dropIf = \@Set dict, predicate -> + @Set (Dict.dropIf dict (\(k, _v) -> predicate k)) + expect first = single "Keep Me" @@ -443,3 +483,13 @@ expect |> insert orderOne wrapperOne == wrapperTwo + +expect + Set.fromList [1, 2, 3, 4, 5] + |> Set.keepIf \k -> k >= 3 + |> Bool.isEq (Set.fromList [3, 4, 5]) + +expect + Set.fromList [1, 2, 3, 4, 5] + |> Set.dropIf \k -> k >= 3 + |> Bool.isEq (Set.fromList [1, 2]) diff --git a/crates/compiler/builtins/roc/main.roc b/crates/compiler/builtins/roc/main.roc index 8e73148b6b..7e4de6e56e 100644 --- a/crates/compiler/builtins/roc/main.roc +++ b/crates/compiler/builtins/roc/main.roc @@ -1,3 +1,3 @@ package "builtins" - exposes [Str, Num, Bool, Result, List, Dict, Set, Decode, Encode, Hash, Box, TotallyNotJson] + exposes [Str, Num, Bool, Result, List, Dict, Set, Decode, Encode, Hash, Box, TotallyNotJson, Inspect] packages {} diff --git a/crates/compiler/builtins/src/bitcode.rs b/crates/compiler/builtins/src/bitcode.rs index 39eae1f97b..5a1c549f2e 100644 --- a/crates/compiler/builtins/src/bitcode.rs +++ b/crates/compiler/builtins/src/bitcode.rs @@ -370,7 +370,7 @@ pub const STR_GET_SCALAR_UNSAFE: &str = "roc_builtins.str.get_scalar_unsafe"; pub const STR_CLONE_TO: &str = "roc_builtins.str.clone_to"; pub const STR_WITH_CAPACITY: &str = "roc_builtins.str.with_capacity"; pub const STR_GRAPHEMES: &str = "roc_builtins.str.graphemes"; -pub const STR_REFCOUNT_PTR: &str = "roc_builtins.str.refcount_ptr"; +pub const STR_ALLOCATION_PTR: &str = "roc_builtins.str.allocation_ptr"; pub const STR_RELEASE_EXCESS_CAPACITY: &str = "roc_builtins.str.release_excess_capacity"; pub const LIST_MAP: &str = "roc_builtins.list.map"; @@ -390,7 +390,7 @@ pub const LIST_PREPEND: &str = "roc_builtins.list.prepend"; pub const LIST_APPEND_UNSAFE: &str = "roc_builtins.list.append_unsafe"; pub const LIST_RESERVE: &str = "roc_builtins.list.reserve"; pub const LIST_CAPACITY: &str = "roc_builtins.list.capacity"; -pub const LIST_REFCOUNT_PTR: &str = "roc_builtins.list.refcount_ptr"; +pub const LIST_ALLOCATION_PTR: &str = "roc_builtins.list.allocation_ptr"; pub const LIST_RELEASE_EXCESS_CAPACITY: &str = "roc_builtins.list.release_excess_capacity"; pub const DEC_ABS: &str = "roc_builtins.dec.abs"; @@ -422,6 +422,7 @@ pub const DEC_TAN: &str = "roc_builtins.dec.tan"; pub const DEC_TO_I128: &str = "roc_builtins.dec.to_i128"; pub const DEC_TO_STR: &str = "roc_builtins.dec.to_str"; +pub const UTILS_DBG_IMPL: &str = "roc_builtins.utils.dbg_impl"; pub const UTILS_TEST_PANIC: &str = "roc_builtins.utils.test_panic"; pub const UTILS_ALLOCATE_WITH_REFCOUNT: &str = "roc_builtins.utils.allocate_with_refcount"; pub const UTILS_INCREF_RC_PTR: &str = "roc_builtins.utils.incref_rc_ptr"; diff --git a/crates/compiler/can/src/copy.rs b/crates/compiler/can/src/copy.rs index e5e183822b..5be29af2cd 100644 --- a/crates/compiler/can/src/copy.rs +++ b/crates/compiler/can/src/copy.rs @@ -670,11 +670,15 @@ fn deep_copy_expr_help(env: &mut C, copied: &mut Vec, expr }, Dbg { + source_location, + source, loc_message, loc_continuation, variable, symbol, } => Dbg { + source_location: source_location.clone(), + source: source.clone(), loc_message: Box::new(loc_message.map(|e| go_help!(e))), loc_continuation: Box::new(loc_continuation.map(|e| go_help!(e))), variable: sub!(*variable), diff --git a/crates/compiler/can/src/derive.rs b/crates/compiler/can/src/derive.rs index fd51376919..7ed29eef6f 100644 --- a/crates/compiler/can/src/derive.rs +++ b/crates/compiler/can/src/derive.rs @@ -8,7 +8,7 @@ use roc_error_macros::internal_error; use roc_module::{called_via::CalledVia, symbol::Symbol}; -use roc_parse::ast; +use roc_parse::ast::{self, Collection}; use roc_region::all::{Loc, Region}; use crate::{env::Env, pattern::Pattern, scope::Scope}; @@ -214,12 +214,13 @@ fn is_eq<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> { } fn to_inspector<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> { + // Inspect for opaques as a tag so it prints `@Opaque payload`. let alloc_pat = |it| env.arena.alloc(Loc::at(DERIVED_REGION, it)); let alloc_expr = |it| env.arena.alloc(Loc::at(DERIVED_REGION, it)); let payload = "#payload"; - // \@Opaq payload + // \@Opaque payload let opaque_ref = alloc_pat(ast::Pattern::OpaqueRef(at_opaque)); let opaque_apply_pattern = ast::Pattern::Apply( opaque_ref, @@ -229,7 +230,7 @@ fn to_inspector<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> { ); // Inspect.toInspector payload - let call_member = alloc_expr(ast::Expr::Apply( + let to_inspector_payload = alloc_expr(ast::Expr::Apply( alloc_expr(ast::Expr::Var { module_name: "Inspect", ident: "toInspector", @@ -241,17 +242,61 @@ fn to_inspector<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> { roc_module::called_via::CalledVia::Space, )); - // TODO: change the derived implementation to be something that includes the opaque symbol in - // the derivation, e.g. something like - // - // \@Opaq payload -> - // Inspect.opaqueWrapper "toString symbol" payload + // Inspect.tag "@opaque" [Inspect.toInspector payload] + let to_inspector_list = alloc_expr(ast::Expr::List(Collection::with_items( + &*env.arena.alloc([&*to_inspector_payload]), + ))); + let opaque_name = alloc_expr(ast::Expr::Str(ast::StrLiteral::PlainLine(at_opaque))); - // \@Opaq payload -> Inspect.toInspector payload - ast::Expr::Closure( + let opaque_inspector = alloc_expr(ast::Expr::Apply( + alloc_expr(ast::Expr::Var { + module_name: "Inspect", + ident: "tag", + }), + &*env.arena.alloc([&*opaque_name, &*to_inspector_list]), + roc_module::called_via::CalledVia::Space, + )); + + let fmt = "#fmt"; + + // \fmt -> Inspect.apply opaqueInspector fmt + let apply_opaque_inspector = alloc_expr(ast::Expr::Apply( + alloc_expr(ast::Expr::Var { + module_name: "Inspect", + ident: "apply", + }), + &*env.arena.alloc([ + &*opaque_inspector, + &*alloc_expr(ast::Expr::Var { + module_name: "", + ident: fmt, + }), + ]), + roc_module::called_via::CalledVia::Space, + )); + + let custom_closure = alloc_expr(ast::Expr::Closure( env.arena + .alloc([Loc::at(DERIVED_REGION, ast::Pattern::Identifier(fmt))]), + apply_opaque_inspector, + )); + + // Inspect.custom \fmt -> ... + let custom = alloc_expr(ast::Expr::Apply( + alloc_expr(ast::Expr::Var { + module_name: "Inspect", + ident: "custom", + }), + env.arena.alloc([&*custom_closure]), + CalledVia::Space, + )); + + // \@Opaque payload -> (Inspect.custom \fmt -> ...) + ast::Expr::Closure( + &*env + .arena .alloc([Loc::at(DERIVED_REGION, opaque_apply_pattern)]), - call_member, + custom, ) } diff --git a/crates/compiler/can/src/expr.rs b/crates/compiler/can/src/expr.rs index 474a721bdb..f93eadeb02 100644 --- a/crates/compiler/can/src/expr.rs +++ b/crates/compiler/can/src/expr.rs @@ -269,6 +269,8 @@ pub enum Expr { }, Dbg { + source_location: Box, + source: Box, loc_message: Box>, loc_continuation: Box>, variable: Variable, @@ -1249,7 +1251,7 @@ pub fn canonicalize_expr<'a>( ast::Expr::Dbg(_, _) => { internal_error!("Dbg should have been desugared by now") } - ast::Expr::LowLevelDbg(message, continuation) => { + ast::Expr::LowLevelDbg((source_location, source), message, continuation) => { let mut output = Output::default(); let (loc_message, output1) = @@ -1276,6 +1278,8 @@ pub fn canonicalize_expr<'a>( ( Dbg { + source_location: (*source_location).into(), + source: (*source).into(), loc_message: Box::new(loc_message), loc_continuation: Box::new(loc_continuation), variable: var_store.fresh(), @@ -2097,6 +2101,8 @@ pub fn inline_calls(var_store: &mut VarStore, expr: Expr) -> Expr { } Dbg { + source_location, + source, loc_message, loc_continuation, variable, @@ -2113,6 +2119,8 @@ pub fn inline_calls(var_store: &mut VarStore, expr: Expr) -> Expr { }; Dbg { + source_location, + source, loc_message: Box::new(loc_message), loc_continuation: Box::new(loc_continuation), variable, @@ -2398,7 +2406,7 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool { | ast::Expr::MalformedClosure => true, // Newlines are disallowed inside interpolation, and these all require newlines ast::Expr::Dbg(_, _) - | ast::Expr::LowLevelDbg(_, _) + | ast::Expr::LowLevelDbg(_, _, _) | ast::Expr::Defs(_, _) | ast::Expr::Expect(_, _) | ast::Expr::When(_, _) diff --git a/crates/compiler/can/src/module.rs b/crates/compiler/can/src/module.rs index 729d53c4aa..1bb5cc4bec 100644 --- a/crates/compiler/can/src/module.rs +++ b/crates/compiler/can/src/module.rs @@ -275,6 +275,8 @@ pub fn canonicalize_module_defs<'a>( loc_defs: &'a mut Defs<'a>, header_type: &roc_parse::header::HeaderType, home: ModuleId, + module_path: &str, + src: &'a str, module_ids: &'a ModuleIds, exposed_ident_ids: IdentIds, dep_idents: &'a IdentIdsByModule, @@ -310,7 +312,7 @@ pub fn canonicalize_module_defs<'a>( // visited a BinOp node we'd recursively try to apply this to each of its nested // operators, and then again on *their* nested operators, ultimately applying the // rules multiple times unnecessarily. - crate::operator::desugar_defs(arena, loc_defs); + crate::operator::desugar_defs(arena, loc_defs, src, &mut None, module_path); let mut rigid_variables = RigidVariables::default(); diff --git a/crates/compiler/can/src/operator.rs b/crates/compiler/can/src/operator.rs index e6bfcd897b..3cc06a623c 100644 --- a/crates/compiler/can/src/operator.rs +++ b/crates/compiler/can/src/operator.rs @@ -11,7 +11,7 @@ use roc_parse::ast::{ AssignedField, Collection, Pattern, RecordBuilderField, StrLiteral, StrSegment, ValueDef, WhenBranch, }; -use roc_region::all::{Loc, Region}; +use roc_region::all::{LineInfo, Loc, Region}; // BinOp precedence logic adapted from Gluon by Markus Westerlind // https://github.com/gluon-lang/gluon - license information can be found in @@ -67,13 +67,19 @@ fn new_op_call_expr<'a>( Loc { region, value } } -fn desugar_value_def<'a>(arena: &'a Bump, def: &'a ValueDef<'a>) -> ValueDef<'a> { +fn desugar_value_def<'a>( + arena: &'a Bump, + def: &'a ValueDef<'a>, + src: &'a str, + line_info: &mut Option, + module_path: &str, +) -> ValueDef<'a> { use ValueDef::*; match def { Body(loc_pattern, loc_expr) => Body( - desugar_loc_pattern(arena, loc_pattern), - desugar_expr(arena, loc_expr), + desugar_loc_pattern(arena, loc_pattern, src, line_info, module_path), + desugar_expr(arena, loc_expr, src, line_info, module_path), ), ann @ Annotation(_, _) => *ann, AnnotatedBody { @@ -87,13 +93,14 @@ fn desugar_value_def<'a>(arena: &'a Bump, def: &'a ValueDef<'a>) -> ValueDef<'a> ann_type, comment: *comment, body_pattern, - body_expr: desugar_expr(arena, body_expr), + body_expr: desugar_expr(arena, body_expr, src, line_info, module_path), }, Dbg { condition, preceding_comment, } => { - let desugared_condition = &*arena.alloc(desugar_expr(arena, condition)); + let desugared_condition = + &*arena.alloc(desugar_expr(arena, condition, src, line_info, module_path)); Dbg { condition: desugared_condition, preceding_comment: *preceding_comment, @@ -103,7 +110,8 @@ fn desugar_value_def<'a>(arena: &'a Bump, def: &'a ValueDef<'a>) -> ValueDef<'a> condition, preceding_comment, } => { - let desugared_condition = &*arena.alloc(desugar_expr(arena, condition)); + let desugared_condition = + &*arena.alloc(desugar_expr(arena, condition, src, line_info, module_path)); Expect { condition: desugared_condition, preceding_comment: *preceding_comment, @@ -113,7 +121,8 @@ fn desugar_value_def<'a>(arena: &'a Bump, def: &'a ValueDef<'a>) -> ValueDef<'a> condition, preceding_comment, } => { - let desugared_condition = &*arena.alloc(desugar_expr(arena, condition)); + let desugared_condition = + &*arena.alloc(desugar_expr(arena, condition, src, line_info, module_path)); ExpectFx { condition: desugared_condition, preceding_comment: *preceding_comment, @@ -122,15 +131,27 @@ fn desugar_value_def<'a>(arena: &'a Bump, def: &'a ValueDef<'a>) -> ValueDef<'a> } } -pub fn desugar_defs<'a>(arena: &'a Bump, defs: &mut roc_parse::ast::Defs<'a>) { +pub fn desugar_defs<'a>( + arena: &'a Bump, + defs: &mut roc_parse::ast::Defs<'a>, + src: &'a str, + line_info: &mut Option, + module_path: &str, +) { for value_def in defs.value_defs.iter_mut() { - *value_def = desugar_value_def(arena, arena.alloc(*value_def)); + *value_def = desugar_value_def(arena, arena.alloc(*value_def), src, line_info, module_path); } } /// Reorder the expression tree based on operator precedence and associativity rules, /// then replace the BinOp nodes with Apply nodes. Also drop SpaceBefore and SpaceAfter nodes. -pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc>) -> &'a Loc> { +pub fn desugar_expr<'a>( + arena: &'a Bump, + loc_expr: &'a Loc>, + src: &'a str, + line_info: &mut Option, + module_path: &str, +) -> &'a Loc> { match &loc_expr.value { Float(..) | Num(..) @@ -153,16 +174,22 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc>) -> &'a Loc StrLiteral::PlainLine(_) => loc_expr, StrLiteral::Line(segments) => { let region = loc_expr.region; - let value = Str(StrLiteral::Line(desugar_str_segments(arena, segments))); + let value = Str(StrLiteral::Line(desugar_str_segments( + arena, + segments, + src, + line_info, + module_path, + ))); arena.alloc(Loc { region, value }) } StrLiteral::Block(lines) => { let region = loc_expr.region; let new_lines = Vec::from_iter_in( - lines - .iter() - .map(|segments| desugar_str_segments(arena, segments)), + lines.iter().map(|segments| { + desugar_str_segments(arena, segments, src, line_info, module_path) + }), arena, ); let value = Str(StrLiteral::Block(new_lines.into_bump_slice())); @@ -177,7 +204,17 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc>) -> &'a Loc region, value: **sub_expr, }; - let value = TupleAccess(&desugar_expr(arena, arena.alloc(loc_sub_expr)).value, paths); + let value = TupleAccess( + &desugar_expr( + arena, + arena.alloc(loc_sub_expr), + src, + line_info, + module_path, + ) + .value, + paths, + ); arena.alloc(Loc { region, value }) } @@ -187,7 +224,17 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc>) -> &'a Loc region, value: **sub_expr, }; - let value = RecordAccess(&desugar_expr(arena, arena.alloc(loc_sub_expr)).value, paths); + let value = RecordAccess( + &desugar_expr( + arena, + arena.alloc(loc_sub_expr), + src, + line_info, + module_path, + ) + .value, + paths, + ); arena.alloc(Loc { region, value }) } @@ -195,7 +242,7 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc>) -> &'a Loc let mut new_items = Vec::with_capacity_in(items.len(), arena); for item in items.iter() { - new_items.push(desugar_expr(arena, item)); + new_items.push(desugar_expr(arena, item, src, line_info, module_path)); } let new_items = new_items.into_bump_slice(); let value: Expr<'a> = List(items.replace_items(new_items)); @@ -205,32 +252,47 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc>) -> &'a Loc value, }) } - Record(fields) => arena.alloc(Loc { - region: loc_expr.region, - value: Record(fields.map_items(arena, |field| { - let value = desugar_field(arena, &field.value); - Loc { + Record(fields) => { + let mut allocated = Vec::with_capacity_in(fields.len(), arena); + for field in fields.iter() { + let value = desugar_field(arena, &field.value, src, line_info, module_path); + allocated.push(Loc { value, region: field.region, - } - })), - }), - Tuple(fields) => arena.alloc(Loc { - region: loc_expr.region, - value: Tuple(fields.map_items(arena, |field| desugar_expr(arena, field))), - }), + }); + } + let fields = fields.replace_items(allocated.into_bump_slice()); + arena.alloc(Loc { + region: loc_expr.region, + value: Record(fields), + }) + } + Tuple(fields) => { + let mut allocated = Vec::with_capacity_in(fields.len(), arena); + for field in fields.iter() { + let expr = desugar_expr(arena, field, src, line_info, module_path); + allocated.push(expr); + } + let fields = fields.replace_items(allocated.into_bump_slice()); + arena.alloc(Loc { + region: loc_expr.region, + value: Tuple(fields), + }) + } RecordUpdate { fields, update } => { // NOTE the `update` field is always a `Var { .. }`, we only desugar it to get rid of // any spaces before/after - let new_update = desugar_expr(arena, update); + let new_update = desugar_expr(arena, update, src, line_info, module_path); - let new_fields = fields.map_items(arena, |field| { - let value = desugar_field(arena, &field.value); - Loc { + let mut allocated = Vec::with_capacity_in(fields.len(), arena); + for field in fields.iter() { + let value = desugar_field(arena, &field.value, src, line_info, module_path); + allocated.push(Loc { value, region: field.region, - } - }); + }); + } + let new_fields = fields.replace_items(allocated.into_bump_slice()); arena.alloc(Loc { region: loc_expr.region, @@ -243,8 +305,8 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc>) -> &'a Loc Closure(loc_patterns, loc_ret) => arena.alloc(Loc { region: loc_expr.region, value: Closure( - desugar_loc_patterns(arena, loc_patterns), - desugar_expr(arena, loc_ret), + desugar_loc_patterns(arena, loc_patterns, src, line_info, module_path), + desugar_expr(arena, loc_ret, src, line_info, module_path), ), }), Backpassing(loc_patterns, loc_body, loc_ret) => { @@ -253,10 +315,11 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc>) -> &'a Loc // loc_ret // first desugar the body, because it may contain |> - let desugared_body = desugar_expr(arena, loc_body); + let desugared_body = desugar_expr(arena, loc_body, src, line_info, module_path); - let desugared_ret = desugar_expr(arena, loc_ret); - let desugared_loc_patterns = desugar_loc_patterns(arena, loc_patterns); + let desugared_ret = desugar_expr(arena, loc_ret, src, line_info, module_path); + let desugared_loc_patterns = + desugar_loc_patterns(arena, loc_patterns, src, line_info, module_path); let closure = Expr::Closure(desugared_loc_patterns, desugared_ret); let loc_closure = Loc::at(loc_expr.region, closure); @@ -289,12 +352,20 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc>) -> &'a Loc value: UnappliedRecordBuilder(loc_expr), region: loc_expr.region, }), - BinOps(lefts, right) => desugar_bin_ops(arena, loc_expr.region, lefts, right), + BinOps(lefts, right) => desugar_bin_ops( + arena, + loc_expr.region, + lefts, + right, + src, + line_info, + module_path, + ), Defs(defs, loc_ret) => { let mut defs = (*defs).clone(); - desugar_defs(arena, &mut defs); + desugar_defs(arena, &mut defs, src, line_info, module_path); - let loc_ret = desugar_expr(arena, loc_ret); + let loc_ret = desugar_expr(arena, loc_ret, src, line_info, module_path); arena.alloc(Loc::at(loc_expr.region, Defs(arena.alloc(defs), loc_ret))) } @@ -326,13 +397,17 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc>) -> &'a Loc } }; - desugared_args.push(desugar_expr(arena, arg)); + desugared_args.push(desugar_expr(arena, arg, src, line_info, module_path)); } let desugared_args = desugared_args.into_bump_slice(); let mut apply: &Loc = arena.alloc(Loc { - value: Apply(desugar_expr(arena, loc_fn), desugared_args, *called_via), + value: Apply( + desugar_expr(arena, loc_fn, src, line_info, module_path), + desugared_args, + *called_via, + ), region: loc_expr.region, }); @@ -341,7 +416,7 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc>) -> &'a Loc Some(apply_exprs) => { for expr in apply_exprs { - let desugared_expr = desugar_expr(arena, expr); + let desugared_expr = desugar_expr(arena, expr, src, line_info, module_path); let args = std::slice::from_ref(arena.alloc(apply)); @@ -356,15 +431,23 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc>) -> &'a Loc apply } When(loc_cond_expr, branches) => { - let loc_desugared_cond = &*arena.alloc(desugar_expr(arena, loc_cond_expr)); + let loc_desugared_cond = &*arena.alloc(desugar_expr( + arena, + loc_cond_expr, + src, + line_info, + module_path, + )); let mut desugared_branches = Vec::with_capacity_in(branches.len(), arena); for branch in branches.iter() { - let desugared_expr = desugar_expr(arena, &branch.value); - let desugared_patterns = desugar_loc_patterns(arena, branch.patterns); + let desugared_expr = + desugar_expr(arena, &branch.value, src, line_info, module_path); + let desugared_patterns = + desugar_loc_patterns(arena, branch.patterns, src, line_info, module_path); let desugared_guard = if let Some(guard) = &branch.guard { - Some(*desugar_expr(arena, guard)) + Some(*desugar_expr(arena, guard, src, line_info, module_path)) } else { None }; @@ -402,7 +485,8 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc>) -> &'a Loc }, }; let loc_fn_var = arena.alloc(Loc { region, value }); - let desugared_args = arena.alloc([desugar_expr(arena, loc_arg)]); + let desugared_args = + arena.alloc([desugar_expr(arena, loc_arg, src, line_info, module_path)]); arena.alloc(Loc { value: Apply(loc_fn_var, desugared_args, CalledVia::UnaryOp(op)), @@ -418,6 +502,9 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc>) -> &'a Loc value: **expr, region: loc_expr.region, }), + src, + line_info, + module_path, ) } ParensAround(expr) => { @@ -427,6 +514,9 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc>) -> &'a Loc value: **expr, region: loc_expr.region, }), + src, + line_info, + module_path, ); arena.alloc(Loc { @@ -436,14 +526,20 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc>) -> &'a Loc } If(if_thens, final_else_branch) => { // If does not get desugared into `when` so we can give more targeted error messages during type checking. - let desugared_final_else = &*arena.alloc(desugar_expr(arena, final_else_branch)); + let desugared_final_else = &*arena.alloc(desugar_expr( + arena, + final_else_branch, + src, + line_info, + module_path, + )); let mut desugared_if_thens = Vec::with_capacity_in(if_thens.len(), arena); for (condition, then_branch) in if_thens.iter() { desugared_if_thens.push(( - *desugar_expr(arena, condition), - *desugar_expr(arena, then_branch), + *desugar_expr(arena, condition, src, line_info, module_path), + *desugar_expr(arena, then_branch, src, line_info, module_path), )); } @@ -453,62 +549,85 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc>) -> &'a Loc }) } Expect(condition, continuation) => { - let desugared_condition = &*arena.alloc(desugar_expr(arena, condition)); - let desugared_continuation = &*arena.alloc(desugar_expr(arena, continuation)); + let desugared_condition = + &*arena.alloc(desugar_expr(arena, condition, src, line_info, module_path)); + let desugared_continuation = &*arena.alloc(desugar_expr( + arena, + continuation, + src, + line_info, + module_path, + )); arena.alloc(Loc { value: Expect(desugared_condition, desugared_continuation), region: loc_expr.region, }) } Dbg(condition, continuation) => { - // Desugars a `dbg x` statement into - // `roc_dbg (Inspect.toDbgStr (Inspect.inspect x))` - let desugared_continuation = &*arena.alloc(desugar_expr(arena, continuation)); + // Desugars a `dbg x` statement into essentially + // Inspect.toStr x |> LowLevelDbg + let desugared_continuation = &*arena.alloc(desugar_expr( + arena, + continuation, + src, + line_info, + module_path, + )); let region = condition.region; - // TODO desugar this in canonicalization instead, so we can work - // in terms of integers exclusively and not need to create strings - // which canonicalization then needs to look up, check if they're exposed, etc - let inspect = Var { + // Inspect.toStr x + let inspect_fn = Var { module_name: ModuleName::INSPECT, - ident: "inspect", + ident: "toStr", }; let loc_inspect_fn_var = arena.alloc(Loc { - value: inspect, + value: inspect_fn, region, }); - let desugared_inspect_args = arena.alloc([desugar_expr(arena, condition)]); + let desugared_inspect_args = + arena.alloc([desugar_expr(arena, condition, src, line_info, module_path)]); - let inspector = arena.alloc(Loc { + let dbg_str = arena.alloc(Loc { value: Apply(loc_inspect_fn_var, desugared_inspect_args, CalledVia::Space), region, }); - let to_dbg_str = Var { - module_name: ModuleName::INSPECT, - ident: "toDbgStr", - }; - let loc_to_dbg_str_fn_var = arena.alloc(Loc { - value: to_dbg_str, - region, - }); - let to_dbg_str_args = arena.alloc([&*inspector]); - let dbg_str = arena.alloc(Loc { - value: Apply(loc_to_dbg_str_fn_var, to_dbg_str_args, CalledVia::Space), - region, - }); + // line_info is an option so that we can lazily calculate it. + // That way it there are no `dbg` statements, we never pay the cast of scanning the source an extra time. + if matches!(line_info, None) { + *line_info = Some(LineInfo::new(src)); + } + let line_col = line_info.as_ref().unwrap().convert_pos(region.start()); + + let dbg_src = src + .split_at(region.start().offset as usize) + .1 + .split_at((region.end().offset - region.start().offset) as usize) + .0; + + // |> LowLevelDbg arena.alloc(Loc { - value: LowLevelDbg(dbg_str, desugared_continuation), + value: LowLevelDbg( + arena.alloc(( + &*arena.alloc_str(&format!("{}:{}", module_path, line_col.line + 1)), + &*arena.alloc_str(dbg_src), + )), + dbg_str, + desugared_continuation, + ), region: loc_expr.region, }) } - LowLevelDbg(_, _) => unreachable!("Only exists after desugaring"), + LowLevelDbg(_, _, _) => unreachable!("Only exists after desugaring"), } } fn desugar_str_segments<'a>( arena: &'a Bump, segments: &'a [StrSegment<'a>], + src: &'a str, + line_info: &mut Option, + module_path: &str, ) -> &'a [StrSegment<'a>] { Vec::from_iter_in( segments.iter().map(|segment| match segment { @@ -522,6 +641,9 @@ fn desugar_str_segments<'a>( region: loc_expr.region, value: *loc_expr.value, }), + src, + line_info, + module_path, ); StrSegment::Interpolated(Loc { region: loc_desugared.region, @@ -537,6 +659,9 @@ fn desugar_str_segments<'a>( fn desugar_field<'a>( arena: &'a Bump, field: &'a AssignedField<'a, Expr<'a>>, + src: &'a str, + line_info: &mut Option, + module_path: &str, ) -> AssignedField<'a, Expr<'a>> { use roc_parse::ast::AssignedField::*; @@ -547,7 +672,7 @@ fn desugar_field<'a>( region: loc_str.region, }, spaces, - desugar_expr(arena, loc_expr), + desugar_expr(arena, loc_expr, src, line_info, module_path), ), OptionalValue(loc_str, spaces, loc_expr) => OptionalValue( Loc { @@ -555,7 +680,7 @@ fn desugar_field<'a>( region: loc_str.region, }, spaces, - desugar_expr(arena, loc_expr), + desugar_expr(arena, loc_expr, src, line_info, module_path), ), LabelOnly(loc_str) => { // Desugar { x } into { x: x } @@ -573,11 +698,11 @@ fn desugar_field<'a>( region: loc_str.region, }, &[], - desugar_expr(arena, arena.alloc(loc_expr)), + desugar_expr(arena, arena.alloc(loc_expr), src, line_info, module_path), ) } - SpaceBefore(field, _spaces) => desugar_field(arena, field), - SpaceAfter(field, _spaces) => desugar_field(arena, field), + SpaceBefore(field, _spaces) => desugar_field(arena, field, src, line_info, module_path), + SpaceAfter(field, _spaces) => desugar_field(arena, field, src, line_info, module_path), Malformed(string) => Malformed(string), } @@ -586,11 +711,14 @@ fn desugar_field<'a>( fn desugar_loc_patterns<'a>( arena: &'a Bump, loc_patterns: &'a [Loc>], + src: &'a str, + line_info: &mut Option, + module_path: &str, ) -> &'a [Loc>] { Vec::from_iter_in( loc_patterns.iter().map(|loc_pattern| Loc { region: loc_pattern.region, - value: desugar_pattern(arena, loc_pattern.value), + value: desugar_pattern(arena, loc_pattern.value, src, line_info, module_path), }), arena, ) @@ -600,14 +728,23 @@ fn desugar_loc_patterns<'a>( fn desugar_loc_pattern<'a>( arena: &'a Bump, loc_pattern: &'a Loc>, + src: &'a str, + line_info: &mut Option, + module_path: &str, ) -> &'a Loc> { arena.alloc(Loc { region: loc_pattern.region, - value: desugar_pattern(arena, loc_pattern.value), + value: desugar_pattern(arena, loc_pattern.value, src, line_info, module_path), }) } -fn desugar_pattern<'a>(arena: &'a Bump, pattern: Pattern<'a>) -> Pattern<'a> { +fn desugar_pattern<'a>( + arena: &'a Bump, + pattern: Pattern<'a>, + src: &'a str, + line_info: &mut Option, + module_path: &str, +) -> Pattern<'a> { use roc_parse::ast::Pattern::*; match pattern { @@ -630,7 +767,7 @@ fn desugar_pattern<'a>(arena: &'a Bump, pattern: Pattern<'a>) -> Pattern<'a> { let desugared_arg_patterns = Vec::from_iter_in( arg_patterns.iter().map(|arg_pattern| Loc { region: arg_pattern.region, - value: desugar_pattern(arena, arg_pattern.value), + value: desugar_pattern(arena, arg_pattern.value, src, line_info, module_path), }), arena, ) @@ -639,26 +776,62 @@ fn desugar_pattern<'a>(arena: &'a Bump, pattern: Pattern<'a>) -> Pattern<'a> { Apply(tag, desugared_arg_patterns) } RecordDestructure(field_patterns) => { - RecordDestructure(field_patterns.map_items(arena, |field_pattern| Loc { - region: field_pattern.region, - value: desugar_pattern(arena, field_pattern.value), - })) + let mut allocated = Vec::with_capacity_in(field_patterns.len(), arena); + for field_pattern in field_patterns.iter() { + let value = + desugar_pattern(arena, field_pattern.value, src, line_info, module_path); + allocated.push(Loc { + value, + region: field_pattern.region, + }); + } + let field_patterns = field_patterns.replace_items(allocated.into_bump_slice()); + + RecordDestructure(field_patterns) } - RequiredField(name, field_pattern) => { - RequiredField(name, desugar_loc_pattern(arena, field_pattern)) + RequiredField(name, field_pattern) => RequiredField( + name, + desugar_loc_pattern(arena, field_pattern, src, line_info, module_path), + ), + OptionalField(name, expr) => { + OptionalField(name, desugar_expr(arena, expr, src, line_info, module_path)) + } + Tuple(patterns) => { + let mut allocated = Vec::with_capacity_in(patterns.len(), arena); + for pattern in patterns.iter() { + let value = desugar_pattern(arena, pattern.value, src, line_info, module_path); + allocated.push(Loc { + value, + region: pattern.region, + }); + } + let patterns = patterns.replace_items(allocated.into_bump_slice()); + + Tuple(patterns) + } + List(patterns) => { + let mut allocated = Vec::with_capacity_in(patterns.len(), arena); + for pattern in patterns.iter() { + let value = desugar_pattern(arena, pattern.value, src, line_info, module_path); + allocated.push(Loc { + value, + region: pattern.region, + }); + } + let patterns = patterns.replace_items(allocated.into_bump_slice()); + + List(patterns) + } + As(sub_pattern, symbol) => As( + desugar_loc_pattern(arena, sub_pattern, src, line_info, module_path), + symbol, + ), + SpaceBefore(sub_pattern, _spaces) => { + desugar_pattern(arena, *sub_pattern, src, line_info, module_path) + } + SpaceAfter(sub_pattern, _spaces) => { + desugar_pattern(arena, *sub_pattern, src, line_info, module_path) } - OptionalField(name, expr) => OptionalField(name, desugar_expr(arena, expr)), - Tuple(patterns) => Tuple(patterns.map_items(arena, |elem_pattern| Loc { - region: elem_pattern.region, - value: desugar_pattern(arena, elem_pattern.value), - })), - List(patterns) => List(patterns.map_items(arena, |elem_pattern| Loc { - region: elem_pattern.region, - value: desugar_pattern(arena, elem_pattern.value), - })), - As(sub_pattern, symbol) => As(desugar_loc_pattern(arena, sub_pattern), symbol), - SpaceBefore(sub_pattern, _spaces) => desugar_pattern(arena, *sub_pattern), - SpaceAfter(sub_pattern, _spaces) => desugar_pattern(arena, *sub_pattern), } } @@ -787,19 +960,22 @@ fn desugar_bin_ops<'a>( whole_region: Region, lefts: &'a [(Loc>, Loc)], right: &'a Loc>, + src: &'a str, + line_info: &mut Option, + module_path: &str, ) -> &'a Loc> { let mut arg_stack: Vec<&'a Loc> = Vec::with_capacity_in(lefts.len() + 1, arena); let mut op_stack: Vec> = Vec::with_capacity_in(lefts.len(), arena); for (loc_expr, loc_op) in lefts { - arg_stack.push(desugar_expr(arena, loc_expr)); + arg_stack.push(desugar_expr(arena, loc_expr, src, line_info, module_path)); match run_binop_step(arena, whole_region, &mut arg_stack, &mut op_stack, *loc_op) { Err(problem) => return problem, Ok(()) => continue, } } - let mut expr = desugar_expr(arena, right); + let mut expr = desugar_expr(arena, right, src, line_info, module_path); for (left, loc_op) in arg_stack.into_iter().zip(op_stack.into_iter()).rev() { expr = arena.alloc(new_op_call_expr(arena, left, loc_op, expr)); diff --git a/crates/compiler/can/src/traverse.rs b/crates/compiler/can/src/traverse.rs index eb92dc14da..f92ae773be 100644 --- a/crates/compiler/can/src/traverse.rs +++ b/crates/compiler/can/src/traverse.rs @@ -387,6 +387,8 @@ pub fn walk_expr(visitor: &mut V, expr: &Expr, var: Variable) { } Expr::Dbg { variable, + source: _, + source_location: _, loc_message, loc_continuation, symbol: _, diff --git a/crates/compiler/can/tests/helpers/mod.rs b/crates/compiler/can/tests/helpers/mod.rs index d2f95267c6..9ebe60e662 100644 --- a/crates/compiler/can/tests/helpers/mod.rs +++ b/crates/compiler/can/tests/helpers/mod.rs @@ -52,7 +52,13 @@ pub fn can_expr_with(arena: &Bump, home: ModuleId, expr_str: &str) -> CanExprOut // visited a BinOp node we'd recursively try to apply this to each of its nested // operators, and then again on *their* nested operators, ultimately applying the // rules multiple times unnecessarily. - let loc_expr = operator::desugar_expr(arena, &loc_expr); + let loc_expr = operator::desugar_expr( + arena, + &loc_expr, + expr_str, + &mut None, + arena.alloc("TestPath"), + ); let mut scope = Scope::new(home, IdentIds::default(), Default::default()); scope.add_alias( diff --git a/crates/compiler/constrain/src/expr.rs b/crates/compiler/constrain/src/expr.rs index 0779f8cfcd..6c64843c72 100644 --- a/crates/compiler/constrain/src/expr.rs +++ b/crates/compiler/constrain/src/expr.rs @@ -741,6 +741,8 @@ pub fn constrain_expr( } Dbg { + source_location: _, + source: _, loc_message, loc_continuation, variable, diff --git a/crates/compiler/fmt/src/def.rs b/crates/compiler/fmt/src/def.rs index 456ff34b34..fa2897c479 100644 --- a/crates/compiler/fmt/src/def.rs +++ b/crates/compiler/fmt/src/def.rs @@ -302,25 +302,14 @@ fn should_outdent(mut rhs: &TypeAnnotation) -> bool { } } -fn fmt_dbg_in_def<'a>( - buf: &mut Buf, - condition: &'a Loc>, - is_multiline: bool, - indent: u16, -) { +fn fmt_dbg_in_def<'a>(buf: &mut Buf, condition: &'a Loc>, _: bool, indent: u16) { buf.ensure_ends_with_newline(); buf.indent(indent); buf.push_str("dbg"); - let return_indent = if is_multiline { - buf.newline(); - indent + INDENT - } else { - buf.spaces(1); - indent - }; + buf.spaces(1); - condition.format(buf, return_indent); + condition.format(buf, indent); } fn fmt_expect<'a>(buf: &mut Buf, condition: &'a Loc>, is_multiline: bool, indent: u16) { diff --git a/crates/compiler/fmt/src/expr.rs b/crates/compiler/fmt/src/expr.rs index 39e6bce4ee..31cbf781c9 100644 --- a/crates/compiler/fmt/src/expr.rs +++ b/crates/compiler/fmt/src/expr.rs @@ -61,8 +61,8 @@ impl<'a> Formattable for Expr<'a> { Expect(condition, continuation) => { condition.is_multiline() || continuation.is_multiline() } - Dbg(condition, continuation) => condition.is_multiline() || continuation.is_multiline(), - LowLevelDbg(_, _) => unreachable!( + Dbg(condition, _) => condition.is_multiline(), + LowLevelDbg(_, _, _) => unreachable!( "LowLevelDbg should only exist after desugaring, not during formatting" ), @@ -438,7 +438,7 @@ impl<'a> Formattable for Expr<'a> { Dbg(condition, continuation) => { fmt_dbg(buf, condition, continuation, self.is_multiline(), indent); } - LowLevelDbg(_, _) => unreachable!( + LowLevelDbg(_, _, _) => unreachable!( "LowLevelDbg should only exist after desugaring, not during formatting" ), If(branches, final_else) => { @@ -956,22 +956,16 @@ fn fmt_dbg<'a>( buf: &mut Buf, condition: &'a Loc>, continuation: &'a Loc>, - is_multiline: bool, + _: bool, indent: u16, ) { buf.ensure_ends_with_newline(); buf.indent(indent); buf.push_str("dbg"); - let return_indent = if is_multiline { - buf.newline(); - indent + INDENT - } else { - buf.spaces(1); - indent - }; + buf.spaces(1); - condition.format(buf, return_indent); + condition.format(buf, indent); // Always put a blank line after the `dbg` line(s) buf.ensure_ends_with_blank_line(); diff --git a/crates/compiler/fmt/src/spaces.rs b/crates/compiler/fmt/src/spaces.rs index 255b18ae56..6bec246881 100644 --- a/crates/compiler/fmt/src/spaces.rs +++ b/crates/compiler/fmt/src/spaces.rs @@ -5,8 +5,8 @@ use roc_parse::{ ast::{ AbilityImpls, AbilityMember, AssignedField, Collection, CommentOrNewline, Defs, Expr, Header, Implements, ImplementsAbilities, ImplementsAbility, ImplementsClause, Module, - Pattern, RecordBuilderField, Spaced, Spaces, StrLiteral, StrSegment, Tag, TypeAnnotation, - TypeDef, TypeHeader, ValueDef, WhenBranch, + Pattern, PatternAs, RecordBuilderField, Spaced, Spaces, StrLiteral, StrSegment, Tag, + TypeAnnotation, TypeDef, TypeHeader, ValueDef, WhenBranch, }, header::{ AppHeader, ExposedName, HostedHeader, ImportsEntry, InterfaceHeader, KeywordItem, @@ -726,7 +726,7 @@ impl<'a> RemoveSpaces<'a> for Expr<'a> { arena.alloc(a.remove_spaces(arena)), arena.alloc(b.remove_spaces(arena)), ), - Expr::LowLevelDbg(_, _) => unreachable!( + Expr::LowLevelDbg(_, _, _) => unreachable!( "LowLevelDbg should only exist after desugaring, not during formatting" ), Expr::Apply(a, b, c) => Expr::Apply( @@ -800,9 +800,10 @@ impl<'a> RemoveSpaces<'a> for Pattern<'a> { Pattern::OptionalField(a, b) => { Pattern::OptionalField(a, arena.alloc(b.remove_spaces(arena))) } - Pattern::As(pattern, pattern_as) => { - Pattern::As(arena.alloc(pattern.remove_spaces(arena)), pattern_as) - } + Pattern::As(pattern, pattern_as) => Pattern::As( + arena.alloc(pattern.remove_spaces(arena)), + pattern_as.remove_spaces(arena), + ), Pattern::NumLiteral(a) => Pattern::NumLiteral(a), Pattern::NonBase10Literal { string, @@ -826,7 +827,10 @@ impl<'a> RemoveSpaces<'a> for Pattern<'a> { Pattern::SingleQuote(a) => Pattern::SingleQuote(a), Pattern::List(pats) => Pattern::List(pats.remove_spaces(arena)), Pattern::Tuple(pats) => Pattern::Tuple(pats.remove_spaces(arena)), - Pattern::ListRest(opt_pattern_as) => Pattern::ListRest(opt_pattern_as), + Pattern::ListRest(opt_pattern_as) => Pattern::ListRest( + opt_pattern_as + .map(|(_, pattern_as)| ([].as_ref(), pattern_as.remove_spaces(arena))), + ), } } } @@ -936,3 +940,12 @@ impl<'a> RemoveSpaces<'a> for ImplementsAbilities<'a> { } } } + +impl<'a> RemoveSpaces<'a> for PatternAs<'a> { + fn remove_spaces(&self, arena: &'a Bump) -> Self { + PatternAs { + spaces_before: &[], + identifier: self.identifier.remove_spaces(arena), + } + } +} diff --git a/crates/compiler/gen_dev/README.md b/crates/compiler/gen_dev/README.md index 22fb5b8dbb..7b055d711a 100644 --- a/crates/compiler/gen_dev/README.md +++ b/crates/compiler/gen_dev/README.md @@ -103,7 +103,7 @@ main = If this file exists somewhere in the repo as `dbg.roc`, we'll be able to compile an object file by issuing the following command: ```console -# `cargo run --` can be replaces with calling the compiled `roc` cli binary. +# `cargo run --` can be replaced with calling the compiled `roc` cli binary. $ cargo run -- build --dev main.roc --no-link ``` @@ -152,7 +152,7 @@ The output lines contain the hexadecimal representation of the x86 opcodes and f As a note, when dealing with relocations, please make sure to compile with PIC. - [Online Assembler](https://defuse.ca/online-x86-assembler.htm#disassembly) - Useful for seeing the actual bytes generated by assembly instructions. - A lot of time it gives on out of multiple options because x86_64 has many ways to do things. + A lot of time it gives one out of multiple options because x86_64 has many ways to do things. 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. diff --git a/crates/compiler/gen_dev/src/lib.rs b/crates/compiler/gen_dev/src/lib.rs index cc1f9c9c62..93a5fb914b 100644 --- a/crates/compiler/gen_dev/src/lib.rs +++ b/crates/compiler/gen_dev/src/lib.rs @@ -1765,6 +1765,21 @@ trait Backend<'a> { let intrinsic = bitcode::NUM_IS_MULTIPLE_OF[int_width].to_string(); self.build_fn_call(sym, intrinsic, args, arg_layouts, ret_layout); } + LowLevel::NumCountLeadingZeroBits => { + let int_width = arg_layouts[0].try_int_width().unwrap(); + let intrinsic = bitcode::NUM_COUNT_LEADING_ZERO_BITS[int_width].to_string(); + self.build_fn_call(sym, intrinsic, args, arg_layouts, ret_layout); + } + LowLevel::NumCountTrailingZeroBits => { + let int_width = arg_layouts[0].try_int_width().unwrap(); + let intrinsic = bitcode::NUM_COUNT_TRAILING_ZERO_BITS[int_width].to_string(); + self.build_fn_call(sym, intrinsic, args, arg_layouts, ret_layout); + } + LowLevel::NumCountOneBits => { + let int_width = arg_layouts[0].try_int_width().unwrap(); + let intrinsic = bitcode::NUM_COUNT_ONE_BITS[int_width].to_string(); + self.build_fn_call(sym, intrinsic, args, arg_layouts, ret_layout); + } LowLevel::ListSublist => { // list: RocList, // alignment: u32, diff --git a/crates/compiler/gen_llvm/src/llvm/bitcode.rs b/crates/compiler/gen_llvm/src/llvm/bitcode.rs index 3e8c8da91c..405bf03ec7 100644 --- a/crates/compiler/gen_llvm/src/llvm/bitcode.rs +++ b/crates/compiler/gen_llvm/src/llvm/bitcode.rs @@ -30,12 +30,25 @@ pub fn call_bitcode_fn<'ctx>( args: &[BasicValueEnum<'ctx>], fn_name: &str, ) -> BasicValueEnum<'ctx> { - call_bitcode_fn_help(env, args, fn_name) + let ret = call_bitcode_fn_help(env, args, fn_name) .try_as_basic_value() .left() .unwrap_or_else(|| { panic!("LLVM error: Did not get return value from bitcode function {fn_name:?}") - }) + }); + + if env.target_info.operating_system == roc_target::OperatingSystem::Windows { + // On windows zig uses a vector type <2xi64> instead of a i128 value + let vec_type = env.context.i64_type().vec_type(2); + if ret.get_type() == vec_type.into() { + return env + .builder + .build_bitcast(ret, env.context.i128_type(), "return_i128") + .unwrap(); + } + } + + ret } pub fn call_void_bitcode_fn<'ctx>( @@ -54,7 +67,35 @@ fn call_bitcode_fn_help<'ctx>( args: &[BasicValueEnum<'ctx>], fn_name: &str, ) -> CallSiteValue<'ctx> { - let it = args.iter().map(|x| (*x).into()); + let it = args + .iter() + .map(|x| { + if env.target_info.operating_system == roc_target::OperatingSystem::Windows { + if x.get_type() == env.context.i128_type().into() { + let parent = env + .builder + .get_insert_block() + .and_then(|b| b.get_parent()) + .unwrap(); + + let alloca = create_entry_block_alloca( + env, + parent, + x.get_type(), + "pass_u128_by_reference", + ); + + env.builder.build_store(alloca, *x).unwrap(); + + alloca.into() + } else { + *x + } + } else { + *x + } + }) + .map(|x| (x).into()); let arguments = bumpalo::collections::Vec::from_iter_in(it, env.arena); let fn_val = env diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index bef89a58d6..03292d1a62 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -710,7 +710,7 @@ impl LlvmBackendMode { match self { LlvmBackendMode::Binary => false, LlvmBackendMode::BinaryDev => false, - LlvmBackendMode::BinaryGlue => false, + LlvmBackendMode::BinaryGlue => true, LlvmBackendMode::GenTest => true, LlvmBackendMode::WasmGenTest => true, LlvmBackendMode::CliTest => true, @@ -910,16 +910,19 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> { &self, env: &Env<'a, 'ctx, 'env>, location: BasicValueEnum<'ctx>, + source: BasicValueEnum<'ctx>, message: BasicValueEnum<'ctx>, ) { let function = self.module.get_function("roc_dbg").unwrap(); let loc = self.string_to_arg(env, location); + let src = self.string_to_arg(env, source); let msg = self.string_to_arg(env, message); - let call = self - .builder - .new_build_call(function, &[loc.into(), msg.into()], "roc_dbg"); + // TODO: at some point it will be a breaking change, but flip order to (loc, src, msg) + let call = + self.builder + .new_build_call(function, &[loc.into(), msg.into(), src.into()], "roc_dbg"); call.set_call_convention(C_CALL_CONV); } @@ -1055,6 +1058,55 @@ pub fn module_from_builtins<'ctx>( let module = Module::parse_bitcode_from_buffer(&memory_buffer, ctx) .unwrap_or_else(|err| panic!("Unable to import builtins bitcode. LLVM error: {err:?}")); + // In testing, this adds about 20ms extra to compilation. + // Long term it would be best if we could do this on the zig side. + // The core issue is that we have to properly labael certain functions as private and DCE them. + // Otherwise, now that zig bundles all of compiler-rt, we would optimize and compile the entire library. + // Anything not depended on by a `roc_builtin.` function could already by DCE'd theoretically. + // That said, this workaround is good enough and fixes compilations times. + + // Also, must_keep is the functions we depend on that would normally be provide by libc. + // They are magically linked to by llvm builtins, so we must specify that they can't be DCE'd. + let must_keep = [ + "_fltused", + "floorf", + "memcpy", + "memset", + // I have no idea why this function is special. + // Without it, some tests hang on M1 mac outside of nix. + "__muloti4", + // fixes `Undefined Symbol in relocation` + "__udivti3", + // Roc special functions + "__roc_force_longjmp", + "__roc_force_setjmp", + "set_shared_buffer", + ]; + for func in module.get_functions() { + let has_definition = func.count_basic_blocks() > 0; + let name = func.get_name().to_string_lossy(); + if has_definition + && !name.starts_with("roc_builtins.") + && !must_keep.contains(&name.as_ref()) + { + func.set_linkage(Linkage::Private); + } + } + + // Note, running DCE here is faster then waiting until full app DCE. + let mpm = PassManager::create(()); + mpm.add_global_dce_pass(); + mpm.run_on(&module); + + // Now that the unused compiler-rt functions have been removed, + // mark that the builtin functions are allowed to be DCE'd if they aren't used. + for func in module.get_functions() { + let name = func.get_name().to_string_lossy(); + if name.starts_with("roc_builtins.") { + func.set_linkage(Linkage::Private); + } + } + // Add LLVM intrinsics. add_intrinsics(ctx, &module); @@ -1227,6 +1279,8 @@ fn promote_to_wasm_test_wrapper<'a, 'ctx>( let subprogram = env.new_subprogram(main_fn_name); c_function.set_subprogram(subprogram); + debug_info_init!(env, c_function); + // STEP 2: build the exposed function's body let builder = env.builder; let context = env.context; @@ -3527,17 +3581,17 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>( } Dbg { + source_location, + source, symbol, variable: _, remainder, } => { if env.mode.runs_expects() { - // TODO: Change location to `filename:line_number` - // let region = unsafe { std::mem::transmute::<_, roc_region::all::Region>(*symbol) }; - let location = - build_string_literal(env, parent, symbol.module_string(&env.interns)); + let location = build_string_literal(env, parent, source_location); + let source = build_string_literal(env, parent, source); let message = scope.load_symbol(symbol); - env.call_dbg(env, location, message); + env.call_dbg(env, location, source, message); } build_exp_stmt( @@ -4363,6 +4417,8 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx>( let subprogram = env.new_subprogram(c_function_name); c_function.set_subprogram(subprogram); + debug_info_init!(env, c_function); + // STEP 2: build the exposed function's body let builder = env.builder; let context = env.context; @@ -4371,8 +4427,6 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx>( builder.position_at_end(entry); - debug_info_init!(env, c_function); - // drop the first argument, which is the pointer we write the result into let args_vector = c_function.get_params(); let mut args = args_vector.as_slice(); @@ -4413,29 +4467,68 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx>( } } - let arguments_for_call = &arguments_for_call.into_bump_slice(); - let call_result = if env.mode.returns_roc_result() { - debug_assert_eq!(args.len(), roc_function.get_params().len()); + if args.len() == roc_function.get_params().len() { + let arguments_for_call = &arguments_for_call.into_bump_slice(); - let roc_wrapper_function = - make_exception_catcher(env, layout_interner, roc_function, return_layout); - debug_assert_eq!( - arguments_for_call.len(), - roc_wrapper_function.get_params().len() - ); + let dbg_loc = builder.get_current_debug_location().unwrap(); + let roc_wrapper_function = + make_exception_catcher(env, layout_interner, roc_function, return_layout); + debug_assert_eq!( + arguments_for_call.len(), + roc_wrapper_function.get_params().len() + ); - builder.position_at_end(entry); + builder.position_at_end(entry); + builder.set_current_debug_location(dbg_loc); - let wrapped_layout = roc_call_result_layout(env.arena, return_layout); - call_direct_roc_function( - env, - layout_interner, - roc_function, - wrapped_layout, - arguments_for_call, - ) + let wrapped_layout = roc_call_result_layout(env.arena, return_layout); + call_direct_roc_function( + env, + layout_interner, + roc_function, + wrapped_layout, + arguments_for_call, + ) + } else { + debug_assert_eq!(args.len() + 1, roc_function.get_params().len()); + + arguments_for_call.push(args[0]); + + let arguments_for_call = &arguments_for_call.into_bump_slice(); + + let dbg_loc = builder.get_current_debug_location().unwrap(); + let roc_wrapper_function = + make_exception_catcher(env, layout_interner, roc_function, return_layout); + + builder.position_at_end(entry); + builder.set_current_debug_location(dbg_loc); + + let wrapped_layout = roc_call_result_layout(env.arena, return_layout); + let call_result = call_direct_roc_function( + env, + layout_interner, + roc_wrapper_function, + wrapped_layout, + arguments_for_call, + ); + + let output_arg_index = 0; + + let output_arg = c_function + .get_nth_param(output_arg_index as u32) + .unwrap() + .into_pointer_value(); + + env.builder.new_build_store(output_arg, call_result); + + builder.new_build_return(None); + + return c_function; + } } else { + let arguments_for_call = &arguments_for_call.into_bump_slice(); + call_direct_roc_function( env, layout_interner, @@ -4459,6 +4552,7 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx>( output_arg, call_result, ); + builder.new_build_return(None); c_function @@ -4511,6 +4605,8 @@ fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx>( let subprogram = env.new_subprogram(c_function_name); c_function.set_subprogram(subprogram); + debug_info_init!(env, c_function); + // STEP 2: build the exposed function's body let builder = env.builder; let context = env.context; @@ -4519,8 +4615,6 @@ fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx>( builder.position_at_end(entry); - debug_info_init!(env, c_function); - // drop the final argument, which is the pointer we write the result into let args_vector = c_function.get_params(); let mut args = args_vector.as_slice(); @@ -4567,10 +4661,12 @@ fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx>( let (call_result, call_result_layout) = { let last_block = builder.get_insert_block().unwrap(); + let dbg_loc = builder.get_current_debug_location().unwrap(); let roc_wrapper_function = make_exception_catcher(env, layout_interner, roc_function, return_layout); builder.position_at_end(last_block); + builder.set_current_debug_location(dbg_loc); let wrapper_result = roc_call_result_layout(env.arena, return_layout); @@ -4622,12 +4718,12 @@ fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx>( let subprogram = env.new_subprogram(&size_function_name); size_function.set_subprogram(subprogram); + debug_info_init!(env, size_function); + let entry = context.append_basic_block(size_function, "entry"); builder.position_at_end(entry); - debug_info_init!(env, size_function); - let size: BasicValueEnum = return_type.size_of().unwrap().into(); builder.new_build_return(Some(&size)); @@ -4713,6 +4809,8 @@ fn expose_function_to_host_help_c_abi_v2<'a, 'ctx>( let subprogram = env.new_subprogram(c_function_name); c_function.set_subprogram(subprogram); + debug_info_init!(env, c_function); + // STEP 2: build the exposed function's body let builder = env.builder; let context = env.context; @@ -4941,12 +5039,12 @@ fn expose_function_to_host_help_c_abi<'a, 'ctx>( let subprogram = env.new_subprogram(&size_function_name); size_function.set_subprogram(subprogram); + debug_info_init!(env, size_function); + let entry = env.context.append_basic_block(size_function, "entry"); env.builder.position_at_end(entry); - debug_info_init!(env, size_function); - let return_type = match env.mode { LlvmBackendMode::GenTest | LlvmBackendMode::WasmGenTest | LlvmBackendMode::CliTest => { roc_call_result_type(env, roc_function.get_type().get_return_type().unwrap()).into() @@ -5343,6 +5441,8 @@ fn make_exception_catching_wrapper<'a, 'ctx>( let subprogram = env.new_subprogram(wrapper_function_name); wrapper_function.set_subprogram(subprogram); + debug_info_init!(env, wrapper_function); + // The exposed main function must adhere to the C calling convention, but the wrapper can still be fastcc. wrapper_function.set_call_conventions(FAST_CALL_CONV); @@ -5819,6 +5919,8 @@ fn build_proc_header<'a, 'ctx>( let subprogram = env.new_subprogram(&fn_name); fn_val.set_subprogram(subprogram); + debug_info_init!(env, fn_val); + if env.exposed_to_host.contains(&symbol) { let arguments = Vec::from_iter_in(proc.args.iter().map(|(layout, _)| *layout), env.arena); expose_function_to_host( diff --git a/crates/compiler/gen_llvm/src/llvm/build_list.rs b/crates/compiler/gen_llvm/src/llvm/build_list.rs index eff73dca32..8c3d899fc9 100644 --- a/crates/compiler/gen_llvm/src/llvm/build_list.rs +++ b/crates/compiler/gen_llvm/src/llvm/build_list.rs @@ -450,7 +450,7 @@ pub(crate) fn list_capacity_or_ref_ptr<'ctx>( // Gets a pointer to just after the refcount for a list or seamless slice. // The value is just after the refcount so that normal lists and seamless slices can share code paths easily. -pub(crate) fn list_refcount_ptr<'ctx>( +pub(crate) fn list_allocation_ptr<'ctx>( env: &Env<'_, 'ctx, '_>, wrapper_struct: StructValue<'ctx>, ) -> PointerValue<'ctx> { @@ -459,7 +459,7 @@ pub(crate) fn list_refcount_ptr<'ctx>( &[wrapper_struct], &[], BitcodeReturns::Basic, - bitcode::LIST_REFCOUNT_PTR, + bitcode::LIST_ALLOCATION_PTR, ) .into_pointer_value() } @@ -864,7 +864,7 @@ pub(crate) fn decref<'ctx>( wrapper_struct: StructValue<'ctx>, alignment: u32, ) { - let refcount_ptr = list_refcount_ptr(env, wrapper_struct); + let refcount_ptr = list_allocation_ptr(env, wrapper_struct); crate::llvm::refcounting::decref_pointer_check_null(env, refcount_ptr, alignment); } diff --git a/crates/compiler/gen_llvm/src/llvm/build_str.rs b/crates/compiler/gen_llvm/src/llvm/build_str.rs index 97924c7ce5..2e1af6f89b 100644 --- a/crates/compiler/gen_llvm/src/llvm/build_str.rs +++ b/crates/compiler/gen_llvm/src/llvm/build_str.rs @@ -48,7 +48,7 @@ pub(crate) fn str_equal<'ctx>( // Gets a pointer to just after the refcount for a list or seamless slice. // The value is just after the refcount so that normal lists and seamless slices can share code paths easily. -pub(crate) fn str_refcount_ptr<'ctx>( +pub(crate) fn str_allocation_ptr<'ctx>( env: &Env<'_, 'ctx, '_>, value: BasicValueEnum<'ctx>, ) -> PointerValue<'ctx> { @@ -57,7 +57,7 @@ pub(crate) fn str_refcount_ptr<'ctx>( &[value], &[], BitcodeReturns::Basic, - bitcode::STR_REFCOUNT_PTR, + bitcode::STR_ALLOCATION_PTR, ) .into_pointer_value() } diff --git a/crates/compiler/gen_llvm/src/llvm/expect.rs b/crates/compiler/gen_llvm/src/llvm/expect.rs index 8f48ec09d9..4cfeab970d 100644 --- a/crates/compiler/gen_llvm/src/llvm/expect.rs +++ b/crates/compiler/gen_llvm/src/llvm/expect.rs @@ -469,6 +469,8 @@ fn build_clone_tag<'a, 'ctx>( let subprogram = env.new_subprogram(&fn_name); function_value.set_subprogram(subprogram); + debug_info_init!(env, function_value); + env.dibuilder.finalize(); build_clone_tag_help( diff --git a/crates/compiler/gen_llvm/src/llvm/externs.rs b/crates/compiler/gen_llvm/src/llvm/externs.rs index c79a1a8e23..8c5be59ffe 100644 --- a/crates/compiler/gen_llvm/src/llvm/externs.rs +++ b/crates/compiler/gen_llvm/src/llvm/externs.rs @@ -1,3 +1,4 @@ +use crate::debug_info_init; use crate::llvm::bitcode::call_void_bitcode_fn; use crate::llvm::build::{add_func, get_panic_msg_ptr, get_panic_tag_ptr, BuilderExt, C_CALL_CONV}; use crate::llvm::build::{CCReturn, Env, FunctionSpec}; @@ -160,8 +161,39 @@ pub fn add_default_roc_externs(env: &Env<'_, '_, '_>) { } } - // TODO: generate a valid impl of dbg here. - unreachable_function(env, "roc_dbg"); + // roc_dbg + { + // The type of this function (but not the implementation) should have + // already been defined by the builtins, which rely on it. + let fn_val = module.get_function("roc_dbg").unwrap(); + let mut params = fn_val.get_param_iter(); + let loc_arg = params.next().unwrap(); + let msg_arg = params.next().unwrap(); + let src_arg = params.next().unwrap(); + + debug_assert!(params.next().is_none()); + + // Add a basic block for the entry point + let entry = ctx.append_basic_block(fn_val, "entry"); + + builder.position_at_end(entry); + + // Call utils.dbg_impl() + let dbg_impl = module.get_function(bitcode::UTILS_DBG_IMPL).unwrap(); + let call = builder.new_build_call( + dbg_impl, + &[loc_arg.into(), msg_arg.into(), src_arg.into()], + "call_utils_dbg_impl", + ); + + call.set_call_convention(C_CALL_CONV); + + builder.new_build_return(None); + + if cfg!(debug_assertions) { + crate::llvm::build::verify_fn(fn_val); + } + } match env.target_info.operating_system { roc_target::OperatingSystem::Windows => { @@ -223,6 +255,8 @@ pub fn add_sjlj_roc_panic(env: &Env<'_, '_, '_>) { let subprogram = env.new_subprogram("roc_panic"); fn_val.set_subprogram(subprogram); + debug_info_init!(env, fn_val); + env.dibuilder.finalize(); // Add a basic block for the entry point diff --git a/crates/compiler/gen_llvm/src/llvm/intrinsics.rs b/crates/compiler/gen_llvm/src/llvm/intrinsics.rs index c11866746b..728f080c5e 100644 --- a/crates/compiler/gen_llvm/src/llvm/intrinsics.rs +++ b/crates/compiler/gen_llvm/src/llvm/intrinsics.rs @@ -80,10 +80,6 @@ pub(crate) fn add_intrinsics<'ctx>(ctx: &'ctx Context, module: &Module<'ctx>) { let i32_type = ctx.i32_type(); let void_type = ctx.void_type(); - if let Some(func) = module.get_function("__muloti4") { - func.set_linkage(Linkage::WeakAny); - } - add_intrinsic( ctx, module, diff --git a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs index ea9fbdecf3..2bf059aff5 100644 --- a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs +++ b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs @@ -1100,13 +1100,22 @@ pub(crate) fn run_low_level<'a, 'ctx>( NumBytesToU128 => { arguments!(list, position); - call_list_bitcode_fn( + let ret = call_list_bitcode_fn( env, &[list.into_struct_value()], &[position], BitcodeReturns::Basic, bitcode::NUM_BYTES_TO_U128, - ) + ); + + if env.target_info.operating_system == roc_target::OperatingSystem::Windows { + // On windows the return type is not a i128, likely due to alignment + env.builder + .build_bitcast(ret, env.context.i128_type(), "empty_string") + .unwrap() + } else { + ret + } } NumCompare => { arguments_with_layouts!((lhs_arg, lhs_layout), (rhs_arg, rhs_layout)); @@ -1535,7 +1544,7 @@ fn build_int_binop<'ctx>( ) .into_struct_value(); - throw_on_overflow(env, parent, result, "integer addition overflowed!") + throw_on_overflow(env, parent, result, "Integer addition overflowed!") } NumAddWrap => bd.new_build_int_add(lhs, rhs, "add_int_wrap").into(), NumAddChecked => { @@ -1566,7 +1575,7 @@ fn build_int_binop<'ctx>( ) .into_struct_value(); - throw_on_overflow(env, parent, result, "integer subtraction overflowed!") + throw_on_overflow(env, parent, result, "Integer subtraction overflowed!") } NumSubWrap => bd.new_build_int_sub(lhs, rhs, "sub_int").into(), NumSubChecked => { @@ -1597,7 +1606,7 @@ fn build_int_binop<'ctx>( ) .into_struct_value(); - throw_on_overflow(env, parent, result, "integer multiplication overflowed!") + throw_on_overflow(env, parent, result, "Integer multiplication overflowed!") } NumMulWrap => bd.new_build_int_mul(lhs, rhs, "mul_int").into(), NumMulSaturated => call_bitcode_fn( @@ -2350,7 +2359,7 @@ fn build_dec_binop<'a, 'ctx>( bitcode::DEC_ADD_WITH_OVERFLOW, lhs, rhs, - "decimal addition overflowed", + "Decimal addition overflowed", ), NumSub => build_dec_binop_throw_on_overflow( env, @@ -2358,7 +2367,7 @@ fn build_dec_binop<'a, 'ctx>( bitcode::DEC_SUB_WITH_OVERFLOW, lhs, rhs, - "decimal subtraction overflowed", + "Decimal subtraction overflowed", ), NumMul => build_dec_binop_throw_on_overflow( env, @@ -2366,7 +2375,7 @@ fn build_dec_binop<'a, 'ctx>( bitcode::DEC_MUL_WITH_OVERFLOW, lhs, rhs, - "decimal multiplication overflowed", + "Decimal multiplication overflowed", ), NumDivFrac => dec_binop_with_unchecked(env, bitcode::DEC_DIV, lhs, rhs), @@ -2596,7 +2605,16 @@ fn build_int_unary_op<'a, 'ctx, 'env>( } } PtrWidth::Bytes8 => { - if target_int_width.stack_size() as usize > env.target_info.ptr_size() { + let return_by_pointer = { + if env.target_info.operating_system + == roc_target::OperatingSystem::Windows + { + target_int_width.stack_size() as usize >= env.target_info.ptr_size() + } else { + target_int_width.stack_size() as usize > env.target_info.ptr_size() + } + }; + if return_by_pointer { let bitcode_return_type = zig_to_int_checked_result_type(env, target_int_width.type_name()); @@ -2659,7 +2677,7 @@ fn int_neg_raise_on_overflow<'ctx>( throw_internal_exception( env, parent, - "integer negation overflowed because its argument is the minimum value", + "Integer negation overflowed because its argument is the minimum value", ); builder.position_at_end(else_block); @@ -2690,7 +2708,7 @@ fn int_abs_raise_on_overflow<'ctx>( throw_internal_exception( env, parent, - "integer absolute overflowed because its argument is the minimum value", + "Integer absolute overflowed because its argument is the minimum value", ); builder.position_at_end(else_block); diff --git a/crates/compiler/gen_llvm/src/llvm/refcounting.rs b/crates/compiler/gen_llvm/src/llvm/refcounting.rs index d676858257..243520d318 100644 --- a/crates/compiler/gen_llvm/src/llvm/refcounting.rs +++ b/crates/compiler/gen_llvm/src/llvm/refcounting.rs @@ -5,9 +5,9 @@ use crate::llvm::build::{ add_func, cast_basic_basic, get_tag_id, tag_pointer_clear_tag_id, Env, FAST_CALL_CONV, }; use crate::llvm::build_list::{ - incrementing_elem_loop, list_capacity_or_ref_ptr, list_refcount_ptr, load_list, + incrementing_elem_loop, list_allocation_ptr, list_capacity_or_ref_ptr, load_list, }; -use crate::llvm::build_str::str_refcount_ptr; +use crate::llvm::build_str::str_allocation_ptr; use crate::llvm::convert::{basic_type_from_layout, zig_str_type, RocUnion}; use crate::llvm::struct_::RocStruct; use bumpalo::collections::Vec; @@ -156,6 +156,8 @@ impl<'ctx> PointerToRefcount<'ctx> { let subprogram = env.new_subprogram(fn_name); function_value.set_subprogram(subprogram); + debug_info_init!(env, function_value); + Self::build_decrement_function_body(env, function_value, alignment); function_value @@ -864,7 +866,7 @@ fn modify_refcount_list_help<'a, 'ctx>( } let refcount_ptr = - PointerToRefcount::from_ptr_to_data(env, list_refcount_ptr(env, original_wrapper)); + PointerToRefcount::from_ptr_to_data(env, list_allocation_ptr(env, original_wrapper)); let call_mode = mode_to_call_mode(fn_val, mode); refcount_ptr.modify(call_mode, layout, env, layout_interner); @@ -971,7 +973,7 @@ fn modify_refcount_str_help<'a, 'ctx>( builder.new_build_conditional_branch(is_big_and_non_empty, modification_block, cont_block); builder.position_at_end(modification_block); - let refcount_ptr = PointerToRefcount::from_ptr_to_data(env, str_refcount_ptr(env, arg_val)); + let refcount_ptr = PointerToRefcount::from_ptr_to_data(env, str_allocation_ptr(env, arg_val)); let call_mode = mode_to_call_mode(fn_val, mode); refcount_ptr.modify( call_mode, @@ -1049,6 +1051,8 @@ pub fn build_header_help<'ctx>( let subprogram = env.new_subprogram(fn_name); fn_val.set_subprogram(subprogram); + debug_info_init!(env, fn_val); + env.dibuilder.finalize(); fn_val diff --git a/crates/compiler/gen_wasm/src/lib.rs b/crates/compiler/gen_wasm/src/lib.rs index 2192e666b5..3cb059f5d1 100644 --- a/crates/compiler/gen_wasm/src/lib.rs +++ b/crates/compiler/gen_wasm/src/lib.rs @@ -290,7 +290,7 @@ mod dummy_platform_functions { } #[no_mangle] - pub unsafe extern "C" fn roc_dbg(_loc: *mut c_void, _msg: *mut c_void) { + pub unsafe extern "C" fn roc_dbg(_loc: *mut c_void, _msg: *mut c_void, _src: *mut c_void) { unimplemented!("It is not valid to call roc dbg from within the compiler. Please use the \"platform\" feature if this is a platform.") } diff --git a/crates/compiler/gen_wasm/src/low_level.rs b/crates/compiler/gen_wasm/src/low_level.rs index cb66ab10c2..dfbb8420af 100644 --- a/crates/compiler/gen_wasm/src/low_level.rs +++ b/crates/compiler/gen_wasm/src/low_level.rs @@ -1382,7 +1382,7 @@ impl<'a> LowLevelCall<'a> { } NumAbs => { const PANIC_MSG: &str = - "integer absolute overflowed because its argument is the minimum value"; + "Integer absolute overflowed because its argument is the minimum value"; self.load_args(backend); @@ -1446,7 +1446,7 @@ impl<'a> LowLevelCall<'a> { } NumNeg => { const PANIC_MSG: &str = - "integer negation overflowed because its argument is the minimum value"; + "Integer negation overflowed because its argument is the minimum value"; self.load_args(backend); match CodeGenNumType::from(self.ret_layout) { diff --git a/crates/compiler/load/tests/helpers/mod.rs b/crates/compiler/load/tests/helpers/mod.rs index cb782897d1..ee8283ceaf 100644 --- a/crates/compiler/load/tests/helpers/mod.rs +++ b/crates/compiler/load/tests/helpers/mod.rs @@ -166,7 +166,13 @@ pub fn can_expr_with<'a>( // visited a BinOp node we'd recursively try to apply this to each of its nested // operators, and then again on *their* nested operators, ultimately applying the // rules multiple times unnecessarily. - let loc_expr = operator::desugar_expr(arena, &loc_expr); + let loc_expr = operator::desugar_expr( + arena, + &loc_expr, + expr_str, + &mut None, + arena.alloc("TestPath"), + ); let mut scope = Scope::new(home, IdentIds::default(), Default::default()); diff --git a/crates/compiler/load_internal/src/file.rs b/crates/compiler/load_internal/src/file.rs index d24f8b96e2..a89e2b270d 100644 --- a/crates/compiler/load_internal/src/file.rs +++ b/crates/compiler/load_internal/src/file.rs @@ -371,6 +371,18 @@ fn start_phase<'a>( checkmate: _, } = typechecked; + let our_exposed_types = state + .exposed_types + .get(&module_id) + .unwrap_or_else(|| internal_error!("Exposed types for {:?} missing", module_id)) + .clone(); + + state.world_abilities.insert( + module_id, + abilities_store.clone(), + our_exposed_types.exposed_types_storage_subs, + ); + let mut imported_module_thunks = bumpalo::collections::Vec::new_in(arena); if let Some(imports) = state.module_cache.imports.get(&module_id) { @@ -397,7 +409,7 @@ fn start_phase<'a>( decls, ident_ids, exposed_to_host: state.exposed_to_host.clone(), - abilities_store, + world_abilities: state.world_abilities.clone_ref(), // TODO: awful, how can we get rid of the clone? exposed_by_module: state.exposed_types.clone(), derived_module, @@ -457,23 +469,8 @@ fn start_phase<'a>( procs_base, layout_cache, module_timing, - abilities_store, expectations, } = found_specializations; - let our_exposed_types = state - .exposed_types - .get(&module_id) - .unwrap_or_else(|| { - internal_error!("Exposed types for {:?} missing", module_id) - }) - .clone(); - - // Add our abilities to the world. - state.world_abilities.insert( - module_id, - abilities_store, - our_exposed_types.exposed_types_storage_subs, - ); ( ident_ids, @@ -598,7 +595,6 @@ enum Msg<'a> { procs_base: ProcsBase<'a>, solved_subs: Solved, module_timing: ModuleTiming, - abilities_store: AbilitiesStore, toplevel_expects: ToplevelExpects, expectations: Option, }, @@ -688,6 +684,7 @@ impl MakeSpecializationsPass { struct State<'a> { pub root_id: ModuleId, pub root_subs: Option, + pub root_path: PathBuf, pub cache_dir: PathBuf, /// If the root is an app module, the shorthand specified in its header's `to` field pub opt_platform_shorthand: Option<&'a str>, @@ -756,6 +753,7 @@ impl<'a> State<'a> { fn new( root_id: ModuleId, + root_path: PathBuf, opt_platform_shorthand: Option<&'a str>, target_info: TargetInfo, function_kind: FunctionKind, @@ -774,6 +772,7 @@ impl<'a> State<'a> { Self { root_id, + root_path, root_subs: None, opt_platform_shorthand, cache_dir, @@ -906,7 +905,7 @@ enum BuildTask<'a> { decls: Declarations, exposed_to_host: ExposedToHost, exposed_by_module: ExposedByModule, - abilities_store: AbilitiesStore, + world_abilities: WorldAbilities, derived_module: SharedDerivedModule, expectations: Option, build_expects: bool, @@ -1081,8 +1080,9 @@ pub struct LoadStart<'a> { arc_modules: Arc>>, ident_ids_by_module: SharedIdentIdsByModule, root_id: ModuleId, - opt_platform_shorthand: Option<&'a str>, + root_path: PathBuf, root_msg: Msg<'a>, + opt_platform_shorthand: Option<&'a str>, src_dir: PathBuf, } @@ -1105,7 +1105,7 @@ impl<'a> LoadStart<'a> { let res_loaded = load_filename( arena, - filename, + filename.clone(), true, None, None, @@ -1140,6 +1140,7 @@ impl<'a> LoadStart<'a> { ident_ids_by_module, src_dir, root_id: header_output.module_id, + root_path: filename, root_msg: header_output.msg, opt_platform_shorthand: header_output.opt_platform_shorthand, }) @@ -1166,7 +1167,7 @@ impl<'a> LoadStart<'a> { let header_output = load_from_str( arena, - filename, + filename.clone(), src, Arc::clone(&arc_modules), Arc::clone(&ident_ids_by_module), @@ -1182,6 +1183,7 @@ impl<'a> LoadStart<'a> { src_dir, ident_ids_by_module, root_id, + root_path: filename, root_msg, opt_platform_shorthand: opt_platform_id, }) @@ -1356,6 +1358,7 @@ pub fn load_single_threaded<'a>( arc_modules, ident_ids_by_module, root_id, + root_path, root_msg, src_dir, opt_platform_shorthand, @@ -1371,6 +1374,7 @@ pub fn load_single_threaded<'a>( let number_of_workers = 1; let mut state = State::new( root_id, + root_path, opt_platform_shorthand, target_info, function_kind, @@ -1507,7 +1511,7 @@ fn state_thread_step<'a>( Ok(ControlFlow::Break(LoadResult::Monomorphized(monomorphized))) } Msg::FailedToReadFile { filename, error } => { - let buf = to_file_problem_report_string(&filename, error); + let buf = to_file_problem_report_string(filename, error); Err(LoadingProblem::FormattedReport(buf)) } @@ -1658,7 +1662,7 @@ pub fn report_loading_problem( } LoadingProblem::FormattedReport(report) => report, LoadingProblem::FileProblem { filename, error } => { - to_file_problem_report_string(&filename, error) + to_file_problem_report_string(filename, error) } err => todo!("Loading error: {:?}", err), } @@ -1681,6 +1685,7 @@ fn load_multi_threaded<'a>( arc_modules, ident_ids_by_module, root_id, + root_path, root_msg, src_dir, opt_platform_shorthand, @@ -1711,6 +1716,7 @@ fn load_multi_threaded<'a>( let mut state = State::new( root_id, + root_path, opt_platform_shorthand, target_info, function_kind, @@ -2242,6 +2248,7 @@ fn update<'a>( let buf = to_https_problem_report_string( url, Problem::InvalidUrl(url_err), + header.module_path, ); return Err(LoadingProblem::FormattedReport(buf)); } @@ -2730,7 +2737,6 @@ fn update<'a>( ident_ids, layout_cache, module_timing, - abilities_store, toplevel_expects, expectations, } => { @@ -2754,7 +2760,6 @@ fn update<'a>( procs_base, subs, module_timing, - abilities_store, expectations, }; @@ -3165,7 +3170,7 @@ fn finish_specialization<'a>( } Valid(To::NewPackage(p_or_p)) => PathBuf::from(p_or_p.as_str()), other => { - let buf = to_missing_platform_report(state.root_id, other); + let buf = report_cannot_run(state.root_id, state.root_path, other); return Err(LoadingProblem::FormattedReport(buf)); } }; @@ -3519,9 +3524,7 @@ fn load_builtin_module_help<'a>( ) -> (HeaderInfo<'a>, roc_parse::state::State<'a>) { let is_root_module = false; let opt_shorthand = None; - let filename = PathBuf::from(filename); - let parse_state = roc_parse::state::State::new(src_bytes.as_bytes()); let parsed = roc_parse::module::parse_header(arena, parse_state.clone()); @@ -3974,6 +3977,7 @@ fn parse_header<'a>( module_timing, )?; + let filename = resolved_header.module_path.clone(); let mut messages = Vec::with_capacity(packages.len() + 1); // It's important that the app header is first in the list! @@ -3988,6 +3992,7 @@ fn parse_header<'a>( module_id, module_ids, ident_ids_by_module, + filename, ); // Look at the app module's `to` keyword to determine which package was the platform. @@ -4090,6 +4095,7 @@ fn load_packages<'a>( module_id: ModuleId, module_ids: Arc>>, ident_ids_by_module: SharedIdentIdsByModule, + filename: PathBuf, ) { // Load all the packages for Loc { value: entry, .. } in packages.iter() { @@ -4127,7 +4133,7 @@ fn load_packages<'a>( } } Err(problem) => { - let buf = to_https_problem_report_string(src, problem); + let buf = to_https_problem_report_string(src, problem, filename); load_messages.push(Msg::FailedToLoad(LoadingProblem::FormattedReport(buf))); return; @@ -5264,6 +5270,8 @@ fn canonicalize_and_constrain<'a>( let ParsedModule { module_id, + module_path, + src, header_type, exposed_ident_ids, parsed_defs, @@ -5286,6 +5294,8 @@ fn canonicalize_and_constrain<'a>( parsed_defs, &header_type, module_id, + &*arena.alloc(module_path.to_string_lossy()), + src, module_ids, exposed_ident_ids, &dep_idents, @@ -5701,7 +5711,7 @@ fn build_pending_specializations<'a>( target_info: TargetInfo, exposed_to_host: ExposedToHost, exposed_by_module: &ExposedByModule, - abilities_store: AbilitiesStore, + world_abilities: WorldAbilities, derived_module: SharedDerivedModule, mut expectations: Option, build_expects: bool, @@ -5734,7 +5744,7 @@ fn build_pending_specializations<'a>( // NB: for getting pending specializations the module view is enough because we only need // to know the types and abilities in our modules. Only for building *all* specializations // do we need a global view. - abilities: AbilitiesView::Module(&abilities_store), + abilities: AbilitiesView::World(&world_abilities), exposed_by_module, derived_module: &derived_module, struct_indexing: UsageTrackingMap::default(), @@ -6134,7 +6144,6 @@ fn build_pending_specializations<'a>( layout_cache, procs_base, module_timing, - abilities_store, toplevel_expects, expectations, } @@ -6374,7 +6383,7 @@ fn run_task<'a>( solved_subs, imported_module_thunks, exposed_to_host, - abilities_store, + world_abilities, exposed_by_module, derived_module, expectations, @@ -6391,7 +6400,7 @@ fn run_task<'a>( target_info, exposed_to_host, &exposed_by_module, - abilities_store, + world_abilities, derived_module, expectations, build_expects, @@ -6584,7 +6593,11 @@ fn to_parse_problem_report<'a>( buf } -fn to_missing_platform_report(module_id: ModuleId, other: &PlatformPath) -> String { +fn report_cannot_run( + module_id: ModuleId, + filename: PathBuf, + platform_path: &PlatformPath, +) -> String { use roc_reporting::report::{Report, RocDocAllocator, DEFAULT_PALETTE}; use ven_pretty::DocAllocator; use PlatformPath::*; @@ -6594,20 +6607,20 @@ fn to_missing_platform_report(module_id: ModuleId, other: &PlatformPath) -> Stri let alloc = RocDocAllocator::new(&[], module_id, &interns); let report = { - match other { + match platform_path { Valid(_) => unreachable!(), NotSpecified => { let doc = alloc.stack([ alloc.reflow("I could not find a platform based on your input file."), - alloc.reflow(r"Does the module header contain an entry that looks like this:"), + alloc.reflow(r"Does the module header have an entry that looks like this?"), alloc - .parser_suggestion(" packages { pf: \"platform\" }") + .parser_suggestion("packages { blah: \"…path or URL to platform…\" }") .indent(4), - alloc.reflow("See also TODO."), + alloc.reflow("Tip: The following part of the tutorial has an example of specifying a platform:\n\n"), ]); Report { - filename: "UNKNOWN.roc".into(), + filename, doc, title: "NO PLATFORM".to_string(), severity: Severity::RuntimeError, @@ -6622,7 +6635,7 @@ fn to_missing_platform_report(module_id: ModuleId, other: &PlatformPath) -> Stri ]); Report { - filename: "UNKNOWN.roc".into(), + filename, doc, title: "NO PLATFORM".to_string(), severity: Severity::RuntimeError, @@ -6637,7 +6650,7 @@ fn to_missing_platform_report(module_id: ModuleId, other: &PlatformPath) -> Stri ]); Report { - filename: "UNKNOWN.roc".into(), + filename, doc, title: "NO PLATFORM".to_string(), severity: Severity::RuntimeError, @@ -6652,7 +6665,7 @@ fn to_missing_platform_report(module_id: ModuleId, other: &PlatformPath) -> Stri ]); Report { - filename: "UNKNOWN.roc".into(), + filename, doc, title: "NO PLATFORM".to_string(), severity: Severity::RuntimeError, diff --git a/crates/compiler/load_internal/src/module.rs b/crates/compiler/load_internal/src/module.rs index c106c4083c..d201980680 100644 --- a/crates/compiler/load_internal/src/module.rs +++ b/crates/compiler/load_internal/src/module.rs @@ -144,7 +144,6 @@ pub(crate) struct FoundSpecializationsModule<'a> { pub(crate) procs_base: ProcsBase<'a>, pub(crate) subs: Subs, pub(crate) module_timing: ModuleTiming, - pub(crate) abilities_store: AbilitiesStore, pub(crate) expectations: Option, } diff --git a/crates/compiler/module/src/low_level.rs b/crates/compiler/module/src/low_level.rs index ae81591b17..c43307548a 100644 --- a/crates/compiler/module/src/low_level.rs +++ b/crates/compiler/module/src/low_level.rs @@ -183,7 +183,7 @@ impl LowLevelWrapperType { /// We use a rust macro to ensure that every LowLevel gets handled macro_rules! map_symbol_to_lowlevel { - ($($lowlevel:ident <= $symbol:ident),* $(,)?) => { + ($($lowlevel:ident <= $($symbol:ident),+);* $(;)?) => { fn for_symbol_help(symbol: Symbol) -> LowLevelWrapperType { use $crate::low_level::LowLevelWrapperType::*; @@ -191,14 +191,14 @@ macro_rules! map_symbol_to_lowlevel { // expands to a big (but non-exhaustive) match on symbols and maps them to a lowlevel match symbol { $( - Symbol::$symbol => CanBeReplacedBy(LowLevel::$lowlevel), + $(Symbol::$symbol)|+ => CanBeReplacedBy(LowLevel::$lowlevel), )* _ => NotALowLevelWrapper, } } - fn _enforce_exhaustiveness(lowlevel: LowLevel) -> Symbol { + fn _enforce_exhaustiveness(lowlevel: LowLevel) -> &'static [Symbol] { // when adding a new lowlevel, this match will stop being exhaustive, and give a // compiler error. Most likely, you are adding a new lowlevel that maps directly to a // symbol. For instance, you want to have `List.foo` to stand for the `ListFoo` @@ -209,7 +209,7 @@ macro_rules! map_symbol_to_lowlevel { // that it isn't and just see if that works. match lowlevel { $( - LowLevel::$lowlevel => Symbol::$symbol, + LowLevel::$lowlevel => &[$(Symbol::$symbol),+], )* // these are higher-order lowlevels. these need the surrounding @@ -259,107 +259,107 @@ macro_rules! map_symbol_to_lowlevel { // pattern of a symbol mapping directly to a lowlevel. In other words, most lowlevels (left) are generated // by only one specific symbol (right) map_symbol_to_lowlevel! { - StrConcat <= STR_CONCAT, - StrJoinWith <= STR_JOIN_WITH, - StrIsEmpty <= STR_IS_EMPTY, - StrStartsWith <= STR_STARTS_WITH, - StrStartsWithScalar <= STR_STARTS_WITH_SCALAR, - StrEndsWith <= STR_ENDS_WITH, - StrSplit <= STR_SPLIT, - StrCountGraphemes <= STR_COUNT_GRAPHEMES, - StrCountUtf8Bytes <= STR_COUNT_UTF8_BYTES, - StrFromUtf8Range <= STR_FROM_UTF8_RANGE_LOWLEVEL, - StrToUtf8 <= STR_TO_UTF8, - StrRepeat <= STR_REPEAT, - StrTrim <= STR_TRIM, - StrTrimStart <= STR_TRIM_START, - StrTrimEnd <= STR_TRIM_END, - StrToScalars <= STR_TO_SCALARS, - StrGetUnsafe <= STR_GET_UNSAFE, - StrSubstringUnsafe <= STR_SUBSTRING_UNSAFE, - StrReserve <= STR_RESERVE, - StrAppendScalar <= STR_APPEND_SCALAR_UNSAFE, - StrGetScalarUnsafe <= STR_GET_SCALAR_UNSAFE, - StrToNum <= STR_TO_NUM, - StrGetCapacity <= STR_CAPACITY, - StrWithCapacity <= STR_WITH_CAPACITY, - StrGraphemes <= STR_GRAPHEMES, - StrReleaseExcessCapacity <= STR_RELEASE_EXCESS_CAPACITY, - ListLen <= LIST_LEN, - ListGetCapacity <= LIST_CAPACITY, - ListWithCapacity <= LIST_WITH_CAPACITY, - ListReserve <= LIST_RESERVE, - ListReleaseExcessCapacity <= LIST_RELEASE_EXCESS_CAPACITY, - ListIsUnique <= LIST_IS_UNIQUE, - ListAppendUnsafe <= LIST_APPEND_UNSAFE, - ListPrepend <= LIST_PREPEND, - ListGetUnsafe <= LIST_GET_UNSAFE, - ListReplaceUnsafe <= LIST_REPLACE_UNSAFE, - ListConcat <= LIST_CONCAT, - ListSublist <= LIST_SUBLIST_LOWLEVEL, - ListDropAt <= LIST_DROP_AT, - ListSwap <= LIST_SWAP, - NumAdd <= NUM_ADD, - NumAddWrap <= NUM_ADD_WRAP, - NumAddChecked <= NUM_ADD_CHECKED_LOWLEVEL, - NumAddSaturated <= NUM_ADD_SATURATED, - NumSub <= NUM_SUB, - NumSubWrap <= NUM_SUB_WRAP, - NumSubChecked <= NUM_SUB_CHECKED_LOWLEVEL, - NumSubSaturated <= NUM_SUB_SATURATED, - NumMul <= NUM_MUL, - NumMulWrap <= NUM_MUL_WRAP, - NumMulSaturated <= NUM_MUL_SATURATED, - NumMulChecked <= NUM_MUL_CHECKED_LOWLEVEL, - NumGt <= NUM_GT, - NumGte <= NUM_GTE, - NumLt <= NUM_LT, - NumLte <= NUM_LTE, - NumCompare <= NUM_COMPARE, - NumDivFrac <= NUM_DIV_FRAC, - NumDivCeilUnchecked <= NUM_DIV_CEIL, - NumDivTruncUnchecked <= NUM_DIV_TRUNC, - NumRemUnchecked <= NUM_REM, - NumIsMultipleOf <= NUM_IS_MULTIPLE_OF, - NumAbs <= NUM_ABS, - NumNeg <= NUM_NEG, - NumSin <= NUM_SIN, - NumCos <= NUM_COS, - NumTan <= NUM_TAN, - NumSqrtUnchecked <= NUM_SQRT, - NumLogUnchecked <= NUM_LOG, - NumRound <= NUM_ROUND, - NumToFrac <= NUM_TO_FRAC, - NumIsNan <= NUM_IS_NAN, - NumIsInfinite <= NUM_IS_INFINITE, - NumIsFinite <= NUM_IS_FINITE, - NumPow <= NUM_POW, - NumCeiling <= NUM_CEILING, - NumPowInt <= NUM_POW_INT, - NumFloor <= NUM_FLOOR, - NumAtan <= NUM_ATAN, - NumAcos <= NUM_ACOS, - 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, - NumShiftLeftBy <= NUM_SHIFT_LEFT, - 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, - I128OfDec <= I128_OF_DEC, - Eq <= BOOL_STRUCTURAL_EQ, - NotEq <= BOOL_STRUCTURAL_NOT_EQ, - And <= BOOL_AND, - Or <= BOOL_OR, - Not <= BOOL_NOT, - Unreachable <= LIST_UNREACHABLE, - DictPseudoSeed <= DICT_PSEUDO_SEED, + StrConcat <= STR_CONCAT; + StrJoinWith <= STR_JOIN_WITH; + StrIsEmpty <= STR_IS_EMPTY; + StrStartsWith <= STR_STARTS_WITH; + StrStartsWithScalar <= STR_STARTS_WITH_SCALAR; + StrEndsWith <= STR_ENDS_WITH; + StrSplit <= STR_SPLIT; + StrCountGraphemes <= STR_COUNT_GRAPHEMES; + StrCountUtf8Bytes <= STR_COUNT_UTF8_BYTES; + StrFromUtf8Range <= STR_FROM_UTF8_RANGE_LOWLEVEL; + StrToUtf8 <= STR_TO_UTF8; + StrRepeat <= STR_REPEAT; + StrTrim <= STR_TRIM; + StrTrimStart <= STR_TRIM_START; + StrTrimEnd <= STR_TRIM_END; + StrToScalars <= STR_TO_SCALARS; + StrGetUnsafe <= STR_GET_UNSAFE; + StrSubstringUnsafe <= STR_SUBSTRING_UNSAFE; + StrReserve <= STR_RESERVE; + StrAppendScalar <= STR_APPEND_SCALAR_UNSAFE; + StrGetScalarUnsafe <= STR_GET_SCALAR_UNSAFE; + StrToNum <= STR_TO_NUM; + StrGetCapacity <= STR_CAPACITY; + StrWithCapacity <= STR_WITH_CAPACITY; + StrGraphemes <= STR_GRAPHEMES; + StrReleaseExcessCapacity <= STR_RELEASE_EXCESS_CAPACITY; + ListLen <= LIST_LEN; + ListGetCapacity <= LIST_CAPACITY; + ListWithCapacity <= LIST_WITH_CAPACITY; + ListReserve <= LIST_RESERVE; + ListReleaseExcessCapacity <= LIST_RELEASE_EXCESS_CAPACITY; + ListIsUnique <= LIST_IS_UNIQUE; + ListAppendUnsafe <= LIST_APPEND_UNSAFE; + ListPrepend <= LIST_PREPEND; + ListGetUnsafe <= LIST_GET_UNSAFE, DICT_LIST_GET_UNSAFE; + ListReplaceUnsafe <= LIST_REPLACE_UNSAFE; + ListConcat <= LIST_CONCAT; + ListSublist <= LIST_SUBLIST_LOWLEVEL; + ListDropAt <= LIST_DROP_AT; + ListSwap <= LIST_SWAP; + NumAdd <= NUM_ADD; + NumAddWrap <= NUM_ADD_WRAP; + NumAddChecked <= NUM_ADD_CHECKED_LOWLEVEL; + NumAddSaturated <= NUM_ADD_SATURATED; + NumSub <= NUM_SUB; + NumSubWrap <= NUM_SUB_WRAP; + NumSubChecked <= NUM_SUB_CHECKED_LOWLEVEL; + NumSubSaturated <= NUM_SUB_SATURATED; + NumMul <= NUM_MUL; + NumMulWrap <= NUM_MUL_WRAP; + NumMulSaturated <= NUM_MUL_SATURATED; + NumMulChecked <= NUM_MUL_CHECKED_LOWLEVEL; + NumGt <= NUM_GT; + NumGte <= NUM_GTE; + NumLt <= NUM_LT; + NumLte <= NUM_LTE; + NumCompare <= NUM_COMPARE; + NumDivFrac <= NUM_DIV_FRAC; + NumDivCeilUnchecked <= NUM_DIV_CEIL; + NumDivTruncUnchecked <= NUM_DIV_TRUNC; + NumRemUnchecked <= NUM_REM; + NumIsMultipleOf <= NUM_IS_MULTIPLE_OF; + NumAbs <= NUM_ABS; + NumNeg <= NUM_NEG; + NumSin <= NUM_SIN; + NumCos <= NUM_COS; + NumTan <= NUM_TAN; + NumSqrtUnchecked <= NUM_SQRT; + NumLogUnchecked <= NUM_LOG; + NumRound <= NUM_ROUND; + NumToFrac <= NUM_TO_FRAC; + NumIsNan <= NUM_IS_NAN; + NumIsInfinite <= NUM_IS_INFINITE; + NumIsFinite <= NUM_IS_FINITE; + NumPow <= NUM_POW; + NumCeiling <= NUM_CEILING; + NumPowInt <= NUM_POW_INT; + NumFloor <= NUM_FLOOR; + NumAtan <= NUM_ATAN; + NumAcos <= NUM_ACOS; + 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; + NumShiftLeftBy <= NUM_SHIFT_LEFT; + 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; + I128OfDec <= I128_OF_DEC; + Eq <= BOOL_STRUCTURAL_EQ; + NotEq <= BOOL_STRUCTURAL_NOT_EQ; + And <= BOOL_AND; + Or <= BOOL_OR; + Not <= BOOL_NOT; + Unreachable <= LIST_UNREACHABLE; + DictPseudoSeed <= DICT_PSEUDO_SEED; } diff --git a/crates/compiler/module/src/symbol.rs b/crates/compiler/module/src/symbol.rs index 7fee728ad4..50b495df5d 100644 --- a/crates/compiler/module/src/symbol.rs +++ b/crates/compiler/module/src/symbol.rs @@ -1439,6 +1439,7 @@ define_builtins! { 83 LIST_WALK_WITH_INDEX: "walkWithIndex" 84 LIST_APPEND_IF_OK: "appendIfOk" 85 LIST_PREPEND_IF_OK: "prependIfOk" + 86 LIST_WALK_WITH_INDEX_UNTIL: "walkWithIndexUntil" } 7 RESULT: "Result" => { 0 RESULT_RESULT: "Result" exposed_type=true // the Result.Result type alias @@ -1484,6 +1485,10 @@ define_builtins! { 24 DICT_IS_EMPTY: "isEmpty" 25 DICT_MAP: "map" 26 DICT_JOINMAP: "joinMap" + 27 DICT_KEEP_IF: "keepIf" + 28 DICT_DROP_IF: "dropIf" + 29 DICT_RESERVE: "reserve" + 30 DICT_RELEASE_EXCESS_CAPACITY: "releaseExcessCapacity" } 9 SET: "Set" => { 0 SET_SET: "Set" exposed_type=true // the Set.Set type alias @@ -1506,6 +1511,11 @@ define_builtins! { 17 SET_IS_EMPTY: "isEmpty" 18 SET_MAP: "map" 19 SET_JOIN_MAP: "joinMap" + 20 SET_KEEP_IF: "keepIf" + 21 SET_DROP_IF: "dropIf" + 22 SET_WITH_CAPACITY: "withCapacity" + 23 SET_RESERVE: "reserve" + 24 SET_RELEASE_EXCESS_CAPACITY: "releaseExcessCapacity" } 10 BOX: "Box" => { 0 BOX_BOX_TYPE: "Box" exposed_apply_type=true // the Box.Box opaque type @@ -1631,8 +1641,7 @@ define_builtins! { 31 INSPECT_APPLY: "apply" 32 INSPECT_TO_INSPECTOR: "toInspector" 33 INSPECT_NAT: "nat" - 34 INSPECT_DBG_FORMATTER: "DbgFormatter" exposed_type=true - 35 INSPECT_TO_DBG_STR: "toDbgStr" + 34 INSPECT_TO_STR: "toStr" } 15 JSON: "TotallyNotJson" => { 0 JSON_JSON: "TotallyNotJson" diff --git a/crates/compiler/mono/src/drop_specialization.rs b/crates/compiler/mono/src/drop_specialization.rs index 1317aa53bf..7ccf6dbc85 100644 --- a/crates/compiler/mono/src/drop_specialization.rs +++ b/crates/compiler/mono/src/drop_specialization.rs @@ -631,10 +631,14 @@ fn specialize_drops_stmt<'a, 'i>( ), }), Stmt::Dbg { + source_location, + source, symbol, variable, remainder, } => arena.alloc(Stmt::Dbg { + source_location, + source, symbol: *symbol, variable: *variable, remainder: specialize_drops_stmt( @@ -1536,7 +1540,7 @@ fn low_level_no_rc(lowlevel: &LowLevel) -> RC { StrGetUnsafe | ListGetUnsafe => RC::NoRc, ListConcat => RC::Rc, StrConcat => RC::Rc, - StrSubstringUnsafe => RC::NoRc, + StrSubstringUnsafe => RC::Rc, StrReserve => RC::Rc, StrAppendScalar => RC::Rc, StrGetScalarUnsafe => RC::NoRc, diff --git a/crates/compiler/mono/src/inc_dec.rs b/crates/compiler/mono/src/inc_dec.rs index 3eabd01c72..9c3e2b0140 100644 --- a/crates/compiler/mono/src/inc_dec.rs +++ b/crates/compiler/mono/src/inc_dec.rs @@ -689,6 +689,8 @@ fn insert_refcount_operations_stmt<'v, 'a>( }) } Stmt::Dbg { + source_location, + source, symbol, variable, remainder, @@ -703,6 +705,8 @@ fn insert_refcount_operations_stmt<'v, 'a>( ); arena.alloc(Stmt::Dbg { + source_location, + source, symbol: *symbol, variable: *variable, remainder: newer_remainder, @@ -1288,7 +1292,7 @@ fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[Ownership] { StrGetUnsafe | ListGetUnsafe => arena.alloc_slice_copy(&[borrowed, irrelevant]), ListConcat => arena.alloc_slice_copy(&[owned, owned]), StrConcat => arena.alloc_slice_copy(&[owned, borrowed]), - StrSubstringUnsafe => arena.alloc_slice_copy(&[borrowed, irrelevant, irrelevant]), + StrSubstringUnsafe => arena.alloc_slice_copy(&[owned, irrelevant, irrelevant]), StrReserve => arena.alloc_slice_copy(&[owned, irrelevant]), StrAppendScalar => arena.alloc_slice_copy(&[owned, irrelevant]), StrGetScalarUnsafe => arena.alloc_slice_copy(&[borrowed, irrelevant]), diff --git a/crates/compiler/mono/src/ir.rs b/crates/compiler/mono/src/ir.rs index 8a1f02f35c..8bb2347710 100644 --- a/crates/compiler/mono/src/ir.rs +++ b/crates/compiler/mono/src/ir.rs @@ -1531,6 +1531,10 @@ pub enum Stmt<'a> { remainder: &'a Stmt<'a>, }, Dbg { + /// The location this dbg is in source as a printable string. + source_location: &'a str, + /// The source code of the expression being debugged. + source: &'a str, /// The expression we're displaying symbol: Symbol, /// The specialized variable of the expression @@ -4606,6 +4610,8 @@ pub fn with_hole<'a>( Expect { .. } => unreachable!("I think this is unreachable"), ExpectFx { .. } => unreachable!("I think this is unreachable"), Dbg { + source_location, + source, loc_message, loc_continuation, variable: cond_variable, @@ -4625,6 +4631,8 @@ pub fn with_hole<'a>( env, procs, layout_cache, + &*arena.alloc(source_location), + &*arena.alloc(source), dbg_symbol, *loc_message, cond_variable, @@ -5896,8 +5904,10 @@ fn compile_dbg<'a>( env: &mut Env<'a, '_>, procs: &mut Procs<'a>, layout_cache: &mut LayoutCache<'a>, + source_location: &'a str, + source: &'a str, dbg_symbol: Symbol, - loc_condition: Loc, + loc_message: Loc, variable: Variable, continuation: Stmt<'a>, ) -> Stmt<'a> { @@ -5908,6 +5918,8 @@ fn compile_dbg<'a>( .fresh_unnamed_flex_var(); let dbg_stmt = Stmt::Dbg { + source_location, + source, symbol: dbg_symbol, variable: spec_var, remainder: env.arena.alloc(continuation), @@ -5918,17 +5930,17 @@ fn compile_dbg<'a>( store_specialized_expectation_lookups(env, [variable], &[spec_var]); let symbol_is_reused = matches!( - can_reuse_symbol(env, layout_cache, procs, &loc_condition.value, variable), + can_reuse_symbol(env, layout_cache, procs, &loc_message.value, variable), ReuseSymbol::Value(_) ); - // skip evaluating the condition if it's just a symbol + // skip evaluating the message if it's just a symbol if symbol_is_reused { dbg_stmt } else { with_hole( env, - loc_condition.value, + loc_message.value, variable, procs, layout_cache, @@ -7141,6 +7153,8 @@ pub fn from_can<'a>( } Dbg { + source_location, + source, loc_message, loc_continuation, variable: cond_variable, @@ -7152,6 +7166,8 @@ pub fn from_can<'a>( env, procs, layout_cache, + &*env.arena.alloc(source_location), + &*env.arena.alloc(source), dbg_symbol, *loc_message, cond_variable, @@ -7625,6 +7641,8 @@ fn substitute_in_stmt_help<'a>( } Dbg { + source_location, + source, symbol, variable, remainder, @@ -7633,6 +7651,8 @@ fn substitute_in_stmt_help<'a>( substitute_in_stmt_help(arena, remainder, subs).unwrap_or(remainder); let expect = Dbg { + source_location, + source, symbol: substitute(subs, *symbol).unwrap_or(*symbol), variable: *variable, remainder: new_remainder, diff --git a/crates/compiler/mono/src/ir/pattern.rs b/crates/compiler/mono/src/ir/pattern.rs index b8f9fdb408..173744d344 100644 --- a/crates/compiler/mono/src/ir/pattern.rs +++ b/crates/compiler/mono/src/ir/pattern.rs @@ -1544,7 +1544,13 @@ fn store_list_pattern<'a>( } } - stmt = store_list_rest(env, list_sym, list_arity, list_layout, opt_rest, stmt); + stmt = match store_list_rest(env, list_sym, list_arity, list_layout, opt_rest, stmt) { + StorePattern::Productive(new) => { + is_productive = true; + new + } + StorePattern::NotProductive(new) => new, + }; if is_productive { StorePattern::Productive(stmt) @@ -1560,8 +1566,12 @@ fn store_list_rest<'a>( list_layout: InLayout<'a>, opt_rest: &Option<(usize, Option)>, mut stmt: Stmt<'a>, -) -> Stmt<'a> { +) -> StorePattern<'a> { + let mut is_productive = false; + if let Some((index, Some(rest_sym))) = opt_rest { + is_productive = true; + let usize_layout = Layout::usize(env.target_info); let total_dropped = list_arity.min_len(); @@ -1608,7 +1618,12 @@ fn store_list_rest<'a>( stmt = Stmt::Let(sym, expr, lay, env.arena.alloc(stmt)); } } - stmt + + if is_productive { + StorePattern::Productive(stmt) + } else { + StorePattern::NotProductive(stmt) + } } #[allow(clippy::too_many_arguments)] diff --git a/crates/compiler/mono/src/reset_reuse.rs b/crates/compiler/mono/src/reset_reuse.rs index cb893903dc..f6a8bd7c52 100644 --- a/crates/compiler/mono/src/reset_reuse.rs +++ b/crates/compiler/mono/src/reset_reuse.rs @@ -651,6 +651,8 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>( }) } Stmt::Dbg { + source_location, + source, symbol, variable, remainder, @@ -666,6 +668,8 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>( ); arena.alloc(Stmt::Dbg { + source_location, + source, symbol: *symbol, variable: *variable, remainder: new_remainder, diff --git a/crates/compiler/mono/src/tail_recursion.rs b/crates/compiler/mono/src/tail_recursion.rs index 5b6bcd29f4..ad827e366e 100644 --- a/crates/compiler/mono/src/tail_recursion.rs +++ b/crates/compiler/mono/src/tail_recursion.rs @@ -330,6 +330,8 @@ fn insert_jumps<'a>( } Dbg { + source_location, + source, symbol, variable, remainder, @@ -342,6 +344,8 @@ fn insert_jumps<'a>( needle_result, ) { Some(cont) => Some(arena.alloc(Dbg { + source_location, + source, symbol: *symbol, variable: *variable, remainder: cont, @@ -1020,10 +1024,14 @@ impl<'a> TrmcEnv<'a> { remainder: arena.alloc(self.walk_stmt(env, remainder)), }, Stmt::Dbg { + source_location, + source, symbol, variable, remainder, } => Stmt::Dbg { + source_location, + source, symbol: *symbol, variable: *variable, remainder: arena.alloc(self.walk_stmt(env, remainder)), diff --git a/crates/compiler/parse/src/ast.rs b/crates/compiler/parse/src/ast.rs index 949d88b443..26df0ec57a 100644 --- a/crates/compiler/parse/src/ast.rs +++ b/crates/compiler/parse/src/ast.rs @@ -302,7 +302,7 @@ pub enum Expr<'a> { Expect(&'a Loc>, &'a Loc>), Dbg(&'a Loc>, &'a Loc>), // This form of debug is a desugared call to roc_dbg - LowLevelDbg(&'a Loc>, &'a Loc>), + LowLevelDbg(&'a (&'a str, &'a str), &'a Loc>, &'a Loc>), // Application /// To apply by name, do Apply(Var(...), ...) @@ -1537,7 +1537,7 @@ impl<'a> Malformed for Expr<'a> { Backpassing(args, call, body) => args.iter().any(|arg| arg.is_malformed()) || call.is_malformed() || body.is_malformed(), Expect(condition, continuation) | Dbg(condition, continuation) => condition.is_malformed() || continuation.is_malformed(), - LowLevelDbg(condition, continuation) => condition.is_malformed() || continuation.is_malformed(), + LowLevelDbg(_, condition, continuation) => condition.is_malformed() || continuation.is_malformed(), Apply(func, args, _) => func.is_malformed() || args.iter().any(|arg| arg.is_malformed()), BinOps(firsts, last) => firsts.iter().any(|(expr, _)| expr.is_malformed()) || last.is_malformed(), UnaryOp(expr, _) => expr.is_malformed(), diff --git a/crates/compiler/parse/src/expr.rs b/crates/compiler/parse/src/expr.rs index f51602a48d..2bbbb75e53 100644 --- a/crates/compiler/parse/src/expr.rs +++ b/crates/compiler/parse/src/expr.rs @@ -1933,7 +1933,7 @@ fn expr_to_pattern_help<'a>(arena: &'a Bump, expr: &Expr<'a>) -> Result [Break state, Continue state]) -> state", + ); + } + #[test] fn list_drop_at() { infer_eq_without_problem( diff --git a/crates/compiler/test_gen/benches/list_map.rs b/crates/compiler/test_gen/benches/list_map.rs index 2aa8243bfd..dadd2b9740 100644 --- a/crates/compiler/test_gen/benches/list_map.rs +++ b/crates/compiler/test_gen/benches/list_map.rs @@ -57,7 +57,7 @@ fn roc_function<'a, 'b>( let config = helpers::llvm::HelperConfig { mode: LlvmBackendMode::GenTest, ignore_problems: false, - add_debug_info: true, + emit_debug_info: true, opt_level: OptLevel::Optimize, }; diff --git a/crates/compiler/test_gen/benches/quicksort.rs b/crates/compiler/test_gen/benches/quicksort.rs index 2b786ac8dd..96b94ff00f 100644 --- a/crates/compiler/test_gen/benches/quicksort.rs +++ b/crates/compiler/test_gen/benches/quicksort.rs @@ -86,7 +86,7 @@ fn roc_function<'a>( let config = helpers::llvm::HelperConfig { mode: LlvmBackendMode::GenTest, ignore_problems: false, - add_debug_info: true, + emit_debug_info: true, opt_level: OptLevel::Optimize, }; diff --git a/crates/compiler/test_gen/src/gen_abilities.rs b/crates/compiler/test_gen/src/gen_abilities.rs index 7c96408390..6a2d2404b4 100644 --- a/crates/compiler/test_gen/src/gen_abilities.rs +++ b/crates/compiler/test_gen/src/gen_abilities.rs @@ -2203,9 +2203,9 @@ mod inspect { app "test" provides [main] to "./platform" main = [ - Inspect.inspect Bool.true, - Inspect.inspect Bool.false, - ] |> List.map Inspect.toDbgStr |> Str.joinWith ", " + Inspect.toStr Bool.true, + Inspect.toStr Bool.false, + ] |> Str.joinWith ", " "# ), RocStr::from("Bool.true, Bool.false"), @@ -2222,22 +2222,22 @@ mod inspect { app "test" provides [main] to "./platform" main = [ - Inspect.inspect 0, # Num a - Inspect.inspect 1u8, # U8 - Inspect.inspect 2i8, # I8 - Inspect.inspect 3u16, # U16 - Inspect.inspect 4i16, # I16 - Inspect.inspect 5u32, # U32 - Inspect.inspect 6i32, # I32 - Inspect.inspect 7u64, # U64 - Inspect.inspect 8i64, # I64 - Inspect.inspect 9u128, # U128 - Inspect.inspect 10i128, # I128 - Inspect.inspect 0.5, # Frac a - Inspect.inspect 1.5f32, # F32 - Inspect.inspect 2.2f64, # F64 - Inspect.inspect (1.1dec + 2.2), # Dec - ] |> List.map Inspect.toDbgStr |> Str.joinWith ", " + Inspect.toStr 0, # Num a + Inspect.toStr 1u8, # U8 + Inspect.toStr 2i8, # I8 + Inspect.toStr 3u16, # U16 + Inspect.toStr 4i16, # I16 + Inspect.toStr 5u32, # U32 + Inspect.toStr 6i32, # I32 + Inspect.toStr 7u64, # U64 + Inspect.toStr 8i64, # I64 + Inspect.toStr 9u128, # U128 + Inspect.toStr 10i128, # I128 + Inspect.toStr 0.5, # Frac a + Inspect.toStr 1.5f32, # F32 + Inspect.toStr 2.2f64, # F64 + Inspect.toStr (1.1dec + 2.2), # Dec + ] |> Str.joinWith ", " "# ), RocStr::from("0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0.5, 1.5, 2.2, 3.3"), @@ -2254,12 +2254,12 @@ mod inspect { app "test" provides [main] to "./platform" main = [ - Inspect.inspect [0, 1, 2], # List (Num *) - Inspect.inspect [1, 0x2, 3], # List (Int *) - Inspect.inspect [0.1 + 0.2, 0.4], # List (Frac *) - Inspect.inspect [1u8, 2u8], # List U8 - Inspect.inspect ["foo"], # List Str - ] |> List.map Inspect.toDbgStr |> Str.joinWith ", " + Inspect.toStr [0, 1, 2], # List (Num *) + Inspect.toStr [1, 0x2, 3], # List (Int *) + Inspect.toStr [0.1 + 0.2, 0.4], # List (Frac *) + Inspect.toStr [1u8, 2u8], # List U8 + Inspect.toStr ["foo"], # List Str + ] |> Str.joinWith ", " "# ), RocStr::from("[0, 1, 2], [1, 2, 3], [0.3, 0.4], [1, 2], [\"foo\"]"), @@ -2276,10 +2276,10 @@ mod inspect { app "test" provides [main] to "./platform" main = [ - Inspect.inspect "", - Inspect.inspect "a small string", - Inspect.inspect "an extraordinarily long string - so long it's on the heap!", - ] |> List.map Inspect.toDbgStr |> Str.joinWith ", " + Inspect.toStr "", + Inspect.toStr "a small string", + Inspect.toStr "an extraordinarily long string - so long it's on the heap!", + ] |> Str.joinWith ", " "# ), RocStr::from( @@ -2299,7 +2299,7 @@ mod inspect { Op := {} - main = Inspect.toDbgStr (Inspect.inspect (@Op {})) + main = Inspect.toStr (@Op {}) "# ), RocStr::from(r#""#), @@ -2317,7 +2317,7 @@ mod inspect { Op := {} - late = \a -> Inspect.toDbgStr (Inspect.inspect a) + late = \a -> Inspect.toStr a main = late (@Op {}) "# diff --git a/crates/compiler/test_gen/src/gen_dict.rs b/crates/compiler/test_gen/src/gen_dict.rs index 6e0181223c..a82a803b96 100644 --- a/crates/compiler/test_gen/src/gen_dict.rs +++ b/crates/compiler/test_gen/src/gen_dict.rs @@ -436,7 +436,7 @@ fn keep_shared() { #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] -fn keep_shared_prefer_first() { +fn keep_shared_value_must_match() { assert_evals_to!( indoc!( r#" @@ -453,14 +453,14 @@ fn keep_shared_prefer_first() { dict2 = Dict.empty {} |> Dict.insert 0 100 - |> Dict.insert 2 200 + |> Dict.insert 2 2 |> Dict.insert 4 300 Dict.keepShared dict1 dict2 |> Dict.values "# ), - RocList::from_slice(&[2, 4]), + RocList::from_slice(&[2]), RocList ); } diff --git a/crates/compiler/test_gen/src/gen_list.rs b/crates/compiler/test_gen/src/gen_list.rs index db6863b8da..adfec177fc 100644 --- a/crates/compiler/test_gen/src/gen_list.rs +++ b/crates/compiler/test_gen/src/gen_list.rs @@ -990,6 +990,27 @@ fn list_walk_until_sum() { ); } +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] +fn list_walk_with_index_until_sum() { + assert_evals_to!( + r#" + List.walkWithIndexUntil [5, 7, 2, 3] 0 (\state, elem, index -> + if elem % 2 == 0 then + Break state + else + # Convert to I64 to sidestep weird bug with WASM codegen + a = Num.toI64 elem + b = Num.toI64 index + c = Num.toI64 state + Continue (a + b + c) + ) + "#, + 13, + i64 + ); +} + #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn list_walk_implements_position() { @@ -2934,7 +2955,7 @@ fn list_map_with_index() { #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] -#[should_panic(expected = r#"Roc failed with message: "integer addition overflowed!"#)] +#[should_panic(expected = r#"Roc failed with message: "Integer addition overflowed!"#)] fn cleanup_because_exception() { assert_evals_to!( indoc!( diff --git a/crates/compiler/test_gen/src/gen_num.rs b/crates/compiler/test_gen/src/gen_num.rs index c6651b9416..29b597fdc7 100644 --- a/crates/compiler/test_gen/src/gen_num.rs +++ b/crates/compiler/test_gen/src/gen_num.rs @@ -575,7 +575,7 @@ fn various_sized_abs() { #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] #[should_panic( - expected = r#"Roc failed with message: "integer absolute overflowed because its argument is the minimum value"# + expected = r#"Roc failed with message: "Integer absolute overflowed because its argument is the minimum value"# )] fn abs_min_int_overflow() { assert_evals_to!( @@ -799,6 +799,26 @@ fn gen_div_checked_by_zero_dec() { ); } +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[should_panic(expected = r#"Roc failed with message: "Decimal division by 0!"#)] +fn gen_div_dec_by_zero() { + assert_evals_to!("1dec / 0", RocDec::from_str_to_i128_unsafe("-1"), i128); +} + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[should_panic(expected = r#"Roc failed with message: "Integer division by 0!"#)] +fn gen_div_ceil_by_zero() { + assert_evals_to!( + r#" + Num.divCeil 5 0 == 0 + "#, + false, + bool + ); +} + #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))] fn gen_int_eq() { @@ -1581,7 +1601,7 @@ fn int_negate() { #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] #[should_panic( - expected = r#"Roc failed with message: "integer negation overflowed because its argument is the minimum value"# + expected = r#"Roc failed with message: "Integer negation overflowed because its argument is the minimum value"# )] fn neg_min_int_overflow() { assert_evals_to!( @@ -1793,6 +1813,7 @@ fn ceiling() { #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] fn floor() { assert_evals_to!("Num.floor 1.9f64", 1, i64); + assert_evals_to!("Num.floor -1.9f64", -2, i64); } #[test] @@ -1809,7 +1830,7 @@ fn atan() { #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] -#[should_panic(expected = r#"Roc failed with message: "integer addition overflowed!"#)] +#[should_panic(expected = r#"Roc failed with message: "Integer addition overflowed!"#)] fn int_add_overflow() { assert_evals_to!( indoc!( @@ -1884,7 +1905,7 @@ fn float_add_overflow() { #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] -#[should_panic(expected = r#"Roc failed with message: "integer subtraction overflowed!"#)] +#[should_panic(expected = r#"Roc failed with message: "Integer subtraction overflowed!"#)] fn int_sub_overflow() { assert_evals_to!("-9_223_372_036_854_775_808 - 1", 0, i64); } @@ -1969,7 +1990,7 @@ fn float_sub_checked() { #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] -#[should_panic(expected = r#"Roc failed with message: "integer multiplication overflowed!"#)] +#[should_panic(expected = r#"Roc failed with message: "Integer multiplication overflowed!"#)] fn int_positive_mul_overflow() { assert_evals_to!( indoc!( @@ -1984,7 +2005,7 @@ fn int_positive_mul_overflow() { #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] -#[should_panic(expected = r#"Roc failed with message: "integer multiplication overflowed!"#)] +#[should_panic(expected = r#"Roc failed with message: "Integer multiplication overflowed!"#)] fn int_negative_mul_overflow() { assert_evals_to!( indoc!( @@ -3849,30 +3870,30 @@ fn condition_polymorphic_num_becomes_float() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] 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); + assert_evals_to!(r#"Num.countLeadingZeroBits 0b0010_1000u8"#, 2, u8); + assert_evals_to!(r#"Num.countLeadingZeroBits 0b0010_1000u16"#, 10, u8); + assert_evals_to!(r#"Num.countLeadingZeroBits 0b0010_1000u32"#, 26, u8); + assert_evals_to!(r#"Num.countLeadingZeroBits 0b0010_1000u64"#, 58, u8); } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] 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); + assert_evals_to!(r#"Num.countTrailingZeroBits 0b0010_1000u8"#, 3, u8); + assert_evals_to!(r#"Num.countTrailingZeroBits 0b0010_0000u16"#, 5, u8); + assert_evals_to!(r#"Num.countTrailingZeroBits 0u32"#, 32, u8); + assert_evals_to!(r#"Num.countTrailingZeroBits 0b0010_1111u64"#, 0, u8); } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] 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); + assert_evals_to!(r#"Num.countOneBits 0b0010_1000u8"#, 2, u8); + assert_evals_to!(r#"Num.countOneBits 0b0010_0000u16"#, 1, u8); + assert_evals_to!(r#"Num.countOneBits 0u32"#, 0, u8); + assert_evals_to!(r#"Num.countOneBits 0b0010_1111u64"#, 5, u8); } #[test] @@ -3907,21 +3928,21 @@ fn num_abs_diff_float() { #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] -#[should_panic(expected = r#"Roc failed with message: "integer subtraction overflowed!"#)] +#[should_panic(expected = r#"Roc failed with message: "Integer subtraction overflowed!"#)] fn num_abs_max_overflow() { assert_evals_to!(r#"Num.absDiff Num.maxI64 -1"#, 0, i64); } #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] -#[should_panic(expected = r#"Roc failed with message: "integer subtraction overflowed!"#)] +#[should_panic(expected = r#"Roc failed with message: "Integer subtraction overflowed!"#)] fn num_abs_int_min_overflow() { assert_evals_to!(r#"Num.absDiff Num.minI64 0"#, 0, i64); } #[test] #[cfg(feature = "gen-llvm")] -#[should_panic(expected = r#"Roc failed with message: "integer subtraction overflowed!"#)] +#[should_panic(expected = r#"Roc failed with message: "Integer subtraction overflowed!"#)] fn num_abs_large_bits_min_overflow() { assert_evals_to!(r#"Num.absDiff Num.minI128 0"#, 0, i128); } diff --git a/crates/compiler/test_gen/src/gen_set.rs b/crates/compiler/test_gen/src/gen_set.rs index e046899e0f..75201c38a4 100644 --- a/crates/compiler/test_gen/src/gen_set.rs +++ b/crates/compiler/test_gen/src/gen_set.rs @@ -120,7 +120,7 @@ fn union() { |> Set.toList "# ), - RocList::from_slice(&[1, 2, 3, 4]), + RocList::from_slice(&[1, 3, 4, 2]), RocList ); } diff --git a/crates/compiler/test_gen/src/helpers/llvm.rs b/crates/compiler/test_gen/src/helpers/llvm.rs index 34bc8dc9fc..7ecbb0ebd5 100644 --- a/crates/compiler/test_gen/src/helpers/llvm.rs +++ b/crates/compiler/test_gen/src/helpers/llvm.rs @@ -233,9 +233,6 @@ fn create_llvm_module<'a>( exposed_to_host: MutSet::default(), }; - // strip Zig debug stuff - module.strip_debug_info(); - // Add roc_alloc, roc_realloc, and roc_dealloc, since the repl has no // platform to provide them. add_default_roc_externs(&env); @@ -279,9 +276,6 @@ fn create_llvm_module<'a>( env.dibuilder.finalize(); - // strip all debug info: we don't use it at the moment and causes weird validation issues - module.strip_debug_info(); - // Uncomment this to see the module's un-optimized LLVM instruction output: // env.module.print_to_stderr(); @@ -325,7 +319,7 @@ fn create_llvm_module<'a>( pub struct HelperConfig { pub mode: LlvmBackendMode, pub ignore_problems: bool, - pub add_debug_info: bool, + pub emit_debug_info: bool, pub opt_level: OptLevel, } @@ -343,56 +337,16 @@ pub fn helper<'a>( let (main_fn_name, delayed_errors, module) = create_llvm_module(arena, src, config, context, &target, function_kind); - let res_lib = if config.add_debug_info { - let module = annotate_with_debug_info(module, context); - llvm_module_to_dylib(&module, &target, config.opt_level) - } else { - llvm_module_to_dylib(module, &target, config.opt_level) - }; + if !config.emit_debug_info { + module.strip_debug_info(); + } + let res_lib = llvm_module_to_dylib(module, &target, config.opt_level); let lib = res_lib.expect("Error loading compiled dylib for test"); (main_fn_name, delayed_errors, lib) } -fn annotate_with_debug_info<'ctx>( - module: &Module<'ctx>, - context: &'ctx inkwell::context::Context, -) -> Module<'ctx> { - use std::process::Command; - - let app_ll_file = "/tmp/roc-debugir.ll"; - let app_dbg_ll_file = "/tmp/roc-debugir.dbg.ll"; - let app_bc_file = "/tmp/roc-debugir.bc"; - - // write the ll code to a file, so we can modify it - module.print_to_file(app_ll_file).unwrap(); - - // run the debugir https://github.com/vaivaswatha/debugir tool - match Command::new("debugir") - .args(["-instnamer", app_ll_file]) - .output() - { - Ok(_) => {} - Err(error) => { - use std::io::ErrorKind; - match error.kind() { - ErrorKind::NotFound => panic!( - r"I could not find the `debugir` tool on the PATH, install it from https://github.com/vaivaswatha/debugir" - ), - _ => panic!("{error:?}"), - } - } - } - - Command::new("llvm-as") - .args([app_dbg_ll_file, "-o", app_bc_file]) - .output() - .unwrap(); - - inkwell::module::Module::parse_bitcode_from_path(app_bc_file, context).unwrap() -} - #[allow(dead_code)] fn wasm32_target_tripple() -> Triple { use target_lexicon::{Architecture, BinaryFormat}; @@ -533,7 +487,7 @@ where let config = HelperConfig { mode: LlvmBackendMode::WasmGenTest, - add_debug_info: false, + emit_debug_info: false, ignore_problems, opt_level: OPT_LEVEL, }; @@ -611,7 +565,7 @@ pub(crate) fn llvm_evals_to( let config = crate::helpers::llvm::HelperConfig { mode: LlvmBackendMode::GenTest, - add_debug_info: false, + emit_debug_info: false, ignore_problems, opt_level: crate::helpers::llvm::OPT_LEVEL, }; 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 53d65943a3..e173e68196 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 @@ -2,80 +2,80 @@ procedure Bool.11 (#Attr.2, #Attr.3): let Bool.23 : Int1 = lowlevel Eq #Attr.2 #Attr.3; ret Bool.23; -procedure List.26 (List.181, List.182, List.183): - let List.564 : [C U64, C U64] = CallByName List.99 List.181 List.182 List.183; - let List.567 : U8 = 1i64; - let List.568 : U8 = GetTagId List.564; - let List.569 : Int1 = lowlevel Eq List.567 List.568; - if List.569 then - let List.184 : U64 = UnionAtIndex (Id 1) (Index 0) List.564; - ret List.184; +procedure List.101 (List.484, List.485, List.486): + let List.587 : U64 = 0i64; + let List.588 : U64 = CallByName List.6 List.484; + let List.586 : [C U64, C U64] = CallByName List.80 List.484 List.485 List.486 List.587 List.588; + ret List.586; + +procedure List.26 (List.197, List.198, List.199): + let List.580 : [C U64, C U64] = CallByName List.101 List.197 List.198 List.199; + let List.583 : U8 = 1i64; + let List.584 : U8 = GetTagId List.580; + let List.585 : Int1 = lowlevel Eq List.583 List.584; + if List.585 then + let List.200 : U64 = UnionAtIndex (Id 1) (Index 0) List.580; + ret List.200; else - let List.185 : U64 = UnionAtIndex (Id 0) (Index 0) List.564; - ret List.185; + let List.201 : U64 = UnionAtIndex (Id 0) (Index 0) List.580; + ret List.201; -procedure List.38 (List.324, List.325): - let List.563 : U64 = CallByName List.6 List.324; - let List.326 : U64 = CallByName Num.77 List.563 List.325; - let List.553 : List U8 = CallByName List.43 List.324 List.326; - ret List.553; +procedure List.38 (List.340, List.341): + let List.579 : U64 = CallByName List.6 List.340; + let List.342 : U64 = CallByName Num.77 List.579 List.341; + let List.569 : List U8 = CallByName List.43 List.340 List.342; + ret List.569; -procedure List.43 (List.322, List.323): - let List.561 : U64 = CallByName List.6 List.322; - let List.560 : U64 = CallByName Num.77 List.561 List.323; - let List.555 : {U64, U64} = Struct {List.323, List.560}; - let List.554 : List U8 = CallByName List.49 List.322 List.555; - ret List.554; +procedure List.43 (List.338, List.339): + let List.577 : U64 = CallByName List.6 List.338; + let List.576 : U64 = CallByName Num.77 List.577 List.339; + let List.571 : {U64, U64} = Struct {List.339, List.576}; + let List.570 : List U8 = CallByName List.49 List.338 List.571; + ret List.570; -procedure List.49 (List.400, List.401): - let List.557 : U64 = StructAtIndex 1 List.401; - let List.558 : U64 = StructAtIndex 0 List.401; - let List.556 : List U8 = CallByName List.72 List.400 List.557 List.558; - ret List.556; +procedure List.49 (List.416, List.417): + let List.573 : U64 = StructAtIndex 1 List.417; + let List.574 : U64 = StructAtIndex 0 List.417; + let List.572 : List U8 = CallByName List.72 List.416 List.573 List.574; + ret List.572; procedure List.6 (#Attr.2): - let List.562 : U64 = lowlevel ListLen #Attr.2; - ret List.562; + let List.578 : U64 = lowlevel ListLen #Attr.2; + ret List.578; procedure List.66 (#Attr.2, #Attr.3): - let List.585 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.585; + let List.601 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.601; procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.559 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.559; + let List.575 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.575; procedure List.80 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): - joinpoint List.573 List.471 List.472 List.473 List.474 List.475: - let List.575 : Int1 = CallByName Num.22 List.474 List.475; - if List.575 then - let List.584 : U8 = CallByName List.66 List.471 List.474; - let List.576 : [C U64, C U64] = CallByName Test.4 List.472 List.584; - let List.581 : U8 = 1i64; - let List.582 : U8 = GetTagId List.576; - let List.583 : Int1 = lowlevel Eq List.581 List.582; - if List.583 then - let List.476 : U64 = UnionAtIndex (Id 1) (Index 0) List.576; - let List.579 : U64 = 1i64; - let List.578 : U64 = CallByName Num.51 List.474 List.579; - jump List.573 List.471 List.476 List.473 List.578 List.475; + joinpoint List.589 List.487 List.488 List.489 List.490 List.491: + let List.591 : Int1 = CallByName Num.22 List.490 List.491; + if List.591 then + let List.600 : U8 = CallByName List.66 List.487 List.490; + let List.592 : [C U64, C U64] = CallByName Test.4 List.488 List.600; + let List.597 : U8 = 1i64; + let List.598 : U8 = GetTagId List.592; + let List.599 : Int1 = lowlevel Eq List.597 List.598; + if List.599 then + let List.492 : U64 = UnionAtIndex (Id 1) (Index 0) List.592; + let List.595 : U64 = 1i64; + let List.594 : U64 = CallByName Num.51 List.490 List.595; + jump List.589 List.487 List.492 List.489 List.594 List.491; else - dec List.471; - let List.477 : U64 = UnionAtIndex (Id 0) (Index 0) List.576; - let List.580 : [C U64, C U64] = TagId(0) List.477; - ret List.580; + dec List.487; + let List.493 : U64 = UnionAtIndex (Id 0) (Index 0) List.592; + let List.596 : [C U64, C U64] = TagId(0) List.493; + ret List.596; else - dec List.471; - let List.574 : [C U64, C U64] = TagId(1) List.472; - ret List.574; + dec List.487; + let List.590 : [C U64, C U64] = TagId(1) List.488; + ret List.590; in - jump List.573 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; - -procedure List.99 (List.468, List.469, List.470): - let List.571 : U64 = 0i64; - let List.572 : U64 = CallByName List.6 List.468; - let List.570 : [C U64, C U64] = CallByName List.80 List.468 List.469 List.470 List.571 List.572; - ret List.570; + jump List.589 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; procedure Num.22 (#Attr.2, #Attr.3): let Num.294 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; 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 5b7029eac1..8e5a61f0bb 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.553 : List {} = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.2 #Attr.3; + let List.569 : List {} = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.2 #Attr.3; decref #Attr.2; - ret List.553; + ret List.569; 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 e025fdcc30..5ce6015e75 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.553 : List [] = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.2 #Attr.3; + let List.569 : List [] = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.2 #Attr.3; decref #Attr.2; - ret List.553; + ret List.569; procedure Test.2 (Test.3): let Test.7 : {} = Struct {}; diff --git a/crates/compiler/test_mono/generated/capture_void_layout_task.txt b/crates/compiler/test_mono/generated/capture_void_layout_task.txt index 627dc58436..4a7557932e 100644 --- a/crates/compiler/test_mono/generated/capture_void_layout_task.txt +++ b/crates/compiler/test_mono/generated/capture_void_layout_task.txt @@ -1,31 +1,31 @@ -procedure List.18 (List.154, List.155, List.156): - let List.554 : U64 = 0i64; - let List.555 : U64 = CallByName List.6 List.154; - let List.553 : [C {}, C *self {{}, []}] = CallByName List.88 List.154 List.155 List.156 List.554 List.555; - ret List.553; +procedure List.18 (List.156, List.157, List.158): + let List.570 : U64 = 0i64; + let List.571 : U64 = CallByName List.6 List.156; + let List.569 : [C {}, C *self {{}, []}] = CallByName List.89 List.156 List.157 List.158 List.570 List.571; + ret List.569; procedure List.6 (#Attr.2): - let List.564 : U64 = lowlevel ListLen #Attr.2; - ret List.564; + let List.580 : U64 = lowlevel ListLen #Attr.2; + ret List.580; procedure List.66 (#Attr.2, #Attr.3): - let List.563 : [] = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.563; + let List.579 : [] = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.579; -procedure List.88 (#Derived_gen.3, #Derived_gen.4, #Derived_gen.5, #Derived_gen.6, #Derived_gen.7): - joinpoint List.556 List.157 List.158 List.159 List.160 List.161: - let List.558 : Int1 = CallByName Num.22 List.160 List.161; - if List.558 then - let List.562 : [] = CallByName List.66 List.157 List.160; - let List.162 : [C {}, C *self {{}, []}] = CallByName Test.29 List.158 List.562 List.159; - let List.561 : U64 = 1i64; - let List.560 : U64 = CallByName Num.51 List.160 List.561; - jump List.556 List.157 List.162 List.159 List.560 List.161; +procedure List.89 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): + joinpoint List.572 List.159 List.160 List.161 List.162 List.163: + let List.574 : Int1 = CallByName Num.22 List.162 List.163; + if List.574 then + let List.578 : [] = CallByName List.66 List.159 List.162; + let List.164 : [C {}, C *self {{}, []}] = CallByName Test.29 List.160 List.578 List.161; + let List.577 : U64 = 1i64; + let List.576 : U64 = CallByName Num.51 List.162 List.577; + jump List.572 List.159 List.164 List.161 List.576 List.163; else - dec List.157; - ret List.158; + dec List.159; + ret List.160; in - jump List.556 #Derived_gen.3 #Derived_gen.4 #Derived_gen.5 #Derived_gen.6 #Derived_gen.7; + jump List.572 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; procedure Num.22 (#Attr.2, #Attr.3): let Num.292 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; 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 2d83961daf..9cbe7071b1 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 @@ -2,49 +2,49 @@ procedure Bool.1 (): let Bool.24 : Int1 = false; ret Bool.24; -procedure List.2 (List.103, List.104): - let List.567 : U64 = CallByName List.6 List.103; - let List.563 : Int1 = CallByName Num.22 List.104 List.567; - if List.563 then - let List.565 : Str = CallByName List.66 List.103 List.104; - inc List.565; - dec List.103; - let List.564 : [C {}, C Str] = TagId(1) List.565; - ret List.564; +procedure List.2 (List.105, List.106): + let List.583 : U64 = CallByName List.6 List.105; + let List.579 : Int1 = CallByName Num.22 List.106 List.583; + if List.579 then + let List.581 : Str = CallByName List.66 List.105 List.106; + inc List.581; + dec List.105; + let List.580 : [C {}, C Str] = TagId(1) List.581; + ret List.580; else - dec List.103; - let List.562 : {} = Struct {}; - let List.561 : [C {}, C Str] = TagId(0) List.562; - ret List.561; + dec List.105; + let List.578 : {} = Struct {}; + let List.577 : [C {}, C Str] = TagId(0) List.578; + ret List.577; procedure List.5 (#Attr.2, #Attr.3): - let List.569 : List Str = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.10 #Attr.3; + let List.585 : List Str = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.10 #Attr.3; decref #Attr.2; - ret List.569; + ret List.585; procedure List.6 (#Attr.2): - let List.568 : U64 = lowlevel ListLen #Attr.2; - ret List.568; + let List.584 : U64 = lowlevel ListLen #Attr.2; + ret List.584; procedure List.66 (#Attr.2, #Attr.3): - let List.566 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.566; + let List.582 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.582; -procedure List.9 (List.315): - let List.560 : U64 = 0i64; - let List.553 : [C {}, C Str] = CallByName List.2 List.315 List.560; - let List.557 : U8 = 1i64; - let List.558 : U8 = GetTagId List.553; - let List.559 : Int1 = lowlevel Eq List.557 List.558; - if List.559 then - let List.316 : Str = UnionAtIndex (Id 1) (Index 0) List.553; - let List.554 : [C {}, C Str] = TagId(1) List.316; - ret List.554; +procedure List.9 (List.331): + let List.576 : U64 = 0i64; + let List.569 : [C {}, C Str] = CallByName List.2 List.331 List.576; + let List.573 : U8 = 1i64; + let List.574 : U8 = GetTagId List.569; + let List.575 : Int1 = lowlevel Eq List.573 List.574; + if List.575 then + let List.332 : Str = UnionAtIndex (Id 1) (Index 0) List.569; + let List.570 : [C {}, C Str] = TagId(1) List.332; + ret List.570; else - dec List.553; - let List.556 : {} = Struct {}; - let List.555 : [C {}, C Str] = TagId(0) List.556; - ret List.555; + dec List.569; + let List.572 : {} = Struct {}; + let List.571 : [C {}, C Str] = TagId(0) List.572; + ret List.571; procedure Num.22 (#Attr.2, #Attr.3): let Num.291 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/closure_in_list.txt b/crates/compiler/test_mono/generated/closure_in_list.txt index 0cc0eab4f5..dad30ed6da 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.553 : U64 = lowlevel ListLen #Attr.2; - ret List.553; + let List.569 : U64 = lowlevel ListLen #Attr.2; + ret List.569; procedure Test.1 (Test.5): let Test.2 : I64 = 41i64; diff --git a/crates/compiler/test_mono/generated/compose_recursive_lambda_set_productive_nullable_wrapped.txt b/crates/compiler/test_mono/generated/compose_recursive_lambda_set_productive_nullable_wrapped.txt index e3386f5867..9795011c89 100644 --- a/crates/compiler/test_mono/generated/compose_recursive_lambda_set_productive_nullable_wrapped.txt +++ b/crates/compiler/test_mono/generated/compose_recursive_lambda_set_productive_nullable_wrapped.txt @@ -2,34 +2,34 @@ procedure Bool.2 (): let Bool.23 : Int1 = true; ret Bool.23; -procedure List.18 (List.154, List.155, List.156): - let List.554 : U64 = 0i64; - let List.555 : U64 = CallByName List.6 List.154; - let List.553 : [, C *self Int1, C *self Int1] = CallByName List.88 List.154 List.155 List.156 List.554 List.555; - ret List.553; +procedure List.18 (List.156, List.157, List.158): + let List.570 : U64 = 0i64; + let List.571 : U64 = CallByName List.6 List.156; + let List.569 : [, C *self Int1, C *self Int1] = CallByName List.89 List.156 List.157 List.158 List.570 List.571; + ret List.569; procedure List.6 (#Attr.2): - let List.564 : U64 = lowlevel ListLen #Attr.2; - ret List.564; + let List.580 : U64 = lowlevel ListLen #Attr.2; + ret List.580; procedure List.66 (#Attr.2, #Attr.3): - let List.563 : Int1 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.563; + let List.579 : Int1 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.579; -procedure List.88 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): - joinpoint List.556 List.157 List.158 List.159 List.160 List.161: - let List.558 : Int1 = CallByName Num.22 List.160 List.161; - if List.558 then - let List.562 : Int1 = CallByName List.66 List.157 List.160; - let List.162 : [, C *self Int1, C *self Int1] = CallByName Test.6 List.158 List.562 List.159; - let List.561 : U64 = 1i64; - let List.560 : U64 = CallByName Num.51 List.160 List.561; - jump List.556 List.157 List.162 List.159 List.560 List.161; +procedure List.89 (#Derived_gen.3, #Derived_gen.4, #Derived_gen.5, #Derived_gen.6, #Derived_gen.7): + joinpoint List.572 List.159 List.160 List.161 List.162 List.163: + let List.574 : Int1 = CallByName Num.22 List.162 List.163; + if List.574 then + let List.578 : Int1 = CallByName List.66 List.159 List.162; + let List.164 : [, C *self Int1, C *self Int1] = CallByName Test.6 List.160 List.578 List.161; + let List.577 : U64 = 1i64; + let List.576 : U64 = CallByName Num.51 List.162 List.577; + jump List.572 List.159 List.164 List.161 List.576 List.163; else - dec List.157; - ret List.158; + dec List.159; + ret List.160; in - jump List.556 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; + jump List.572 #Derived_gen.3 #Derived_gen.4 #Derived_gen.5 #Derived_gen.6 #Derived_gen.7; procedure Num.22 (#Attr.2, #Attr.3): let Num.292 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/dbg_in_expect.txt b/crates/compiler/test_mono/generated/dbg_in_expect.txt index 064c6634f8..77cbd8800f 100644 --- a/crates/compiler/test_mono/generated/dbg_in_expect.txt +++ b/crates/compiler/test_mono/generated/dbg_in_expect.txt @@ -2,48 +2,52 @@ procedure Bool.2 (): let Bool.23 : Int1 = true; ret Bool.23; -procedure Inspect.249 (Inspect.250, Inspect.248): +procedure Inspect.251 (Inspect.252, Inspect.250): + let Inspect.327 : Str = "\""; + let Inspect.326 : Str = CallByName Inspect.61 Inspect.252 Inspect.327; + let Inspect.322 : Str = CallByName Inspect.61 Inspect.326 Inspect.250; let Inspect.323 : Str = "\""; - let Inspect.322 : Str = CallByName Inspect.61 Inspect.250 Inspect.323; - let Inspect.318 : Str = CallByName Inspect.61 Inspect.322 Inspect.248; - let Inspect.319 : Str = "\""; - let Inspect.317 : Str = CallByName Inspect.61 Inspect.318 Inspect.319; + let Inspect.321 : Str = CallByName Inspect.61 Inspect.322 Inspect.323; + ret Inspect.321; + +procedure Inspect.30 (Inspect.148): + ret Inspect.148; + +procedure Inspect.34 (Inspect.153): + let Inspect.309 : Str = CallByName Inspect.5 Inspect.153; + let Inspect.308 : Str = CallByName Inspect.62 Inspect.309; + ret Inspect.308; + +procedure Inspect.36 (Inspect.305): + let Inspect.315 : Str = ""; + ret Inspect.315; + +procedure Inspect.44 (Inspect.250): + let Inspect.317 : Str = CallByName Inspect.30 Inspect.250; ret Inspect.317; -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.35 (Inspect.300): - ret Inspect.300; - -procedure Inspect.36 (Inspect.304): - let Inspect.311 : Str = ""; +procedure Inspect.5 (Inspect.151): + let Inspect.316 : Str = CallByName Inspect.44 Inspect.151; + let Inspect.313 : {} = Struct {}; + let Inspect.312 : Str = CallByName Inspect.36 Inspect.313; + let Inspect.311 : Str = CallByName Inspect.251 Inspect.312 Inspect.316; ret Inspect.311; -procedure Inspect.44 (Inspect.248): - let Inspect.313 : Str = CallByName Inspect.30 Inspect.248; - ret Inspect.313; +procedure Inspect.61 (Inspect.304, Inspect.300): + let Inspect.325 : Str = CallByName Str.3 Inspect.304 Inspect.300; + dec Inspect.300; + ret Inspect.325; -procedure Inspect.5 (Inspect.150): - let Inspect.312 : Str = CallByName Inspect.44 Inspect.150; - let Inspect.309 : {} = Struct {}; - let Inspect.308 : Str = CallByName Inspect.36 Inspect.309; - let Inspect.307 : Str = CallByName Inspect.249 Inspect.308 Inspect.312; - ret Inspect.307; - -procedure Inspect.61 (Inspect.303, Inspect.298): - let Inspect.321 : Str = CallByName Str.3 Inspect.303 Inspect.298; - dec Inspect.298; - ret Inspect.321; +procedure Inspect.62 (Inspect.306): + ret Inspect.306; procedure Str.3 (#Attr.2, #Attr.3): let Str.292 : Str = lowlevel StrConcat #Attr.2 #Attr.3; ret Str.292; procedure Test.1 (): - let Test.5 : Str = ""; - let Test.4 : Str = CallByName Inspect.5 Test.5; - let Test.0 : Str = CallByName Inspect.35 Test.4; + let Test.4 : Str = ""; + let Test.0 : Str = CallByName Inspect.34 Test.4; dbg Test.0; dec Test.0; let Test.3 : Int1 = CallByName Bool.2; diff --git a/crates/compiler/test_mono/generated/dbg_str_followed_by_number.txt b/crates/compiler/test_mono/generated/dbg_str_followed_by_number.txt index 30f3e3f208..a8eaeeb542 100644 --- a/crates/compiler/test_mono/generated/dbg_str_followed_by_number.txt +++ b/crates/compiler/test_mono/generated/dbg_str_followed_by_number.txt @@ -1,45 +1,49 @@ -procedure Inspect.249 (Inspect.250, Inspect.248): +procedure Inspect.251 (Inspect.252, Inspect.250): + let Inspect.327 : Str = "\""; + let Inspect.326 : Str = CallByName Inspect.61 Inspect.252 Inspect.327; + let Inspect.322 : Str = CallByName Inspect.61 Inspect.326 Inspect.250; let Inspect.323 : Str = "\""; - let Inspect.322 : Str = CallByName Inspect.61 Inspect.250 Inspect.323; - let Inspect.318 : Str = CallByName Inspect.61 Inspect.322 Inspect.248; - let Inspect.319 : Str = "\""; - let Inspect.317 : Str = CallByName Inspect.61 Inspect.318 Inspect.319; + let Inspect.321 : Str = CallByName Inspect.61 Inspect.322 Inspect.323; + ret Inspect.321; + +procedure Inspect.30 (Inspect.148): + ret Inspect.148; + +procedure Inspect.34 (Inspect.153): + let Inspect.309 : Str = CallByName Inspect.5 Inspect.153; + let Inspect.308 : Str = CallByName Inspect.62 Inspect.309; + ret Inspect.308; + +procedure Inspect.36 (Inspect.305): + let Inspect.315 : Str = ""; + ret Inspect.315; + +procedure Inspect.44 (Inspect.250): + let Inspect.317 : Str = CallByName Inspect.30 Inspect.250; ret Inspect.317; -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.35 (Inspect.300): - ret Inspect.300; - -procedure Inspect.36 (Inspect.304): - let Inspect.311 : Str = ""; +procedure Inspect.5 (Inspect.151): + let Inspect.316 : Str = CallByName Inspect.44 Inspect.151; + let Inspect.313 : {} = Struct {}; + let Inspect.312 : Str = CallByName Inspect.36 Inspect.313; + let Inspect.311 : Str = CallByName Inspect.251 Inspect.312 Inspect.316; ret Inspect.311; -procedure Inspect.44 (Inspect.248): - let Inspect.313 : Str = CallByName Inspect.30 Inspect.248; - ret Inspect.313; +procedure Inspect.61 (Inspect.304, Inspect.300): + let Inspect.325 : Str = CallByName Str.3 Inspect.304 Inspect.300; + dec Inspect.300; + ret Inspect.325; -procedure Inspect.5 (Inspect.150): - let Inspect.312 : Str = CallByName Inspect.44 Inspect.150; - let Inspect.309 : {} = Struct {}; - let Inspect.308 : Str = CallByName Inspect.36 Inspect.309; - let Inspect.307 : Str = CallByName Inspect.249 Inspect.308 Inspect.312; - ret Inspect.307; - -procedure Inspect.61 (Inspect.303, Inspect.298): - let Inspect.321 : Str = CallByName Str.3 Inspect.303 Inspect.298; - dec Inspect.298; - ret Inspect.321; +procedure Inspect.62 (Inspect.306): + ret Inspect.306; procedure Str.3 (#Attr.2, #Attr.3): let Str.292 : Str = lowlevel StrConcat #Attr.2 #Attr.3; ret Str.292; procedure Test.0 (): - let Test.4 : Str = ""; - let Test.3 : Str = CallByName Inspect.5 Test.4; - let Test.1 : Str = CallByName Inspect.35 Test.3; + let Test.3 : Str = ""; + let Test.1 : Str = CallByName Inspect.34 Test.3; dbg Test.1; dec Test.1; let Test.2 : I64 = 42i64; diff --git a/crates/compiler/test_mono/generated/dict.txt b/crates/compiler/test_mono/generated/dict.txt index 6c0f78543c..a9c9bf3f21 100644 --- a/crates/compiler/test_mono/generated/dict.txt +++ b/crates/compiler/test_mono/generated/dict.txt @@ -1,93 +1,40 @@ -procedure Dict.1 (Dict.557): - let Dict.567 : List {[], []} = Array []; - let Dict.574 : U64 = 0i64; - let Dict.575 : U64 = 8i64; - let Dict.568 : List U64 = CallByName List.11 Dict.574 Dict.575; - let Dict.571 : I8 = CallByName Dict.40; - let Dict.572 : U64 = 8i64; - let Dict.569 : List I8 = CallByName List.11 Dict.571 Dict.572; - let Dict.570 : U64 = 0i64; - let Dict.566 : {List {[], []}, List U64, List I8, U64} = Struct {Dict.567, Dict.568, Dict.569, Dict.570}; - ret Dict.566; +procedure Dict.1 (Dict.726): + let Dict.735 : List {U32, U32} = Array []; + let Dict.736 : List {[], []} = Array []; + let Dict.737 : U64 = 0i64; + let Dict.44 : Float32 = CallByName Dict.44; + let Dict.45 : U8 = CallByName Dict.45; + let Dict.734 : {List {U32, U32}, List {[], []}, U64, Float32, U8} = Struct {Dict.735, Dict.736, Dict.737, Dict.44, Dict.45}; + ret Dict.734; -procedure Dict.4 (Dict.564): - let Dict.105 : U64 = StructAtIndex 3 Dict.564; - let #Derived_gen.8 : List {[], []} = StructAtIndex 0 Dict.564; - dec #Derived_gen.8; - let #Derived_gen.7 : List U64 = StructAtIndex 1 Dict.564; - dec #Derived_gen.7; - let #Derived_gen.6 : List I8 = StructAtIndex 2 Dict.564; - dec #Derived_gen.6; - ret Dict.105; +procedure Dict.4 (Dict.732): + let Dict.157 : List {[], []} = StructAtIndex 1 Dict.732; + let #Derived_gen.0 : List {U32, U32} = StructAtIndex 0 Dict.732; + dec #Derived_gen.0; + let Dict.733 : U64 = CallByName List.6 Dict.157; + dec Dict.157; + ret Dict.733; -procedure Dict.40 (): - let Dict.573 : I8 = -128i64; - ret Dict.573; +procedure Dict.44 (): + let Dict.741 : Float32 = 0.8f64; + ret Dict.741; -procedure List.11 (List.133, List.134): - let List.554 : List I8 = CallByName List.68 List.134; - let List.553 : List I8 = CallByName List.86 List.133 List.134 List.554; - ret List.553; +procedure Dict.45 (): + let Dict.739 : U8 = 64i64; + let Dict.740 : U8 = 3i64; + let Dict.738 : U8 = CallByName Num.20 Dict.739 Dict.740; + ret Dict.738; -procedure List.11 (List.133, List.134): - let List.566 : List U64 = CallByName List.68 List.134; - let List.565 : List U64 = CallByName List.86 List.133 List.134 List.566; - ret List.565; +procedure List.6 (#Attr.2): + let List.569 : U64 = lowlevel ListLen #Attr.2; + ret List.569; -procedure List.68 (#Attr.2): - let List.564 : List I8 = lowlevel ListWithCapacity #Attr.2; - ret List.564; - -procedure List.68 (#Attr.2): - let List.576 : List U64 = lowlevel ListWithCapacity #Attr.2; - ret List.576; - -procedure List.71 (#Attr.2, #Attr.3): - let List.561 : List I8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.561; - -procedure List.71 (#Attr.2, #Attr.3): - let List.573 : List U64 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.573; - -procedure List.86 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): - joinpoint List.555 List.135 List.136 List.137: - let List.563 : U64 = 0i64; - let List.557 : Int1 = CallByName Num.24 List.136 List.563; - if List.557 then - let List.562 : U64 = 1i64; - let List.559 : U64 = CallByName Num.75 List.136 List.562; - let List.560 : List I8 = CallByName List.71 List.137 List.135; - jump List.555 List.135 List.559 List.560; - else - ret List.137; - in - jump List.555 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2; - -procedure List.86 (#Derived_gen.3, #Derived_gen.4, #Derived_gen.5): - joinpoint List.567 List.135 List.136 List.137: - let List.575 : U64 = 0i64; - let List.569 : Int1 = CallByName Num.24 List.136 List.575; - if List.569 then - let List.574 : U64 = 1i64; - let List.571 : U64 = CallByName Num.75 List.136 List.574; - let List.572 : List U64 = CallByName List.71 List.137 List.135; - jump List.567 List.135 List.571 List.572; - else - ret List.137; - in - jump List.567 #Derived_gen.3 #Derived_gen.4 #Derived_gen.5; - -procedure Num.24 (#Attr.2, #Attr.3): - let Num.294 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; - ret Num.294; - -procedure Num.75 (#Attr.2, #Attr.3): - let Num.292 : U64 = lowlevel NumSubWrap #Attr.2 #Attr.3; - ret Num.292; +procedure Num.20 (#Attr.2, #Attr.3): + let Num.291 : U8 = lowlevel NumSub #Attr.2 #Attr.3; + ret Num.291; procedure Test.0 (): let Test.3 : {} = Struct {}; - let Test.2 : {List {[], []}, List U64, List I8, U64} = CallByName Dict.1 Test.3; + let Test.2 : {List {U32, U32}, List {[], []}, U64, Float32, U8} = CallByName Dict.1 Test.3; let Test.1 : U64 = CallByName Dict.4 Test.2; ret Test.1; 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 8b5bf63331..4f8f4c2940 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 @@ -2,27 +2,27 @@ procedure Bool.1 (): let Bool.23 : Int1 = false; ret Bool.23; -procedure List.2 (List.103, List.104): - let List.559 : U64 = CallByName List.6 List.103; - let List.555 : Int1 = CallByName Num.22 List.104 List.559; - if List.555 then - let List.557 : {} = CallByName List.66 List.103 List.104; - dec List.103; - let List.556 : [C {}, C {}] = TagId(1) List.557; - ret List.556; +procedure List.2 (List.105, List.106): + let List.575 : U64 = CallByName List.6 List.105; + let List.571 : Int1 = CallByName Num.22 List.106 List.575; + if List.571 then + let List.573 : {} = CallByName List.66 List.105 List.106; + dec List.105; + let List.572 : [C {}, C {}] = TagId(1) List.573; + ret List.572; else - dec List.103; - let List.554 : {} = Struct {}; - let List.553 : [C {}, C {}] = TagId(0) List.554; - ret List.553; + dec List.105; + let List.570 : {} = Struct {}; + let List.569 : [C {}, C {}] = TagId(0) List.570; + ret List.569; procedure List.6 (#Attr.2): - let List.560 : U64 = lowlevel ListLen #Attr.2; - ret List.560; + let List.576 : U64 = lowlevel ListLen #Attr.2; + ret List.576; procedure List.66 (#Attr.2, #Attr.3): - let List.558 : {} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.558; + let List.574 : {} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.574; procedure Num.22 (#Attr.2, #Attr.3): let Num.291 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/encode.txt b/crates/compiler/test_mono/generated/encode.txt index 633387ef87..121a386fe6 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.119, List.120): - let List.556 : U64 = 1i64; - let List.554 : List U8 = CallByName List.70 List.119 List.556; - let List.553 : List U8 = CallByName List.71 List.554 List.120; - ret List.553; +procedure List.4 (List.121, List.122): + let List.572 : U64 = 1i64; + let List.570 : List U8 = CallByName List.70 List.121 List.572; + let List.569 : List U8 = CallByName List.71 List.570 List.122; + ret List.569; procedure List.70 (#Attr.2, #Attr.3): - let List.557 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.557; + let List.573 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.573; procedure List.71 (#Attr.2, #Attr.3): - let List.555 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.555; + let List.571 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.571; 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 d8d00be715..1d88fc081a 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 @@ -73,242 +73,242 @@ procedure Encode.26 (Encode.105, Encode.106): let Encode.108 : List U8 = CallByName Encode.24 Encode.109 Encode.110 Encode.106; ret Encode.108; +procedure List.101 (List.484, List.485, List.486): + let List.749 : U64 = 0i64; + let List.750 : U64 = CallByName List.6 List.484; + let List.748 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.484 List.485 List.486 List.749 List.750; + ret List.748; + procedure List.13 (#Attr.2, #Attr.3): - let List.713 : List Str = lowlevel ListPrepend #Attr.2 #Attr.3; - ret List.713; + let List.729 : List Str = lowlevel ListPrepend #Attr.2 #Attr.3; + ret List.729; -procedure List.18 (List.154, List.155, List.156): - let List.583 : U64 = 0i64; - let List.584 : U64 = CallByName List.6 List.154; - let List.582 : {List U8, U64} = CallByName List.88 List.154 List.155 List.156 List.583 List.584; - ret List.582; +procedure List.18 (List.156, List.157, List.158): + let List.599 : U64 = 0i64; + let List.600 : U64 = CallByName List.6 List.156; + let List.598 : {List U8, U64} = CallByName List.89 List.156 List.157 List.158 List.599 List.600; + ret List.598; -procedure List.18 (List.154, List.155, List.156): - let List.651 : U64 = 0i64; - let List.652 : U64 = CallByName List.6 List.154; - let List.650 : {List U8, U64} = CallByName List.88 List.154 List.155 List.156 List.651 List.652; - ret List.650; +procedure List.18 (List.156, List.157, List.158): + let List.667 : U64 = 0i64; + let List.668 : U64 = CallByName List.6 List.156; + let List.666 : {List U8, U64} = CallByName List.89 List.156 List.157 List.158 List.667 List.668; + ret List.666; -procedure List.18 (List.154, List.155, List.156): - let List.663 : U64 = 0i64; - let List.664 : U64 = CallByName List.6 List.154; - let List.662 : List U8 = CallByName List.88 List.154 List.155 List.156 List.663 List.664; - ret List.662; +procedure List.18 (List.156, List.157, List.158): + let List.679 : U64 = 0i64; + let List.680 : U64 = CallByName List.6 List.156; + let List.678 : List U8 = CallByName List.89 List.156 List.157 List.158 List.679 List.680; + ret List.678; -procedure List.26 (List.181, List.182, List.183): - let List.726 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.99 List.181 List.182 List.183; - let List.729 : U8 = 1i64; - let List.730 : U8 = GetTagId List.726; - let List.731 : Int1 = lowlevel Eq List.729 List.730; - if List.731 then - let List.184 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.726; - ret List.184; +procedure List.26 (List.197, List.198, List.199): + let List.742 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.101 List.197 List.198 List.199; + let List.745 : U8 = 1i64; + let List.746 : U8 = GetTagId List.742; + let List.747 : Int1 = lowlevel Eq List.745 List.746; + if List.747 then + let List.200 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.742; + ret List.200; else - let List.185 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.726; - ret List.185; + let List.201 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.742; + ret List.201; -procedure List.38 (List.324, List.325): - let List.703 : U64 = CallByName List.6 List.324; - let List.326 : U64 = CallByName Num.77 List.703 List.325; - let List.702 : List Str = CallByName List.43 List.324 List.326; - ret List.702; +procedure List.38 (List.340, List.341): + let List.719 : U64 = CallByName List.6 List.340; + let List.342 : U64 = CallByName Num.77 List.719 List.341; + let List.718 : List Str = CallByName List.43 List.340 List.342; + ret List.718; -procedure List.4 (List.119, List.120): - let List.646 : U64 = 1i64; - let List.645 : List Str = CallByName List.70 List.119 List.646; - let List.644 : List Str = CallByName List.71 List.645 List.120; - ret List.644; - -procedure List.4 (List.119, List.120): - let List.649 : U64 = 1i64; - let List.648 : List U8 = CallByName List.70 List.119 List.649; - let List.647 : List U8 = CallByName List.71 List.648 List.120; - ret List.647; - -procedure List.43 (List.322, List.323): - let List.693 : U64 = CallByName List.6 List.322; - let List.692 : U64 = CallByName Num.77 List.693 List.323; - let List.687 : {U64, U64} = Struct {List.323, List.692}; - let List.686 : List Str = CallByName List.49 List.322 List.687; - ret List.686; - -procedure List.49 (List.400, List.401): - let List.689 : U64 = StructAtIndex 1 List.401; - let List.690 : U64 = StructAtIndex 0 List.401; - let List.688 : List Str = CallByName List.72 List.400 List.689 List.690; - ret List.688; - -procedure List.49 (List.400, List.401): - let List.717 : U64 = StructAtIndex 1 List.401; - let List.718 : U64 = StructAtIndex 0 List.401; - let List.716 : List U8 = CallByName List.72 List.400 List.717 List.718; - ret List.716; - -procedure List.52 (List.415, List.416): - let List.417 : U64 = CallByName List.6 List.415; - joinpoint List.724 List.418: - let List.722 : U64 = 0i64; - let List.721 : {U64, U64} = Struct {List.418, List.722}; - inc List.415; - let List.419 : List U8 = CallByName List.49 List.415 List.721; - let List.720 : U64 = CallByName Num.75 List.417 List.418; - let List.715 : {U64, U64} = Struct {List.720, List.418}; - let List.420 : List U8 = CallByName List.49 List.415 List.715; - let List.714 : {List U8, List U8} = Struct {List.419, List.420}; - ret List.714; - in - let List.725 : Int1 = CallByName Num.24 List.417 List.416; - if List.725 then - jump List.724 List.416; - else - jump List.724 List.417; - -procedure List.6 (#Attr.2): - let List.620 : U64 = lowlevel ListLen #Attr.2; - ret List.620; - -procedure List.6 (#Attr.2): - let List.709 : U64 = lowlevel ListLen #Attr.2; - ret List.709; - -procedure List.6 (#Attr.2): - let List.710 : U64 = lowlevel ListLen #Attr.2; - ret List.710; - -procedure List.6 (#Attr.2): - let List.712 : U64 = lowlevel ListLen #Attr.2; - ret List.712; - -procedure List.66 (#Attr.2, #Attr.3): - let List.592 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.592; - -procedure List.66 (#Attr.2, #Attr.3): - let List.660 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; +procedure List.4 (List.121, List.122): + let List.662 : U64 = 1i64; + let List.661 : List Str = CallByName List.70 List.121 List.662; + let List.660 : List Str = CallByName List.71 List.661 List.122; ret List.660; +procedure List.4 (List.121, List.122): + let List.665 : U64 = 1i64; + let List.664 : List U8 = CallByName List.70 List.121 List.665; + let List.663 : List U8 = CallByName List.71 List.664 List.122; + ret List.663; + +procedure List.43 (List.338, List.339): + let List.709 : U64 = CallByName List.6 List.338; + let List.708 : U64 = CallByName Num.77 List.709 List.339; + let List.703 : {U64, U64} = Struct {List.339, List.708}; + let List.702 : List Str = CallByName List.49 List.338 List.703; + ret List.702; + +procedure List.49 (List.416, List.417): + let List.705 : U64 = StructAtIndex 1 List.417; + let List.706 : U64 = StructAtIndex 0 List.417; + let List.704 : List Str = CallByName List.72 List.416 List.705 List.706; + ret List.704; + +procedure List.49 (List.416, List.417): + let List.733 : U64 = StructAtIndex 1 List.417; + let List.734 : U64 = StructAtIndex 0 List.417; + let List.732 : List U8 = CallByName List.72 List.416 List.733 List.734; + ret List.732; + +procedure List.52 (List.431, List.432): + let List.433 : U64 = CallByName List.6 List.431; + joinpoint List.740 List.434: + let List.738 : U64 = 0i64; + let List.737 : {U64, U64} = Struct {List.434, List.738}; + inc List.431; + let List.435 : List U8 = CallByName List.49 List.431 List.737; + let List.736 : U64 = CallByName Num.75 List.433 List.434; + let List.731 : {U64, U64} = Struct {List.736, List.434}; + let List.436 : List U8 = CallByName List.49 List.431 List.731; + let List.730 : {List U8, List U8} = Struct {List.435, List.436}; + ret List.730; + in + let List.741 : Int1 = CallByName Num.24 List.433 List.432; + if List.741 then + jump List.740 List.432; + else + jump List.740 List.433; + +procedure List.6 (#Attr.2): + let List.636 : U64 = lowlevel ListLen #Attr.2; + ret List.636; + +procedure List.6 (#Attr.2): + let List.725 : U64 = lowlevel ListLen #Attr.2; + ret List.725; + +procedure List.6 (#Attr.2): + let List.726 : U64 = lowlevel ListLen #Attr.2; + ret List.726; + +procedure List.6 (#Attr.2): + let List.728 : U64 = lowlevel ListLen #Attr.2; + ret List.728; + procedure List.66 (#Attr.2, #Attr.3): - let List.672 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.672; + let List.608 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.608; -procedure List.68 (#Attr.2): - let List.705 : List Str = lowlevel ListWithCapacity #Attr.2; - ret List.705; - -procedure List.68 (#Attr.2): - let List.707 : List U8 = lowlevel ListWithCapacity #Attr.2; - ret List.707; - -procedure List.70 (#Attr.2, #Attr.3): - let List.626 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.626; - -procedure List.70 (#Attr.2, #Attr.3): - let List.643 : List Str = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.643; - -procedure List.71 (#Attr.2, #Attr.3): - let List.624 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.624; - -procedure List.71 (#Attr.2, #Attr.3): - let List.641 : List Str = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.641; - -procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.691 : List Str = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.691; - -procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.719 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.719; - -procedure List.8 (#Attr.2, #Attr.3): - let List.676 : List Str = lowlevel ListConcat #Attr.2 #Attr.3; +procedure List.66 (#Attr.2, #Attr.3): + let List.676 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; ret List.676; +procedure List.66 (#Attr.2, #Attr.3): + let List.688 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.688; + +procedure List.68 (#Attr.2): + let List.721 : List Str = lowlevel ListWithCapacity #Attr.2; + ret List.721; + +procedure List.68 (#Attr.2): + let List.723 : List U8 = lowlevel ListWithCapacity #Attr.2; + ret List.723; + +procedure List.70 (#Attr.2, #Attr.3): + let List.642 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.642; + +procedure List.70 (#Attr.2, #Attr.3): + let List.659 : List Str = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.659; + +procedure List.71 (#Attr.2, #Attr.3): + let List.640 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.640; + +procedure List.71 (#Attr.2, #Attr.3): + let List.657 : List Str = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.657; + +procedure List.72 (#Attr.2, #Attr.3, #Attr.4): + let List.707 : List Str = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.707; + +procedure List.72 (#Attr.2, #Attr.3, #Attr.4): + let List.735 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.735; + procedure List.8 (#Attr.2, #Attr.3): - let List.684 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.684; + let List.692 : List Str = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.692; -procedure List.80 (#Derived_gen.20, #Derived_gen.21, #Derived_gen.22, #Derived_gen.23, #Derived_gen.24): - joinpoint List.735 List.471 List.472 List.473 List.474 List.475: - let List.737 : Int1 = CallByName Num.22 List.474 List.475; - if List.737 then - let List.746 : U8 = CallByName List.66 List.471 List.474; - let List.738 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.472 List.746; - let List.743 : U8 = 1i64; - let List.744 : U8 = GetTagId List.738; - let List.745 : Int1 = lowlevel Eq List.743 List.744; - if List.745 then - let List.476 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.738; - let List.741 : U64 = 1i64; - let List.740 : U64 = CallByName Num.51 List.474 List.741; - jump List.735 List.471 List.476 List.473 List.740 List.475; +procedure List.8 (#Attr.2, #Attr.3): + let List.700 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.700; + +procedure List.80 (#Derived_gen.30, #Derived_gen.31, #Derived_gen.32, #Derived_gen.33, #Derived_gen.34): + joinpoint List.751 List.487 List.488 List.489 List.490 List.491: + let List.753 : Int1 = CallByName Num.22 List.490 List.491; + if List.753 then + let List.762 : U8 = CallByName List.66 List.487 List.490; + let List.754 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.488 List.762; + let List.759 : U8 = 1i64; + let List.760 : U8 = GetTagId List.754; + let List.761 : Int1 = lowlevel Eq List.759 List.760; + if List.761 then + let List.492 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.754; + let List.757 : U64 = 1i64; + let List.756 : U64 = CallByName Num.51 List.490 List.757; + jump List.751 List.487 List.492 List.489 List.756 List.491; else - dec List.471; - let List.477 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.738; - let List.742 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.477; - ret List.742; + dec List.487; + let List.493 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.754; + let List.758 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.493; + ret List.758; else - dec List.471; - let List.736 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.472; - ret List.736; + dec List.487; + let List.752 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.488; + ret List.752; in - jump List.735 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22 #Derived_gen.23 #Derived_gen.24; + jump List.751 #Derived_gen.30 #Derived_gen.31 #Derived_gen.32 #Derived_gen.33 #Derived_gen.34; -procedure List.88 (#Derived_gen.25, #Derived_gen.26, #Derived_gen.27, #Derived_gen.28, #Derived_gen.29): - joinpoint List.585 List.157 List.158 List.159 List.160 List.161: - let List.587 : Int1 = CallByName Num.22 List.160 List.161; - if List.587 then - let List.591 : {Str, Str} = CallByName List.66 List.157 List.160; - inc List.591; - let List.162 : {List U8, U64} = CallByName TotallyNotJson.237 List.158 List.591 List.159; - let List.590 : U64 = 1i64; - let List.589 : U64 = CallByName Num.51 List.160 List.590; - jump List.585 List.157 List.162 List.159 List.589 List.161; +procedure List.89 (#Derived_gen.20, #Derived_gen.21, #Derived_gen.22, #Derived_gen.23, #Derived_gen.24): + joinpoint List.601 List.159 List.160 List.161 List.162 List.163: + let List.603 : Int1 = CallByName Num.22 List.162 List.163; + if List.603 then + let List.607 : {Str, Str} = CallByName List.66 List.159 List.162; + inc List.607; + let List.164 : {List U8, U64} = CallByName TotallyNotJson.237 List.160 List.607 List.161; + let List.606 : U64 = 1i64; + let List.605 : U64 = CallByName Num.51 List.162 List.606; + jump List.601 List.159 List.164 List.161 List.605 List.163; else - dec List.157; - ret List.158; + dec List.159; + ret List.160; in - jump List.585 #Derived_gen.25 #Derived_gen.26 #Derived_gen.27 #Derived_gen.28 #Derived_gen.29; + jump List.601 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22 #Derived_gen.23 #Derived_gen.24; -procedure List.88 (#Derived_gen.37, #Derived_gen.38, #Derived_gen.39, #Derived_gen.40, #Derived_gen.41): - joinpoint List.653 List.157 List.158 List.159 List.160 List.161: - let List.655 : Int1 = CallByName Num.22 List.160 List.161; - if List.655 then - let List.659 : {Str, Str} = CallByName List.66 List.157 List.160; - inc List.659; - let List.162 : {List U8, U64} = CallByName TotallyNotJson.237 List.158 List.659 List.159; - let List.658 : U64 = 1i64; - let List.657 : U64 = CallByName Num.51 List.160 List.658; - jump List.653 List.157 List.162 List.159 List.657 List.161; +procedure List.89 (#Derived_gen.25, #Derived_gen.26, #Derived_gen.27, #Derived_gen.28, #Derived_gen.29): + joinpoint List.681 List.159 List.160 List.161 List.162 List.163: + let List.683 : Int1 = CallByName Num.22 List.162 List.163; + if List.683 then + let List.687 : U8 = CallByName List.66 List.159 List.162; + let List.164 : List U8 = CallByName TotallyNotJson.215 List.160 List.687; + let List.686 : U64 = 1i64; + let List.685 : U64 = CallByName Num.51 List.162 List.686; + jump List.681 List.159 List.164 List.161 List.685 List.163; else - dec List.157; - ret List.158; + dec List.159; + ret List.160; in - jump List.653 #Derived_gen.37 #Derived_gen.38 #Derived_gen.39 #Derived_gen.40 #Derived_gen.41; + jump List.681 #Derived_gen.25 #Derived_gen.26 #Derived_gen.27 #Derived_gen.28 #Derived_gen.29; -procedure List.88 (#Derived_gen.45, #Derived_gen.46, #Derived_gen.47, #Derived_gen.48, #Derived_gen.49): - joinpoint List.665 List.157 List.158 List.159 List.160 List.161: - let List.667 : Int1 = CallByName Num.22 List.160 List.161; - if List.667 then - let List.671 : U8 = CallByName List.66 List.157 List.160; - let List.162 : List U8 = CallByName TotallyNotJson.215 List.158 List.671; - let List.670 : U64 = 1i64; - let List.669 : U64 = CallByName Num.51 List.160 List.670; - jump List.665 List.157 List.162 List.159 List.669 List.161; +procedure List.89 (#Derived_gen.42, #Derived_gen.43, #Derived_gen.44, #Derived_gen.45, #Derived_gen.46): + joinpoint List.669 List.159 List.160 List.161 List.162 List.163: + let List.671 : Int1 = CallByName Num.22 List.162 List.163; + if List.671 then + let List.675 : {Str, Str} = CallByName List.66 List.159 List.162; + inc List.675; + let List.164 : {List U8, U64} = CallByName TotallyNotJson.237 List.160 List.675 List.161; + let List.674 : U64 = 1i64; + let List.673 : U64 = CallByName Num.51 List.162 List.674; + jump List.669 List.159 List.164 List.161 List.673 List.163; else - dec List.157; - ret List.158; + dec List.159; + ret List.160; in - jump List.665 #Derived_gen.45 #Derived_gen.46 #Derived_gen.47 #Derived_gen.48 #Derived_gen.49; - -procedure List.99 (List.468, List.469, List.470): - let List.733 : U64 = 0i64; - let List.734 : U64 = CallByName List.6 List.468; - let List.732 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.468 List.469 List.470 List.733 List.734; - ret List.732; + jump List.669 #Derived_gen.42 #Derived_gen.43 #Derived_gen.44 #Derived_gen.45 #Derived_gen.46; procedure Num.127 (#Attr.2): let Num.312 : U8 = lowlevel NumIntCast #Attr.2; @@ -1439,7 +1439,7 @@ procedure TotallyNotJson.97 (TotallyNotJson.837): dec TotallyNotJson.1567; ret TotallyNotJson.1565; -procedure TotallyNotJson.98 (#Derived_gen.36): +procedure TotallyNotJson.98 (#Derived_gen.41): joinpoint TotallyNotJson.1573 TotallyNotJson.1169: let TotallyNotJson.842 : List Str = StructAtIndex 0 TotallyNotJson.1169; let TotallyNotJson.841 : List Str = StructAtIndex 1 TotallyNotJson.1169; @@ -1477,7 +1477,7 @@ procedure TotallyNotJson.98 (#Derived_gen.36): let TotallyNotJson.1574 : {List Str, List Str} = Struct {TotallyNotJson.842, TotallyNotJson.841}; ret TotallyNotJson.1574; in - jump TotallyNotJson.1573 #Derived_gen.36; + jump TotallyNotJson.1573 #Derived_gen.41; procedure Test.0 (): let Test.12 : Str = "bar"; 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 3614d098ac..34ccd66d7d 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 @@ -46,212 +46,212 @@ procedure Encode.26 (Encode.105, Encode.106): let Encode.108 : List U8 = CallByName Encode.24 Encode.109 Encode.110 Encode.106; ret Encode.108; +procedure List.101 (List.484, List.485, List.486): + let List.681 : U64 = 0i64; + let List.682 : U64 = CallByName List.6 List.484; + let List.680 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.484 List.485 List.486 List.681 List.682; + ret List.680; + procedure List.13 (#Attr.2, #Attr.3): - let List.645 : List Str = lowlevel ListPrepend #Attr.2 #Attr.3; - ret List.645; + let List.661 : List Str = lowlevel ListPrepend #Attr.2 #Attr.3; + ret List.661; -procedure List.18 (List.154, List.155, List.156): - let List.583 : U64 = 0i64; - let List.584 : U64 = CallByName List.6 List.154; - let List.582 : {List U8, U64} = CallByName List.88 List.154 List.155 List.156 List.583 List.584; - ret List.582; +procedure List.18 (List.156, List.157, List.158): + let List.599 : U64 = 0i64; + let List.600 : U64 = CallByName List.6 List.156; + let List.598 : {List U8, U64} = CallByName List.89 List.156 List.157 List.158 List.599 List.600; + ret List.598; -procedure List.18 (List.154, List.155, List.156): - let List.595 : U64 = 0i64; - let List.596 : U64 = CallByName List.6 List.154; - let List.594 : List U8 = CallByName List.88 List.154 List.155 List.156 List.595 List.596; - ret List.594; +procedure List.18 (List.156, List.157, List.158): + let List.611 : U64 = 0i64; + let List.612 : U64 = CallByName List.6 List.156; + let List.610 : List U8 = CallByName List.89 List.156 List.157 List.158 List.611 List.612; + ret List.610; -procedure List.26 (List.181, List.182, List.183): - let List.658 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.99 List.181 List.182 List.183; - let List.661 : U8 = 1i64; - let List.662 : U8 = GetTagId List.658; - let List.663 : Int1 = lowlevel Eq List.661 List.662; - if List.663 then - let List.184 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.658; - ret List.184; +procedure List.26 (List.197, List.198, List.199): + let List.674 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.101 List.197 List.198 List.199; + let List.677 : U8 = 1i64; + let List.678 : U8 = GetTagId List.674; + let List.679 : Int1 = lowlevel Eq List.677 List.678; + if List.679 then + let List.200 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.674; + ret List.200; else - let List.185 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.658; - ret List.185; + let List.201 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.674; + ret List.201; -procedure List.38 (List.324, List.325): - let List.635 : U64 = CallByName List.6 List.324; - let List.326 : U64 = CallByName Num.77 List.635 List.325; - let List.634 : List Str = CallByName List.43 List.324 List.326; - ret List.634; +procedure List.38 (List.340, List.341): + let List.651 : U64 = CallByName List.6 List.340; + let List.342 : U64 = CallByName Num.77 List.651 List.341; + let List.650 : List Str = CallByName List.43 List.340 List.342; + ret List.650; -procedure List.4 (List.119, List.120): - let List.578 : U64 = 1i64; - let List.577 : List Str = CallByName List.70 List.119 List.578; - let List.576 : List Str = CallByName List.71 List.577 List.120; - ret List.576; - -procedure List.4 (List.119, List.120): - let List.581 : U64 = 1i64; - let List.580 : List U8 = CallByName List.70 List.119 List.581; - let List.579 : List U8 = CallByName List.71 List.580 List.120; - ret List.579; - -procedure List.43 (List.322, List.323): - let List.625 : U64 = CallByName List.6 List.322; - let List.624 : U64 = CallByName Num.77 List.625 List.323; - let List.619 : {U64, U64} = Struct {List.323, List.624}; - let List.618 : List Str = CallByName List.49 List.322 List.619; - ret List.618; - -procedure List.49 (List.400, List.401): - let List.621 : U64 = StructAtIndex 1 List.401; - let List.622 : U64 = StructAtIndex 0 List.401; - let List.620 : List Str = CallByName List.72 List.400 List.621 List.622; - ret List.620; - -procedure List.49 (List.400, List.401): - let List.649 : U64 = StructAtIndex 1 List.401; - let List.650 : U64 = StructAtIndex 0 List.401; - let List.648 : List U8 = CallByName List.72 List.400 List.649 List.650; - ret List.648; - -procedure List.52 (List.415, List.416): - let List.417 : U64 = CallByName List.6 List.415; - joinpoint List.656 List.418: - let List.654 : U64 = 0i64; - let List.653 : {U64, U64} = Struct {List.418, List.654}; - inc List.415; - let List.419 : List U8 = CallByName List.49 List.415 List.653; - let List.652 : U64 = CallByName Num.75 List.417 List.418; - let List.647 : {U64, U64} = Struct {List.652, List.418}; - let List.420 : List U8 = CallByName List.49 List.415 List.647; - let List.646 : {List U8, List U8} = Struct {List.419, List.420}; - ret List.646; - in - let List.657 : Int1 = CallByName Num.24 List.417 List.416; - if List.657 then - jump List.656 List.416; - else - jump List.656 List.417; - -procedure List.6 (#Attr.2): - let List.641 : U64 = lowlevel ListLen #Attr.2; - ret List.641; - -procedure List.6 (#Attr.2): - let List.642 : U64 = lowlevel ListLen #Attr.2; - ret List.642; - -procedure List.6 (#Attr.2): - let List.644 : U64 = lowlevel ListLen #Attr.2; - ret List.644; - -procedure List.66 (#Attr.2, #Attr.3): - let List.592 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; +procedure List.4 (List.121, List.122): + let List.594 : U64 = 1i64; + let List.593 : List Str = CallByName List.70 List.121 List.594; + let List.592 : List Str = CallByName List.71 List.593 List.122; ret List.592; +procedure List.4 (List.121, List.122): + let List.597 : U64 = 1i64; + let List.596 : List U8 = CallByName List.70 List.121 List.597; + let List.595 : List U8 = CallByName List.71 List.596 List.122; + ret List.595; + +procedure List.43 (List.338, List.339): + let List.641 : U64 = CallByName List.6 List.338; + let List.640 : U64 = CallByName Num.77 List.641 List.339; + let List.635 : {U64, U64} = Struct {List.339, List.640}; + let List.634 : List Str = CallByName List.49 List.338 List.635; + ret List.634; + +procedure List.49 (List.416, List.417): + let List.637 : U64 = StructAtIndex 1 List.417; + let List.638 : U64 = StructAtIndex 0 List.417; + let List.636 : List Str = CallByName List.72 List.416 List.637 List.638; + ret List.636; + +procedure List.49 (List.416, List.417): + let List.665 : U64 = StructAtIndex 1 List.417; + let List.666 : U64 = StructAtIndex 0 List.417; + let List.664 : List U8 = CallByName List.72 List.416 List.665 List.666; + ret List.664; + +procedure List.52 (List.431, List.432): + let List.433 : U64 = CallByName List.6 List.431; + joinpoint List.672 List.434: + let List.670 : U64 = 0i64; + let List.669 : {U64, U64} = Struct {List.434, List.670}; + inc List.431; + let List.435 : List U8 = CallByName List.49 List.431 List.669; + let List.668 : U64 = CallByName Num.75 List.433 List.434; + let List.663 : {U64, U64} = Struct {List.668, List.434}; + let List.436 : List U8 = CallByName List.49 List.431 List.663; + let List.662 : {List U8, List U8} = Struct {List.435, List.436}; + ret List.662; + in + let List.673 : Int1 = CallByName Num.24 List.433 List.432; + if List.673 then + jump List.672 List.432; + else + jump List.672 List.433; + +procedure List.6 (#Attr.2): + let List.657 : U64 = lowlevel ListLen #Attr.2; + ret List.657; + +procedure List.6 (#Attr.2): + let List.658 : U64 = lowlevel ListLen #Attr.2; + ret List.658; + +procedure List.6 (#Attr.2): + let List.660 : U64 = lowlevel ListLen #Attr.2; + ret List.660; + procedure List.66 (#Attr.2, #Attr.3): - let List.604 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.604; - -procedure List.68 (#Attr.2): - let List.637 : List Str = lowlevel ListWithCapacity #Attr.2; - ret List.637; - -procedure List.68 (#Attr.2): - let List.639 : List U8 = lowlevel ListWithCapacity #Attr.2; - ret List.639; - -procedure List.70 (#Attr.2, #Attr.3): - let List.558 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.558; - -procedure List.70 (#Attr.2, #Attr.3): - let List.575 : List Str = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.575; - -procedure List.71 (#Attr.2, #Attr.3): - let List.556 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.556; - -procedure List.71 (#Attr.2, #Attr.3): - let List.573 : List Str = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.573; - -procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.623 : List Str = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.623; - -procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.651 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.651; - -procedure List.8 (#Attr.2, #Attr.3): - let List.608 : List Str = lowlevel ListConcat #Attr.2 #Attr.3; + let List.608 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; ret List.608; +procedure List.66 (#Attr.2, #Attr.3): + let List.620 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.620; + +procedure List.68 (#Attr.2): + let List.653 : List Str = lowlevel ListWithCapacity #Attr.2; + ret List.653; + +procedure List.68 (#Attr.2): + let List.655 : List U8 = lowlevel ListWithCapacity #Attr.2; + ret List.655; + +procedure List.70 (#Attr.2, #Attr.3): + let List.574 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.574; + +procedure List.70 (#Attr.2, #Attr.3): + let List.591 : List Str = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.591; + +procedure List.71 (#Attr.2, #Attr.3): + let List.572 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.572; + +procedure List.71 (#Attr.2, #Attr.3): + let List.589 : List Str = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.589; + +procedure List.72 (#Attr.2, #Attr.3, #Attr.4): + let List.639 : List Str = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.639; + +procedure List.72 (#Attr.2, #Attr.3, #Attr.4): + let List.667 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.667; + procedure List.8 (#Attr.2, #Attr.3): - let List.616 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.616; + let List.624 : List Str = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.624; + +procedure List.8 (#Attr.2, #Attr.3): + let List.632 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.632; procedure List.80 (#Derived_gen.10, #Derived_gen.11, #Derived_gen.12, #Derived_gen.13, #Derived_gen.14): - joinpoint List.667 List.471 List.472 List.473 List.474 List.475: - let List.669 : Int1 = CallByName Num.22 List.474 List.475; - if List.669 then - let List.678 : U8 = CallByName List.66 List.471 List.474; - let List.670 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.472 List.678; - let List.675 : U8 = 1i64; - let List.676 : U8 = GetTagId List.670; - let List.677 : Int1 = lowlevel Eq List.675 List.676; - if List.677 then - let List.476 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.670; - let List.673 : U64 = 1i64; - let List.672 : U64 = CallByName Num.51 List.474 List.673; - jump List.667 List.471 List.476 List.473 List.672 List.475; + joinpoint List.683 List.487 List.488 List.489 List.490 List.491: + let List.685 : Int1 = CallByName Num.22 List.490 List.491; + if List.685 then + let List.694 : U8 = CallByName List.66 List.487 List.490; + let List.686 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.488 List.694; + let List.691 : U8 = 1i64; + let List.692 : U8 = GetTagId List.686; + let List.693 : Int1 = lowlevel Eq List.691 List.692; + if List.693 then + let List.492 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.686; + let List.689 : U64 = 1i64; + let List.688 : U64 = CallByName Num.51 List.490 List.689; + jump List.683 List.487 List.492 List.489 List.688 List.491; else - dec List.471; - let List.477 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.670; - let List.674 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.477; - ret List.674; + dec List.487; + let List.493 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.686; + let List.690 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.493; + ret List.690; else - dec List.471; - let List.668 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.472; - ret List.668; + dec List.487; + let List.684 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.488; + ret List.684; in - jump List.667 #Derived_gen.10 #Derived_gen.11 #Derived_gen.12 #Derived_gen.13 #Derived_gen.14; + jump List.683 #Derived_gen.10 #Derived_gen.11 #Derived_gen.12 #Derived_gen.13 #Derived_gen.14; -procedure List.88 (#Derived_gen.16, #Derived_gen.17, #Derived_gen.18, #Derived_gen.19, #Derived_gen.20): - joinpoint List.585 List.157 List.158 List.159 List.160 List.161: - let List.587 : Int1 = CallByName Num.22 List.160 List.161; - if List.587 then - let List.591 : {Str, Str} = CallByName List.66 List.157 List.160; - inc List.591; - let List.162 : {List U8, U64} = CallByName TotallyNotJson.237 List.158 List.591 List.159; - let List.590 : U64 = 1i64; - let List.589 : U64 = CallByName Num.51 List.160 List.590; - jump List.585 List.157 List.162 List.159 List.589 List.161; +procedure List.89 (#Derived_gen.25, #Derived_gen.26, #Derived_gen.27, #Derived_gen.28, #Derived_gen.29): + joinpoint List.613 List.159 List.160 List.161 List.162 List.163: + let List.615 : Int1 = CallByName Num.22 List.162 List.163; + if List.615 then + let List.619 : U8 = CallByName List.66 List.159 List.162; + let List.164 : List U8 = CallByName TotallyNotJson.215 List.160 List.619; + let List.618 : U64 = 1i64; + let List.617 : U64 = CallByName Num.51 List.162 List.618; + jump List.613 List.159 List.164 List.161 List.617 List.163; else - dec List.157; - ret List.158; + dec List.159; + ret List.160; in - jump List.585 #Derived_gen.16 #Derived_gen.17 #Derived_gen.18 #Derived_gen.19 #Derived_gen.20; + jump List.613 #Derived_gen.25 #Derived_gen.26 #Derived_gen.27 #Derived_gen.28 #Derived_gen.29; -procedure List.88 (#Derived_gen.31, #Derived_gen.32, #Derived_gen.33, #Derived_gen.34, #Derived_gen.35): - joinpoint List.597 List.157 List.158 List.159 List.160 List.161: - let List.599 : Int1 = CallByName Num.22 List.160 List.161; - if List.599 then - let List.603 : U8 = CallByName List.66 List.157 List.160; - let List.162 : List U8 = CallByName TotallyNotJson.215 List.158 List.603; - let List.602 : U64 = 1i64; - let List.601 : U64 = CallByName Num.51 List.160 List.602; - jump List.597 List.157 List.162 List.159 List.601 List.161; +procedure List.89 (#Derived_gen.31, #Derived_gen.32, #Derived_gen.33, #Derived_gen.34, #Derived_gen.35): + joinpoint List.601 List.159 List.160 List.161 List.162 List.163: + let List.603 : Int1 = CallByName Num.22 List.162 List.163; + if List.603 then + let List.607 : {Str, Str} = CallByName List.66 List.159 List.162; + inc List.607; + let List.164 : {List U8, U64} = CallByName TotallyNotJson.237 List.160 List.607 List.161; + let List.606 : U64 = 1i64; + let List.605 : U64 = CallByName Num.51 List.162 List.606; + jump List.601 List.159 List.164 List.161 List.605 List.163; else - dec List.157; - ret List.158; + dec List.159; + ret List.160; in - jump List.597 #Derived_gen.31 #Derived_gen.32 #Derived_gen.33 #Derived_gen.34 #Derived_gen.35; - -procedure List.99 (List.468, List.469, List.470): - let List.665 : U64 = 0i64; - let List.666 : U64 = CallByName List.6 List.468; - let List.664 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.468 List.469 List.470 List.665 List.666; - ret List.664; + jump List.601 #Derived_gen.31 #Derived_gen.32 #Derived_gen.33 #Derived_gen.34 #Derived_gen.35; procedure Num.127 (#Attr.2): let Num.296 : U8 = lowlevel NumIntCast #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 0d290184f8..12d0964dec 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 @@ -53,212 +53,212 @@ procedure Encode.26 (Encode.105, Encode.106): let Encode.108 : List U8 = CallByName Encode.24 Encode.109 Encode.110 Encode.106; ret Encode.108; +procedure List.101 (List.484, List.485, List.486): + let List.681 : U64 = 0i64; + let List.682 : U64 = CallByName List.6 List.484; + let List.680 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.484 List.485 List.486 List.681 List.682; + ret List.680; + procedure List.13 (#Attr.2, #Attr.3): - let List.645 : List Str = lowlevel ListPrepend #Attr.2 #Attr.3; - ret List.645; + let List.661 : List Str = lowlevel ListPrepend #Attr.2 #Attr.3; + ret List.661; -procedure List.18 (List.154, List.155, List.156): - let List.583 : U64 = 0i64; - let List.584 : U64 = CallByName List.6 List.154; - let List.582 : {List U8, U64} = CallByName List.88 List.154 List.155 List.156 List.583 List.584; - ret List.582; +procedure List.18 (List.156, List.157, List.158): + let List.599 : U64 = 0i64; + let List.600 : U64 = CallByName List.6 List.156; + let List.598 : {List U8, U64} = CallByName List.89 List.156 List.157 List.158 List.599 List.600; + ret List.598; -procedure List.18 (List.154, List.155, List.156): - let List.595 : U64 = 0i64; - let List.596 : U64 = CallByName List.6 List.154; - let List.594 : List U8 = CallByName List.88 List.154 List.155 List.156 List.595 List.596; - ret List.594; +procedure List.18 (List.156, List.157, List.158): + let List.611 : U64 = 0i64; + let List.612 : U64 = CallByName List.6 List.156; + let List.610 : List U8 = CallByName List.89 List.156 List.157 List.158 List.611 List.612; + ret List.610; -procedure List.26 (List.181, List.182, List.183): - let List.658 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.99 List.181 List.182 List.183; - let List.661 : U8 = 1i64; - let List.662 : U8 = GetTagId List.658; - let List.663 : Int1 = lowlevel Eq List.661 List.662; - if List.663 then - let List.184 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.658; - ret List.184; +procedure List.26 (List.197, List.198, List.199): + let List.674 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.101 List.197 List.198 List.199; + let List.677 : U8 = 1i64; + let List.678 : U8 = GetTagId List.674; + let List.679 : Int1 = lowlevel Eq List.677 List.678; + if List.679 then + let List.200 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.674; + ret List.200; else - let List.185 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.658; - ret List.185; + let List.201 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.674; + ret List.201; -procedure List.38 (List.324, List.325): - let List.635 : U64 = CallByName List.6 List.324; - let List.326 : U64 = CallByName Num.77 List.635 List.325; - let List.634 : List Str = CallByName List.43 List.324 List.326; - ret List.634; +procedure List.38 (List.340, List.341): + let List.651 : U64 = CallByName List.6 List.340; + let List.342 : U64 = CallByName Num.77 List.651 List.341; + let List.650 : List Str = CallByName List.43 List.340 List.342; + ret List.650; -procedure List.4 (List.119, List.120): - let List.578 : U64 = 1i64; - let List.577 : List Str = CallByName List.70 List.119 List.578; - let List.576 : List Str = CallByName List.71 List.577 List.120; - ret List.576; - -procedure List.4 (List.119, List.120): - let List.581 : U64 = 1i64; - let List.580 : List U8 = CallByName List.70 List.119 List.581; - let List.579 : List U8 = CallByName List.71 List.580 List.120; - ret List.579; - -procedure List.43 (List.322, List.323): - let List.625 : U64 = CallByName List.6 List.322; - let List.624 : U64 = CallByName Num.77 List.625 List.323; - let List.619 : {U64, U64} = Struct {List.323, List.624}; - let List.618 : List Str = CallByName List.49 List.322 List.619; - ret List.618; - -procedure List.49 (List.400, List.401): - let List.621 : U64 = StructAtIndex 1 List.401; - let List.622 : U64 = StructAtIndex 0 List.401; - let List.620 : List Str = CallByName List.72 List.400 List.621 List.622; - ret List.620; - -procedure List.49 (List.400, List.401): - let List.649 : U64 = StructAtIndex 1 List.401; - let List.650 : U64 = StructAtIndex 0 List.401; - let List.648 : List U8 = CallByName List.72 List.400 List.649 List.650; - ret List.648; - -procedure List.52 (List.415, List.416): - let List.417 : U64 = CallByName List.6 List.415; - joinpoint List.656 List.418: - let List.654 : U64 = 0i64; - let List.653 : {U64, U64} = Struct {List.418, List.654}; - inc List.415; - let List.419 : List U8 = CallByName List.49 List.415 List.653; - let List.652 : U64 = CallByName Num.75 List.417 List.418; - let List.647 : {U64, U64} = Struct {List.652, List.418}; - let List.420 : List U8 = CallByName List.49 List.415 List.647; - let List.646 : {List U8, List U8} = Struct {List.419, List.420}; - ret List.646; - in - let List.657 : Int1 = CallByName Num.24 List.417 List.416; - if List.657 then - jump List.656 List.416; - else - jump List.656 List.417; - -procedure List.6 (#Attr.2): - let List.641 : U64 = lowlevel ListLen #Attr.2; - ret List.641; - -procedure List.6 (#Attr.2): - let List.642 : U64 = lowlevel ListLen #Attr.2; - ret List.642; - -procedure List.6 (#Attr.2): - let List.644 : U64 = lowlevel ListLen #Attr.2; - ret List.644; - -procedure List.66 (#Attr.2, #Attr.3): - let List.592 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; +procedure List.4 (List.121, List.122): + let List.594 : U64 = 1i64; + let List.593 : List Str = CallByName List.70 List.121 List.594; + let List.592 : List Str = CallByName List.71 List.593 List.122; ret List.592; +procedure List.4 (List.121, List.122): + let List.597 : U64 = 1i64; + let List.596 : List U8 = CallByName List.70 List.121 List.597; + let List.595 : List U8 = CallByName List.71 List.596 List.122; + ret List.595; + +procedure List.43 (List.338, List.339): + let List.641 : U64 = CallByName List.6 List.338; + let List.640 : U64 = CallByName Num.77 List.641 List.339; + let List.635 : {U64, U64} = Struct {List.339, List.640}; + let List.634 : List Str = CallByName List.49 List.338 List.635; + ret List.634; + +procedure List.49 (List.416, List.417): + let List.637 : U64 = StructAtIndex 1 List.417; + let List.638 : U64 = StructAtIndex 0 List.417; + let List.636 : List Str = CallByName List.72 List.416 List.637 List.638; + ret List.636; + +procedure List.49 (List.416, List.417): + let List.665 : U64 = StructAtIndex 1 List.417; + let List.666 : U64 = StructAtIndex 0 List.417; + let List.664 : List U8 = CallByName List.72 List.416 List.665 List.666; + ret List.664; + +procedure List.52 (List.431, List.432): + let List.433 : U64 = CallByName List.6 List.431; + joinpoint List.672 List.434: + let List.670 : U64 = 0i64; + let List.669 : {U64, U64} = Struct {List.434, List.670}; + inc List.431; + let List.435 : List U8 = CallByName List.49 List.431 List.669; + let List.668 : U64 = CallByName Num.75 List.433 List.434; + let List.663 : {U64, U64} = Struct {List.668, List.434}; + let List.436 : List U8 = CallByName List.49 List.431 List.663; + let List.662 : {List U8, List U8} = Struct {List.435, List.436}; + ret List.662; + in + let List.673 : Int1 = CallByName Num.24 List.433 List.432; + if List.673 then + jump List.672 List.432; + else + jump List.672 List.433; + +procedure List.6 (#Attr.2): + let List.657 : U64 = lowlevel ListLen #Attr.2; + ret List.657; + +procedure List.6 (#Attr.2): + let List.658 : U64 = lowlevel ListLen #Attr.2; + ret List.658; + +procedure List.6 (#Attr.2): + let List.660 : U64 = lowlevel ListLen #Attr.2; + ret List.660; + procedure List.66 (#Attr.2, #Attr.3): - let List.604 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.604; - -procedure List.68 (#Attr.2): - let List.637 : List Str = lowlevel ListWithCapacity #Attr.2; - ret List.637; - -procedure List.68 (#Attr.2): - let List.639 : List U8 = lowlevel ListWithCapacity #Attr.2; - ret List.639; - -procedure List.70 (#Attr.2, #Attr.3): - let List.558 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.558; - -procedure List.70 (#Attr.2, #Attr.3): - let List.575 : List Str = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.575; - -procedure List.71 (#Attr.2, #Attr.3): - let List.556 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.556; - -procedure List.71 (#Attr.2, #Attr.3): - let List.573 : List Str = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.573; - -procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.623 : List Str = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.623; - -procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.651 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.651; - -procedure List.8 (#Attr.2, #Attr.3): - let List.608 : List Str = lowlevel ListConcat #Attr.2 #Attr.3; + let List.608 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; ret List.608; +procedure List.66 (#Attr.2, #Attr.3): + let List.620 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.620; + +procedure List.68 (#Attr.2): + let List.653 : List Str = lowlevel ListWithCapacity #Attr.2; + ret List.653; + +procedure List.68 (#Attr.2): + let List.655 : List U8 = lowlevel ListWithCapacity #Attr.2; + ret List.655; + +procedure List.70 (#Attr.2, #Attr.3): + let List.574 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.574; + +procedure List.70 (#Attr.2, #Attr.3): + let List.591 : List Str = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.591; + +procedure List.71 (#Attr.2, #Attr.3): + let List.572 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.572; + +procedure List.71 (#Attr.2, #Attr.3): + let List.589 : List Str = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.589; + +procedure List.72 (#Attr.2, #Attr.3, #Attr.4): + let List.639 : List Str = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.639; + +procedure List.72 (#Attr.2, #Attr.3, #Attr.4): + let List.667 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.667; + procedure List.8 (#Attr.2, #Attr.3): - let List.616 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.616; + let List.624 : List Str = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.624; + +procedure List.8 (#Attr.2, #Attr.3): + let List.632 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.632; procedure List.80 (#Derived_gen.14, #Derived_gen.15, #Derived_gen.16, #Derived_gen.17, #Derived_gen.18): - joinpoint List.667 List.471 List.472 List.473 List.474 List.475: - let List.669 : Int1 = CallByName Num.22 List.474 List.475; - if List.669 then - let List.678 : U8 = CallByName List.66 List.471 List.474; - let List.670 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.472 List.678; - let List.675 : U8 = 1i64; - let List.676 : U8 = GetTagId List.670; - let List.677 : Int1 = lowlevel Eq List.675 List.676; - if List.677 then - let List.476 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.670; - let List.673 : U64 = 1i64; - let List.672 : U64 = CallByName Num.51 List.474 List.673; - jump List.667 List.471 List.476 List.473 List.672 List.475; + joinpoint List.683 List.487 List.488 List.489 List.490 List.491: + let List.685 : Int1 = CallByName Num.22 List.490 List.491; + if List.685 then + let List.694 : U8 = CallByName List.66 List.487 List.490; + let List.686 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.488 List.694; + let List.691 : U8 = 1i64; + let List.692 : U8 = GetTagId List.686; + let List.693 : Int1 = lowlevel Eq List.691 List.692; + if List.693 then + let List.492 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.686; + let List.689 : U64 = 1i64; + let List.688 : U64 = CallByName Num.51 List.490 List.689; + jump List.683 List.487 List.492 List.489 List.688 List.491; else - dec List.471; - let List.477 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.670; - let List.674 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.477; - ret List.674; + dec List.487; + let List.493 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.686; + let List.690 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.493; + ret List.690; else - dec List.471; - let List.668 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.472; - ret List.668; + dec List.487; + let List.684 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.488; + ret List.684; in - jump List.667 #Derived_gen.14 #Derived_gen.15 #Derived_gen.16 #Derived_gen.17 #Derived_gen.18; + jump List.683 #Derived_gen.14 #Derived_gen.15 #Derived_gen.16 #Derived_gen.17 #Derived_gen.18; -procedure List.88 (#Derived_gen.20, #Derived_gen.21, #Derived_gen.22, #Derived_gen.23, #Derived_gen.24): - joinpoint List.585 List.157 List.158 List.159 List.160 List.161: - let List.587 : Int1 = CallByName Num.22 List.160 List.161; - if List.587 then - let List.591 : {Str, Str} = CallByName List.66 List.157 List.160; - inc List.591; - let List.162 : {List U8, U64} = CallByName TotallyNotJson.237 List.158 List.591 List.159; - let List.590 : U64 = 1i64; - let List.589 : U64 = CallByName Num.51 List.160 List.590; - jump List.585 List.157 List.162 List.159 List.589 List.161; +procedure List.89 (#Derived_gen.29, #Derived_gen.30, #Derived_gen.31, #Derived_gen.32, #Derived_gen.33): + joinpoint List.613 List.159 List.160 List.161 List.162 List.163: + let List.615 : Int1 = CallByName Num.22 List.162 List.163; + if List.615 then + let List.619 : U8 = CallByName List.66 List.159 List.162; + let List.164 : List U8 = CallByName TotallyNotJson.215 List.160 List.619; + let List.618 : U64 = 1i64; + let List.617 : U64 = CallByName Num.51 List.162 List.618; + jump List.613 List.159 List.164 List.161 List.617 List.163; else - dec List.157; - ret List.158; + dec List.159; + ret List.160; in - jump List.585 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22 #Derived_gen.23 #Derived_gen.24; + jump List.613 #Derived_gen.29 #Derived_gen.30 #Derived_gen.31 #Derived_gen.32 #Derived_gen.33; -procedure List.88 (#Derived_gen.35, #Derived_gen.36, #Derived_gen.37, #Derived_gen.38, #Derived_gen.39): - joinpoint List.597 List.157 List.158 List.159 List.160 List.161: - let List.599 : Int1 = CallByName Num.22 List.160 List.161; - if List.599 then - let List.603 : U8 = CallByName List.66 List.157 List.160; - let List.162 : List U8 = CallByName TotallyNotJson.215 List.158 List.603; - let List.602 : U64 = 1i64; - let List.601 : U64 = CallByName Num.51 List.160 List.602; - jump List.597 List.157 List.162 List.159 List.601 List.161; +procedure List.89 (#Derived_gen.35, #Derived_gen.36, #Derived_gen.37, #Derived_gen.38, #Derived_gen.39): + joinpoint List.601 List.159 List.160 List.161 List.162 List.163: + let List.603 : Int1 = CallByName Num.22 List.162 List.163; + if List.603 then + let List.607 : {Str, Str} = CallByName List.66 List.159 List.162; + inc List.607; + let List.164 : {List U8, U64} = CallByName TotallyNotJson.237 List.160 List.607 List.161; + let List.606 : U64 = 1i64; + let List.605 : U64 = CallByName Num.51 List.162 List.606; + jump List.601 List.159 List.164 List.161 List.605 List.163; else - dec List.157; - ret List.158; + dec List.159; + ret List.160; in - jump List.597 #Derived_gen.35 #Derived_gen.36 #Derived_gen.37 #Derived_gen.38 #Derived_gen.39; - -procedure List.99 (List.468, List.469, List.470): - let List.665 : U64 = 0i64; - let List.666 : U64 = CallByName List.6 List.468; - let List.664 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.468 List.469 List.470 List.665 List.666; - ret List.664; + jump List.601 #Derived_gen.35 #Derived_gen.36 #Derived_gen.37 #Derived_gen.38 #Derived_gen.39; procedure Num.127 (#Attr.2): let Num.296 : U8 = lowlevel NumIntCast #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 faba9cdacc..6ee8452eb5 100644 --- a/crates/compiler/test_mono/generated/encode_derived_string.txt +++ b/crates/compiler/test_mono/generated/encode_derived_string.txt @@ -11,115 +11,115 @@ procedure Encode.26 (Encode.105, Encode.106): let Encode.108 : List U8 = CallByName Encode.24 Encode.109 Encode.110 Encode.106; ret Encode.108; -procedure List.18 (List.154, List.155, List.156): - let List.567 : U64 = 0i64; - let List.568 : U64 = CallByName List.6 List.154; - let List.566 : List U8 = CallByName List.88 List.154 List.155 List.156 List.567 List.568; - ret List.566; +procedure List.101 (List.484, List.485, List.486): + let List.612 : U64 = 0i64; + let List.613 : U64 = CallByName List.6 List.484; + let List.611 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.484 List.485 List.486 List.612 List.613; + ret List.611; -procedure List.26 (List.181, List.182, List.183): - let List.589 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.99 List.181 List.182 List.183; - let List.592 : U8 = 1i64; - let List.593 : U8 = GetTagId List.589; - let List.594 : Int1 = lowlevel Eq List.592 List.593; - if List.594 then - let List.184 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.589; - ret List.184; - else - let List.185 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.589; - ret List.185; - -procedure List.49 (List.400, List.401): - let List.580 : U64 = StructAtIndex 1 List.401; - let List.581 : U64 = StructAtIndex 0 List.401; - let List.579 : List U8 = CallByName List.72 List.400 List.580 List.581; - ret List.579; - -procedure List.52 (List.415, List.416): - let List.417 : U64 = CallByName List.6 List.415; - joinpoint List.587 List.418: - let List.585 : U64 = 0i64; - let List.584 : {U64, U64} = Struct {List.418, List.585}; - inc List.415; - let List.419 : List U8 = CallByName List.49 List.415 List.584; - let List.583 : U64 = CallByName Num.75 List.417 List.418; - let List.578 : {U64, U64} = Struct {List.583, List.418}; - let List.420 : List U8 = CallByName List.49 List.415 List.578; - let List.577 : {List U8, List U8} = Struct {List.419, List.420}; - ret List.577; - in - let List.588 : Int1 = CallByName Num.24 List.417 List.416; - if List.588 then - jump List.587 List.416; - else - jump List.587 List.417; - -procedure List.6 (#Attr.2): - let List.565 : U64 = lowlevel ListLen #Attr.2; - ret List.565; - -procedure List.66 (#Attr.2, #Attr.3): - let List.576 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.576; - -procedure List.68 (#Attr.2): - let List.563 : List U8 = lowlevel ListWithCapacity #Attr.2; - ret List.563; - -procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.582 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; +procedure List.18 (List.156, List.157, List.158): + let List.583 : U64 = 0i64; + let List.584 : U64 = CallByName List.6 List.156; + let List.582 : List U8 = CallByName List.89 List.156 List.157 List.158 List.583 List.584; ret List.582; +procedure List.26 (List.197, List.198, List.199): + let List.605 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.101 List.197 List.198 List.199; + let List.608 : U8 = 1i64; + let List.609 : U8 = GetTagId List.605; + let List.610 : Int1 = lowlevel Eq List.608 List.609; + if List.610 then + let List.200 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.605; + ret List.200; + else + let List.201 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.605; + ret List.201; + +procedure List.49 (List.416, List.417): + let List.596 : U64 = StructAtIndex 1 List.417; + let List.597 : U64 = StructAtIndex 0 List.417; + let List.595 : List U8 = CallByName List.72 List.416 List.596 List.597; + ret List.595; + +procedure List.52 (List.431, List.432): + let List.433 : U64 = CallByName List.6 List.431; + joinpoint List.603 List.434: + let List.601 : U64 = 0i64; + let List.600 : {U64, U64} = Struct {List.434, List.601}; + inc List.431; + let List.435 : List U8 = CallByName List.49 List.431 List.600; + let List.599 : U64 = CallByName Num.75 List.433 List.434; + let List.594 : {U64, U64} = Struct {List.599, List.434}; + let List.436 : List U8 = CallByName List.49 List.431 List.594; + let List.593 : {List U8, List U8} = Struct {List.435, List.436}; + ret List.593; + in + let List.604 : Int1 = CallByName Num.24 List.433 List.432; + if List.604 then + jump List.603 List.432; + else + jump List.603 List.433; + +procedure List.6 (#Attr.2): + let List.581 : U64 = lowlevel ListLen #Attr.2; + ret List.581; + +procedure List.66 (#Attr.2, #Attr.3): + let List.592 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.592; + +procedure List.68 (#Attr.2): + let List.579 : List U8 = lowlevel ListWithCapacity #Attr.2; + ret List.579; + +procedure List.72 (#Attr.2, #Attr.3, #Attr.4): + let List.598 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.598; + procedure List.8 (#Attr.2, #Attr.3): - let List.561 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.561; + let List.577 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.577; procedure List.80 (#Derived_gen.8, #Derived_gen.9, #Derived_gen.10, #Derived_gen.11, #Derived_gen.12): - joinpoint List.598 List.471 List.472 List.473 List.474 List.475: - let List.600 : Int1 = CallByName Num.22 List.474 List.475; - if List.600 then - let List.609 : U8 = CallByName List.66 List.471 List.474; - let List.601 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.472 List.609; - let List.606 : U8 = 1i64; - let List.607 : U8 = GetTagId List.601; - let List.608 : Int1 = lowlevel Eq List.606 List.607; - if List.608 then - let List.476 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.601; - let List.604 : U64 = 1i64; - let List.603 : U64 = CallByName Num.51 List.474 List.604; - jump List.598 List.471 List.476 List.473 List.603 List.475; + joinpoint List.614 List.487 List.488 List.489 List.490 List.491: + let List.616 : Int1 = CallByName Num.22 List.490 List.491; + if List.616 then + let List.625 : U8 = CallByName List.66 List.487 List.490; + let List.617 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.488 List.625; + let List.622 : U8 = 1i64; + let List.623 : U8 = GetTagId List.617; + let List.624 : Int1 = lowlevel Eq List.622 List.623; + if List.624 then + let List.492 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.617; + let List.620 : U64 = 1i64; + let List.619 : U64 = CallByName Num.51 List.490 List.620; + jump List.614 List.487 List.492 List.489 List.619 List.491; else - dec List.471; - let List.477 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.601; - let List.605 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.477; - ret List.605; + dec List.487; + let List.493 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.617; + let List.621 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.493; + ret List.621; else - dec List.471; - let List.599 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.472; - ret List.599; + dec List.487; + let List.615 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.488; + ret List.615; in - jump List.598 #Derived_gen.8 #Derived_gen.9 #Derived_gen.10 #Derived_gen.11 #Derived_gen.12; + jump List.614 #Derived_gen.8 #Derived_gen.9 #Derived_gen.10 #Derived_gen.11 #Derived_gen.12; -procedure List.88 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): - joinpoint List.569 List.157 List.158 List.159 List.160 List.161: - let List.571 : Int1 = CallByName Num.22 List.160 List.161; - if List.571 then - let List.575 : U8 = CallByName List.66 List.157 List.160; - let List.162 : List U8 = CallByName TotallyNotJson.215 List.158 List.575; - let List.574 : U64 = 1i64; - let List.573 : U64 = CallByName Num.51 List.160 List.574; - jump List.569 List.157 List.162 List.159 List.573 List.161; +procedure List.89 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): + joinpoint List.585 List.159 List.160 List.161 List.162 List.163: + let List.587 : Int1 = CallByName Num.22 List.162 List.163; + if List.587 then + let List.591 : U8 = CallByName List.66 List.159 List.162; + let List.164 : List U8 = CallByName TotallyNotJson.215 List.160 List.591; + let List.590 : U64 = 1i64; + let List.589 : U64 = CallByName Num.51 List.162 List.590; + jump List.585 List.159 List.164 List.161 List.589 List.163; else - dec List.157; - ret List.158; + dec List.159; + ret List.160; in - jump List.569 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; - -procedure List.99 (List.468, List.469, List.470): - let List.596 : U64 = 0i64; - let List.597 : U64 = CallByName List.6 List.468; - let List.595 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.468 List.469 List.470 List.596 List.597; - ret List.595; + jump List.585 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; procedure Num.19 (#Attr.2, #Attr.3): let Num.292 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; 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 62a1aa5f46..ef63b007eb 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 @@ -40,159 +40,159 @@ procedure Encode.26 (Encode.105, Encode.106): let Encode.108 : List U8 = CallByName Encode.24 Encode.109 Encode.110 Encode.106; ret Encode.108; -procedure List.18 (List.154, List.155, List.156): - let List.581 : U64 = 0i64; - let List.582 : U64 = CallByName List.6 List.154; - let List.580 : {List U8, U64} = CallByName List.88 List.154 List.155 List.156 List.581 List.582; - ret List.580; +procedure List.101 (List.484, List.485, List.486): + let List.653 : U64 = 0i64; + let List.654 : U64 = CallByName List.6 List.484; + let List.652 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.484 List.485 List.486 List.653 List.654; + ret List.652; -procedure List.18 (List.154, List.155, List.156): - let List.593 : U64 = 0i64; - let List.594 : U64 = CallByName List.6 List.154; - let List.592 : List U8 = CallByName List.88 List.154 List.155 List.156 List.593 List.594; - ret List.592; +procedure List.18 (List.156, List.157, List.158): + let List.597 : U64 = 0i64; + let List.598 : U64 = CallByName List.6 List.156; + let List.596 : {List U8, U64} = CallByName List.89 List.156 List.157 List.158 List.597 List.598; + ret List.596; -procedure List.26 (List.181, List.182, List.183): - let List.630 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.99 List.181 List.182 List.183; - let List.633 : U8 = 1i64; - let List.634 : U8 = GetTagId List.630; - let List.635 : Int1 = lowlevel Eq List.633 List.634; - if List.635 then - let List.184 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.630; - ret List.184; +procedure List.18 (List.156, List.157, List.158): + let List.609 : U64 = 0i64; + let List.610 : U64 = CallByName List.6 List.156; + let List.608 : List U8 = CallByName List.89 List.156 List.157 List.158 List.609 List.610; + ret List.608; + +procedure List.26 (List.197, List.198, List.199): + let List.646 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.101 List.197 List.198 List.199; + let List.649 : U8 = 1i64; + let List.650 : U8 = GetTagId List.646; + let List.651 : Int1 = lowlevel Eq List.649 List.650; + if List.651 then + let List.200 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.646; + ret List.200; else - let List.185 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.630; - ret List.185; + let List.201 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.646; + ret List.201; -procedure List.4 (List.119, List.120): - let List.579 : U64 = 1i64; - let List.578 : List U8 = CallByName List.70 List.119 List.579; - let List.577 : List U8 = CallByName List.71 List.578 List.120; - ret List.577; +procedure List.4 (List.121, List.122): + let List.595 : U64 = 1i64; + let List.594 : List U8 = CallByName List.70 List.121 List.595; + let List.593 : List U8 = CallByName List.71 List.594 List.122; + ret List.593; -procedure List.49 (List.400, List.401): - let List.621 : U64 = StructAtIndex 1 List.401; - let List.622 : U64 = StructAtIndex 0 List.401; - let List.620 : List U8 = CallByName List.72 List.400 List.621 List.622; +procedure List.49 (List.416, List.417): + let List.637 : U64 = StructAtIndex 1 List.417; + let List.638 : U64 = StructAtIndex 0 List.417; + let List.636 : List U8 = CallByName List.72 List.416 List.637 List.638; + ret List.636; + +procedure List.52 (List.431, List.432): + let List.433 : U64 = CallByName List.6 List.431; + joinpoint List.644 List.434: + let List.642 : U64 = 0i64; + let List.641 : {U64, U64} = Struct {List.434, List.642}; + inc List.431; + let List.435 : List U8 = CallByName List.49 List.431 List.641; + let List.640 : U64 = CallByName Num.75 List.433 List.434; + let List.635 : {U64, U64} = Struct {List.640, List.434}; + let List.436 : List U8 = CallByName List.49 List.431 List.635; + let List.634 : {List U8, List U8} = Struct {List.435, List.436}; + ret List.634; + in + let List.645 : Int1 = CallByName Num.24 List.433 List.432; + if List.645 then + jump List.644 List.432; + else + jump List.644 List.433; + +procedure List.6 (#Attr.2): + let List.620 : U64 = lowlevel ListLen #Attr.2; ret List.620; -procedure List.52 (List.415, List.416): - let List.417 : U64 = CallByName List.6 List.415; - joinpoint List.628 List.418: - let List.626 : U64 = 0i64; - let List.625 : {U64, U64} = Struct {List.418, List.626}; - inc List.415; - let List.419 : List U8 = CallByName List.49 List.415 List.625; - let List.624 : U64 = CallByName Num.75 List.417 List.418; - let List.619 : {U64, U64} = Struct {List.624, List.418}; - let List.420 : List U8 = CallByName List.49 List.415 List.619; - let List.618 : {List U8, List U8} = Struct {List.419, List.420}; - ret List.618; - in - let List.629 : Int1 = CallByName Num.24 List.417 List.416; - if List.629 then - jump List.628 List.416; - else - jump List.628 List.417; - procedure List.6 (#Attr.2): - let List.604 : U64 = lowlevel ListLen #Attr.2; - ret List.604; + let List.622 : U64 = lowlevel ListLen #Attr.2; + ret List.622; -procedure List.6 (#Attr.2): - let List.606 : U64 = lowlevel ListLen #Attr.2; +procedure List.66 (#Attr.2, #Attr.3): + let List.606 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; ret List.606; procedure List.66 (#Attr.2, #Attr.3): - let List.590 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.590; - -procedure List.66 (#Attr.2, #Attr.3): - let List.602 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.602; + let List.618 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.618; procedure List.68 (#Attr.2): - let List.617 : List U8 = lowlevel ListWithCapacity #Attr.2; - ret List.617; + let List.633 : List U8 = lowlevel ListWithCapacity #Attr.2; + ret List.633; procedure List.70 (#Attr.2, #Attr.3): - let List.558 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.558; + let List.574 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.574; procedure List.71 (#Attr.2, #Attr.3): - let List.556 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.556; + let List.572 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.572; procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.623 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.623; + let List.639 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.639; procedure List.8 (#Attr.2, #Attr.3): - let List.615 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.615; + let List.631 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.631; procedure List.80 (#Derived_gen.26, #Derived_gen.27, #Derived_gen.28, #Derived_gen.29, #Derived_gen.30): - joinpoint List.639 List.471 List.472 List.473 List.474 List.475: - let List.641 : Int1 = CallByName Num.22 List.474 List.475; - if List.641 then - let List.650 : U8 = CallByName List.66 List.471 List.474; - let List.642 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.472 List.650; - let List.647 : U8 = 1i64; - let List.648 : U8 = GetTagId List.642; - let List.649 : Int1 = lowlevel Eq List.647 List.648; - if List.649 then - let List.476 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.642; - let List.645 : U64 = 1i64; - let List.644 : U64 = CallByName Num.51 List.474 List.645; - jump List.639 List.471 List.476 List.473 List.644 List.475; + joinpoint List.655 List.487 List.488 List.489 List.490 List.491: + let List.657 : Int1 = CallByName Num.22 List.490 List.491; + if List.657 then + let List.666 : U8 = CallByName List.66 List.487 List.490; + let List.658 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.488 List.666; + let List.663 : U8 = 1i64; + let List.664 : U8 = GetTagId List.658; + let List.665 : Int1 = lowlevel Eq List.663 List.664; + if List.665 then + let List.492 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.658; + let List.661 : U64 = 1i64; + let List.660 : U64 = CallByName Num.51 List.490 List.661; + jump List.655 List.487 List.492 List.489 List.660 List.491; else - dec List.471; - let List.477 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.642; - let List.646 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.477; - ret List.646; + dec List.487; + let List.493 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.658; + let List.662 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.493; + ret List.662; else - dec List.471; - let List.640 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.472; - ret List.640; + dec List.487; + let List.656 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.488; + ret List.656; in - jump List.639 #Derived_gen.26 #Derived_gen.27 #Derived_gen.28 #Derived_gen.29 #Derived_gen.30; + jump List.655 #Derived_gen.26 #Derived_gen.27 #Derived_gen.28 #Derived_gen.29 #Derived_gen.30; -procedure List.88 (#Derived_gen.10, #Derived_gen.11, #Derived_gen.12, #Derived_gen.13, #Derived_gen.14): - joinpoint List.583 List.157 List.158 List.159 List.160 List.161: - let List.585 : Int1 = CallByName Num.22 List.160 List.161; - if List.585 then - let List.589 : Str = CallByName List.66 List.157 List.160; - inc List.589; - let List.162 : {List U8, U64} = CallByName TotallyNotJson.267 List.158 List.589 List.159; - let List.588 : U64 = 1i64; - let List.587 : U64 = CallByName Num.51 List.160 List.588; - jump List.583 List.157 List.162 List.159 List.587 List.161; +procedure List.89 (#Derived_gen.10, #Derived_gen.11, #Derived_gen.12, #Derived_gen.13, #Derived_gen.14): + joinpoint List.611 List.159 List.160 List.161 List.162 List.163: + let List.613 : Int1 = CallByName Num.22 List.162 List.163; + if List.613 then + let List.617 : U8 = CallByName List.66 List.159 List.162; + let List.164 : List U8 = CallByName TotallyNotJson.215 List.160 List.617; + let List.616 : U64 = 1i64; + let List.615 : U64 = CallByName Num.51 List.162 List.616; + jump List.611 List.159 List.164 List.161 List.615 List.163; else - dec List.157; - ret List.158; + dec List.159; + ret List.160; in - jump List.583 #Derived_gen.10 #Derived_gen.11 #Derived_gen.12 #Derived_gen.13 #Derived_gen.14; + jump List.611 #Derived_gen.10 #Derived_gen.11 #Derived_gen.12 #Derived_gen.13 #Derived_gen.14; -procedure List.88 (#Derived_gen.21, #Derived_gen.22, #Derived_gen.23, #Derived_gen.24, #Derived_gen.25): - joinpoint List.595 List.157 List.158 List.159 List.160 List.161: - let List.597 : Int1 = CallByName Num.22 List.160 List.161; - if List.597 then - let List.601 : U8 = CallByName List.66 List.157 List.160; - let List.162 : List U8 = CallByName TotallyNotJson.215 List.158 List.601; - let List.600 : U64 = 1i64; - let List.599 : U64 = CallByName Num.51 List.160 List.600; - jump List.595 List.157 List.162 List.159 List.599 List.161; +procedure List.89 (#Derived_gen.18, #Derived_gen.19, #Derived_gen.20, #Derived_gen.21, #Derived_gen.22): + joinpoint List.599 List.159 List.160 List.161 List.162 List.163: + let List.601 : Int1 = CallByName Num.22 List.162 List.163; + if List.601 then + let List.605 : Str = CallByName List.66 List.159 List.162; + inc List.605; + let List.164 : {List U8, U64} = CallByName TotallyNotJson.267 List.160 List.605 List.161; + let List.604 : U64 = 1i64; + let List.603 : U64 = CallByName Num.51 List.162 List.604; + jump List.599 List.159 List.164 List.161 List.603 List.163; else - dec List.157; - ret List.158; + dec List.159; + ret List.160; in - jump List.595 #Derived_gen.21 #Derived_gen.22 #Derived_gen.23 #Derived_gen.24 #Derived_gen.25; - -procedure List.99 (List.468, List.469, List.470): - let List.637 : U64 = 0i64; - let List.638 : U64 = CallByName List.6 List.468; - let List.636 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.468 List.469 List.470 List.637 List.638; - ret List.636; + jump List.599 #Derived_gen.18 #Derived_gen.19 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22; procedure Num.127 (#Attr.2): let Num.298 : U8 = lowlevel NumIntCast #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 afbbc21779..78f685c25c 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 @@ -43,159 +43,159 @@ procedure Encode.26 (Encode.105, Encode.106): let Encode.108 : List U8 = CallByName Encode.24 Encode.109 Encode.110 Encode.106; ret Encode.108; -procedure List.18 (List.154, List.155, List.156): - let List.581 : U64 = 0i64; - let List.582 : U64 = CallByName List.6 List.154; - let List.580 : {List U8, U64} = CallByName List.88 List.154 List.155 List.156 List.581 List.582; - ret List.580; +procedure List.101 (List.484, List.485, List.486): + let List.653 : U64 = 0i64; + let List.654 : U64 = CallByName List.6 List.484; + let List.652 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.484 List.485 List.486 List.653 List.654; + ret List.652; -procedure List.18 (List.154, List.155, List.156): - let List.593 : U64 = 0i64; - let List.594 : U64 = CallByName List.6 List.154; - let List.592 : List U8 = CallByName List.88 List.154 List.155 List.156 List.593 List.594; - ret List.592; +procedure List.18 (List.156, List.157, List.158): + let List.597 : U64 = 0i64; + let List.598 : U64 = CallByName List.6 List.156; + let List.596 : {List U8, U64} = CallByName List.89 List.156 List.157 List.158 List.597 List.598; + ret List.596; -procedure List.26 (List.181, List.182, List.183): - let List.630 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.99 List.181 List.182 List.183; - let List.633 : U8 = 1i64; - let List.634 : U8 = GetTagId List.630; - let List.635 : Int1 = lowlevel Eq List.633 List.634; - if List.635 then - let List.184 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.630; - ret List.184; +procedure List.18 (List.156, List.157, List.158): + let List.609 : U64 = 0i64; + let List.610 : U64 = CallByName List.6 List.156; + let List.608 : List U8 = CallByName List.89 List.156 List.157 List.158 List.609 List.610; + ret List.608; + +procedure List.26 (List.197, List.198, List.199): + let List.646 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.101 List.197 List.198 List.199; + let List.649 : U8 = 1i64; + let List.650 : U8 = GetTagId List.646; + let List.651 : Int1 = lowlevel Eq List.649 List.650; + if List.651 then + let List.200 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.646; + ret List.200; else - let List.185 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.630; - ret List.185; + let List.201 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.646; + ret List.201; -procedure List.4 (List.119, List.120): - let List.579 : U64 = 1i64; - let List.578 : List U8 = CallByName List.70 List.119 List.579; - let List.577 : List U8 = CallByName List.71 List.578 List.120; - ret List.577; +procedure List.4 (List.121, List.122): + let List.595 : U64 = 1i64; + let List.594 : List U8 = CallByName List.70 List.121 List.595; + let List.593 : List U8 = CallByName List.71 List.594 List.122; + ret List.593; -procedure List.49 (List.400, List.401): - let List.621 : U64 = StructAtIndex 1 List.401; - let List.622 : U64 = StructAtIndex 0 List.401; - let List.620 : List U8 = CallByName List.72 List.400 List.621 List.622; +procedure List.49 (List.416, List.417): + let List.637 : U64 = StructAtIndex 1 List.417; + let List.638 : U64 = StructAtIndex 0 List.417; + let List.636 : List U8 = CallByName List.72 List.416 List.637 List.638; + ret List.636; + +procedure List.52 (List.431, List.432): + let List.433 : U64 = CallByName List.6 List.431; + joinpoint List.644 List.434: + let List.642 : U64 = 0i64; + let List.641 : {U64, U64} = Struct {List.434, List.642}; + inc List.431; + let List.435 : List U8 = CallByName List.49 List.431 List.641; + let List.640 : U64 = CallByName Num.75 List.433 List.434; + let List.635 : {U64, U64} = Struct {List.640, List.434}; + let List.436 : List U8 = CallByName List.49 List.431 List.635; + let List.634 : {List U8, List U8} = Struct {List.435, List.436}; + ret List.634; + in + let List.645 : Int1 = CallByName Num.24 List.433 List.432; + if List.645 then + jump List.644 List.432; + else + jump List.644 List.433; + +procedure List.6 (#Attr.2): + let List.620 : U64 = lowlevel ListLen #Attr.2; ret List.620; -procedure List.52 (List.415, List.416): - let List.417 : U64 = CallByName List.6 List.415; - joinpoint List.628 List.418: - let List.626 : U64 = 0i64; - let List.625 : {U64, U64} = Struct {List.418, List.626}; - inc List.415; - let List.419 : List U8 = CallByName List.49 List.415 List.625; - let List.624 : U64 = CallByName Num.75 List.417 List.418; - let List.619 : {U64, U64} = Struct {List.624, List.418}; - let List.420 : List U8 = CallByName List.49 List.415 List.619; - let List.618 : {List U8, List U8} = Struct {List.419, List.420}; - ret List.618; - in - let List.629 : Int1 = CallByName Num.24 List.417 List.416; - if List.629 then - jump List.628 List.416; - else - jump List.628 List.417; - procedure List.6 (#Attr.2): - let List.604 : U64 = lowlevel ListLen #Attr.2; - ret List.604; + let List.622 : U64 = lowlevel ListLen #Attr.2; + ret List.622; -procedure List.6 (#Attr.2): - let List.606 : U64 = lowlevel ListLen #Attr.2; +procedure List.66 (#Attr.2, #Attr.3): + let List.606 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; ret List.606; procedure List.66 (#Attr.2, #Attr.3): - let List.590 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.590; - -procedure List.66 (#Attr.2, #Attr.3): - let List.602 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.602; + let List.618 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.618; procedure List.68 (#Attr.2): - let List.617 : List U8 = lowlevel ListWithCapacity #Attr.2; - ret List.617; + let List.633 : List U8 = lowlevel ListWithCapacity #Attr.2; + ret List.633; procedure List.70 (#Attr.2, #Attr.3): - let List.558 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.558; + let List.574 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.574; procedure List.71 (#Attr.2, #Attr.3): - let List.556 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.556; + let List.572 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.572; procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.623 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.623; + let List.639 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.639; procedure List.8 (#Attr.2, #Attr.3): - let List.615 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.615; + let List.631 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.631; -procedure List.80 (#Derived_gen.19, #Derived_gen.20, #Derived_gen.21, #Derived_gen.22, #Derived_gen.23): - joinpoint List.639 List.471 List.472 List.473 List.474 List.475: - let List.641 : Int1 = CallByName Num.22 List.474 List.475; - if List.641 then - let List.650 : U8 = CallByName List.66 List.471 List.474; - let List.642 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.472 List.650; - let List.647 : U8 = 1i64; - let List.648 : U8 = GetTagId List.642; - let List.649 : Int1 = lowlevel Eq List.647 List.648; - if List.649 then - let List.476 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.642; - let List.645 : U64 = 1i64; - let List.644 : U64 = CallByName Num.51 List.474 List.645; - jump List.639 List.471 List.476 List.473 List.644 List.475; +procedure List.80 (#Derived_gen.14, #Derived_gen.15, #Derived_gen.16, #Derived_gen.17, #Derived_gen.18): + joinpoint List.655 List.487 List.488 List.489 List.490 List.491: + let List.657 : Int1 = CallByName Num.22 List.490 List.491; + if List.657 then + let List.666 : U8 = CallByName List.66 List.487 List.490; + let List.658 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.488 List.666; + let List.663 : U8 = 1i64; + let List.664 : U8 = GetTagId List.658; + let List.665 : Int1 = lowlevel Eq List.663 List.664; + if List.665 then + let List.492 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.658; + let List.661 : U64 = 1i64; + let List.660 : U64 = CallByName Num.51 List.490 List.661; + jump List.655 List.487 List.492 List.489 List.660 List.491; else - dec List.471; - let List.477 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.642; - let List.646 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.477; - ret List.646; + dec List.487; + let List.493 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.658; + let List.662 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.493; + ret List.662; else - dec List.471; - let List.640 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.472; - ret List.640; + dec List.487; + let List.656 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.488; + ret List.656; in - jump List.639 #Derived_gen.19 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22 #Derived_gen.23; + jump List.655 #Derived_gen.14 #Derived_gen.15 #Derived_gen.16 #Derived_gen.17 #Derived_gen.18; -procedure List.88 (#Derived_gen.11, #Derived_gen.12, #Derived_gen.13, #Derived_gen.14, #Derived_gen.15): - joinpoint List.595 List.157 List.158 List.159 List.160 List.161: - let List.597 : Int1 = CallByName Num.22 List.160 List.161; - if List.597 then - let List.601 : U8 = CallByName List.66 List.157 List.160; - let List.162 : List U8 = CallByName TotallyNotJson.215 List.158 List.601; - let List.600 : U64 = 1i64; - let List.599 : U64 = CallByName Num.51 List.160 List.600; - jump List.595 List.157 List.162 List.159 List.599 List.161; +procedure List.89 (#Derived_gen.19, #Derived_gen.20, #Derived_gen.21, #Derived_gen.22, #Derived_gen.23): + joinpoint List.611 List.159 List.160 List.161 List.162 List.163: + let List.613 : Int1 = CallByName Num.22 List.162 List.163; + if List.613 then + let List.617 : U8 = CallByName List.66 List.159 List.162; + let List.164 : List U8 = CallByName TotallyNotJson.215 List.160 List.617; + let List.616 : U64 = 1i64; + let List.615 : U64 = CallByName Num.51 List.162 List.616; + jump List.611 List.159 List.164 List.161 List.615 List.163; else - dec List.157; - ret List.158; + dec List.159; + ret List.160; in - jump List.595 #Derived_gen.11 #Derived_gen.12 #Derived_gen.13 #Derived_gen.14 #Derived_gen.15; + jump List.611 #Derived_gen.19 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22 #Derived_gen.23; -procedure List.88 (#Derived_gen.27, #Derived_gen.28, #Derived_gen.29, #Derived_gen.30, #Derived_gen.31): - joinpoint List.583 List.157 List.158 List.159 List.160 List.161: - let List.585 : Int1 = CallByName Num.22 List.160 List.161; - if List.585 then - let List.589 : Str = CallByName List.66 List.157 List.160; - inc List.589; - let List.162 : {List U8, U64} = CallByName TotallyNotJson.267 List.158 List.589 List.159; - let List.588 : U64 = 1i64; - let List.587 : U64 = CallByName Num.51 List.160 List.588; - jump List.583 List.157 List.162 List.159 List.587 List.161; +procedure List.89 (#Derived_gen.24, #Derived_gen.25, #Derived_gen.26, #Derived_gen.27, #Derived_gen.28): + joinpoint List.599 List.159 List.160 List.161 List.162 List.163: + let List.601 : Int1 = CallByName Num.22 List.162 List.163; + if List.601 then + let List.605 : Str = CallByName List.66 List.159 List.162; + inc List.605; + let List.164 : {List U8, U64} = CallByName TotallyNotJson.267 List.160 List.605 List.161; + let List.604 : U64 = 1i64; + let List.603 : U64 = CallByName Num.51 List.162 List.604; + jump List.599 List.159 List.164 List.161 List.603 List.163; else - dec List.157; - ret List.158; + dec List.159; + ret List.160; in - jump List.583 #Derived_gen.27 #Derived_gen.28 #Derived_gen.29 #Derived_gen.30 #Derived_gen.31; - -procedure List.99 (List.468, List.469, List.470): - let List.637 : U64 = 0i64; - let List.638 : U64 = CallByName List.6 List.468; - let List.636 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.468 List.469 List.470 List.637 List.638; - ret List.636; + jump List.599 #Derived_gen.24 #Derived_gen.25 #Derived_gen.26 #Derived_gen.27 #Derived_gen.28; procedure Num.127 (#Attr.2): let Num.298 : U8 = lowlevel NumIntCast #Attr.2; diff --git a/crates/compiler/test_mono/generated/inspect_derived_dict.txt b/crates/compiler/test_mono/generated/inspect_derived_dict.txt index 9a1a403404..f3f5a2b85e 100644 --- a/crates/compiler/test_mono/generated/inspect_derived_dict.txt +++ b/crates/compiler/test_mono/generated/inspect_derived_dict.txt @@ -1,1202 +1,1213 @@ procedure Bool.1 (): - let Bool.30 : Int1 = false; - ret Bool.30; - -procedure Bool.11 (#Attr.2, #Attr.3): - let Bool.25 : Int1 = lowlevel Eq #Attr.2 #Attr.3; - ret Bool.25; - -procedure Bool.11 (#Attr.2, #Attr.3): - let Bool.26 : Int1 = lowlevel Eq #Attr.2 #Attr.3; - ret Bool.26; + let Bool.32 : Int1 = false; + ret Bool.32; procedure Bool.11 (#Attr.2, #Attr.3): let Bool.28 : Int1 = lowlevel Eq #Attr.2 #Attr.3; ret Bool.28; -procedure Bool.2 (): - let Bool.29 : Int1 = true; +procedure Bool.11 (#Attr.2, #Attr.3): + let Bool.29 : Int1 = lowlevel Eq #Attr.2 #Attr.3; ret Bool.29; -procedure Dict.1 (Dict.557): - let Dict.720 : List {Str, I64} = Array []; - let Dict.726 : U64 = 0i64; - let Dict.727 : U64 = 8i64; - let Dict.721 : List U64 = CallByName List.11 Dict.726 Dict.727; - let Dict.724 : I8 = CallByName Dict.40; - let Dict.725 : U64 = 8i64; - let Dict.722 : List I8 = CallByName List.11 Dict.724 Dict.725; - let Dict.723 : U64 = 0i64; - let Dict.719 : {List {Str, I64}, List U64, List I8, U64} = Struct {Dict.720, Dict.721, Dict.722, Dict.723}; - ret Dict.719; +procedure Bool.11 (#Attr.2, #Attr.3): + let Bool.30 : Int1 = lowlevel Eq #Attr.2 #Attr.3; + ret Bool.30; -procedure Dict.10 (Dict.558, Dict.127, Dict.128): - let Dict.126 : List {Str, I64} = StructAtIndex 0 Dict.558; - let #Derived_gen.61 : List U64 = StructAtIndex 1 Dict.558; - dec #Derived_gen.61; - let #Derived_gen.60 : List I8 = StructAtIndex 2 Dict.558; - dec #Derived_gen.60; - let Dict.981 : {Str, Int1} = CallByName List.18 Dict.126 Dict.127 Dict.128; - ret Dict.981; +procedure Bool.12 (#Attr.2, #Attr.3): + let Bool.24 : Int1 = lowlevel NotEq #Attr.2 #Attr.3; + ret Bool.24; -procedure Dict.101 (Dict.102, Dict.568): - let Dict.103 : Str = StructAtIndex 0 Dict.568; - let Dict.104 : I64 = StructAtIndex 1 Dict.568; - let Dict.569 : {List {Str, I64}, List U64, List I8, U64} = CallByName Dict.8 Dict.102 Dict.103 Dict.104; - ret Dict.569; +procedure Bool.12 (#Attr.2, #Attr.3): + let Bool.26 : Int1 = lowlevel NotEq #Attr.2 #Attr.3; + ret Bool.26; -procedure Dict.12 (Dict.100): - let Dict.718 : {} = Struct {}; - let Dict.566 : {List {Str, I64}, List U64, List I8, U64} = CallByName Dict.1 Dict.718; - let Dict.567 : {} = Struct {}; - let Dict.565 : {List {Str, I64}, List U64, List I8, U64} = CallByName List.18 Dict.100 Dict.566 Dict.567; - ret Dict.565; +procedure Bool.2 (): + let Bool.31 : Int1 = true; + ret Bool.31; -procedure Dict.129 (Dict.130, Dict.983, Dict.128): - let Dict.131 : Str = StructAtIndex 0 Dict.983; - let Dict.132 : I64 = StructAtIndex 1 Dict.983; - let Dict.985 : {Str, Int1} = CallByName Inspect.190 Dict.130 Dict.131 Dict.132 Dict.128; - ret Dict.985; +procedure Bool.7 (Bool.19, Bool.20): + let Bool.25 : Int1 = CallByName Bool.12 Bool.19 Bool.20; + ret Bool.25; -procedure Dict.22 (#Attr.2, #Attr.3): - let Dict.574 : U64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - dec #Attr.2; - ret Dict.574; +procedure Bool.7 (Bool.19, Bool.20): + let Bool.27 : Int1 = CallByName Bool.12 Bool.19 Bool.20; + ret Bool.27; -procedure Dict.22 (#Attr.2, #Attr.3): - let Dict.597 : I8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - dec #Attr.2; - ret Dict.597; +procedure Dict.1 (Dict.726): + let Dict.896 : List {U32, U32} = Array []; + let Dict.897 : List {Str, I64} = Array []; + let Dict.898 : U64 = 0i64; + let Dict.44 : Float32 = CallByName Dict.44; + let Dict.45 : U8 = CallByName Dict.45; + let Dict.895 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = Struct {Dict.896, Dict.897, Dict.898, Dict.44, Dict.45}; + ret Dict.895; -procedure Dict.22 (#Attr.2, #Attr.3): - let Dict.665 : {Str, I64} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - inc Dict.665; - dec #Attr.2; - ret Dict.665; +procedure Dict.10 (Dict.727, Dict.180, Dict.181): + let Dict.179 : List {Str, I64} = StructAtIndex 1 Dict.727; + let #Derived_gen.68 : List {U32, U32} = StructAtIndex 0 Dict.727; + dec #Derived_gen.68; + let Dict.1113 : {Str, Int1} = CallByName List.18 Dict.179 Dict.180 Dict.181; + ret Dict.1113; -procedure Dict.22 (#Attr.2, #Attr.3): - let Dict.781 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - dec #Attr.2; - ret Dict.781; - -procedure Dict.23 (#Attr.2): - let Dict.659 : U64 = lowlevel DictPseudoSeed #Attr.2; - ret Dict.659; - -procedure Dict.31 (Dict.93): - let Dict.973 : {List {Str, I64}, List U64, List I8, U64} = CallByName Inspect.30 Dict.93; - ret Dict.973; - -procedure Dict.33 (Dict.554, Dict.237, Dict.238, Dict.239, Dict.240): - let Dict.235 : List {Str, I64} = StructAtIndex 0 Dict.554; - let Dict.234 : List U64 = StructAtIndex 1 Dict.554; - let Dict.233 : List I8 = StructAtIndex 2 Dict.554; - inc Dict.233; - let Dict.236 : U64 = StructAtIndex 3 Dict.554; - let Dict.607 : U64 = CallByName List.6 Dict.233; - let Dict.602 : U64 = CallByName Dict.45 Dict.607; - let Dict.241 : {U64, U64, U64} = CallByName Dict.42 Dict.239 Dict.602; - let Dict.580 : U64 = 0i64; - let Dict.242 : U64 = CallByName Dict.34 Dict.233 Dict.241 Dict.580; - let Dict.243 : U64 = CallByName List.6 Dict.235; - let Dict.579 : {Str, I64} = Struct {Dict.237, Dict.238}; - let Dict.244 : List {Str, I64} = CallByName List.4 Dict.235 Dict.579; - let Dict.577 : List U64 = CallByName List.3 Dict.234 Dict.242 Dict.243; - let Dict.578 : List I8 = CallByName List.3 Dict.233 Dict.242 Dict.240; - let Dict.576 : {List {Str, I64}, List U64, List I8, U64} = Struct {Dict.244, Dict.577, Dict.578, Dict.236}; - ret Dict.576; - -procedure Dict.34 (#Derived_gen.42, #Derived_gen.43, #Derived_gen.44): - joinpoint Dict.581 Dict.245 Dict.246 Dict.247: - let Dict.599 : U64 = StructAtIndex 2 Dict.246; - let Dict.598 : U64 = CallByName Dict.44 Dict.599; - let Dict.248 : U64 = CallByName Num.51 Dict.598 Dict.247; - inc Dict.245; - let Dict.249 : I8 = CallByName Dict.22 Dict.245 Dict.248; - let Dict.596 : I8 = 0i64; - let Dict.594 : Int1 = CallByName Num.22 Dict.249 Dict.596; - if Dict.594 then - dec Dict.245; - ret Dict.248; - else - let Dict.593 : U64 = 7i64; - let Dict.585 : Int1 = CallByName Bool.11 Dict.247 Dict.593; - if Dict.585 then - let Dict.587 : {U64, U64, U64} = CallByName Dict.43 Dict.246; - let Dict.588 : U64 = 0i64; - jump Dict.581 Dict.245 Dict.587 Dict.588; - else - let Dict.584 : U64 = 1i64; - let Dict.583 : U64 = CallByName Num.51 Dict.247 Dict.584; - jump Dict.581 Dict.245 Dict.246 Dict.583; - in - jump Dict.581 #Derived_gen.42 #Derived_gen.43 #Derived_gen.44; - -procedure Dict.35 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4, #Derived_gen.5, #Derived_gen.6): - joinpoint Dict.686 Dict.250 Dict.251 Dict.252 Dict.253 Dict.254 Dict.255 Dict.256: - let Dict.712 : U64 = StructAtIndex 2 Dict.255; - let Dict.711 : U64 = CallByName Dict.44 Dict.712; - let Dict.257 : U64 = CallByName Num.51 Dict.711 Dict.256; - inc Dict.250; - let Dict.258 : I8 = CallByName Dict.22 Dict.250 Dict.257; - let Dict.710 : I8 = CallByName Dict.40; - let Dict.707 : Int1 = CallByName Bool.11 Dict.258 Dict.710; - if Dict.707 then - dec Dict.250; - dec Dict.251; - dec Dict.252; - dec Dict.254; - let Dict.709 : {} = Struct {}; - let Dict.708 : [C {}, C U64] = TagId(0) Dict.709; - ret Dict.708; - else - let Dict.695 : Int1 = CallByName Bool.11 Dict.258 Dict.253; - if Dict.695 then - inc Dict.251; - let Dict.261 : U64 = CallByName Dict.22 Dict.251 Dict.257; - inc Dict.252; - let Dict.706 : {Str, I64} = CallByName Dict.22 Dict.252 Dict.261; - let Dict.262 : Str = StructAtIndex 0 Dict.706; - let Dict.704 : Int1 = CallByName Bool.11 Dict.262 Dict.254; - dec Dict.262; - if Dict.704 then - dec Dict.250; - dec Dict.251; - dec Dict.252; - dec Dict.254; - let Dict.705 : [C {}, C U64] = TagId(1) Dict.257; - ret Dict.705; - else - let Dict.703 : U64 = 7i64; - let Dict.699 : Int1 = CallByName Bool.11 Dict.256 Dict.703; - if Dict.699 then - let Dict.701 : {U64, U64, U64} = CallByName Dict.43 Dict.255; - let Dict.702 : U64 = 0i64; - jump Dict.686 Dict.250 Dict.251 Dict.252 Dict.253 Dict.254 Dict.701 Dict.702; - else - let Dict.698 : U64 = 1i64; - let Dict.697 : U64 = CallByName Num.51 Dict.256 Dict.698; - jump Dict.686 Dict.250 Dict.251 Dict.252 Dict.253 Dict.254 Dict.255 Dict.697; - else - let Dict.694 : U64 = 7i64; - let Dict.690 : Int1 = CallByName Bool.11 Dict.256 Dict.694; - if Dict.690 then - let Dict.692 : {U64, U64, U64} = CallByName Dict.43 Dict.255; - let Dict.693 : U64 = 0i64; - jump Dict.686 Dict.250 Dict.251 Dict.252 Dict.253 Dict.254 Dict.692 Dict.693; - else - let Dict.689 : U64 = 1i64; - let Dict.688 : U64 = CallByName Num.51 Dict.256 Dict.689; - jump Dict.686 Dict.250 Dict.251 Dict.252 Dict.253 Dict.254 Dict.255 Dict.688; - in - jump Dict.686 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4 #Derived_gen.5 #Derived_gen.6; - -procedure Dict.36 (Dict.551): - let Dict.266 : List {Str, I64} = StructAtIndex 0 Dict.551; - let Dict.265 : List U64 = StructAtIndex 1 Dict.551; - let Dict.264 : List I8 = StructAtIndex 2 Dict.551; - let Dict.267 : U64 = StructAtIndex 3 Dict.551; - let Dict.268 : U64 = CallByName List.6 Dict.265; - let Dict.679 : U8 = 3i64; - let Dict.678 : U64 = CallByName Num.74 Dict.268 Dict.679; - let Dict.269 : U64 = CallByName Num.75 Dict.268 Dict.678; - let Dict.612 : Int1 = CallByName Num.24 Dict.267 Dict.269; - if Dict.612 then - let Dict.614 : {List {Str, I64}, List U64, List I8, U64} = Struct {Dict.266, Dict.265, Dict.264, Dict.267}; - let Dict.613 : {List {Str, I64}, List U64, List I8, U64} = CallByName Dict.37 Dict.614; - ret Dict.613; - else - let Dict.611 : {List {Str, I64}, List U64, List I8, U64} = Struct {Dict.266, Dict.265, Dict.264, Dict.267}; - ret Dict.611; - -procedure Dict.37 (Dict.552): - let Dict.272 : List {Str, I64} = StructAtIndex 0 Dict.552; - inc Dict.272; - let Dict.271 : List U64 = StructAtIndex 1 Dict.552; - let Dict.270 : List I8 = StructAtIndex 2 Dict.552; - let Dict.273 : U64 = StructAtIndex 3 Dict.552; - let Dict.676 : U64 = 2i64; - let Dict.677 : U64 = CallByName List.6 Dict.271; - let Dict.274 : U64 = CallByName Num.21 Dict.676 Dict.677; - let Dict.675 : U64 = 0i64; - let Dict.671 : List U64 = CallByName List.11 Dict.675 Dict.274; - let Dict.673 : I8 = CallByName Dict.40; - let Dict.672 : List I8 = CallByName List.11 Dict.673 Dict.274; - let Dict.275 : {List {Str, I64}, List U64, List I8, U64} = Struct {Dict.272, Dict.671, Dict.672, Dict.273}; - let Dict.616 : U64 = 0i64; - let Dict.615 : {List {Str, I64}, List U64, List I8, U64} = CallByName Dict.38 Dict.275 Dict.270 Dict.271 Dict.272 Dict.616; - ret Dict.615; - -procedure Dict.38 (#Derived_gen.32, #Derived_gen.33, #Derived_gen.34, #Derived_gen.35, #Derived_gen.36): - joinpoint Dict.617 Dict.276 Dict.277 Dict.278 Dict.279 Dict.280: - inc Dict.277; - let Dict.618 : [C {}, C I8] = CallByName List.2 Dict.277 Dict.280; - let Dict.668 : U8 = 1i64; - let Dict.669 : U8 = GetTagId Dict.618; - let Dict.670 : Int1 = lowlevel Eq Dict.668 Dict.669; - if Dict.670 then - let Dict.281 : I8 = UnionAtIndex (Id 1) (Index 0) Dict.618; - joinpoint Dict.623 Dict.282: - let Dict.621 : U64 = 1i64; - let Dict.620 : U64 = CallByName Num.51 Dict.280 Dict.621; - jump Dict.617 Dict.282 Dict.277 Dict.278 Dict.279 Dict.620; - in - let Dict.666 : I8 = 0i64; - let Dict.624 : Int1 = CallByName Num.25 Dict.281 Dict.666; - if Dict.624 then - inc Dict.278; - let Dict.283 : U64 = CallByName Dict.22 Dict.278 Dict.280; - inc Dict.279; - let Dict.664 : {Str, I64} = CallByName Dict.22 Dict.279 Dict.283; - let Dict.284 : Str = StructAtIndex 0 Dict.664; - let Dict.622 : {List {Str, I64}, List U64, List I8, U64} = CallByName Dict.39 Dict.276 Dict.284 Dict.283; - jump Dict.623 Dict.622; - else - jump Dict.623 Dict.276; - else - dec Dict.277; - dec Dict.279; - dec Dict.278; - ret Dict.276; - in - jump Dict.617 #Derived_gen.32 #Derived_gen.33 #Derived_gen.34 #Derived_gen.35 #Derived_gen.36; - -procedure Dict.39 (Dict.553, Dict.289, Dict.290): - let Dict.287 : List {Str, I64} = StructAtIndex 0 Dict.553; - let Dict.286 : List U64 = StructAtIndex 1 Dict.553; - let Dict.285 : List I8 = StructAtIndex 2 Dict.553; - inc Dict.285; - let Dict.288 : U64 = StructAtIndex 3 Dict.553; - let Dict.639 : [C , C U64] = TagId(0) ; - let Dict.638 : {U64, U64} = CallByName Dict.48 Dict.639; - let Dict.636 : {U64, U64} = CallByName Hash.19 Dict.638 Dict.289; - let Dict.291 : U64 = CallByName Dict.51 Dict.636; - let Dict.292 : U64 = CallByName Dict.46 Dict.291; - let Dict.293 : I8 = CallByName Dict.47 Dict.291; - let Dict.630 : U64 = CallByName List.6 Dict.285; - let Dict.629 : U64 = CallByName Dict.45 Dict.630; - let Dict.294 : {U64, U64, U64} = CallByName Dict.42 Dict.292 Dict.629; - let Dict.628 : U64 = 0i64; - let Dict.295 : U64 = CallByName Dict.34 Dict.285 Dict.294 Dict.628; - let Dict.626 : List U64 = CallByName List.3 Dict.286 Dict.295 Dict.290; - let Dict.627 : List I8 = CallByName List.3 Dict.285 Dict.295 Dict.293; - let Dict.625 : {List {Str, I64}, List U64, List I8, U64} = Struct {Dict.287, Dict.626, Dict.627, Dict.288}; - ret Dict.625; - -procedure Dict.40 (): - let Dict.674 : I8 = -128i64; - ret Dict.674; - -procedure Dict.42 (Dict.297, Dict.298): - let Dict.606 : U64 = 1i64; - let Dict.299 : U64 = CallByName Num.77 Dict.298 Dict.606; - let Dict.605 : U64 = CallByName Num.137 Dict.297; - let Dict.300 : U64 = CallByName Num.69 Dict.605 Dict.299; - let Dict.604 : U64 = 1i64; - let Dict.603 : {U64, U64, U64} = Struct {Dict.299, Dict.604, Dict.300}; - ret Dict.603; - -procedure Dict.43 (Dict.562): - let Dict.303 : U64 = StructAtIndex 0 Dict.562; - let Dict.302 : U64 = StructAtIndex 1 Dict.562; - let Dict.301 : U64 = StructAtIndex 2 Dict.562; - let Dict.592 : U64 = CallByName Num.51 Dict.301 Dict.302; - let Dict.304 : U64 = CallByName Num.69 Dict.592 Dict.303; - let Dict.591 : U64 = 1i64; - let Dict.590 : U64 = CallByName Num.51 Dict.302 Dict.591; - let Dict.589 : {U64, U64, U64} = Struct {Dict.303, Dict.590, Dict.304}; - ret Dict.589; - -procedure Dict.44 (Dict.305): - let Dict.601 : U8 = 3i64; - let Dict.600 : U64 = CallByName Num.72 Dict.305 Dict.601; - ret Dict.600; - -procedure Dict.45 (Dict.306): - let Dict.609 : U8 = 3i64; - let Dict.608 : U64 = CallByName Num.74 Dict.306 Dict.609; - ret Dict.608; - -procedure Dict.46 (Dict.307): - let Dict.635 : U8 = 7i64; - let Dict.634 : U64 = CallByName Num.74 Dict.307 Dict.635; - ret Dict.634; - -procedure Dict.47 (Dict.308): - let Dict.633 : U64 = 127i64; - let Dict.632 : U64 = CallByName Num.69 Dict.308 Dict.633; - let Dict.631 : I8 = CallByName Num.117 Dict.632; - ret Dict.631; - -procedure Dict.48 (Dict.309): - joinpoint Dict.656 Dict.310: - let Dict.641 : U64 = CallByName Dict.50 Dict.310; - let Dict.640 : {U64, U64} = Struct {Dict.641, Dict.310}; - ret Dict.640; - in - let Dict.661 : U8 = 0i64; - let Dict.662 : U8 = GetTagId Dict.309; - let Dict.663 : Int1 = lowlevel Eq Dict.661 Dict.662; - if Dict.663 then - let Dict.658 : {} = Struct {}; - let Dict.657 : U64 = CallByName Dict.23 Dict.658; - jump Dict.656 Dict.657; - else - let Dict.311 : U64 = UnionAtIndex (Id 1) (Index 0) Dict.309; - jump Dict.656 Dict.311; - -procedure Dict.49 (Dict.541, Dict.542): - let Dict.314 : U64 = StructAtIndex 0 Dict.542; - let Dict.315 : U64 = StructAtIndex 1 Dict.542; - let Dict.317 : U64 = StructAtIndex 2 Dict.542; - let Dict.316 : U64 = StructAtIndex 3 Dict.542; - let Dict.312 : U64 = StructAtIndex 0 Dict.541; - let Dict.313 : U64 = StructAtIndex 1 Dict.541; - let Dict.749 : U64 = CallByName Dict.61; - let Dict.747 : U64 = CallByName Num.70 Dict.314 Dict.749; - let Dict.748 : U64 = CallByName Num.70 Dict.315 Dict.316; - let Dict.318 : {U64, U64} = CallByName Dict.65 Dict.747 Dict.748; - let Dict.744 : U64 = StructAtIndex 0 Dict.318; - let Dict.745 : U64 = CallByName Dict.60; - let Dict.743 : U64 = CallByName Num.70 Dict.744 Dict.745; - let Dict.319 : U64 = CallByName Num.70 Dict.743 Dict.317; - let Dict.740 : U64 = StructAtIndex 1 Dict.318; - let Dict.741 : U64 = CallByName Dict.61; - let Dict.320 : U64 = CallByName Num.70 Dict.740 Dict.741; - let Dict.321 : U64 = CallByName Dict.64 Dict.319 Dict.320; - let Dict.732 : U64 = CallByName Dict.64 Dict.313 Dict.321; - let Dict.731 : {U64, U64} = Struct {Dict.312, Dict.732}; - ret Dict.731; - -procedure Dict.50 (Dict.322): - let Dict.654 : U64 = CallByName Dict.60; - let Dict.644 : U64 = CallByName Num.70 Dict.322 Dict.654; - let Dict.645 : U64 = CallByName Dict.61; - let Dict.643 : U64 = CallByName Dict.64 Dict.644 Dict.645; - let Dict.642 : U64 = CallByName Num.70 Dict.643 Dict.322; - ret Dict.642; - -procedure Dict.51 (Dict.561): - let Dict.323 : U64 = StructAtIndex 1 Dict.561; - ret Dict.323; - -procedure Dict.57 (Dict.535, Dict.362): - let Dict.360 : U64 = StructAtIndex 0 Dict.535; - let Dict.361 : U64 = StructAtIndex 1 Dict.535; - let Dict.363 : U64 = CallByName List.6 Dict.362; - joinpoint Dict.938 Dict.364: - let Dict.931 : {U64, U64} = Struct {Dict.360, Dict.361}; - let Dict.933 : U64 = StructAtIndex 0 Dict.364; - let Dict.934 : U64 = StructAtIndex 1 Dict.364; - let Dict.935 : U64 = CallByName Num.133 Dict.363; - let Dict.936 : U64 = StructAtIndex 2 Dict.364; - let Dict.932 : {U64, U64, U64, U64} = Struct {Dict.933, Dict.934, Dict.935, Dict.936}; - let Dict.930 : {U64, U64} = CallByName Dict.49 Dict.931 Dict.932; - ret Dict.930; - in - let Dict.972 : U64 = 16i64; - let Dict.943 : Int1 = CallByName Num.23 Dict.363 Dict.972; - if Dict.943 then - joinpoint Dict.945 Dict.937: - jump Dict.938 Dict.937; - in - let Dict.971 : U64 = 4i64; - let Dict.953 : Int1 = CallByName Num.25 Dict.363 Dict.971; - if Dict.953 then - let Dict.970 : U8 = 3i64; - let Dict.968 : U64 = CallByName Num.74 Dict.363 Dict.970; - let Dict.969 : U8 = 2i64; - let Dict.365 : U64 = CallByName Num.72 Dict.968 Dict.969; - let Dict.967 : U64 = 0i64; - inc 3 Dict.362; - let Dict.965 : U64 = CallByName Dict.67 Dict.362 Dict.967; - let Dict.966 : U8 = 32i64; - let Dict.963 : U64 = CallByName Num.72 Dict.965 Dict.966; - let Dict.964 : U64 = CallByName Dict.67 Dict.362 Dict.365; - let Dict.366 : U64 = CallByName Num.71 Dict.963 Dict.964; - let Dict.962 : U64 = 4i64; - let Dict.961 : U64 = CallByName Num.75 Dict.363 Dict.962; - let Dict.959 : U64 = CallByName Dict.67 Dict.362 Dict.961; - let Dict.960 : U8 = 32i64; - let Dict.954 : U64 = CallByName Num.72 Dict.959 Dict.960; - let Dict.958 : U64 = 4i64; - let Dict.957 : U64 = CallByName Num.75 Dict.363 Dict.958; - let Dict.956 : U64 = CallByName Num.75 Dict.957 Dict.365; - let Dict.955 : U64 = CallByName Dict.67 Dict.362 Dict.956; - let Dict.367 : U64 = CallByName Num.71 Dict.954 Dict.955; - let Dict.944 : {U64, U64, U64} = Struct {Dict.366, Dict.367, Dict.360}; - jump Dict.945 Dict.944; - else - let Dict.952 : U64 = 0i64; - let Dict.948 : Int1 = CallByName Num.24 Dict.363 Dict.952; - if Dict.948 then - let Dict.951 : U64 = 0i64; - let Dict.949 : U64 = CallByName Dict.68 Dict.362 Dict.951 Dict.363; - let Dict.950 : U64 = 0i64; - let Dict.944 : {U64, U64, U64} = Struct {Dict.949, Dict.950, Dict.360}; - jump Dict.945 Dict.944; - else - dec Dict.362; - let Dict.946 : U64 = 0i64; - let Dict.947 : U64 = 0i64; - let Dict.944 : {U64, U64, U64} = Struct {Dict.946, Dict.947, Dict.360}; - jump Dict.945 Dict.944; - else - let Dict.942 : U64 = 48i64; - let Dict.940 : Int1 = CallByName Num.23 Dict.363 Dict.942; - if Dict.940 then - let Dict.941 : U64 = 0i64; - let Dict.937 : {U64, U64, U64} = CallByName Dict.59 Dict.360 Dict.362 Dict.941 Dict.363; - jump Dict.938 Dict.937; - else - let Dict.939 : U64 = 0i64; - let Dict.937 : {U64, U64, U64} = CallByName Dict.58 Dict.360 Dict.360 Dict.360 Dict.362 Dict.939 Dict.363; - jump Dict.938 Dict.937; - -procedure Dict.58 (#Derived_gen.51, #Derived_gen.52, #Derived_gen.53, #Derived_gen.54, #Derived_gen.55, #Derived_gen.56): - joinpoint Dict.757 Dict.368 Dict.369 Dict.370 Dict.371 Dict.372 Dict.373: - inc 6 Dict.371; - let Dict.864 : U64 = CallByName Dict.66 Dict.371 Dict.372; - let Dict.865 : U64 = CallByName Dict.61; - let Dict.859 : U64 = CallByName Num.70 Dict.864 Dict.865; - let Dict.863 : U64 = 8i64; - let Dict.862 : U64 = CallByName Num.51 Dict.372 Dict.863; - let Dict.861 : U64 = CallByName Dict.66 Dict.371 Dict.862; - let Dict.860 : U64 = CallByName Num.70 Dict.861 Dict.368; - let Dict.374 : U64 = CallByName Dict.64 Dict.859 Dict.860; - let Dict.858 : U64 = 16i64; - let Dict.857 : U64 = CallByName Num.51 Dict.372 Dict.858; - let Dict.854 : U64 = CallByName Dict.66 Dict.371 Dict.857; - let Dict.855 : U64 = CallByName Dict.62; - let Dict.849 : U64 = CallByName Num.70 Dict.854 Dict.855; - let Dict.853 : U64 = 24i64; - let Dict.852 : U64 = CallByName Num.51 Dict.372 Dict.853; - let Dict.851 : U64 = CallByName Dict.66 Dict.371 Dict.852; - let Dict.850 : U64 = CallByName Num.70 Dict.851 Dict.369; - let Dict.375 : U64 = CallByName Dict.64 Dict.849 Dict.850; - let Dict.848 : U64 = 32i64; - let Dict.847 : U64 = CallByName Num.51 Dict.372 Dict.848; - let Dict.844 : U64 = CallByName Dict.66 Dict.371 Dict.847; - let Dict.845 : U64 = CallByName Dict.63; - let Dict.839 : U64 = CallByName Num.70 Dict.844 Dict.845; - let Dict.843 : U64 = 40i64; - let Dict.842 : U64 = CallByName Num.51 Dict.372 Dict.843; - let Dict.841 : U64 = CallByName Dict.66 Dict.371 Dict.842; - let Dict.840 : U64 = CallByName Num.70 Dict.841 Dict.370; - let Dict.376 : U64 = CallByName Dict.64 Dict.839 Dict.840; - let Dict.838 : U64 = 48i64; - let Dict.377 : U64 = CallByName Num.75 Dict.373 Dict.838; - let Dict.837 : U64 = 48i64; - let Dict.378 : U64 = CallByName Num.51 Dict.372 Dict.837; - let Dict.836 : U64 = 48i64; - let Dict.834 : Int1 = CallByName Num.24 Dict.377 Dict.836; - if Dict.834 then - jump Dict.757 Dict.374 Dict.375 Dict.376 Dict.371 Dict.378 Dict.377; - else - let Dict.833 : U64 = 16i64; - let Dict.808 : Int1 = CallByName Num.24 Dict.377 Dict.833; - if Dict.808 then - let Dict.832 : U64 = CallByName Num.70 Dict.375 Dict.374; - let Dict.379 : U64 = CallByName Num.70 Dict.376 Dict.832; - let Dict.809 : {U64, U64, U64} = CallByName Dict.59 Dict.379 Dict.371 Dict.378 Dict.377; - ret Dict.809; - else - inc Dict.371; - let Dict.807 : U64 = CallByName Num.70 Dict.375 Dict.374; - let Dict.380 : U64 = CallByName Num.70 Dict.376 Dict.807; - let Dict.806 : U64 = 16i64; - let Dict.805 : U64 = CallByName Num.75 Dict.377 Dict.806; - let Dict.804 : U64 = CallByName Num.51 Dict.805 Dict.378; - let Dict.759 : U64 = CallByName Dict.66 Dict.371 Dict.804; - let Dict.803 : U64 = 8i64; - let Dict.802 : U64 = CallByName Num.75 Dict.377 Dict.803; - let Dict.761 : U64 = CallByName Num.51 Dict.802 Dict.378; - let Dict.760 : U64 = CallByName Dict.66 Dict.371 Dict.761; - let Dict.758 : {U64, U64, U64} = Struct {Dict.759, Dict.760, Dict.380}; - ret Dict.758; - in - jump Dict.757 #Derived_gen.51 #Derived_gen.52 #Derived_gen.53 #Derived_gen.54 #Derived_gen.55 #Derived_gen.56; - -procedure Dict.59 (#Derived_gen.17, #Derived_gen.18, #Derived_gen.19, #Derived_gen.20): - joinpoint Dict.810 Dict.381 Dict.382 Dict.383 Dict.384: - inc 2 Dict.382; - let Dict.830 : U64 = CallByName Dict.66 Dict.382 Dict.383; - let Dict.831 : U64 = CallByName Dict.61; - let Dict.825 : U64 = CallByName Num.70 Dict.830 Dict.831; - let Dict.829 : U64 = 8i64; - let Dict.828 : U64 = CallByName Num.51 Dict.383 Dict.829; - let Dict.827 : U64 = CallByName Dict.66 Dict.382 Dict.828; - let Dict.826 : U64 = CallByName Num.70 Dict.827 Dict.381; - let Dict.385 : U64 = CallByName Dict.64 Dict.825 Dict.826; - let Dict.824 : U64 = 16i64; - let Dict.386 : U64 = CallByName Num.75 Dict.384 Dict.824; - let Dict.823 : U64 = 16i64; - let Dict.387 : U64 = CallByName Num.51 Dict.383 Dict.823; - let Dict.822 : U64 = 16i64; - let Dict.812 : Int1 = CallByName Num.23 Dict.386 Dict.822; - if Dict.812 then - inc Dict.382; - let Dict.821 : U64 = 16i64; - let Dict.820 : U64 = CallByName Num.75 Dict.386 Dict.821; - let Dict.819 : U64 = CallByName Num.51 Dict.820 Dict.387; - let Dict.814 : U64 = CallByName Dict.66 Dict.382 Dict.819; - let Dict.818 : U64 = 8i64; - let Dict.817 : U64 = CallByName Num.75 Dict.386 Dict.818; - let Dict.816 : U64 = CallByName Num.51 Dict.817 Dict.387; - let Dict.815 : U64 = CallByName Dict.66 Dict.382 Dict.816; - let Dict.813 : {U64, U64, U64} = Struct {Dict.814, Dict.815, Dict.385}; - ret Dict.813; - else - jump Dict.810 Dict.385 Dict.382 Dict.387 Dict.386; - in - jump Dict.810 #Derived_gen.17 #Derived_gen.18 #Derived_gen.19 #Derived_gen.20; - -procedure Dict.60 (): - let Dict.746 : U64 = 11562461410679940143i64; - ret Dict.746; - -procedure Dict.61 (): - let Dict.742 : U64 = 16646288086500911323i64; - ret Dict.742; - -procedure Dict.62 (): - let Dict.856 : U64 = 10285213230658275043i64; - ret Dict.856; - -procedure Dict.63 (): - let Dict.846 : U64 = 6384245875588680899i64; - ret Dict.846; - -procedure Dict.64 (Dict.388, Dict.389): - let Dict.734 : {U64, U64} = CallByName Dict.65 Dict.388 Dict.389; - let Dict.390 : U64 = StructAtIndex 0 Dict.734; - let Dict.391 : U64 = StructAtIndex 1 Dict.734; - let Dict.733 : U64 = CallByName Num.70 Dict.390 Dict.391; +procedure Dict.12 (Dict.152): + let Dict.894 : {} = Struct {}; + let Dict.734 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = CallByName Dict.1 Dict.894; + let Dict.735 : {} = Struct {}; + let Dict.733 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = CallByName List.18 Dict.152 Dict.734 Dict.735; ret Dict.733; -procedure Dict.65 (Dict.392, Dict.393): - let Dict.738 : U128 = CallByName Num.135 Dict.392; - let Dict.739 : U128 = CallByName Num.135 Dict.393; - let Dict.394 : U128 = CallByName Num.21 Dict.738 Dict.739; - let Dict.395 : U64 = CallByName Num.133 Dict.394; - let Dict.737 : U8 = 64i64; - let Dict.736 : U128 = CallByName Num.74 Dict.394 Dict.737; - let Dict.396 : U64 = CallByName Num.133 Dict.736; - let Dict.735 : {U64, U64} = Struct {Dict.395, Dict.396}; - ret Dict.735; +procedure Dict.120 (Dict.121, Dict.119): + let Dict.1110 : {} = Struct {}; + let Dict.1111 : {} = Struct {}; + let Dict.1112 : {} = Struct {}; + let Dict.1109 : {{List {U32, U32}, List {Str, I64}, U64, Float32, U8}, {}, {}, {}} = CallByName Inspect.39 Dict.119 Dict.1110 Dict.1111 Dict.1112; + let Dict.1108 : Str = CallByName Inspect.31 Dict.1109 Dict.121; + ret Dict.1108; -procedure Dict.66 (Dict.397, Dict.398): - inc 7 Dict.397; - let Dict.801 : U8 = CallByName Dict.22 Dict.397 Dict.398; - let Dict.399 : U64 = CallByName Num.133 Dict.801; - let Dict.800 : U64 = 1i64; - let Dict.799 : U64 = CallByName Num.51 Dict.398 Dict.800; - let Dict.798 : U8 = CallByName Dict.22 Dict.397 Dict.799; - let Dict.400 : U64 = CallByName Num.133 Dict.798; - let Dict.797 : U64 = 2i64; - let Dict.796 : U64 = CallByName Num.51 Dict.398 Dict.797; - let Dict.795 : U8 = CallByName Dict.22 Dict.397 Dict.796; - let Dict.401 : U64 = CallByName Num.133 Dict.795; - let Dict.794 : U64 = 3i64; - let Dict.793 : U64 = CallByName Num.51 Dict.398 Dict.794; - let Dict.792 : U8 = CallByName Dict.22 Dict.397 Dict.793; - let Dict.402 : U64 = CallByName Num.133 Dict.792; - let Dict.791 : U64 = 4i64; - let Dict.790 : U64 = CallByName Num.51 Dict.398 Dict.791; - let Dict.789 : U8 = CallByName Dict.22 Dict.397 Dict.790; - let Dict.403 : U64 = CallByName Num.133 Dict.789; - let Dict.788 : U64 = 5i64; - let Dict.787 : U64 = CallByName Num.51 Dict.398 Dict.788; - let Dict.786 : U8 = CallByName Dict.22 Dict.397 Dict.787; - let Dict.404 : U64 = CallByName Num.133 Dict.786; - let Dict.785 : U64 = 6i64; - let Dict.784 : U64 = CallByName Num.51 Dict.398 Dict.785; - let Dict.783 : U8 = CallByName Dict.22 Dict.397 Dict.784; - let Dict.405 : U64 = CallByName Num.133 Dict.783; - let Dict.782 : U64 = 7i64; - let Dict.780 : U64 = CallByName Num.51 Dict.398 Dict.782; - let Dict.779 : U8 = CallByName Dict.22 Dict.397 Dict.780; - let Dict.406 : U64 = CallByName Num.133 Dict.779; - let Dict.778 : U8 = 8i64; - let Dict.777 : U64 = CallByName Num.72 Dict.400 Dict.778; - let Dict.407 : U64 = CallByName Num.71 Dict.399 Dict.777; - let Dict.776 : U8 = 16i64; - let Dict.773 : U64 = CallByName Num.72 Dict.401 Dict.776; - let Dict.775 : U8 = 24i64; - let Dict.774 : U64 = CallByName Num.72 Dict.402 Dict.775; - let Dict.408 : U64 = CallByName Num.71 Dict.773 Dict.774; - let Dict.772 : U8 = 32i64; - let Dict.769 : U64 = CallByName Num.72 Dict.403 Dict.772; - let Dict.771 : U8 = 40i64; - let Dict.770 : U64 = CallByName Num.72 Dict.404 Dict.771; - let Dict.409 : U64 = CallByName Num.71 Dict.769 Dict.770; - let Dict.768 : U8 = 48i64; - let Dict.765 : U64 = CallByName Num.72 Dict.405 Dict.768; - let Dict.767 : U8 = 56i64; - let Dict.766 : U64 = CallByName Num.72 Dict.406 Dict.767; - let Dict.410 : U64 = CallByName Num.71 Dict.765 Dict.766; - let Dict.763 : U64 = CallByName Num.71 Dict.407 Dict.408; - let Dict.764 : U64 = CallByName Num.71 Dict.409 Dict.410; - let Dict.762 : U64 = CallByName Num.71 Dict.763 Dict.764; - ret Dict.762; +procedure Dict.153 (Dict.154, Dict.736): + let Dict.155 : Str = StructAtIndex 0 Dict.736; + let Dict.156 : I64 = StructAtIndex 1 Dict.736; + let Dict.737 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = CallByName Dict.8 Dict.154 Dict.155 Dict.156; + ret Dict.737; -procedure Dict.67 (Dict.411, Dict.412): - inc 3 Dict.411; - let Dict.913 : U8 = CallByName Dict.22 Dict.411 Dict.412; - let Dict.413 : U64 = CallByName Num.133 Dict.913; - let Dict.912 : U64 = 1i64; - let Dict.911 : U64 = CallByName Num.51 Dict.412 Dict.912; - let Dict.910 : U8 = CallByName Dict.22 Dict.411 Dict.911; - let Dict.414 : U64 = CallByName Num.133 Dict.910; - let Dict.909 : U64 = 2i64; - let Dict.908 : U64 = CallByName Num.51 Dict.412 Dict.909; - let Dict.907 : U8 = CallByName Dict.22 Dict.411 Dict.908; - let Dict.415 : U64 = CallByName Num.133 Dict.907; - let Dict.906 : U64 = 3i64; - let Dict.905 : U64 = CallByName Num.51 Dict.412 Dict.906; - let Dict.904 : U8 = CallByName Dict.22 Dict.411 Dict.905; - let Dict.416 : U64 = CallByName Num.133 Dict.904; - let Dict.903 : U8 = 8i64; - let Dict.902 : U64 = CallByName Num.72 Dict.414 Dict.903; - let Dict.417 : U64 = CallByName Num.71 Dict.413 Dict.902; - let Dict.901 : U8 = 16i64; - let Dict.898 : U64 = CallByName Num.72 Dict.415 Dict.901; - let Dict.900 : U8 = 24i64; - let Dict.899 : U64 = CallByName Num.72 Dict.416 Dict.900; - let Dict.418 : U64 = CallByName Num.71 Dict.898 Dict.899; - let Dict.897 : U64 = CallByName Num.71 Dict.417 Dict.418; - ret Dict.897; +procedure Dict.182 (Dict.183, Dict.1115, Dict.181): + let Dict.184 : Str = StructAtIndex 0 Dict.1115; + let Dict.185 : I64 = StructAtIndex 1 Dict.1115; + let Dict.1117 : {Str, Int1} = CallByName Inspect.192 Dict.183 Dict.184 Dict.185 Dict.181; + ret Dict.1117; -procedure Dict.68 (Dict.419, Dict.420, Dict.421): - inc 2 Dict.419; - let Dict.891 : U8 = CallByName Dict.22 Dict.419 Dict.420; - let Dict.422 : U64 = CallByName Num.133 Dict.891; - let Dict.890 : U8 = 1i64; - let Dict.889 : U64 = CallByName Num.74 Dict.421 Dict.890; - let Dict.888 : U64 = CallByName Num.51 Dict.889 Dict.420; - let Dict.887 : U8 = CallByName Dict.22 Dict.419 Dict.888; - let Dict.423 : U64 = CallByName Num.133 Dict.887; - let Dict.886 : U64 = 1i64; - let Dict.885 : U64 = CallByName Num.75 Dict.421 Dict.886; - let Dict.884 : U64 = CallByName Num.51 Dict.885 Dict.420; - let Dict.883 : U8 = CallByName Dict.22 Dict.419 Dict.884; - let Dict.424 : U64 = CallByName Num.133 Dict.883; - let Dict.882 : U8 = 16i64; - let Dict.879 : U64 = CallByName Num.72 Dict.422 Dict.882; - let Dict.881 : U8 = 8i64; - let Dict.880 : U64 = CallByName Num.72 Dict.423 Dict.881; - let Dict.425 : U64 = CallByName Num.71 Dict.879 Dict.880; - let Dict.878 : U64 = CallByName Num.71 Dict.425 Dict.424; - ret Dict.878; +procedure Dict.20 (Dict.723): + let Dict.149 : U64 = StructAtIndex 2 Dict.723; + let #Derived_gen.70 : List {U32, U32} = StructAtIndex 0 Dict.723; + dec #Derived_gen.70; + let #Derived_gen.69 : List {Str, I64} = StructAtIndex 1 Dict.723; + dec #Derived_gen.69; + let Dict.892 : U64 = CallByName Num.137 Dict.149; + ret Dict.892; -procedure Dict.8 (Dict.550, Dict.168, Dict.169): - let Dict.166 : List {Str, I64} = StructAtIndex 0 Dict.550; - inc Dict.166; - let Dict.165 : List U64 = StructAtIndex 1 Dict.550; - inc Dict.165; - let Dict.164 : List I8 = StructAtIndex 2 Dict.550; - inc Dict.164; - let Dict.167 : U64 = StructAtIndex 3 Dict.550; - let Dict.717 : [C , C U64] = TagId(0) ; - let Dict.716 : {U64, U64} = CallByName Dict.48 Dict.717; - inc 2 Dict.168; - let Dict.715 : {U64, U64} = CallByName Hash.19 Dict.716 Dict.168; - let Dict.170 : U64 = CallByName Dict.51 Dict.715; - let Dict.171 : U64 = CallByName Dict.46 Dict.170; - let Dict.172 : I8 = CallByName Dict.47 Dict.170; - let Dict.714 : U64 = CallByName List.6 Dict.164; - let Dict.713 : U64 = CallByName Dict.45 Dict.714; - let Dict.173 : {U64, U64, U64} = CallByName Dict.42 Dict.171 Dict.713; - let Dict.685 : U64 = 0i64; - let Dict.570 : [C {}, C U64] = CallByName Dict.35 Dict.164 Dict.165 Dict.166 Dict.172 Dict.168 Dict.173 Dict.685; - let Dict.682 : U8 = 1i64; - let Dict.683 : U8 = GetTagId Dict.570; - let Dict.684 : Int1 = lowlevel Eq Dict.682 Dict.683; - if Dict.684 then - inc Dict.165; - let Dict.175 : U64 = UnionAtIndex (Id 1) (Index 0) Dict.570; - let Dict.176 : U64 = CallByName Dict.22 Dict.165 Dict.175; - let Dict.573 : {Str, I64} = Struct {Dict.168, Dict.169}; - let Dict.572 : List {Str, I64} = CallByName List.3 Dict.166 Dict.176 Dict.573; - let Dict.571 : {List {Str, I64}, List U64, List I8, U64} = Struct {Dict.572, Dict.165, Dict.164, Dict.167}; - ret Dict.571; +procedure Dict.22 (#Attr.2, #Attr.3): + let Dict.771 : {U32, U32} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret Dict.771; + +procedure Dict.22 (#Attr.2, #Attr.3): + let Dict.787 : {Str, I64} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret Dict.787; + +procedure Dict.22 (#Attr.2, #Attr.3): + let Dict.956 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret Dict.956; + +procedure Dict.23 (#Attr.2): + let Dict.825 : U64 = lowlevel DictPseudoSeed #Attr.2; + ret Dict.825; + +procedure Dict.36 (Dict.119): + let Dict.1105 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = CallByName Inspect.30 Dict.119; + ret Dict.1105; + +procedure Dict.38 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4, #Derived_gen.5, #Derived_gen.6, #Derived_gen.7, #Derived_gen.8): + joinpoint Dict.739 Dict.222 Dict.223 Dict.224 Dict.225 Dict.226 Dict.227 Dict.228 Dict.229 Dict.230: + let Dict.790 : U64 = CallByName Num.137 Dict.224; + let Dict.231 : {U32, U32} = CallByName Dict.22 Dict.222 Dict.790; + let Dict.789 : U32 = StructAtIndex 1 Dict.231; + let Dict.777 : Int1 = CallByName Bool.11 Dict.225 Dict.789; + if Dict.777 then + let Dict.788 : U32 = StructAtIndex 0 Dict.231; + let Dict.786 : U64 = CallByName Num.137 Dict.788; + let Dict.785 : {Str, I64} = CallByName Dict.22 Dict.223 Dict.786; + let Dict.232 : Str = StructAtIndex 0 Dict.785; + let Dict.780 : Int1 = CallByName Bool.11 Dict.232 Dict.226; + if Dict.780 then + let Dict.784 : U32 = StructAtIndex 0 Dict.231; + let Dict.782 : U64 = CallByName Num.137 Dict.784; + let Dict.783 : {Str, I64} = Struct {Dict.226, Dict.227}; + let Dict.233 : List {Str, I64} = CallByName List.3 Dict.223 Dict.782 Dict.783; + let Dict.781 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = Struct {Dict.222, Dict.233, Dict.228, Dict.229, Dict.230}; + ret Dict.781; + else + let Dict.779 : U64 = CallByName List.6 Dict.222; + let Dict.234 : U64 = CallByName Dict.68 Dict.224 Dict.779; + let Dict.235 : U32 = CallByName Dict.48 Dict.225; + jump Dict.739 Dict.222 Dict.223 Dict.234 Dict.235 Dict.226 Dict.227 Dict.228 Dict.229 Dict.230; + else + let Dict.776 : U32 = StructAtIndex 1 Dict.231; + let Dict.753 : Int1 = CallByName Num.24 Dict.225 Dict.776; + if Dict.753 then + let Dict.775 : {Str, I64} = Struct {Dict.226, Dict.227}; + let Dict.236 : List {Str, I64} = CallByName List.4 Dict.223 Dict.775; + let Dict.773 : U64 = CallByName List.6 Dict.236; + let Dict.774 : U64 = 1i64; + let Dict.237 : U64 = CallByName Num.20 Dict.773 Dict.774; + let Dict.772 : U32 = CallByName Num.131 Dict.237; + let Dict.755 : {U32, U32} = Struct {Dict.772, Dict.225}; + let Dict.238 : List {U32, U32} = CallByName Dict.67 Dict.222 Dict.755 Dict.224; + let Dict.754 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = Struct {Dict.238, Dict.236, Dict.228, Dict.229, Dict.230}; + ret Dict.754; + else + let Dict.746 : U64 = CallByName List.6 Dict.222; + let Dict.239 : U64 = CallByName Dict.68 Dict.224 Dict.746; + let Dict.240 : U32 = CallByName Dict.48 Dict.225; + jump Dict.739 Dict.222 Dict.223 Dict.239 Dict.240 Dict.226 Dict.227 Dict.228 Dict.229 Dict.230; + in + jump Dict.739 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4 #Derived_gen.5 #Derived_gen.6 #Derived_gen.7 #Derived_gen.8; + +procedure Dict.399 (Dict.400, Dict.848, Dict.402, Dict.398): + let Dict.401 : Str = StructAtIndex 0 Dict.848; + inc Dict.400; + let Dict.853 : {U64, U32} = CallByName Dict.65 Dict.400 Dict.401 Dict.398; + let Dict.403 : U64 = StructAtIndex 0 Dict.853; + let Dict.404 : U32 = StructAtIndex 1 Dict.853; + let Dict.852 : U32 = CallByName Num.131 Dict.402; + let Dict.851 : {U32, U32} = Struct {Dict.852, Dict.404}; + let Dict.850 : List {U32, U32} = CallByName Dict.67 Dict.400 Dict.851 Dict.403; + ret Dict.850; + +procedure Dict.4 (Dict.732): + let Dict.157 : List {Str, I64} = StructAtIndex 1 Dict.732; + let #Derived_gen.66 : List {U32, U32} = StructAtIndex 0 Dict.732; + dec #Derived_gen.66; + let Dict.893 : U64 = CallByName List.6 Dict.157; + dec Dict.157; + ret Dict.893; + +procedure Dict.41 (): + let Dict.870 : U32 = 0i64; + let Dict.871 : U32 = 0i64; + let Dict.869 : {U32, U32} = Struct {Dict.870, Dict.871}; + ret Dict.869; + +procedure Dict.42 (): + let Dict.744 : U32 = 1i64; + let Dict.745 : U8 = 8i64; + let Dict.743 : U32 = CallByName Num.72 Dict.744 Dict.745; + ret Dict.743; + +procedure Dict.43 (): + let Dict.799 : U32 = CallByName Dict.42; + let Dict.800 : U32 = 1i64; + let Dict.798 : U32 = CallByName Num.75 Dict.799 Dict.800; + ret Dict.798; + +procedure Dict.44 (): + let Dict.902 : Float32 = 0.8f64; + ret Dict.902; + +procedure Dict.45 (): + let Dict.900 : U8 = 64i64; + let Dict.901 : U8 = 3i64; + let Dict.899 : U8 = CallByName Num.20 Dict.900 Dict.901; + ret Dict.899; + +procedure Dict.46 (): + let Dict.842 : U64 = 1i64; + let Dict.843 : U8 = 32i64; + let Dict.841 : U64 = CallByName Num.72 Dict.842 Dict.843; + ret Dict.841; + +procedure Dict.47 (): + let Dict.840 : U64 = CallByName Dict.46; + ret Dict.840; + +procedure Dict.48 (Dict.307): + let Dict.742 : U32 = CallByName Dict.42; + let Dict.741 : U32 = CallByName Num.19 Dict.307 Dict.742; + ret Dict.741; + +procedure Dict.59 (Dict.722): + let Dict.377 : List {Str, I64} = StructAtIndex 1 Dict.722; + let Dict.378 : U64 = StructAtIndex 2 Dict.722; + let Dict.379 : Float32 = StructAtIndex 3 Dict.722; + let Dict.380 : U8 = StructAtIndex 4 Dict.722; + let #Derived_gen.67 : List {U32, U32} = StructAtIndex 0 Dict.722; + dec #Derived_gen.67; + let Dict.888 : U64 = CallByName Dict.47; + let Dict.844 : Int1 = CallByName Bool.7 Dict.378 Dict.888; + if Dict.844 then + inc Dict.377; + let Dict.887 : U8 = 1i64; + let Dict.381 : U8 = CallByName Num.20 Dict.380 Dict.887; + let Dict.864 : {List {U32, U32}, U64} = CallByName Dict.60 Dict.381 Dict.379; + let Dict.382 : List {U32, U32} = StructAtIndex 0 Dict.864; + let Dict.383 : U64 = StructAtIndex 1 Dict.864; + let Dict.384 : List {U32, U32} = CallByName Dict.64 Dict.382 Dict.377 Dict.381; + let Dict.845 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = Struct {Dict.384, Dict.377, Dict.383, Dict.379, Dict.381}; + ret Dict.845; else - let Dict.681 : U64 = 1i64; - let Dict.680 : U64 = CallByName Num.51 Dict.167 Dict.681; - let Dict.610 : {List {Str, I64}, List U64, List I8, U64} = Struct {Dict.166, Dict.165, Dict.164, Dict.680}; - let Dict.177 : {List {Str, I64}, List U64, List I8, U64} = CallByName Dict.36 Dict.610; - let Dict.575 : {List {Str, I64}, List U64, List I8, U64} = CallByName Dict.33 Dict.177 Dict.168 Dict.169 Dict.171 Dict.172; - ret Dict.575; + dec Dict.377; + let Dict.835 : Str = "Dict hit limit of "; + let Dict.839 : U64 = CallByName Dict.47; + let Dict.837 : Str = CallByName Num.96 Dict.839; + let Dict.838 : Str = " elements. Unable to grow more."; + let Dict.836 : Str = CallByName Str.3 Dict.837 Dict.838; + dec Dict.838; + let Dict.834 : Str = CallByName Str.3 Dict.835 Dict.836; + dec Dict.836; + Crash Dict.834 -procedure Dict.94 (Dict.95, Dict.93): - let Dict.978 : {} = Struct {}; - let Dict.979 : {} = Struct {}; - let Dict.980 : {} = Struct {}; - let Dict.977 : {{List {Str, I64}, List U64, List I8, U64}, {}, {}, {}} = CallByName Inspect.39 Dict.93 Dict.978 Dict.979 Dict.980; - let Dict.976 : Str = CallByName Inspect.31 Dict.977 Dict.95; - ret Dict.976; +procedure Dict.60 (Dict.385, Dict.386): + let Dict.387 : U64 = CallByName Dict.63 Dict.385; + let Dict.880 : U64 = CallByName Dict.47; + let Dict.874 : Int1 = CallByName Bool.11 Dict.387 Dict.880; + if Dict.874 then + let Dict.877 : {U32, U32} = CallByName Dict.41; + let Dict.879 : U64 = CallByName Dict.47; + let Dict.878 : U64 = CallByName Num.137 Dict.879; + let Dict.876 : List {U32, U32} = CallByName List.11 Dict.877 Dict.878; + let Dict.47 : U64 = CallByName Dict.47; + let Dict.875 : {List {U32, U32}, U64} = Struct {Dict.876, Dict.47}; + ret Dict.875; + else + let Dict.873 : Float32 = CallByName Num.139 Dict.387; + let Dict.872 : Float32 = CallByName Num.21 Dict.873 Dict.386; + let Dict.388 : U64 = CallByName Num.50 Dict.872; + let Dict.867 : {U32, U32} = CallByName Dict.41; + let Dict.868 : U64 = CallByName Num.137 Dict.387; + let Dict.866 : List {U32, U32} = CallByName List.11 Dict.867 Dict.868; + let Dict.865 : {List {U32, U32}, U64} = Struct {Dict.866, Dict.388}; + ret Dict.865; + +procedure Dict.63 (Dict.395): + let Dict.884 : U64 = 1i64; + let Dict.886 : U8 = 64i64; + let Dict.885 : U8 = CallByName Num.20 Dict.886 Dict.395; + let Dict.882 : U64 = CallByName Num.72 Dict.884 Dict.885; + let Dict.883 : U64 = CallByName Dict.47; + let Dict.881 : U64 = CallByName Num.159 Dict.882 Dict.883; + ret Dict.881; + +procedure Dict.64 (Dict.396, Dict.397, Dict.398): + let Dict.846 : List {U32, U32} = CallByName List.83 Dict.397 Dict.396 Dict.398; + ret Dict.846; + +procedure Dict.65 (Dict.405, Dict.406, Dict.407): + let Dict.408 : U64 = CallByName Dict.69 Dict.406; + let Dict.409 : U32 = CallByName Dict.70 Dict.408; + let Dict.410 : U64 = CallByName Dict.71 Dict.408 Dict.407; + let Dict.854 : {U64, U32} = CallByName Dict.66 Dict.405 Dict.410 Dict.409; + ret Dict.854; + +procedure Dict.66 (#Derived_gen.32, #Derived_gen.33, #Derived_gen.34): + joinpoint Dict.855 Dict.411 Dict.412 Dict.413: + let Dict.863 : U64 = CallByName Num.137 Dict.412; + let Dict.414 : {U32, U32} = CallByName Dict.22 Dict.411 Dict.863; + let Dict.862 : U32 = StructAtIndex 1 Dict.414; + let Dict.857 : Int1 = CallByName Num.22 Dict.413 Dict.862; + if Dict.857 then + let Dict.861 : U64 = CallByName List.6 Dict.411; + let Dict.859 : U64 = CallByName Dict.68 Dict.412 Dict.861; + let Dict.860 : U32 = CallByName Dict.48 Dict.413; + jump Dict.855 Dict.411 Dict.859 Dict.860; + else + dec Dict.411; + let Dict.856 : {U64, U32} = Struct {Dict.412, Dict.413}; + ret Dict.856; + in + jump Dict.855 #Derived_gen.32 #Derived_gen.33 #Derived_gen.34; + +procedure Dict.67 (#Derived_gen.43, #Derived_gen.44, #Derived_gen.45): + joinpoint Dict.756 Dict.415 Dict.416 Dict.417: + let Dict.770 : U64 = CallByName Num.137 Dict.417; + let Dict.418 : {U32, U32} = CallByName Dict.22 Dict.415 Dict.770; + let Dict.768 : U32 = StructAtIndex 1 Dict.418; + let Dict.769 : U32 = 0i64; + let Dict.759 : Int1 = CallByName Bool.7 Dict.768 Dict.769; + if Dict.759 then + let Dict.767 : U64 = CallByName Num.137 Dict.417; + let Dict.419 : List {U32, U32} = CallByName List.3 Dict.415 Dict.767 Dict.416; + let Dict.764 : U32 = StructAtIndex 0 Dict.418; + let Dict.765 : U32 = StructAtIndex 1 Dict.418; + let Dict.766 : U32 = CallByName Dict.48 Dict.765; + let Dict.761 : {U32, U32} = Struct {Dict.764, Dict.766}; + let Dict.763 : U64 = CallByName List.6 Dict.419; + let Dict.762 : U64 = CallByName Dict.68 Dict.417 Dict.763; + jump Dict.756 Dict.419 Dict.761 Dict.762; + else + let Dict.758 : U64 = CallByName Num.137 Dict.417; + let Dict.757 : List {U32, U32} = CallByName List.3 Dict.415 Dict.758 Dict.416; + ret Dict.757; + in + jump Dict.756 #Derived_gen.43 #Derived_gen.44 #Derived_gen.45; + +procedure Dict.68 (Dict.420, Dict.421): + let Dict.752 : U64 = 1i64; + let Dict.751 : U64 = CallByName Num.51 Dict.420 Dict.752; + let Dict.748 : Int1 = CallByName Bool.7 Dict.751 Dict.421; + if Dict.748 then + let Dict.750 : U64 = 1i64; + let Dict.749 : U64 = CallByName Num.51 Dict.420 Dict.750; + ret Dict.749; + else + let Dict.747 : U64 = 0i64; + ret Dict.747; + +procedure Dict.69 (Dict.422): + let Dict.805 : [C , C U64] = TagId(0) ; + let Dict.804 : {U64, U64} = CallByName Dict.73 Dict.805; + let Dict.802 : {U64, U64} = CallByName Hash.19 Dict.804 Dict.422; + let Dict.801 : U64 = CallByName Dict.76 Dict.802; + ret Dict.801; + +procedure Dict.70 (Dict.424): + let Dict.796 : U32 = CallByName Num.131 Dict.424; + let Dict.797 : U32 = CallByName Dict.43; + let Dict.794 : U32 = CallByName Num.69 Dict.796 Dict.797; + let Dict.795 : U32 = CallByName Dict.42; + let Dict.793 : U32 = CallByName Num.71 Dict.794 Dict.795; + ret Dict.793; + +procedure Dict.71 (Dict.425, Dict.426): + let Dict.792 : U64 = CallByName Num.74 Dict.425 Dict.426; + let Dict.791 : U64 = CallByName Num.137 Dict.792; + ret Dict.791; + +procedure Dict.73 (Dict.428): + joinpoint Dict.822 Dict.429: + let Dict.807 : U64 = CallByName Dict.75 Dict.429; + let Dict.806 : {U64, U64} = Struct {Dict.807, Dict.429}; + ret Dict.806; + in + let Dict.827 : U8 = 0i64; + let Dict.828 : U8 = GetTagId Dict.428; + let Dict.829 : Int1 = lowlevel Eq Dict.827 Dict.828; + if Dict.829 then + let Dict.824 : {} = Struct {}; + let Dict.823 : U64 = CallByName Dict.23 Dict.824; + jump Dict.822 Dict.823; + else + let Dict.430 : U64 = UnionAtIndex (Id 1) (Index 0) Dict.428; + jump Dict.822 Dict.430; + +procedure Dict.74 (Dict.711, Dict.712): + let Dict.433 : U64 = StructAtIndex 0 Dict.712; + let Dict.434 : U64 = StructAtIndex 1 Dict.712; + let Dict.436 : U64 = StructAtIndex 2 Dict.712; + let Dict.435 : U64 = StructAtIndex 3 Dict.712; + let Dict.431 : U64 = StructAtIndex 0 Dict.711; + let Dict.432 : U64 = StructAtIndex 1 Dict.711; + let Dict.924 : U64 = CallByName Dict.86; + let Dict.922 : U64 = CallByName Num.70 Dict.433 Dict.924; + let Dict.923 : U64 = CallByName Num.70 Dict.434 Dict.435; + let Dict.437 : {U64, U64} = CallByName Dict.90 Dict.922 Dict.923; + let Dict.919 : U64 = StructAtIndex 0 Dict.437; + let Dict.920 : U64 = CallByName Dict.85; + let Dict.918 : U64 = CallByName Num.70 Dict.919 Dict.920; + let Dict.438 : U64 = CallByName Num.70 Dict.918 Dict.436; + let Dict.915 : U64 = StructAtIndex 1 Dict.437; + let Dict.916 : U64 = CallByName Dict.86; + let Dict.439 : U64 = CallByName Num.70 Dict.915 Dict.916; + let Dict.440 : U64 = CallByName Dict.89 Dict.438 Dict.439; + let Dict.907 : U64 = CallByName Dict.89 Dict.432 Dict.440; + let Dict.906 : {U64, U64} = Struct {Dict.431, Dict.907}; + ret Dict.906; + +procedure Dict.75 (Dict.441): + let Dict.820 : U64 = CallByName Dict.85; + let Dict.810 : U64 = CallByName Num.70 Dict.441 Dict.820; + let Dict.811 : U64 = CallByName Dict.86; + let Dict.809 : U64 = CallByName Dict.89 Dict.810 Dict.811; + let Dict.808 : U64 = CallByName Num.70 Dict.809 Dict.441; + ret Dict.808; + +procedure Dict.76 (Dict.730): + let Dict.442 : U64 = StructAtIndex 1 Dict.730; + ret Dict.442; + +procedure Dict.8 (Dict.211, Dict.212, Dict.213): + joinpoint Dict.832 Dict.830: + let Dict.214 : List {U32, U32} = StructAtIndex 0 Dict.830; + let Dict.215 : List {Str, I64} = StructAtIndex 1 Dict.830; + let Dict.216 : U64 = StructAtIndex 2 Dict.830; + let Dict.217 : Float32 = StructAtIndex 3 Dict.830; + let Dict.218 : U8 = StructAtIndex 4 Dict.830; + inc Dict.212; + let Dict.219 : U64 = CallByName Dict.69 Dict.212; + let Dict.220 : U32 = CallByName Dict.70 Dict.219; + let Dict.221 : U64 = CallByName Dict.71 Dict.219 Dict.218; + let Dict.738 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = CallByName Dict.38 Dict.214 Dict.215 Dict.221 Dict.220 Dict.212 Dict.213 Dict.216 Dict.217 Dict.218; + ret Dict.738; + in + inc 2 Dict.211; + let Dict.890 : U64 = CallByName Dict.4 Dict.211; + let Dict.891 : U64 = CallByName Dict.20 Dict.211; + let Dict.889 : Int1 = CallByName Num.22 Dict.890 Dict.891; + if Dict.889 then + jump Dict.832 Dict.211; + else + let Dict.831 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = CallByName Dict.59 Dict.211; + jump Dict.832 Dict.831; + +procedure Dict.82 (Dict.705, Dict.481): + let Dict.479 : U64 = StructAtIndex 0 Dict.705; + let Dict.480 : U64 = StructAtIndex 1 Dict.705; + let Dict.482 : U64 = CallByName List.6 Dict.481; + joinpoint Dict.930 Dict.483: + let Dict.904 : {U64, U64} = Struct {Dict.479, Dict.480}; + let Dict.925 : U64 = StructAtIndex 0 Dict.483; + let Dict.926 : U64 = StructAtIndex 1 Dict.483; + let Dict.927 : U64 = CallByName Num.133 Dict.482; + let Dict.928 : U64 = StructAtIndex 2 Dict.483; + let Dict.905 : {U64, U64, U64, U64} = Struct {Dict.925, Dict.926, Dict.927, Dict.928}; + let Dict.903 : {U64, U64} = CallByName Dict.74 Dict.904 Dict.905; + ret Dict.903; + in + let Dict.1104 : U64 = 16i64; + let Dict.1044 : Int1 = CallByName Num.23 Dict.482 Dict.1104; + if Dict.1044 then + joinpoint Dict.1046 Dict.929: + jump Dict.930 Dict.929; + in + let Dict.1103 : U64 = 4i64; + let Dict.1068 : Int1 = CallByName Num.25 Dict.482 Dict.1103; + if Dict.1068 then + let Dict.1102 : U8 = 3i64; + let Dict.1100 : U64 = CallByName Num.74 Dict.482 Dict.1102; + let Dict.1101 : U8 = 2i64; + let Dict.484 : U64 = CallByName Num.72 Dict.1100 Dict.1101; + let Dict.1099 : U64 = 0i64; + inc 3 Dict.481; + let Dict.1097 : U64 = CallByName Dict.92 Dict.481 Dict.1099; + let Dict.1098 : U8 = 32i64; + let Dict.1095 : U64 = CallByName Num.72 Dict.1097 Dict.1098; + let Dict.1096 : U64 = CallByName Dict.92 Dict.481 Dict.484; + let Dict.485 : U64 = CallByName Num.71 Dict.1095 Dict.1096; + let Dict.1094 : U64 = 4i64; + let Dict.1093 : U64 = CallByName Num.75 Dict.482 Dict.1094; + let Dict.1091 : U64 = CallByName Dict.92 Dict.481 Dict.1093; + let Dict.1092 : U8 = 32i64; + let Dict.1069 : U64 = CallByName Num.72 Dict.1091 Dict.1092; + let Dict.1090 : U64 = 4i64; + let Dict.1089 : U64 = CallByName Num.75 Dict.482 Dict.1090; + let Dict.1071 : U64 = CallByName Num.75 Dict.1089 Dict.484; + let Dict.1070 : U64 = CallByName Dict.92 Dict.481 Dict.1071; + let Dict.486 : U64 = CallByName Num.71 Dict.1069 Dict.1070; + let Dict.1045 : {U64, U64, U64} = Struct {Dict.485, Dict.486, Dict.479}; + jump Dict.1046 Dict.1045; + else + let Dict.1067 : U64 = 0i64; + let Dict.1049 : Int1 = CallByName Num.24 Dict.482 Dict.1067; + if Dict.1049 then + let Dict.1052 : U64 = 0i64; + let Dict.1050 : U64 = CallByName Dict.93 Dict.481 Dict.1052 Dict.482; + let Dict.1051 : U64 = 0i64; + let Dict.1045 : {U64, U64, U64} = Struct {Dict.1050, Dict.1051, Dict.479}; + jump Dict.1046 Dict.1045; + else + dec Dict.481; + let Dict.1047 : U64 = 0i64; + let Dict.1048 : U64 = 0i64; + let Dict.1045 : {U64, U64, U64} = Struct {Dict.1047, Dict.1048, Dict.479}; + jump Dict.1046 Dict.1045; + else + let Dict.1043 : U64 = 48i64; + let Dict.1041 : Int1 = CallByName Num.23 Dict.482 Dict.1043; + if Dict.1041 then + let Dict.1042 : U64 = 0i64; + let Dict.929 : {U64, U64, U64} = CallByName Dict.84 Dict.479 Dict.481 Dict.1042 Dict.482; + jump Dict.930 Dict.929; + else + let Dict.931 : U64 = 0i64; + let Dict.929 : {U64, U64, U64} = CallByName Dict.83 Dict.479 Dict.479 Dict.479 Dict.481 Dict.931 Dict.482; + jump Dict.930 Dict.929; + +procedure Dict.83 (#Derived_gen.26, #Derived_gen.27, #Derived_gen.28, #Derived_gen.29, #Derived_gen.30, #Derived_gen.31): + joinpoint Dict.932 Dict.487 Dict.488 Dict.489 Dict.490 Dict.491 Dict.492: + inc 6 Dict.490; + let Dict.1039 : U64 = CallByName Dict.91 Dict.490 Dict.491; + let Dict.1040 : U64 = CallByName Dict.86; + let Dict.1034 : U64 = CallByName Num.70 Dict.1039 Dict.1040; + let Dict.1038 : U64 = 8i64; + let Dict.1037 : U64 = CallByName Num.51 Dict.491 Dict.1038; + let Dict.1036 : U64 = CallByName Dict.91 Dict.490 Dict.1037; + let Dict.1035 : U64 = CallByName Num.70 Dict.1036 Dict.487; + let Dict.493 : U64 = CallByName Dict.89 Dict.1034 Dict.1035; + let Dict.1033 : U64 = 16i64; + let Dict.1032 : U64 = CallByName Num.51 Dict.491 Dict.1033; + let Dict.1029 : U64 = CallByName Dict.91 Dict.490 Dict.1032; + let Dict.1030 : U64 = CallByName Dict.87; + let Dict.1024 : U64 = CallByName Num.70 Dict.1029 Dict.1030; + let Dict.1028 : U64 = 24i64; + let Dict.1027 : U64 = CallByName Num.51 Dict.491 Dict.1028; + let Dict.1026 : U64 = CallByName Dict.91 Dict.490 Dict.1027; + let Dict.1025 : U64 = CallByName Num.70 Dict.1026 Dict.488; + let Dict.494 : U64 = CallByName Dict.89 Dict.1024 Dict.1025; + let Dict.1023 : U64 = 32i64; + let Dict.1022 : U64 = CallByName Num.51 Dict.491 Dict.1023; + let Dict.1019 : U64 = CallByName Dict.91 Dict.490 Dict.1022; + let Dict.1020 : U64 = CallByName Dict.88; + let Dict.1014 : U64 = CallByName Num.70 Dict.1019 Dict.1020; + let Dict.1018 : U64 = 40i64; + let Dict.1017 : U64 = CallByName Num.51 Dict.491 Dict.1018; + let Dict.1016 : U64 = CallByName Dict.91 Dict.490 Dict.1017; + let Dict.1015 : U64 = CallByName Num.70 Dict.1016 Dict.489; + let Dict.495 : U64 = CallByName Dict.89 Dict.1014 Dict.1015; + let Dict.1013 : U64 = 48i64; + let Dict.496 : U64 = CallByName Num.75 Dict.492 Dict.1013; + let Dict.1012 : U64 = 48i64; + let Dict.497 : U64 = CallByName Num.51 Dict.491 Dict.1012; + let Dict.1011 : U64 = 48i64; + let Dict.1009 : Int1 = CallByName Num.24 Dict.496 Dict.1011; + if Dict.1009 then + jump Dict.932 Dict.493 Dict.494 Dict.495 Dict.490 Dict.497 Dict.496; + else + let Dict.1008 : U64 = 16i64; + let Dict.983 : Int1 = CallByName Num.24 Dict.496 Dict.1008; + if Dict.983 then + let Dict.1007 : U64 = CallByName Num.70 Dict.494 Dict.493; + let Dict.498 : U64 = CallByName Num.70 Dict.495 Dict.1007; + let Dict.984 : {U64, U64, U64} = CallByName Dict.84 Dict.498 Dict.490 Dict.497 Dict.496; + ret Dict.984; + else + inc Dict.490; + let Dict.982 : U64 = CallByName Num.70 Dict.494 Dict.493; + let Dict.499 : U64 = CallByName Num.70 Dict.495 Dict.982; + let Dict.981 : U64 = 16i64; + let Dict.980 : U64 = CallByName Num.75 Dict.496 Dict.981; + let Dict.979 : U64 = CallByName Num.51 Dict.980 Dict.497; + let Dict.934 : U64 = CallByName Dict.91 Dict.490 Dict.979; + let Dict.978 : U64 = 8i64; + let Dict.977 : U64 = CallByName Num.75 Dict.496 Dict.978; + let Dict.936 : U64 = CallByName Num.51 Dict.977 Dict.497; + let Dict.935 : U64 = CallByName Dict.91 Dict.490 Dict.936; + let Dict.933 : {U64, U64, U64} = Struct {Dict.934, Dict.935, Dict.499}; + ret Dict.933; + in + jump Dict.932 #Derived_gen.26 #Derived_gen.27 #Derived_gen.28 #Derived_gen.29 #Derived_gen.30 #Derived_gen.31; + +procedure Dict.84 (#Derived_gen.59, #Derived_gen.60, #Derived_gen.61, #Derived_gen.62): + joinpoint Dict.985 Dict.500 Dict.501 Dict.502 Dict.503: + inc 2 Dict.501; + let Dict.1005 : U64 = CallByName Dict.91 Dict.501 Dict.502; + let Dict.1006 : U64 = CallByName Dict.86; + let Dict.1000 : U64 = CallByName Num.70 Dict.1005 Dict.1006; + let Dict.1004 : U64 = 8i64; + let Dict.1003 : U64 = CallByName Num.51 Dict.502 Dict.1004; + let Dict.1002 : U64 = CallByName Dict.91 Dict.501 Dict.1003; + let Dict.1001 : U64 = CallByName Num.70 Dict.1002 Dict.500; + let Dict.504 : U64 = CallByName Dict.89 Dict.1000 Dict.1001; + let Dict.999 : U64 = 16i64; + let Dict.505 : U64 = CallByName Num.75 Dict.503 Dict.999; + let Dict.998 : U64 = 16i64; + let Dict.506 : U64 = CallByName Num.51 Dict.502 Dict.998; + let Dict.997 : U64 = 16i64; + let Dict.987 : Int1 = CallByName Num.23 Dict.505 Dict.997; + if Dict.987 then + inc Dict.501; + let Dict.996 : U64 = 16i64; + let Dict.995 : U64 = CallByName Num.75 Dict.505 Dict.996; + let Dict.994 : U64 = CallByName Num.51 Dict.995 Dict.506; + let Dict.989 : U64 = CallByName Dict.91 Dict.501 Dict.994; + let Dict.993 : U64 = 8i64; + let Dict.992 : U64 = CallByName Num.75 Dict.505 Dict.993; + let Dict.991 : U64 = CallByName Num.51 Dict.992 Dict.506; + let Dict.990 : U64 = CallByName Dict.91 Dict.501 Dict.991; + let Dict.988 : {U64, U64, U64} = Struct {Dict.989, Dict.990, Dict.504}; + ret Dict.988; + else + jump Dict.985 Dict.504 Dict.501 Dict.506 Dict.505; + in + jump Dict.985 #Derived_gen.59 #Derived_gen.60 #Derived_gen.61 #Derived_gen.62; + +procedure Dict.85 (): + let Dict.921 : U64 = 11562461410679940143i64; + ret Dict.921; + +procedure Dict.86 (): + let Dict.917 : U64 = 16646288086500911323i64; + ret Dict.917; + +procedure Dict.87 (): + let Dict.1031 : U64 = 10285213230658275043i64; + ret Dict.1031; + +procedure Dict.88 (): + let Dict.1021 : U64 = 6384245875588680899i64; + ret Dict.1021; + +procedure Dict.89 (Dict.507, Dict.508): + let Dict.909 : {U64, U64} = CallByName Dict.90 Dict.507 Dict.508; + let Dict.509 : U64 = StructAtIndex 0 Dict.909; + let Dict.510 : U64 = StructAtIndex 1 Dict.909; + let Dict.908 : U64 = CallByName Num.70 Dict.509 Dict.510; + ret Dict.908; + +procedure Dict.90 (Dict.511, Dict.512): + let Dict.913 : U128 = CallByName Num.135 Dict.511; + let Dict.914 : U128 = CallByName Num.135 Dict.512; + let Dict.513 : U128 = CallByName Num.21 Dict.913 Dict.914; + let Dict.514 : U64 = CallByName Num.133 Dict.513; + let Dict.912 : U8 = 64i64; + let Dict.911 : U128 = CallByName Num.74 Dict.513 Dict.912; + let Dict.515 : U64 = CallByName Num.133 Dict.911; + let Dict.910 : {U64, U64} = Struct {Dict.514, Dict.515}; + ret Dict.910; + +procedure Dict.91 (Dict.516, Dict.517): + let Dict.976 : U8 = CallByName Dict.22 Dict.516 Dict.517; + let Dict.518 : U64 = CallByName Num.133 Dict.976; + let Dict.975 : U64 = 1i64; + let Dict.974 : U64 = CallByName Num.51 Dict.517 Dict.975; + let Dict.973 : U8 = CallByName Dict.22 Dict.516 Dict.974; + let Dict.519 : U64 = CallByName Num.133 Dict.973; + let Dict.972 : U64 = 2i64; + let Dict.971 : U64 = CallByName Num.51 Dict.517 Dict.972; + let Dict.970 : U8 = CallByName Dict.22 Dict.516 Dict.971; + let Dict.520 : U64 = CallByName Num.133 Dict.970; + let Dict.969 : U64 = 3i64; + let Dict.968 : U64 = CallByName Num.51 Dict.517 Dict.969; + let Dict.967 : U8 = CallByName Dict.22 Dict.516 Dict.968; + let Dict.521 : U64 = CallByName Num.133 Dict.967; + let Dict.966 : U64 = 4i64; + let Dict.965 : U64 = CallByName Num.51 Dict.517 Dict.966; + let Dict.964 : U8 = CallByName Dict.22 Dict.516 Dict.965; + let Dict.522 : U64 = CallByName Num.133 Dict.964; + let Dict.963 : U64 = 5i64; + let Dict.962 : U64 = CallByName Num.51 Dict.517 Dict.963; + let Dict.961 : U8 = CallByName Dict.22 Dict.516 Dict.962; + let Dict.523 : U64 = CallByName Num.133 Dict.961; + let Dict.960 : U64 = 6i64; + let Dict.959 : U64 = CallByName Num.51 Dict.517 Dict.960; + let Dict.958 : U8 = CallByName Dict.22 Dict.516 Dict.959; + let Dict.524 : U64 = CallByName Num.133 Dict.958; + let Dict.957 : U64 = 7i64; + let Dict.955 : U64 = CallByName Num.51 Dict.517 Dict.957; + let Dict.954 : U8 = CallByName Dict.22 Dict.516 Dict.955; + dec Dict.516; + let Dict.525 : U64 = CallByName Num.133 Dict.954; + let Dict.953 : U8 = 8i64; + let Dict.952 : U64 = CallByName Num.72 Dict.519 Dict.953; + let Dict.526 : U64 = CallByName Num.71 Dict.518 Dict.952; + let Dict.951 : U8 = 16i64; + let Dict.948 : U64 = CallByName Num.72 Dict.520 Dict.951; + let Dict.950 : U8 = 24i64; + let Dict.949 : U64 = CallByName Num.72 Dict.521 Dict.950; + let Dict.527 : U64 = CallByName Num.71 Dict.948 Dict.949; + let Dict.947 : U8 = 32i64; + let Dict.944 : U64 = CallByName Num.72 Dict.522 Dict.947; + let Dict.946 : U8 = 40i64; + let Dict.945 : U64 = CallByName Num.72 Dict.523 Dict.946; + let Dict.528 : U64 = CallByName Num.71 Dict.944 Dict.945; + let Dict.943 : U8 = 48i64; + let Dict.940 : U64 = CallByName Num.72 Dict.524 Dict.943; + let Dict.942 : U8 = 56i64; + let Dict.941 : U64 = CallByName Num.72 Dict.525 Dict.942; + let Dict.529 : U64 = CallByName Num.71 Dict.940 Dict.941; + let Dict.938 : U64 = CallByName Num.71 Dict.526 Dict.527; + let Dict.939 : U64 = CallByName Num.71 Dict.528 Dict.529; + let Dict.937 : U64 = CallByName Num.71 Dict.938 Dict.939; + ret Dict.937; + +procedure Dict.92 (Dict.530, Dict.531): + let Dict.1088 : U8 = CallByName Dict.22 Dict.530 Dict.531; + let Dict.532 : U64 = CallByName Num.133 Dict.1088; + let Dict.1087 : U64 = 1i64; + let Dict.1086 : U64 = CallByName Num.51 Dict.531 Dict.1087; + let Dict.1085 : U8 = CallByName Dict.22 Dict.530 Dict.1086; + let Dict.533 : U64 = CallByName Num.133 Dict.1085; + let Dict.1084 : U64 = 2i64; + let Dict.1083 : U64 = CallByName Num.51 Dict.531 Dict.1084; + let Dict.1082 : U8 = CallByName Dict.22 Dict.530 Dict.1083; + let Dict.534 : U64 = CallByName Num.133 Dict.1082; + let Dict.1081 : U64 = 3i64; + let Dict.1080 : U64 = CallByName Num.51 Dict.531 Dict.1081; + let Dict.1079 : U8 = CallByName Dict.22 Dict.530 Dict.1080; + dec Dict.530; + let Dict.535 : U64 = CallByName Num.133 Dict.1079; + let Dict.1078 : U8 = 8i64; + let Dict.1077 : U64 = CallByName Num.72 Dict.533 Dict.1078; + let Dict.536 : U64 = CallByName Num.71 Dict.532 Dict.1077; + let Dict.1076 : U8 = 16i64; + let Dict.1073 : U64 = CallByName Num.72 Dict.534 Dict.1076; + let Dict.1075 : U8 = 24i64; + let Dict.1074 : U64 = CallByName Num.72 Dict.535 Dict.1075; + let Dict.537 : U64 = CallByName Num.71 Dict.1073 Dict.1074; + let Dict.1072 : U64 = CallByName Num.71 Dict.536 Dict.537; + ret Dict.1072; + +procedure Dict.93 (Dict.538, Dict.539, Dict.540): + let Dict.1066 : U8 = CallByName Dict.22 Dict.538 Dict.539; + let Dict.541 : U64 = CallByName Num.133 Dict.1066; + let Dict.1065 : U8 = 1i64; + let Dict.1064 : U64 = CallByName Num.74 Dict.540 Dict.1065; + let Dict.1063 : U64 = CallByName Num.51 Dict.1064 Dict.539; + let Dict.1062 : U8 = CallByName Dict.22 Dict.538 Dict.1063; + let Dict.542 : U64 = CallByName Num.133 Dict.1062; + let Dict.1061 : U64 = 1i64; + let Dict.1060 : U64 = CallByName Num.75 Dict.540 Dict.1061; + let Dict.1059 : U64 = CallByName Num.51 Dict.1060 Dict.539; + let Dict.1058 : U8 = CallByName Dict.22 Dict.538 Dict.1059; + dec Dict.538; + let Dict.543 : U64 = CallByName Num.133 Dict.1058; + let Dict.1057 : U8 = 16i64; + let Dict.1054 : U64 = CallByName Num.72 Dict.541 Dict.1057; + let Dict.1056 : U8 = 8i64; + let Dict.1055 : U64 = CallByName Num.72 Dict.542 Dict.1056; + let Dict.544 : U64 = CallByName Num.71 Dict.1054 Dict.1055; + let Dict.1053 : U64 = CallByName Num.71 Dict.544 Dict.543; + ret Dict.1053; procedure Hash.19 (Hash.39, Hash.40): - let Hash.79 : List U8 = CallByName Str.12 Hash.40; - let Hash.78 : {U64, U64} = CallByName Dict.57 Hash.39 Hash.79; - ret Hash.78; - -procedure Inspect.186 (Inspect.187, #Attr.12): - let Inspect.185 : {} = StructAtIndex 3 #Attr.12; - let Inspect.184 : {} = StructAtIndex 2 #Attr.12; - let Inspect.183 : {} = StructAtIndex 1 #Attr.12; - let Inspect.182 : {List {Str, I64}, List U64, List I8, U64} = StructAtIndex 0 #Attr.12; - let Inspect.355 : Str = "{"; - let Inspect.328 : Str = CallByName Inspect.61 Inspect.187 Inspect.355; - let Inspect.329 : {{List {Str, I64}, List U64, List I8, U64}, {}, {}, {}} = Struct {Inspect.182, Inspect.183, Inspect.184, Inspect.185}; - let Inspect.324 : {Str, Int1} = CallByName Inspect.188 Inspect.328 Inspect.329; - let Inspect.325 : {} = Struct {}; - let Inspect.320 : Str = CallByName Inspect.200 Inspect.324; - let Inspect.321 : Str = "}"; - let Inspect.319 : Str = CallByName Inspect.61 Inspect.320 Inspect.321; - ret Inspect.319; + let Hash.77 : List U8 = CallByName Str.12 Hash.40; + let Hash.76 : {U64, U64} = CallByName Dict.82 Hash.39 Hash.77; + ret Hash.76; procedure Inspect.188 (Inspect.189, #Attr.12): - let Inspect.185 : {} = StructAtIndex 3 #Attr.12; - let Inspect.184 : {} = StructAtIndex 2 #Attr.12; - let Inspect.183 : {} = StructAtIndex 1 #Attr.12; - let Inspect.182 : {List {Str, I64}, List U64, List I8, U64} = StructAtIndex 0 #Attr.12; - let Inspect.354 : Int1 = CallByName Bool.1; - let Inspect.332 : {Str, Int1} = Struct {Inspect.189, Inspect.354}; - let Inspect.333 : {{}, {}} = Struct {Inspect.184, Inspect.185}; - let Inspect.331 : {Str, Int1} = CallByName Dict.10 Inspect.182 Inspect.332 Inspect.333; - ret Inspect.331; - -procedure Inspect.190 (Inspect.334, Inspect.193, Inspect.194, #Attr.12): + let Inspect.187 : {} = StructAtIndex 3 #Attr.12; + let Inspect.186 : {} = StructAtIndex 2 #Attr.12; let Inspect.185 : {} = StructAtIndex 1 #Attr.12; - let Inspect.184 : {} = StructAtIndex 0 #Attr.12; - let Inspect.191 : Str = StructAtIndex 0 Inspect.334; - let Inspect.192 : Int1 = StructAtIndex 1 Inspect.334; - joinpoint Inspect.352 Inspect.195: - let Inspect.349 : Str = CallByName Inspect.44 Inspect.193; - let Inspect.347 : Str = CallByName Inspect.31 Inspect.349 Inspect.195; - let Inspect.348 : Str = ": "; - let Inspect.341 : Str = CallByName Inspect.61 Inspect.347 Inspect.348; - let Inspect.342 : {I64, {}} = Struct {Inspect.194, Inspect.185}; - let Inspect.337 : Str = CallByName Inspect.196 Inspect.341 Inspect.342; - let Inspect.338 : {} = Struct {}; - let Inspect.336 : {Str, Int1} = CallByName Inspect.198 Inspect.337; - ret Inspect.336; - in - if Inspect.192 then - let Inspect.353 : Str = ", "; - let Inspect.351 : Str = CallByName Inspect.61 Inspect.191 Inspect.353; - jump Inspect.352 Inspect.351; - else - jump Inspect.352 Inspect.191; - -procedure Inspect.196 (Inspect.197, #Attr.12): - let Inspect.185 : {} = StructAtIndex 1 #Attr.12; - let Inspect.194 : I64 = StructAtIndex 0 #Attr.12; - let Inspect.345 : I64 = CallByName Inspect.54 Inspect.194; - let Inspect.344 : Str = CallByName Inspect.31 Inspect.345 Inspect.197; - ret Inspect.344; - -procedure Inspect.198 (Inspect.199): - let Inspect.340 : Int1 = CallByName Bool.2; - let Inspect.339 : {Str, Int1} = Struct {Inspect.199, Inspect.340}; - ret Inspect.339; - -procedure Inspect.200 (Inspect.326): - let Inspect.327 : Str = StructAtIndex 0 Inspect.326; - ret Inspect.327; - -procedure Inspect.249 (Inspect.250, Inspect.248): - let Inspect.370 : Str = "\""; - let Inspect.369 : Str = CallByName Inspect.61 Inspect.250 Inspect.370; - let Inspect.367 : Str = CallByName Inspect.61 Inspect.369 Inspect.248; - let Inspect.368 : Str = "\""; - let Inspect.366 : Str = CallByName Inspect.61 Inspect.367 Inspect.368; - ret Inspect.366; - -procedure Inspect.277 (Inspect.278, Inspect.276): - let Inspect.361 : Str = CallByName Num.96 Inspect.276; - let Inspect.360 : Str = CallByName Inspect.61 Inspect.278 Inspect.361; - ret Inspect.360; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.31 (Inspect.305, Inspect.149): - let Inspect.314 : Str = CallByName Inspect.186 Inspect.149 Inspect.305; - ret Inspect.314; - -procedure Inspect.31 (Inspect.305, Inspect.149): - let Inspect.346 : Str = CallByName Inspect.277 Inspect.149 Inspect.305; - ret Inspect.346; - -procedure Inspect.31 (Inspect.305, Inspect.149): - let Inspect.350 : Str = CallByName Inspect.249 Inspect.149 Inspect.305; - ret Inspect.350; - -procedure Inspect.35 (Inspect.300): - ret Inspect.300; - -procedure Inspect.36 (Inspect.304): - let Inspect.311 : Str = ""; - ret Inspect.311; - -procedure Inspect.39 (Inspect.182, Inspect.183, Inspect.184, Inspect.185): - let Inspect.316 : {{List {Str, I64}, List U64, List I8, U64}, {}, {}, {}} = Struct {Inspect.182, Inspect.183, Inspect.184, Inspect.185}; - let Inspect.315 : {{List {Str, I64}, List U64, List I8, U64}, {}, {}, {}} = CallByName Inspect.30 Inspect.316; - ret Inspect.315; - -procedure Inspect.44 (Inspect.248): - let Inspect.362 : Str = CallByName Inspect.30 Inspect.248; - ret Inspect.362; - -procedure Inspect.5 (Inspect.150): - let Inspect.312 : {List {Str, I64}, List U64, List I8, U64} = CallByName Dict.31 Inspect.150; - let Inspect.309 : {} = Struct {}; - let Inspect.308 : Str = CallByName Inspect.36 Inspect.309; - let Inspect.307 : Str = CallByName Dict.94 Inspect.308 Inspect.312; - ret Inspect.307; - -procedure Inspect.54 (Inspect.276): - let Inspect.356 : I64 = CallByName Inspect.30 Inspect.276; - ret Inspect.356; - -procedure Inspect.61 (Inspect.303, Inspect.298): - let Inspect.323 : Str = CallByName Str.3 Inspect.303 Inspect.298; - dec Inspect.298; + let Inspect.184 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = StructAtIndex 0 #Attr.12; + let Inspect.359 : Str = "{"; + let Inspect.332 : Str = CallByName Inspect.61 Inspect.189 Inspect.359; + let Inspect.333 : {{List {U32, U32}, List {Str, I64}, U64, Float32, U8}, {}, {}, {}} = Struct {Inspect.184, Inspect.185, Inspect.186, Inspect.187}; + let Inspect.328 : {Str, Int1} = CallByName Inspect.190 Inspect.332 Inspect.333; + let Inspect.329 : {} = Struct {}; + let Inspect.324 : Str = CallByName Inspect.202 Inspect.328; + let Inspect.325 : Str = "}"; + let Inspect.323 : Str = CallByName Inspect.61 Inspect.324 Inspect.325; ret Inspect.323; -procedure List.11 (List.133, List.134): - let List.635 : List I8 = CallByName List.68 List.134; - let List.634 : List I8 = CallByName List.86 List.133 List.134 List.635; - ret List.634; +procedure Inspect.190 (Inspect.191, #Attr.12): + let Inspect.187 : {} = StructAtIndex 3 #Attr.12; + let Inspect.186 : {} = StructAtIndex 2 #Attr.12; + let Inspect.185 : {} = StructAtIndex 1 #Attr.12; + let Inspect.184 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = StructAtIndex 0 #Attr.12; + let Inspect.358 : Int1 = CallByName Bool.1; + let Inspect.336 : {Str, Int1} = Struct {Inspect.191, Inspect.358}; + let Inspect.337 : {{}, {}} = Struct {Inspect.186, Inspect.187}; + let Inspect.335 : {Str, Int1} = CallByName Dict.10 Inspect.184 Inspect.336 Inspect.337; + ret Inspect.335; -procedure List.11 (List.133, List.134): - let List.637 : List U64 = CallByName List.68 List.134; - let List.636 : List U64 = CallByName List.86 List.133 List.134 List.637; - ret List.636; - -procedure List.18 (List.154, List.155, List.156): - let List.554 : U64 = 0i64; - let List.555 : U64 = CallByName List.6 List.154; - let List.553 : {List {Str, I64}, List U64, List I8, U64} = CallByName List.88 List.154 List.155 List.156 List.554 List.555; - ret List.553; - -procedure List.18 (List.154, List.155, List.156): - let List.641 : U64 = 0i64; - let List.642 : U64 = CallByName List.6 List.154; - let List.640 : {Str, Int1} = CallByName List.88 List.154 List.155 List.156 List.641 List.642; - ret List.640; - -procedure List.2 (List.103, List.104): - let List.609 : U64 = CallByName List.6 List.103; - let List.605 : Int1 = CallByName Num.22 List.104 List.609; - if List.605 then - let List.607 : I8 = CallByName List.66 List.103 List.104; - dec List.103; - let List.606 : [C {}, C I8] = TagId(1) List.607; - ret List.606; +procedure Inspect.192 (Inspect.338, Inspect.195, Inspect.196, #Attr.12): + let Inspect.187 : {} = StructAtIndex 1 #Attr.12; + let Inspect.186 : {} = StructAtIndex 0 #Attr.12; + let Inspect.193 : Str = StructAtIndex 0 Inspect.338; + let Inspect.194 : Int1 = StructAtIndex 1 Inspect.338; + joinpoint Inspect.356 Inspect.197: + let Inspect.353 : Str = CallByName Inspect.44 Inspect.195; + let Inspect.351 : Str = CallByName Inspect.31 Inspect.353 Inspect.197; + let Inspect.352 : Str = ": "; + let Inspect.345 : Str = CallByName Inspect.61 Inspect.351 Inspect.352; + let Inspect.346 : {I64, {}} = Struct {Inspect.196, Inspect.187}; + let Inspect.341 : Str = CallByName Inspect.198 Inspect.345 Inspect.346; + let Inspect.342 : {} = Struct {}; + let Inspect.340 : {Str, Int1} = CallByName Inspect.200 Inspect.341; + ret Inspect.340; + in + if Inspect.194 then + let Inspect.357 : Str = ", "; + let Inspect.355 : Str = CallByName Inspect.61 Inspect.193 Inspect.357; + jump Inspect.356 Inspect.355; else - dec List.103; - let List.604 : {} = Struct {}; - let List.603 : [C {}, C I8] = TagId(0) List.604; - ret List.603; + jump Inspect.356 Inspect.193; -procedure List.3 (List.111, List.112, List.113): - let List.566 : {List {Str, I64}, {Str, I64}} = CallByName List.64 List.111 List.112 List.113; - let List.565 : List {Str, I64} = StructAtIndex 0 List.566; - let #Derived_gen.62 : {Str, I64} = StructAtIndex 1 List.566; - dec #Derived_gen.62; - ret List.565; +procedure Inspect.198 (Inspect.199, #Attr.12): + let Inspect.187 : {} = StructAtIndex 1 #Attr.12; + let Inspect.196 : I64 = StructAtIndex 0 #Attr.12; + let Inspect.349 : I64 = CallByName Inspect.54 Inspect.196; + let Inspect.348 : Str = CallByName Inspect.31 Inspect.349 Inspect.199; + ret Inspect.348; -procedure List.3 (List.111, List.112, List.113): - let List.589 : {List I8, I8} = CallByName List.64 List.111 List.112 List.113; - let List.588 : List I8 = StructAtIndex 0 List.589; - ret List.588; +procedure Inspect.200 (Inspect.201): + let Inspect.344 : Int1 = CallByName Bool.2; + let Inspect.343 : {Str, Int1} = Struct {Inspect.201, Inspect.344}; + ret Inspect.343; -procedure List.3 (List.111, List.112, List.113): - let List.591 : {List U64, U64} = CallByName List.64 List.111 List.112 List.113; - let List.590 : List U64 = StructAtIndex 0 List.591; - ret List.590; +procedure Inspect.202 (Inspect.330): + let Inspect.331 : Str = StructAtIndex 0 Inspect.330; + ret Inspect.331; -procedure List.4 (List.119, List.120): - let List.595 : U64 = 1i64; - let List.593 : List {Str, I64} = CallByName List.70 List.119 List.595; - let List.592 : List {Str, I64} = CallByName List.71 List.593 List.120; - ret List.592; +procedure Inspect.251 (Inspect.252, Inspect.250): + let Inspect.374 : Str = "\""; + let Inspect.373 : Str = CallByName Inspect.61 Inspect.252 Inspect.374; + let Inspect.371 : Str = CallByName Inspect.61 Inspect.373 Inspect.250; + let Inspect.372 : Str = "\""; + let Inspect.370 : Str = CallByName Inspect.61 Inspect.371 Inspect.372; + ret Inspect.370; -procedure List.6 (#Attr.2): - let List.601 : U64 = lowlevel ListLen #Attr.2; - ret List.601; +procedure Inspect.279 (Inspect.280, Inspect.278): + let Inspect.365 : Str = CallByName Num.96 Inspect.278; + let Inspect.364 : Str = CallByName Inspect.61 Inspect.280 Inspect.365; + ret Inspect.364; -procedure List.6 (#Attr.2): - let List.602 : U64 = lowlevel ListLen #Attr.2; - ret List.602; +procedure Inspect.30 (Inspect.148): + ret Inspect.148; -procedure List.6 (#Attr.2): - let List.639 : U64 = lowlevel ListLen #Attr.2; - ret List.639; +procedure Inspect.30 (Inspect.148): + ret Inspect.148; -procedure List.6 (#Attr.2): - let List.651 : U64 = lowlevel ListLen #Attr.2; - ret List.651; +procedure Inspect.30 (Inspect.148): + ret Inspect.148; -procedure List.64 (List.108, List.109, List.110): - let List.571 : U64 = CallByName List.6 List.108; - let List.568 : Int1 = CallByName Num.22 List.109 List.571; - if List.568 then - let List.569 : {List {Str, I64}, {Str, I64}} = CallByName List.67 List.108 List.109 List.110; - ret List.569; - else - let List.567 : {List {Str, I64}, {Str, I64}} = Struct {List.108, List.110}; - ret List.567; +procedure Inspect.30 (Inspect.148): + ret Inspect.148; -procedure List.64 (List.108, List.109, List.110): - let List.578 : U64 = CallByName List.6 List.108; - let List.575 : Int1 = CallByName Num.22 List.109 List.578; - if List.575 then - let List.576 : {List I8, I8} = CallByName List.67 List.108 List.109 List.110; - ret List.576; - else - let List.574 : {List I8, I8} = Struct {List.108, List.110}; - ret List.574; +procedure Inspect.31 (Inspect.307, Inspect.150): + let Inspect.318 : Str = CallByName Inspect.188 Inspect.150 Inspect.307; + ret Inspect.318; -procedure List.64 (List.108, List.109, List.110): - let List.586 : U64 = CallByName List.6 List.108; - let List.583 : Int1 = CallByName Num.22 List.109 List.586; - if List.583 then - let List.584 : {List U64, U64} = CallByName List.67 List.108 List.109 List.110; - ret List.584; - else - let List.582 : {List U64, U64} = Struct {List.108, List.110}; - ret List.582; +procedure Inspect.31 (Inspect.307, Inspect.150): + let Inspect.350 : Str = CallByName Inspect.279 Inspect.150 Inspect.307; + ret Inspect.350; -procedure List.66 (#Attr.2, #Attr.3): - let List.608 : I8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.608; +procedure Inspect.31 (Inspect.307, Inspect.150): + let Inspect.354 : Str = CallByName Inspect.251 Inspect.150 Inspect.307; + ret Inspect.354; -procedure List.66 (#Attr.2, #Attr.3): - let List.650 : {Str, I64} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.650; +procedure Inspect.34 (Inspect.153): + let Inspect.309 : Str = CallByName Inspect.5 Inspect.153; + let Inspect.308 : Str = CallByName Inspect.62 Inspect.309; + ret Inspect.308; -procedure List.67 (#Attr.2, #Attr.3, #Attr.4): - let List.570 : {List {Str, I64}, {Str, I64}} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; - ret List.570; +procedure Inspect.36 (Inspect.305): + let Inspect.315 : Str = ""; + ret Inspect.315; -procedure List.67 (#Attr.2, #Attr.3, #Attr.4): - let List.577 : {List I8, I8} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; - ret List.577; +procedure Inspect.39 (Inspect.184, Inspect.185, Inspect.186, Inspect.187): + let Inspect.320 : {{List {U32, U32}, List {Str, I64}, U64, Float32, U8}, {}, {}, {}} = Struct {Inspect.184, Inspect.185, Inspect.186, Inspect.187}; + let Inspect.319 : {{List {U32, U32}, List {Str, I64}, U64, Float32, U8}, {}, {}, {}} = CallByName Inspect.30 Inspect.320; + ret Inspect.319; -procedure List.67 (#Attr.2, #Attr.3, #Attr.4): - let List.585 : {List U64, U64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; - ret List.585; +procedure Inspect.44 (Inspect.250): + let Inspect.366 : Str = CallByName Inspect.30 Inspect.250; + ret Inspect.366; -procedure List.68 (#Attr.2): - let List.621 : List I8 = lowlevel ListWithCapacity #Attr.2; - ret List.621; +procedure Inspect.5 (Inspect.151): + let Inspect.316 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = CallByName Dict.36 Inspect.151; + let Inspect.313 : {} = Struct {}; + let Inspect.312 : Str = CallByName Inspect.36 Inspect.313; + let Inspect.311 : Str = CallByName Dict.120 Inspect.312 Inspect.316; + ret Inspect.311; -procedure List.68 (#Attr.2): - let List.633 : List U64 = lowlevel ListWithCapacity #Attr.2; - ret List.633; +procedure Inspect.54 (Inspect.278): + let Inspect.360 : I64 = CallByName Inspect.30 Inspect.278; + ret Inspect.360; -procedure List.70 (#Attr.2, #Attr.3): - let List.596 : List {Str, I64} = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.596; +procedure Inspect.61 (Inspect.304, Inspect.300): + let Inspect.327 : Str = CallByName Str.3 Inspect.304 Inspect.300; + dec Inspect.300; + ret Inspect.327; -procedure List.71 (#Attr.2, #Attr.3): - let List.594 : List {Str, I64} = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.594; +procedure Inspect.62 (Inspect.306): + ret Inspect.306; -procedure List.71 (#Attr.2, #Attr.3): - let List.618 : List I8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.618; - -procedure List.71 (#Attr.2, #Attr.3): - let List.630 : List U64 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; +procedure List.11 (List.135, List.136): + let List.631 : List {U32, U32} = CallByName List.68 List.136; + let List.630 : List {U32, U32} = CallByName List.87 List.135 List.136 List.631; ret List.630; -procedure List.86 (#Derived_gen.57, #Derived_gen.58, #Derived_gen.59): - joinpoint List.624 List.135 List.136 List.137: - let List.632 : U64 = 0i64; - let List.626 : Int1 = CallByName Num.24 List.136 List.632; - if List.626 then - let List.631 : U64 = 1i64; - let List.628 : U64 = CallByName Num.75 List.136 List.631; - let List.629 : List U64 = CallByName List.71 List.137 List.135; - jump List.624 List.135 List.628 List.629; - else - ret List.137; - in - jump List.624 #Derived_gen.57 #Derived_gen.58 #Derived_gen.59; +procedure List.18 (List.156, List.157, List.158): + let List.570 : U64 = 0i64; + let List.571 : U64 = CallByName List.6 List.156; + let List.569 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = CallByName List.89 List.156 List.157 List.158 List.570 List.571; + ret List.569; -procedure List.86 (#Derived_gen.7, #Derived_gen.8, #Derived_gen.9): - joinpoint List.612 List.135 List.136 List.137: - let List.620 : U64 = 0i64; - let List.614 : Int1 = CallByName Num.24 List.136 List.620; - if List.614 then - let List.619 : U64 = 1i64; - let List.616 : U64 = CallByName Num.75 List.136 List.619; - let List.617 : List I8 = CallByName List.71 List.137 List.135; - jump List.612 List.135 List.616 List.617; - else - ret List.137; - in - jump List.612 #Derived_gen.7 #Derived_gen.8 #Derived_gen.9; +procedure List.18 (List.156, List.157, List.158): + let List.634 : U64 = 0i64; + let List.635 : U64 = CallByName List.6 List.156; + let List.633 : {Str, Int1} = CallByName List.89 List.156 List.157 List.158 List.634 List.635; + ret List.633; -procedure List.88 (#Derived_gen.21, #Derived_gen.22, #Derived_gen.23, #Derived_gen.24, #Derived_gen.25): - joinpoint List.643 List.157 List.158 List.159 List.160 List.161: - let List.645 : Int1 = CallByName Num.22 List.160 List.161; - if List.645 then - let List.649 : {Str, I64} = CallByName List.66 List.157 List.160; - inc List.649; - let List.162 : {Str, Int1} = CallByName Dict.129 List.158 List.649 List.159; - let List.648 : U64 = 1i64; - let List.647 : U64 = CallByName Num.51 List.160 List.648; - jump List.643 List.157 List.162 List.159 List.647 List.161; - else - dec List.157; - ret List.158; - in - jump List.643 #Derived_gen.21 #Derived_gen.22 #Derived_gen.23 #Derived_gen.24 #Derived_gen.25; +procedure List.3 (List.113, List.114, List.115): + let List.595 : {List {U32, U32}, {U32, U32}} = CallByName List.64 List.113 List.114 List.115; + let List.594 : List {U32, U32} = StructAtIndex 0 List.595; + ret List.594; -procedure List.88 (#Derived_gen.37, #Derived_gen.38, #Derived_gen.39, #Derived_gen.40, #Derived_gen.41): - joinpoint List.556 List.157 List.158 List.159 List.160 List.161: - let List.558 : Int1 = CallByName Num.22 List.160 List.161; - if List.558 then - let List.562 : {Str, I64} = CallByName List.66 List.157 List.160; - inc List.562; - let List.162 : {List {Str, I64}, List U64, List I8, U64} = CallByName Dict.101 List.158 List.562; - let List.561 : U64 = 1i64; - let List.560 : U64 = CallByName Num.51 List.160 List.561; - jump List.556 List.157 List.162 List.159 List.560 List.161; - else - dec List.157; - ret List.158; - in - jump List.556 #Derived_gen.37 #Derived_gen.38 #Derived_gen.39 #Derived_gen.40 #Derived_gen.41; +procedure List.3 (List.113, List.114, List.115): + let List.597 : {List {Str, I64}, {Str, I64}} = CallByName List.64 List.113 List.114 List.115; + let List.596 : List {Str, I64} = StructAtIndex 0 List.597; + let #Derived_gen.71 : {Str, I64} = StructAtIndex 1 List.597; + dec #Derived_gen.71; + ret List.596; -procedure Num.117 (#Attr.2): - let Num.311 : I8 = lowlevel NumIntCast #Attr.2; - ret Num.311; +procedure List.4 (List.121, List.122): + let List.606 : U64 = 1i64; + let List.604 : List {Str, I64} = CallByName List.70 List.121 List.606; + let List.603 : List {Str, I64} = CallByName List.71 List.604 List.122; + ret List.603; + +procedure List.6 (#Attr.2): + let List.585 : U64 = lowlevel ListLen #Attr.2; + ret List.585; + +procedure List.6 (#Attr.2): + let List.632 : U64 = lowlevel ListLen #Attr.2; + ret List.632; + +procedure List.6 (#Attr.2): + let List.644 : U64 = lowlevel ListLen #Attr.2; + ret List.644; + +procedure List.64 (List.110, List.111, List.112): + let List.593 : U64 = CallByName List.6 List.110; + let List.590 : Int1 = CallByName Num.22 List.111 List.593; + if List.590 then + let List.591 : {List {U32, U32}, {U32, U32}} = CallByName List.67 List.110 List.111 List.112; + ret List.591; + else + let List.589 : {List {U32, U32}, {U32, U32}} = Struct {List.110, List.112}; + ret List.589; + +procedure List.64 (List.110, List.111, List.112): + let List.602 : U64 = CallByName List.6 List.110; + let List.599 : Int1 = CallByName Num.22 List.111 List.602; + if List.599 then + let List.600 : {List {Str, I64}, {Str, I64}} = CallByName List.67 List.110 List.111 List.112; + ret List.600; + else + let List.598 : {List {Str, I64}, {Str, I64}} = Struct {List.110, List.112}; + ret List.598; + +procedure List.66 (#Attr.2, #Attr.3): + let List.643 : {Str, I64} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.643; + +procedure List.67 (#Attr.2, #Attr.3, #Attr.4): + let List.592 : {List {U32, U32}, {U32, U32}} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; + ret List.592; + +procedure List.67 (#Attr.2, #Attr.3, #Attr.4): + let List.601 : {List {Str, I64}, {Str, I64}} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; + ret List.601; + +procedure List.68 (#Attr.2): + let List.629 : List {U32, U32} = lowlevel ListWithCapacity #Attr.2; + ret List.629; + +procedure List.70 (#Attr.2, #Attr.3): + let List.607 : List {Str, I64} = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.607; + +procedure List.71 (#Attr.2, #Attr.3): + let List.605 : List {Str, I64} = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.605; + +procedure List.71 (#Attr.2, #Attr.3): + let List.626 : List {U32, U32} = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.626; + +procedure List.83 (List.165, List.166, List.167): + let List.609 : U64 = 0i64; + let List.610 : U64 = CallByName List.6 List.165; + let List.608 : List {U32, U32} = CallByName List.90 List.165 List.166 List.167 List.609 List.610; + ret List.608; + +procedure List.87 (#Derived_gen.46, #Derived_gen.47, #Derived_gen.48): + joinpoint List.620 List.137 List.138 List.139: + let List.628 : U64 = 0i64; + let List.622 : Int1 = CallByName Num.24 List.138 List.628; + if List.622 then + let List.627 : U64 = 1i64; + let List.624 : U64 = CallByName Num.75 List.138 List.627; + let List.625 : List {U32, U32} = CallByName List.71 List.139 List.137; + jump List.620 List.137 List.624 List.625; + else + ret List.139; + in + jump List.620 #Derived_gen.46 #Derived_gen.47 #Derived_gen.48; + +procedure List.89 (#Derived_gen.17, #Derived_gen.18, #Derived_gen.19, #Derived_gen.20, #Derived_gen.21): + joinpoint List.572 List.159 List.160 List.161 List.162 List.163: + let List.574 : Int1 = CallByName Num.22 List.162 List.163; + if List.574 then + let List.578 : {Str, I64} = CallByName List.66 List.159 List.162; + inc List.578; + let List.164 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = CallByName Dict.153 List.160 List.578; + let List.577 : U64 = 1i64; + let List.576 : U64 = CallByName Num.51 List.162 List.577; + jump List.572 List.159 List.164 List.161 List.576 List.163; + else + dec List.159; + ret List.160; + in + jump List.572 #Derived_gen.17 #Derived_gen.18 #Derived_gen.19 #Derived_gen.20 #Derived_gen.21; + +procedure List.89 (#Derived_gen.54, #Derived_gen.55, #Derived_gen.56, #Derived_gen.57, #Derived_gen.58): + joinpoint List.636 List.159 List.160 List.161 List.162 List.163: + let List.638 : Int1 = CallByName Num.22 List.162 List.163; + if List.638 then + let List.642 : {Str, I64} = CallByName List.66 List.159 List.162; + inc List.642; + let List.164 : {Str, Int1} = CallByName Dict.182 List.160 List.642 List.161; + let List.641 : U64 = 1i64; + let List.640 : U64 = CallByName Num.51 List.162 List.641; + jump List.636 List.159 List.164 List.161 List.640 List.163; + else + dec List.159; + ret List.160; + in + jump List.636 #Derived_gen.54 #Derived_gen.55 #Derived_gen.56 #Derived_gen.57 #Derived_gen.58; + +procedure List.90 (#Derived_gen.49, #Derived_gen.50, #Derived_gen.51, #Derived_gen.52, #Derived_gen.53): + joinpoint List.611 List.168 List.169 List.170 List.171 List.172: + let List.613 : Int1 = CallByName Num.22 List.171 List.172; + if List.613 then + let List.617 : {Str, I64} = CallByName List.66 List.168 List.171; + inc List.617; + let List.173 : List {U32, U32} = CallByName Dict.399 List.169 List.617 List.171 List.170; + let List.616 : U64 = 1i64; + let List.615 : U64 = CallByName Num.51 List.171 List.616; + jump List.611 List.168 List.173 List.170 List.615 List.172; + else + dec List.168; + ret List.169; + in + jump List.611 #Derived_gen.49 #Derived_gen.50 #Derived_gen.51 #Derived_gen.52 #Derived_gen.53; + +procedure Num.131 (#Attr.2): + let Num.310 : U32 = lowlevel NumIntCast #Attr.2; + ret Num.310; procedure Num.133 (#Attr.2): - let Num.353 : U64 = lowlevel NumIntCast #Attr.2; - ret Num.353; + let Num.365 : U64 = lowlevel NumIntCast #Attr.2; + ret Num.365; procedure Num.133 (#Attr.2): - let Num.369 : U64 = lowlevel NumIntCast #Attr.2; - ret Num.369; + let Num.366 : U64 = lowlevel NumIntCast #Attr.2; + ret Num.366; procedure Num.133 (#Attr.2): - let Num.370 : U64 = lowlevel NumIntCast #Attr.2; - ret Num.370; + let Num.381 : U64 = lowlevel NumIntCast #Attr.2; + ret Num.381; procedure Num.135 (#Attr.2): - let Num.377 : U128 = lowlevel NumIntCast #Attr.2; - ret Num.377; + let Num.387 : U128 = lowlevel NumIntCast #Attr.2; + ret Num.387; procedure Num.137 (#Attr.2): - let Num.305 : U64 = lowlevel NumIntCast #Attr.2; - ret Num.305; + let Num.301 : U64 = lowlevel NumIntCast #Attr.2; + ret Num.301; + +procedure Num.137 (#Attr.2): + let Num.307 : U64 = lowlevel NumIntCast #Attr.2; + ret Num.307; + +procedure Num.139 (#Attr.2): + let Num.334 : Float32 = lowlevel NumToFloatCast #Attr.2; + ret Num.334; + +procedure Num.159 (Num.240, Num.241): + let Num.336 : Int1 = CallByName Num.22 Num.240 Num.241; + if Num.336 then + ret Num.240; + else + ret Num.241; + +procedure Num.19 (#Attr.2, #Attr.3): + let Num.291 : U32 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.291; + +procedure Num.20 (#Attr.2, #Attr.3): + let Num.311 : U64 = lowlevel NumSub #Attr.2 #Attr.3; + ret Num.311; + +procedure Num.20 (#Attr.2, #Attr.3): + let Num.314 : U8 = lowlevel NumSub #Attr.2 #Attr.3; + ret Num.314; procedure Num.21 (#Attr.2, #Attr.3): - let Num.318 : U64 = lowlevel NumMul #Attr.2 #Attr.3; - ret Num.318; + let Num.327 : Float32 = lowlevel NumMul #Attr.2 #Attr.3; + ret Num.327; procedure Num.21 (#Attr.2, #Attr.3): - let Num.375 : U128 = lowlevel NumMul #Attr.2 #Attr.3; - ret Num.375; + let Num.385 : U128 = lowlevel NumMul #Attr.2 #Attr.3; + ret Num.385; procedure Num.22 (#Attr.2, #Attr.3): - let Num.303 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; - ret Num.303; + let Num.331 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.331; procedure Num.22 (#Attr.2, #Attr.3): - let Num.462 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; - ret Num.462; + let Num.460 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.460; procedure Num.23 (#Attr.2, #Attr.3): let Num.453 : Int1 = lowlevel NumLte #Attr.2 #Attr.3; ret Num.453; procedure Num.24 (#Attr.2, #Attr.3): - let Num.457 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; + let Num.315 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; + ret Num.315; + +procedure Num.24 (#Attr.2, #Attr.3): + let Num.456 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; + ret Num.456; + +procedure Num.25 (#Attr.2, #Attr.3): + let Num.457 : Int1 = lowlevel NumGte #Attr.2 #Attr.3; ret Num.457; -procedure Num.25 (#Attr.2, #Attr.3): - let Num.321 : Int1 = lowlevel NumGte #Attr.2 #Attr.3; - ret Num.321; - -procedure Num.25 (#Attr.2, #Attr.3): - let Num.459 : Int1 = lowlevel NumGte #Attr.2 #Attr.3; - ret Num.459; +procedure Num.50 (#Attr.2): + let Num.333 : U64 = lowlevel NumFloor #Attr.2; + ret Num.333; procedure Num.51 (#Attr.2, #Attr.3): - let Num.461 : U64 = lowlevel NumAddWrap #Attr.2 #Attr.3; - ret Num.461; + let Num.459 : U64 = lowlevel NumAddWrap #Attr.2 #Attr.3; + ret Num.459; procedure Num.69 (#Attr.2, #Attr.3): - let Num.302 : U64 = lowlevel NumBitwiseAnd #Attr.2 #Attr.3; - ret Num.302; + let Num.319 : U32 = lowlevel NumBitwiseAnd #Attr.2 #Attr.3; + ret Num.319; procedure Num.70 (#Attr.2, #Attr.3): - let Num.351 : U64 = lowlevel NumBitwiseXor #Attr.2 #Attr.3; - ret Num.351; + let Num.363 : U64 = lowlevel NumBitwiseXor #Attr.2 #Attr.3; + ret Num.363; procedure Num.71 (#Attr.2, #Attr.3): - let Num.393 : U64 = lowlevel NumBitwiseOr #Attr.2 #Attr.3; - ret Num.393; + let Num.318 : U32 = lowlevel NumBitwiseOr #Attr.2 #Attr.3; + ret Num.318; + +procedure Num.71 (#Attr.2, #Attr.3): + let Num.401 : U64 = lowlevel NumBitwiseOr #Attr.2 #Attr.3; + ret Num.401; procedure Num.72 (#Attr.2, #Attr.3): - let Num.411 : U64 = lowlevel NumShiftLeftBy #Attr.2 #Attr.3; - ret Num.411; + let Num.292 : U32 = lowlevel NumShiftLeftBy #Attr.2 #Attr.3; + ret Num.292; + +procedure Num.72 (#Attr.2, #Attr.3): + let Num.416 : U64 = lowlevel NumShiftLeftBy #Attr.2 #Attr.3; + ret Num.416; procedure Num.74 (#Attr.2, #Attr.3): - let Num.371 : U128 = lowlevel NumShiftRightZfBy #Attr.2 #Attr.3; - ret Num.371; + let Num.382 : U128 = lowlevel NumShiftRightZfBy #Attr.2 #Attr.3; + ret Num.382; procedure Num.74 (#Attr.2, #Attr.3): - let Num.374 : U64 = lowlevel NumShiftRightZfBy #Attr.2 #Attr.3; - ret Num.374; + let Num.384 : U64 = lowlevel NumShiftRightZfBy #Attr.2 #Attr.3; + ret Num.384; procedure Num.75 (#Attr.2, #Attr.3): - let Num.448 : U64 = lowlevel NumSubWrap #Attr.2 #Attr.3; - ret Num.448; + let Num.320 : U32 = lowlevel NumSubWrap #Attr.2 #Attr.3; + ret Num.320; -procedure Num.77 (#Attr.2, #Attr.3): - let Num.306 : U64 = lowlevel NumSubSaturated #Attr.2 #Attr.3; - ret Num.306; +procedure Num.75 (#Attr.2, #Attr.3): + let Num.450 : U64 = lowlevel NumSubWrap #Attr.2 #Attr.3; + ret Num.450; procedure Num.96 (#Attr.2): - let Num.460 : Str = lowlevel NumToStr #Attr.2; - ret Num.460; + let Num.330 : Str = lowlevel NumToStr #Attr.2; + ret Num.330; + +procedure Num.96 (#Attr.2): + let Num.458 : Str = lowlevel NumToStr #Attr.2; + ret Num.458; procedure Str.12 (#Attr.2): - let Str.293 : List U8 = lowlevel StrToUtf8 #Attr.2; - ret Str.293; - -procedure Str.3 (#Attr.2, #Attr.3): - let Str.294 : Str = lowlevel StrConcat #Attr.2 #Attr.3; + let Str.294 : List U8 = lowlevel StrToUtf8 #Attr.2; ret Str.294; +procedure Str.3 (#Attr.2, #Attr.3): + let Str.295 : Str = lowlevel StrConcat #Attr.2 #Attr.3; + ret Str.295; + procedure Test.0 (): - let Test.9 : Str = "a"; - let Test.10 : I64 = 1i64; - let Test.5 : {Str, I64} = Struct {Test.9, Test.10}; - let Test.7 : Str = "b"; - let Test.8 : I64 = 2i64; - let Test.6 : {Str, I64} = Struct {Test.7, Test.8}; - let Test.4 : List {Str, I64} = Array [Test.5, Test.6]; - let Test.3 : {List {Str, I64}, List U64, List I8, U64} = CallByName Dict.12 Test.4; - let Test.2 : Str = CallByName Inspect.5 Test.3; - let Test.1 : Str = CallByName Inspect.35 Test.2; + let Test.8 : Str = "a"; + let Test.9 : I64 = 1i64; + let Test.4 : {Str, I64} = Struct {Test.8, Test.9}; + let Test.6 : Str = "b"; + let Test.7 : I64 = 2i64; + let Test.5 : {Str, I64} = Struct {Test.6, Test.7}; + let Test.3 : List {Str, I64} = Array [Test.4, Test.5]; + let Test.2 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = CallByName Dict.12 Test.3; + let Test.1 : Str = CallByName Inspect.34 Test.2; ret Test.1; diff --git a/crates/compiler/test_mono/generated/inspect_derived_list.txt b/crates/compiler/test_mono/generated/inspect_derived_list.txt index f26482263b..dbe4e11869 100644 --- a/crates/compiler/test_mono/generated/inspect_derived_list.txt +++ b/crates/compiler/test_mono/generated/inspect_derived_list.txt @@ -21,133 +21,138 @@ procedure Bool.2 (): let Bool.23 : Int1 = true; ret Bool.23; -procedure Inspect.155 (Inspect.156, #Attr.12): - let Inspect.154 : {} = StructAtIndex 2 #Attr.12; - let Inspect.153 : {} = StructAtIndex 1 #Attr.12; - let Inspect.152 : List I64 = StructAtIndex 0 #Attr.12; - let Inspect.347 : Str = "["; - let Inspect.328 : Str = CallByName Inspect.61 Inspect.156 Inspect.347; - let Inspect.329 : {List I64, {}, {}} = Struct {Inspect.152, Inspect.153, Inspect.154}; - let Inspect.324 : {Str, Int1} = CallByName Inspect.157 Inspect.328 Inspect.329; - let Inspect.325 : {} = Struct {}; - let Inspect.320 : Str = CallByName Inspect.166 Inspect.324; - let Inspect.321 : Str = "]"; - let Inspect.319 : Str = CallByName Inspect.61 Inspect.320 Inspect.321; - ret Inspect.319; - procedure Inspect.157 (Inspect.158, #Attr.12): - let Inspect.154 : {} = StructAtIndex 2 #Attr.12; - let Inspect.153 : {} = StructAtIndex 1 #Attr.12; - let Inspect.152 : List I64 = StructAtIndex 0 #Attr.12; - let Inspect.346 : Int1 = CallByName Bool.1; - let Inspect.332 : {Str, Int1} = Struct {Inspect.158, Inspect.346}; - let Inspect.331 : {Str, Int1} = CallByName List.18 Inspect.152 Inspect.332 Inspect.154; - ret Inspect.331; - -procedure Inspect.159 (Inspect.334, Inspect.162, Inspect.154): - let Inspect.160 : Str = StructAtIndex 0 Inspect.334; - let Inspect.161 : Int1 = StructAtIndex 1 Inspect.334; - joinpoint Inspect.344 Inspect.163: - let Inspect.341 : I64 = CallByName #Derived.3 Inspect.162; - let Inspect.337 : Str = CallByName Inspect.31 Inspect.341 Inspect.163; - let Inspect.338 : {} = Struct {}; - let Inspect.336 : {Str, Int1} = CallByName Inspect.164 Inspect.337; - ret Inspect.336; - in - if Inspect.161 then - let Inspect.345 : Str = ", "; - let Inspect.343 : Str = CallByName Inspect.61 Inspect.160 Inspect.345; - jump Inspect.344 Inspect.343; - else - jump Inspect.344 Inspect.160; - -procedure Inspect.164 (Inspect.165): - let Inspect.340 : Int1 = CallByName Bool.2; - let Inspect.339 : {Str, Int1} = Struct {Inspect.165, Inspect.340}; - ret Inspect.339; - -procedure Inspect.166 (Inspect.326): - let Inspect.327 : Str = StructAtIndex 0 Inspect.326; - ret Inspect.327; - -procedure Inspect.277 (Inspect.278, Inspect.276): - let Inspect.353 : Str = CallByName Num.96 Inspect.276; - let Inspect.352 : Str = CallByName Inspect.61 Inspect.278 Inspect.353; - ret Inspect.352; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.31 (Inspect.305, Inspect.149): - let Inspect.314 : Str = CallByName Inspect.155 Inspect.149 Inspect.305; - ret Inspect.314; - -procedure Inspect.31 (Inspect.305, Inspect.149): - let Inspect.342 : Str = CallByName Inspect.277 Inspect.149 Inspect.305; - ret Inspect.342; - -procedure Inspect.35 (Inspect.300): - ret Inspect.300; - -procedure Inspect.36 (Inspect.304): - let Inspect.311 : Str = ""; - ret Inspect.311; - -procedure Inspect.37 (Inspect.152, Inspect.153, Inspect.154): - let Inspect.316 : {List I64, {}, {}} = Struct {Inspect.152, Inspect.153, Inspect.154}; - let Inspect.315 : {List I64, {}, {}} = CallByName Inspect.30 Inspect.316; - ret Inspect.315; - -procedure Inspect.5 (Inspect.150): - let Inspect.312 : List I64 = CallByName #Derived.0 Inspect.150; - let Inspect.309 : {} = Struct {}; - let Inspect.308 : Str = CallByName Inspect.36 Inspect.309; - let Inspect.307 : Str = CallByName #Derived.4 Inspect.308 Inspect.312; - ret Inspect.307; - -procedure Inspect.54 (Inspect.276): - let Inspect.348 : I64 = CallByName Inspect.30 Inspect.276; - ret Inspect.348; - -procedure Inspect.61 (Inspect.303, Inspect.298): - let Inspect.323 : Str = CallByName Str.3 Inspect.303 Inspect.298; - dec Inspect.298; + let Inspect.156 : {} = StructAtIndex 2 #Attr.12; + let Inspect.155 : {} = StructAtIndex 1 #Attr.12; + let Inspect.154 : List I64 = StructAtIndex 0 #Attr.12; + let Inspect.351 : Str = "["; + let Inspect.332 : Str = CallByName Inspect.61 Inspect.158 Inspect.351; + let Inspect.333 : {List I64, {}, {}} = Struct {Inspect.154, Inspect.155, Inspect.156}; + let Inspect.328 : {Str, Int1} = CallByName Inspect.159 Inspect.332 Inspect.333; + let Inspect.329 : {} = Struct {}; + let Inspect.324 : Str = CallByName Inspect.168 Inspect.328; + let Inspect.325 : Str = "]"; + let Inspect.323 : Str = CallByName Inspect.61 Inspect.324 Inspect.325; ret Inspect.323; -procedure List.18 (List.154, List.155, List.156): - let List.554 : U64 = 0i64; - let List.555 : U64 = CallByName List.6 List.154; - let List.553 : {Str, Int1} = CallByName List.88 List.154 List.155 List.156 List.554 List.555; - ret List.553; +procedure Inspect.159 (Inspect.160, #Attr.12): + let Inspect.156 : {} = StructAtIndex 2 #Attr.12; + let Inspect.155 : {} = StructAtIndex 1 #Attr.12; + let Inspect.154 : List I64 = StructAtIndex 0 #Attr.12; + let Inspect.350 : Int1 = CallByName Bool.1; + let Inspect.336 : {Str, Int1} = Struct {Inspect.160, Inspect.350}; + let Inspect.335 : {Str, Int1} = CallByName List.18 Inspect.154 Inspect.336 Inspect.156; + ret Inspect.335; + +procedure Inspect.161 (Inspect.338, Inspect.164, Inspect.156): + let Inspect.162 : Str = StructAtIndex 0 Inspect.338; + let Inspect.163 : Int1 = StructAtIndex 1 Inspect.338; + joinpoint Inspect.348 Inspect.165: + let Inspect.345 : I64 = CallByName #Derived.3 Inspect.164; + let Inspect.341 : Str = CallByName Inspect.31 Inspect.345 Inspect.165; + let Inspect.342 : {} = Struct {}; + let Inspect.340 : {Str, Int1} = CallByName Inspect.166 Inspect.341; + ret Inspect.340; + in + if Inspect.163 then + let Inspect.349 : Str = ", "; + let Inspect.347 : Str = CallByName Inspect.61 Inspect.162 Inspect.349; + jump Inspect.348 Inspect.347; + else + jump Inspect.348 Inspect.162; + +procedure Inspect.166 (Inspect.167): + let Inspect.344 : Int1 = CallByName Bool.2; + let Inspect.343 : {Str, Int1} = Struct {Inspect.167, Inspect.344}; + ret Inspect.343; + +procedure Inspect.168 (Inspect.330): + let Inspect.331 : Str = StructAtIndex 0 Inspect.330; + ret Inspect.331; + +procedure Inspect.279 (Inspect.280, Inspect.278): + let Inspect.357 : Str = CallByName Num.96 Inspect.278; + let Inspect.356 : Str = CallByName Inspect.61 Inspect.280 Inspect.357; + ret Inspect.356; + +procedure Inspect.30 (Inspect.148): + ret Inspect.148; + +procedure Inspect.30 (Inspect.148): + ret Inspect.148; + +procedure Inspect.30 (Inspect.148): + ret Inspect.148; + +procedure Inspect.31 (Inspect.307, Inspect.150): + let Inspect.318 : Str = CallByName Inspect.157 Inspect.150 Inspect.307; + ret Inspect.318; + +procedure Inspect.31 (Inspect.307, Inspect.150): + let Inspect.346 : Str = CallByName Inspect.279 Inspect.150 Inspect.307; + ret Inspect.346; + +procedure Inspect.34 (Inspect.153): + let Inspect.309 : Str = CallByName Inspect.5 Inspect.153; + let Inspect.308 : Str = CallByName Inspect.62 Inspect.309; + ret Inspect.308; + +procedure Inspect.36 (Inspect.305): + let Inspect.315 : Str = ""; + ret Inspect.315; + +procedure Inspect.37 (Inspect.154, Inspect.155, Inspect.156): + let Inspect.320 : {List I64, {}, {}} = Struct {Inspect.154, Inspect.155, Inspect.156}; + let Inspect.319 : {List I64, {}, {}} = CallByName Inspect.30 Inspect.320; + ret Inspect.319; + +procedure Inspect.5 (Inspect.151): + let Inspect.316 : List I64 = CallByName #Derived.0 Inspect.151; + let Inspect.313 : {} = Struct {}; + let Inspect.312 : Str = CallByName Inspect.36 Inspect.313; + let Inspect.311 : Str = CallByName #Derived.4 Inspect.312 Inspect.316; + ret Inspect.311; + +procedure Inspect.54 (Inspect.278): + let Inspect.352 : I64 = CallByName Inspect.30 Inspect.278; + ret Inspect.352; + +procedure Inspect.61 (Inspect.304, Inspect.300): + let Inspect.327 : Str = CallByName Str.3 Inspect.304 Inspect.300; + dec Inspect.300; + ret Inspect.327; + +procedure Inspect.62 (Inspect.306): + ret Inspect.306; + +procedure List.18 (List.156, List.157, List.158): + let List.570 : U64 = 0i64; + let List.571 : U64 = CallByName List.6 List.156; + let List.569 : {Str, Int1} = CallByName List.89 List.156 List.157 List.158 List.570 List.571; + ret List.569; procedure List.6 (#Attr.2): - let List.564 : U64 = lowlevel ListLen #Attr.2; - ret List.564; + let List.580 : U64 = lowlevel ListLen #Attr.2; + ret List.580; procedure List.66 (#Attr.2, #Attr.3): - let List.563 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.563; + let List.579 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.579; -procedure List.88 (#Derived_gen.17, #Derived_gen.18, #Derived_gen.19, #Derived_gen.20, #Derived_gen.21): - joinpoint List.556 List.157 List.158 List.159 List.160 List.161: - let List.558 : Int1 = CallByName Num.22 List.160 List.161; - if List.558 then - let List.562 : I64 = CallByName List.66 List.157 List.160; - let List.162 : {Str, Int1} = CallByName Inspect.159 List.158 List.562 List.159; - let List.561 : U64 = 1i64; - let List.560 : U64 = CallByName Num.51 List.160 List.561; - jump List.556 List.157 List.162 List.159 List.560 List.161; +procedure List.89 (#Derived_gen.19, #Derived_gen.20, #Derived_gen.21, #Derived_gen.22, #Derived_gen.23): + joinpoint List.572 List.159 List.160 List.161 List.162 List.163: + let List.574 : Int1 = CallByName Num.22 List.162 List.163; + if List.574 then + let List.578 : I64 = CallByName List.66 List.159 List.162; + let List.164 : {Str, Int1} = CallByName Inspect.161 List.160 List.578 List.161; + let List.577 : U64 = 1i64; + let List.576 : U64 = CallByName Num.51 List.162 List.577; + jump List.572 List.159 List.164 List.161 List.576 List.163; else - dec List.157; - ret List.158; + dec List.159; + ret List.160; in - jump List.556 #Derived_gen.17 #Derived_gen.18 #Derived_gen.19 #Derived_gen.20 #Derived_gen.21; + jump List.572 #Derived_gen.19 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22 #Derived_gen.23; procedure Num.22 (#Attr.2, #Attr.3): let Num.293 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; @@ -166,7 +171,6 @@ procedure Str.3 (#Attr.2, #Attr.3): ret Str.292; procedure Test.0 (): - let Test.3 : List I64 = Array [1i64, 2i64, 3i64]; - let Test.2 : Str = CallByName Inspect.5 Test.3; - let Test.1 : Str = CallByName Inspect.35 Test.2; + let Test.2 : List I64 = Array [1i64, 2i64, 3i64]; + let Test.1 : Str = CallByName Inspect.34 Test.2; ret Test.1; diff --git a/crates/compiler/test_mono/generated/inspect_derived_nested_record_string.txt b/crates/compiler/test_mono/generated/inspect_derived_nested_record_string.txt index fd513aaaec..376a483e4d 100644 --- a/crates/compiler/test_mono/generated/inspect_derived_nested_record_string.txt +++ b/crates/compiler/test_mono/generated/inspect_derived_nested_record_string.txt @@ -32,228 +32,233 @@ procedure Bool.2 (): let Bool.25 : Int1 = true; ret Bool.25; -procedure Inspect.228 (Inspect.229, Inspect.227): - let Inspect.352 : Str = "{"; - let Inspect.328 : Str = CallByName Inspect.61 Inspect.229 Inspect.352; - let Inspect.324 : {Str, Int1} = CallByName Inspect.230 Inspect.328 Inspect.227; - let Inspect.325 : {} = Struct {}; - let Inspect.320 : Str = CallByName Inspect.242 Inspect.324; - let Inspect.321 : Str = "}"; - let Inspect.319 : Str = CallByName Inspect.61 Inspect.320 Inspect.321; - ret Inspect.319; +procedure Inspect.230 (Inspect.231, Inspect.229): + let Inspect.356 : Str = "{"; + let Inspect.332 : Str = CallByName Inspect.61 Inspect.231 Inspect.356; + let Inspect.328 : {Str, Int1} = CallByName Inspect.232 Inspect.332 Inspect.229; + let Inspect.329 : {} = Struct {}; + let Inspect.324 : Str = CallByName Inspect.244 Inspect.328; + let Inspect.325 : Str = "}"; + let Inspect.323 : Str = CallByName Inspect.61 Inspect.324 Inspect.325; + ret Inspect.323; -procedure Inspect.228 (Inspect.229, Inspect.227): - let Inspect.392 : Str = "{"; - let Inspect.368 : Str = CallByName Inspect.61 Inspect.229 Inspect.392; - let Inspect.364 : {Str, Int1} = CallByName Inspect.230 Inspect.368 Inspect.227; - let Inspect.365 : {} = Struct {}; - let Inspect.360 : Str = CallByName Inspect.242 Inspect.364; - let Inspect.361 : Str = "}"; - let Inspect.359 : Str = CallByName Inspect.61 Inspect.360 Inspect.361; - ret Inspect.359; - -procedure Inspect.230 (Inspect.231, Inspect.227): - let Inspect.351 : Int1 = CallByName Bool.1; - let Inspect.332 : {Str, Int1} = Struct {Inspect.231, Inspect.351}; - let Inspect.333 : {} = Struct {}; - let Inspect.331 : {Str, Int1} = CallByName List.18 Inspect.227 Inspect.332 Inspect.333; - ret Inspect.331; - -procedure Inspect.230 (Inspect.231, Inspect.227): - let Inspect.391 : Int1 = CallByName Bool.1; - let Inspect.372 : {Str, Int1} = Struct {Inspect.231, Inspect.391}; - let Inspect.373 : {} = Struct {}; - let Inspect.371 : {Str, Int1} = CallByName List.18 Inspect.227 Inspect.372 Inspect.373; - ret Inspect.371; - -procedure Inspect.232 (Inspect.334, Inspect.335): - let Inspect.235 : Str = StructAtIndex 0 Inspect.335; - let Inspect.236 : Str = StructAtIndex 1 Inspect.335; - let Inspect.233 : Str = StructAtIndex 0 Inspect.334; - let Inspect.234 : Int1 = StructAtIndex 1 Inspect.334; - joinpoint Inspect.349 Inspect.237: - let Inspect.346 : Str = CallByName Inspect.61 Inspect.237 Inspect.235; - let Inspect.347 : Str = ": "; - let Inspect.341 : Str = CallByName Inspect.61 Inspect.346 Inspect.347; - let Inspect.337 : Str = CallByName Inspect.238 Inspect.341 Inspect.236; - let Inspect.338 : {} = Struct {}; - let Inspect.336 : {Str, Int1} = CallByName Inspect.240 Inspect.337; - ret Inspect.336; - in - if Inspect.234 then - let Inspect.350 : Str = ", "; - let Inspect.348 : Str = CallByName Inspect.61 Inspect.233 Inspect.350; - jump Inspect.349 Inspect.348; - else - jump Inspect.349 Inspect.233; - -procedure Inspect.232 (Inspect.334, Inspect.335): - let Inspect.235 : Str = StructAtIndex 0 Inspect.335; - let Inspect.236 : Str = StructAtIndex 1 Inspect.335; - let Inspect.233 : Str = StructAtIndex 0 Inspect.334; - let Inspect.234 : Int1 = StructAtIndex 1 Inspect.334; - joinpoint Inspect.389 Inspect.237: - let Inspect.386 : Str = CallByName Inspect.61 Inspect.237 Inspect.235; - let Inspect.387 : Str = ": "; - let Inspect.381 : Str = CallByName Inspect.61 Inspect.386 Inspect.387; - let Inspect.377 : Str = CallByName Inspect.238 Inspect.381 Inspect.236; - let Inspect.378 : {} = Struct {}; - let Inspect.376 : {Str, Int1} = CallByName Inspect.240 Inspect.377; - ret Inspect.376; - in - if Inspect.234 then - let Inspect.390 : Str = ", "; - let Inspect.388 : Str = CallByName Inspect.61 Inspect.233 Inspect.390; - jump Inspect.389 Inspect.388; - else - jump Inspect.389 Inspect.233; - -procedure Inspect.238 (Inspect.239, Inspect.236): - let Inspect.344 : Str = CallByName Inspect.31 Inspect.236 Inspect.239; - ret Inspect.344; - -procedure Inspect.238 (Inspect.239, Inspect.236): - let Inspect.384 : Str = CallByName Inspect.31 Inspect.236 Inspect.239; - ret Inspect.384; - -procedure Inspect.240 (Inspect.241): - let Inspect.380 : Int1 = CallByName Bool.2; - let Inspect.379 : {Str, Int1} = Struct {Inspect.241, Inspect.380}; - ret Inspect.379; - -procedure Inspect.242 (Inspect.326): - let Inspect.367 : Str = StructAtIndex 0 Inspect.326; - ret Inspect.367; - -procedure Inspect.249 (Inspect.250, Inspect.248): - let Inspect.401 : Str = "\""; - let Inspect.400 : Str = CallByName Inspect.61 Inspect.250 Inspect.401; - let Inspect.398 : Str = CallByName Inspect.61 Inspect.400 Inspect.248; - let Inspect.399 : Str = "\""; - let Inspect.397 : Str = CallByName Inspect.61 Inspect.398 Inspect.399; - ret Inspect.397; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.31 (Inspect.305, Inspect.149): - let Inspect.314 : Str = CallByName Inspect.228 Inspect.149 Inspect.305; - ret Inspect.314; - -procedure Inspect.31 (Inspect.305, Inspect.149): - let Inspect.345 : Str = CallByName #Derived.6 Inspect.149 Inspect.305; - ret Inspect.345; - -procedure Inspect.31 (Inspect.305, Inspect.149): - let Inspect.354 : Str = CallByName Inspect.228 Inspect.149 Inspect.305; - ret Inspect.354; - -procedure Inspect.31 (Inspect.305, Inspect.149): - let Inspect.385 : Str = CallByName Inspect.249 Inspect.149 Inspect.305; - ret Inspect.385; - -procedure Inspect.35 (Inspect.300): - ret Inspect.300; - -procedure Inspect.36 (Inspect.304): - let Inspect.311 : Str = ""; - ret Inspect.311; - -procedure Inspect.42 (Inspect.227): - let Inspect.315 : List {Str, Str} = CallByName Inspect.30 Inspect.227; - ret Inspect.315; - -procedure Inspect.42 (Inspect.227): - let Inspect.355 : List {Str, Str} = CallByName Inspect.30 Inspect.227; - ret Inspect.355; - -procedure Inspect.44 (Inspect.248): - let Inspect.393 : Str = CallByName Inspect.30 Inspect.248; - ret Inspect.393; - -procedure Inspect.5 (Inspect.150): - let Inspect.312 : Str = CallByName #Derived.0 Inspect.150; - let Inspect.309 : {} = Struct {}; - let Inspect.308 : Str = CallByName Inspect.36 Inspect.309; - let Inspect.307 : Str = CallByName #Derived.2 Inspect.308 Inspect.312; - ret Inspect.307; - -procedure Inspect.61 (Inspect.303, Inspect.298): - let Inspect.363 : Str = CallByName Str.3 Inspect.303 Inspect.298; - dec Inspect.298; +procedure Inspect.230 (Inspect.231, Inspect.229): + let Inspect.396 : Str = "{"; + let Inspect.372 : Str = CallByName Inspect.61 Inspect.231 Inspect.396; + let Inspect.368 : {Str, Int1} = CallByName Inspect.232 Inspect.372 Inspect.229; + let Inspect.369 : {} = Struct {}; + let Inspect.364 : Str = CallByName Inspect.244 Inspect.368; + let Inspect.365 : Str = "}"; + let Inspect.363 : Str = CallByName Inspect.61 Inspect.364 Inspect.365; ret Inspect.363; -procedure List.18 (List.154, List.155, List.156): - let List.554 : U64 = 0i64; - let List.555 : U64 = CallByName List.6 List.154; - let List.553 : {Str, Int1} = CallByName List.88 List.154 List.155 List.156 List.554 List.555; - ret List.553; +procedure Inspect.232 (Inspect.233, Inspect.229): + let Inspect.355 : Int1 = CallByName Bool.1; + let Inspect.336 : {Str, Int1} = Struct {Inspect.233, Inspect.355}; + let Inspect.337 : {} = Struct {}; + let Inspect.335 : {Str, Int1} = CallByName List.18 Inspect.229 Inspect.336 Inspect.337; + ret Inspect.335; -procedure List.18 (List.154, List.155, List.156): - let List.566 : U64 = 0i64; - let List.567 : U64 = CallByName List.6 List.154; - let List.565 : {Str, Int1} = CallByName List.88 List.154 List.155 List.156 List.566 List.567; - ret List.565; +procedure Inspect.232 (Inspect.233, Inspect.229): + let Inspect.395 : Int1 = CallByName Bool.1; + let Inspect.376 : {Str, Int1} = Struct {Inspect.233, Inspect.395}; + let Inspect.377 : {} = Struct {}; + let Inspect.375 : {Str, Int1} = CallByName List.18 Inspect.229 Inspect.376 Inspect.377; + ret Inspect.375; + +procedure Inspect.234 (Inspect.338, Inspect.339): + let Inspect.237 : Str = StructAtIndex 0 Inspect.339; + let Inspect.238 : Str = StructAtIndex 1 Inspect.339; + let Inspect.235 : Str = StructAtIndex 0 Inspect.338; + let Inspect.236 : Int1 = StructAtIndex 1 Inspect.338; + joinpoint Inspect.353 Inspect.239: + let Inspect.350 : Str = CallByName Inspect.61 Inspect.239 Inspect.237; + let Inspect.351 : Str = ": "; + let Inspect.345 : Str = CallByName Inspect.61 Inspect.350 Inspect.351; + let Inspect.341 : Str = CallByName Inspect.240 Inspect.345 Inspect.238; + let Inspect.342 : {} = Struct {}; + let Inspect.340 : {Str, Int1} = CallByName Inspect.242 Inspect.341; + ret Inspect.340; + in + if Inspect.236 then + let Inspect.354 : Str = ", "; + let Inspect.352 : Str = CallByName Inspect.61 Inspect.235 Inspect.354; + jump Inspect.353 Inspect.352; + else + jump Inspect.353 Inspect.235; + +procedure Inspect.234 (Inspect.338, Inspect.339): + let Inspect.237 : Str = StructAtIndex 0 Inspect.339; + let Inspect.238 : Str = StructAtIndex 1 Inspect.339; + let Inspect.235 : Str = StructAtIndex 0 Inspect.338; + let Inspect.236 : Int1 = StructAtIndex 1 Inspect.338; + joinpoint Inspect.393 Inspect.239: + let Inspect.390 : Str = CallByName Inspect.61 Inspect.239 Inspect.237; + let Inspect.391 : Str = ": "; + let Inspect.385 : Str = CallByName Inspect.61 Inspect.390 Inspect.391; + let Inspect.381 : Str = CallByName Inspect.240 Inspect.385 Inspect.238; + let Inspect.382 : {} = Struct {}; + let Inspect.380 : {Str, Int1} = CallByName Inspect.242 Inspect.381; + ret Inspect.380; + in + if Inspect.236 then + let Inspect.394 : Str = ", "; + let Inspect.392 : Str = CallByName Inspect.61 Inspect.235 Inspect.394; + jump Inspect.393 Inspect.392; + else + jump Inspect.393 Inspect.235; + +procedure Inspect.240 (Inspect.241, Inspect.238): + let Inspect.348 : Str = CallByName Inspect.31 Inspect.238 Inspect.241; + ret Inspect.348; + +procedure Inspect.240 (Inspect.241, Inspect.238): + let Inspect.388 : Str = CallByName Inspect.31 Inspect.238 Inspect.241; + ret Inspect.388; + +procedure Inspect.242 (Inspect.243): + let Inspect.384 : Int1 = CallByName Bool.2; + let Inspect.383 : {Str, Int1} = Struct {Inspect.243, Inspect.384}; + ret Inspect.383; + +procedure Inspect.244 (Inspect.330): + let Inspect.371 : Str = StructAtIndex 0 Inspect.330; + ret Inspect.371; + +procedure Inspect.251 (Inspect.252, Inspect.250): + let Inspect.405 : Str = "\""; + let Inspect.404 : Str = CallByName Inspect.61 Inspect.252 Inspect.405; + let Inspect.402 : Str = CallByName Inspect.61 Inspect.404 Inspect.250; + let Inspect.403 : Str = "\""; + let Inspect.401 : Str = CallByName Inspect.61 Inspect.402 Inspect.403; + ret Inspect.401; + +procedure Inspect.30 (Inspect.148): + ret Inspect.148; + +procedure Inspect.30 (Inspect.148): + ret Inspect.148; + +procedure Inspect.30 (Inspect.148): + ret Inspect.148; + +procedure Inspect.30 (Inspect.148): + ret Inspect.148; + +procedure Inspect.30 (Inspect.148): + ret Inspect.148; + +procedure Inspect.31 (Inspect.307, Inspect.150): + let Inspect.318 : Str = CallByName Inspect.230 Inspect.150 Inspect.307; + ret Inspect.318; + +procedure Inspect.31 (Inspect.307, Inspect.150): + let Inspect.349 : Str = CallByName #Derived.6 Inspect.150 Inspect.307; + ret Inspect.349; + +procedure Inspect.31 (Inspect.307, Inspect.150): + let Inspect.358 : Str = CallByName Inspect.230 Inspect.150 Inspect.307; + ret Inspect.358; + +procedure Inspect.31 (Inspect.307, Inspect.150): + let Inspect.389 : Str = CallByName Inspect.251 Inspect.150 Inspect.307; + ret Inspect.389; + +procedure Inspect.34 (Inspect.153): + let Inspect.309 : Str = CallByName Inspect.5 Inspect.153; + let Inspect.308 : Str = CallByName Inspect.62 Inspect.309; + ret Inspect.308; + +procedure Inspect.36 (Inspect.305): + let Inspect.315 : Str = ""; + ret Inspect.315; + +procedure Inspect.42 (Inspect.229): + let Inspect.319 : List {Str, Str} = CallByName Inspect.30 Inspect.229; + ret Inspect.319; + +procedure Inspect.42 (Inspect.229): + let Inspect.359 : List {Str, Str} = CallByName Inspect.30 Inspect.229; + ret Inspect.359; + +procedure Inspect.44 (Inspect.250): + let Inspect.397 : Str = CallByName Inspect.30 Inspect.250; + ret Inspect.397; + +procedure Inspect.5 (Inspect.151): + let Inspect.316 : Str = CallByName #Derived.0 Inspect.151; + let Inspect.313 : {} = Struct {}; + let Inspect.312 : Str = CallByName Inspect.36 Inspect.313; + let Inspect.311 : Str = CallByName #Derived.2 Inspect.312 Inspect.316; + ret Inspect.311; + +procedure Inspect.61 (Inspect.304, Inspect.300): + let Inspect.367 : Str = CallByName Str.3 Inspect.304 Inspect.300; + dec Inspect.300; + ret Inspect.367; + +procedure Inspect.62 (Inspect.306): + ret Inspect.306; + +procedure List.18 (List.156, List.157, List.158): + let List.570 : U64 = 0i64; + let List.571 : U64 = CallByName List.6 List.156; + let List.569 : {Str, Int1} = CallByName List.89 List.156 List.157 List.158 List.570 List.571; + ret List.569; + +procedure List.18 (List.156, List.157, List.158): + let List.582 : U64 = 0i64; + let List.583 : U64 = CallByName List.6 List.156; + let List.581 : {Str, Int1} = CallByName List.89 List.156 List.157 List.158 List.582 List.583; + ret List.581; procedure List.6 (#Attr.2): - let List.564 : U64 = lowlevel ListLen #Attr.2; - ret List.564; + let List.580 : U64 = lowlevel ListLen #Attr.2; + ret List.580; procedure List.6 (#Attr.2): - let List.576 : U64 = lowlevel ListLen #Attr.2; - ret List.576; + let List.592 : U64 = lowlevel ListLen #Attr.2; + ret List.592; procedure List.66 (#Attr.2, #Attr.3): - let List.563 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.563; + let List.579 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.579; procedure List.66 (#Attr.2, #Attr.3): - let List.575 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.575; + let List.591 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.591; -procedure List.88 (#Derived_gen.30, #Derived_gen.31, #Derived_gen.32, #Derived_gen.33, #Derived_gen.34): - joinpoint List.568 List.157 List.158 List.159 List.160 List.161: - let List.570 : Int1 = CallByName Num.22 List.160 List.161; - if List.570 then - let List.574 : {Str, Str} = CallByName List.66 List.157 List.160; - inc List.574; - let List.162 : {Str, Int1} = CallByName Inspect.232 List.158 List.574; - let List.573 : U64 = 1i64; - let List.572 : U64 = CallByName Num.51 List.160 List.573; - jump List.568 List.157 List.162 List.159 List.572 List.161; +procedure List.89 (#Derived_gen.22, #Derived_gen.23, #Derived_gen.24, #Derived_gen.25, #Derived_gen.26): + joinpoint List.572 List.159 List.160 List.161 List.162 List.163: + let List.574 : Int1 = CallByName Num.22 List.162 List.163; + if List.574 then + let List.578 : {Str, Str} = CallByName List.66 List.159 List.162; + inc List.578; + let List.164 : {Str, Int1} = CallByName Inspect.234 List.160 List.578; + let List.577 : U64 = 1i64; + let List.576 : U64 = CallByName Num.51 List.162 List.577; + jump List.572 List.159 List.164 List.161 List.576 List.163; else - dec List.157; - ret List.158; + dec List.159; + ret List.160; in - jump List.568 #Derived_gen.30 #Derived_gen.31 #Derived_gen.32 #Derived_gen.33 #Derived_gen.34; + jump List.572 #Derived_gen.22 #Derived_gen.23 #Derived_gen.24 #Derived_gen.25 #Derived_gen.26; -procedure List.88 (#Derived_gen.41, #Derived_gen.42, #Derived_gen.43, #Derived_gen.44, #Derived_gen.45): - joinpoint List.556 List.157 List.158 List.159 List.160 List.161: - let List.558 : Int1 = CallByName Num.22 List.160 List.161; - if List.558 then - let List.562 : {Str, Str} = CallByName List.66 List.157 List.160; - inc List.562; - let List.162 : {Str, Int1} = CallByName Inspect.232 List.158 List.562; - let List.561 : U64 = 1i64; - let List.560 : U64 = CallByName Num.51 List.160 List.561; - jump List.556 List.157 List.162 List.159 List.560 List.161; +procedure List.89 (#Derived_gen.43, #Derived_gen.44, #Derived_gen.45, #Derived_gen.46, #Derived_gen.47): + joinpoint List.584 List.159 List.160 List.161 List.162 List.163: + let List.586 : Int1 = CallByName Num.22 List.162 List.163; + if List.586 then + let List.590 : {Str, Str} = CallByName List.66 List.159 List.162; + inc List.590; + let List.164 : {Str, Int1} = CallByName Inspect.234 List.160 List.590; + let List.589 : U64 = 1i64; + let List.588 : U64 = CallByName Num.51 List.162 List.589; + jump List.584 List.159 List.164 List.161 List.588 List.163; else - dec List.157; - ret List.158; + dec List.159; + ret List.160; in - jump List.556 #Derived_gen.41 #Derived_gen.42 #Derived_gen.43 #Derived_gen.44 #Derived_gen.45; + jump List.584 #Derived_gen.43 #Derived_gen.44 #Derived_gen.45 #Derived_gen.46 #Derived_gen.47; procedure Num.22 (#Attr.2, #Attr.3): let Num.294 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; @@ -268,7 +273,6 @@ procedure Str.3 (#Attr.2, #Attr.3): ret Str.293; procedure Test.0 (): - let Test.5 : Str = "bar"; - let Test.2 : Str = CallByName Inspect.5 Test.5; - let Test.1 : Str = CallByName Inspect.35 Test.2; + let Test.4 : Str = "bar"; + let Test.1 : Str = CallByName Inspect.34 Test.4; ret Test.1; diff --git a/crates/compiler/test_mono/generated/inspect_derived_record.txt b/crates/compiler/test_mono/generated/inspect_derived_record.txt index 756bb71eeb..4159f3f3da 100644 --- a/crates/compiler/test_mono/generated/inspect_derived_record.txt +++ b/crates/compiler/test_mono/generated/inspect_derived_record.txt @@ -24,156 +24,161 @@ procedure Bool.2 (): let Bool.23 : Int1 = true; ret Bool.23; -procedure Inspect.228 (Inspect.229, Inspect.227): - let Inspect.353 : Str = "{"; - let Inspect.328 : Str = CallByName Inspect.61 Inspect.229 Inspect.353; - let Inspect.324 : {Str, Int1} = CallByName Inspect.230 Inspect.328 Inspect.227; - let Inspect.325 : {} = Struct {}; - let Inspect.320 : Str = CallByName Inspect.242 Inspect.324; - let Inspect.321 : Str = "}"; - let Inspect.319 : Str = CallByName Inspect.61 Inspect.320 Inspect.321; - ret Inspect.319; - -procedure Inspect.230 (Inspect.231, Inspect.227): - let Inspect.352 : Int1 = CallByName Bool.1; - let Inspect.332 : {Str, Int1} = Struct {Inspect.231, Inspect.352}; - let Inspect.333 : {} = Struct {}; - let Inspect.331 : {Str, Int1} = CallByName List.18 Inspect.227 Inspect.332 Inspect.333; - ret Inspect.331; - -procedure Inspect.232 (Inspect.334, Inspect.335): - let Inspect.236 : [C I64, C Decimal] = StructAtIndex 0 Inspect.335; - let Inspect.235 : Str = StructAtIndex 1 Inspect.335; - let Inspect.233 : Str = StructAtIndex 0 Inspect.334; - let Inspect.234 : Int1 = StructAtIndex 1 Inspect.334; - joinpoint Inspect.350 Inspect.237: - let Inspect.347 : Str = CallByName Inspect.61 Inspect.237 Inspect.235; - let Inspect.348 : Str = ": "; - let Inspect.341 : Str = CallByName Inspect.61 Inspect.347 Inspect.348; - let Inspect.337 : Str = CallByName Inspect.238 Inspect.341 Inspect.236; - let Inspect.338 : {} = Struct {}; - let Inspect.336 : {Str, Int1} = CallByName Inspect.240 Inspect.337; - ret Inspect.336; - in - if Inspect.234 then - let Inspect.351 : Str = ", "; - let Inspect.349 : Str = CallByName Inspect.61 Inspect.233 Inspect.351; - jump Inspect.350 Inspect.349; - else - jump Inspect.350 Inspect.233; - -procedure Inspect.238 (Inspect.239, Inspect.236): - let Inspect.344 : Str = CallByName Inspect.31 Inspect.236 Inspect.239; - ret Inspect.344; - -procedure Inspect.240 (Inspect.241): - let Inspect.340 : Int1 = CallByName Bool.2; - let Inspect.339 : {Str, Int1} = Struct {Inspect.241, Inspect.340}; - ret Inspect.339; - -procedure Inspect.242 (Inspect.326): - let Inspect.327 : Str = StructAtIndex 0 Inspect.326; - ret Inspect.327; - -procedure Inspect.277 (Inspect.278, #Attr.12): - let Inspect.366 : I64 = UnionAtIndex (Id 0) (Index 0) #Attr.12; - let Inspect.365 : Str = CallByName Num.96 Inspect.366; - let Inspect.364 : Str = CallByName Inspect.61 Inspect.278 Inspect.365; - ret Inspect.364; - -procedure Inspect.295 (Inspect.296, #Attr.12): - let Inspect.360 : Decimal = UnionAtIndex (Id 1) (Index 0) #Attr.12; - let Inspect.359 : Str = CallByName Num.96 Inspect.360; - let Inspect.358 : Str = CallByName Inspect.61 Inspect.296 Inspect.359; - ret Inspect.358; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.31 (Inspect.305, Inspect.149): - let Inspect.314 : Str = CallByName Inspect.228 Inspect.149 Inspect.305; - ret Inspect.314; - -procedure Inspect.31 (Inspect.305, Inspect.149): - let Inspect.346 : U8 = GetTagId Inspect.305; - switch Inspect.346: - case 0: - let Inspect.345 : Str = CallByName Inspect.277 Inspect.149 Inspect.305; - ret Inspect.345; - - default: - let Inspect.345 : Str = CallByName Inspect.295 Inspect.149 Inspect.305; - ret Inspect.345; - - -procedure Inspect.35 (Inspect.300): - ret Inspect.300; - -procedure Inspect.36 (Inspect.304): - let Inspect.311 : Str = ""; - ret Inspect.311; - -procedure Inspect.42 (Inspect.227): - let Inspect.315 : List {[C I64, C Decimal], Str} = CallByName Inspect.30 Inspect.227; - ret Inspect.315; - -procedure Inspect.5 (Inspect.150): - let Inspect.312 : {Decimal, I64} = CallByName #Derived.0 Inspect.150; - let Inspect.309 : {} = Struct {}; - let Inspect.308 : Str = CallByName Inspect.36 Inspect.309; - let Inspect.307 : Str = CallByName #Derived.2 Inspect.308 Inspect.312; - ret Inspect.307; - -procedure Inspect.54 (Inspect.276): - let Inspect.362 : [C I64, C Decimal] = TagId(0) Inspect.276; - let Inspect.361 : [C I64, C Decimal] = CallByName Inspect.30 Inspect.362; - ret Inspect.361; - -procedure Inspect.60 (Inspect.294): - let Inspect.355 : [C I64, C Decimal] = TagId(1) Inspect.294; - let Inspect.354 : [C I64, C Decimal] = CallByName Inspect.30 Inspect.355; - ret Inspect.354; - -procedure Inspect.61 (Inspect.303, Inspect.298): - let Inspect.323 : Str = CallByName Str.3 Inspect.303 Inspect.298; - dec Inspect.298; +procedure Inspect.230 (Inspect.231, Inspect.229): + let Inspect.357 : Str = "{"; + let Inspect.332 : Str = CallByName Inspect.61 Inspect.231 Inspect.357; + let Inspect.328 : {Str, Int1} = CallByName Inspect.232 Inspect.332 Inspect.229; + let Inspect.329 : {} = Struct {}; + let Inspect.324 : Str = CallByName Inspect.244 Inspect.328; + let Inspect.325 : Str = "}"; + let Inspect.323 : Str = CallByName Inspect.61 Inspect.324 Inspect.325; ret Inspect.323; -procedure List.18 (List.154, List.155, List.156): - let List.554 : U64 = 0i64; - let List.555 : U64 = CallByName List.6 List.154; - let List.553 : {Str, Int1} = CallByName List.88 List.154 List.155 List.156 List.554 List.555; - ret List.553; +procedure Inspect.232 (Inspect.233, Inspect.229): + let Inspect.356 : Int1 = CallByName Bool.1; + let Inspect.336 : {Str, Int1} = Struct {Inspect.233, Inspect.356}; + let Inspect.337 : {} = Struct {}; + let Inspect.335 : {Str, Int1} = CallByName List.18 Inspect.229 Inspect.336 Inspect.337; + ret Inspect.335; + +procedure Inspect.234 (Inspect.338, Inspect.339): + let Inspect.238 : [C I64, C Decimal] = StructAtIndex 0 Inspect.339; + let Inspect.237 : Str = StructAtIndex 1 Inspect.339; + let Inspect.235 : Str = StructAtIndex 0 Inspect.338; + let Inspect.236 : Int1 = StructAtIndex 1 Inspect.338; + joinpoint Inspect.354 Inspect.239: + let Inspect.351 : Str = CallByName Inspect.61 Inspect.239 Inspect.237; + let Inspect.352 : Str = ": "; + let Inspect.345 : Str = CallByName Inspect.61 Inspect.351 Inspect.352; + let Inspect.341 : Str = CallByName Inspect.240 Inspect.345 Inspect.238; + let Inspect.342 : {} = Struct {}; + let Inspect.340 : {Str, Int1} = CallByName Inspect.242 Inspect.341; + ret Inspect.340; + in + if Inspect.236 then + let Inspect.355 : Str = ", "; + let Inspect.353 : Str = CallByName Inspect.61 Inspect.235 Inspect.355; + jump Inspect.354 Inspect.353; + else + jump Inspect.354 Inspect.235; + +procedure Inspect.240 (Inspect.241, Inspect.238): + let Inspect.348 : Str = CallByName Inspect.31 Inspect.238 Inspect.241; + ret Inspect.348; + +procedure Inspect.242 (Inspect.243): + let Inspect.344 : Int1 = CallByName Bool.2; + let Inspect.343 : {Str, Int1} = Struct {Inspect.243, Inspect.344}; + ret Inspect.343; + +procedure Inspect.244 (Inspect.330): + let Inspect.331 : Str = StructAtIndex 0 Inspect.330; + ret Inspect.331; + +procedure Inspect.279 (Inspect.280, #Attr.12): + let Inspect.370 : I64 = UnionAtIndex (Id 0) (Index 0) #Attr.12; + let Inspect.369 : Str = CallByName Num.96 Inspect.370; + let Inspect.368 : Str = CallByName Inspect.61 Inspect.280 Inspect.369; + ret Inspect.368; + +procedure Inspect.297 (Inspect.298, #Attr.12): + let Inspect.364 : Decimal = UnionAtIndex (Id 1) (Index 0) #Attr.12; + let Inspect.363 : Str = CallByName Num.96 Inspect.364; + let Inspect.362 : Str = CallByName Inspect.61 Inspect.298 Inspect.363; + ret Inspect.362; + +procedure Inspect.30 (Inspect.148): + ret Inspect.148; + +procedure Inspect.30 (Inspect.148): + ret Inspect.148; + +procedure Inspect.30 (Inspect.148): + ret Inspect.148; + +procedure Inspect.31 (Inspect.307, Inspect.150): + let Inspect.318 : Str = CallByName Inspect.230 Inspect.150 Inspect.307; + ret Inspect.318; + +procedure Inspect.31 (Inspect.307, Inspect.150): + let Inspect.350 : U8 = GetTagId Inspect.307; + switch Inspect.350: + case 0: + let Inspect.349 : Str = CallByName Inspect.279 Inspect.150 Inspect.307; + ret Inspect.349; + + default: + let Inspect.349 : Str = CallByName Inspect.297 Inspect.150 Inspect.307; + ret Inspect.349; + + +procedure Inspect.34 (Inspect.153): + let Inspect.309 : Str = CallByName Inspect.5 Inspect.153; + let Inspect.308 : Str = CallByName Inspect.62 Inspect.309; + ret Inspect.308; + +procedure Inspect.36 (Inspect.305): + let Inspect.315 : Str = ""; + ret Inspect.315; + +procedure Inspect.42 (Inspect.229): + let Inspect.319 : List {[C I64, C Decimal], Str} = CallByName Inspect.30 Inspect.229; + ret Inspect.319; + +procedure Inspect.5 (Inspect.151): + let Inspect.316 : {Decimal, I64} = CallByName #Derived.0 Inspect.151; + let Inspect.313 : {} = Struct {}; + let Inspect.312 : Str = CallByName Inspect.36 Inspect.313; + let Inspect.311 : Str = CallByName #Derived.2 Inspect.312 Inspect.316; + ret Inspect.311; + +procedure Inspect.54 (Inspect.278): + let Inspect.366 : [C I64, C Decimal] = TagId(0) Inspect.278; + let Inspect.365 : [C I64, C Decimal] = CallByName Inspect.30 Inspect.366; + ret Inspect.365; + +procedure Inspect.60 (Inspect.296): + let Inspect.359 : [C I64, C Decimal] = TagId(1) Inspect.296; + let Inspect.358 : [C I64, C Decimal] = CallByName Inspect.30 Inspect.359; + ret Inspect.358; + +procedure Inspect.61 (Inspect.304, Inspect.300): + let Inspect.327 : Str = CallByName Str.3 Inspect.304 Inspect.300; + dec Inspect.300; + ret Inspect.327; + +procedure Inspect.62 (Inspect.306): + ret Inspect.306; + +procedure List.18 (List.156, List.157, List.158): + let List.570 : U64 = 0i64; + let List.571 : U64 = CallByName List.6 List.156; + let List.569 : {Str, Int1} = CallByName List.89 List.156 List.157 List.158 List.570 List.571; + ret List.569; procedure List.6 (#Attr.2): - let List.564 : U64 = lowlevel ListLen #Attr.2; - ret List.564; + let List.580 : U64 = lowlevel ListLen #Attr.2; + ret List.580; procedure List.66 (#Attr.2, #Attr.3): - let List.563 : {[C I64, C Decimal], Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.563; + let List.579 : {[C I64, C Decimal], Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.579; -procedure List.88 (#Derived_gen.14, #Derived_gen.15, #Derived_gen.16, #Derived_gen.17, #Derived_gen.18): - joinpoint List.556 List.157 List.158 List.159 List.160 List.161: - let List.558 : Int1 = CallByName Num.22 List.160 List.161; - if List.558 then - let List.562 : {[C I64, C Decimal], Str} = CallByName List.66 List.157 List.160; - inc List.562; - let List.162 : {Str, Int1} = CallByName Inspect.232 List.158 List.562; - let List.561 : U64 = 1i64; - let List.560 : U64 = CallByName Num.51 List.160 List.561; - jump List.556 List.157 List.162 List.159 List.560 List.161; +procedure List.89 (#Derived_gen.14, #Derived_gen.15, #Derived_gen.16, #Derived_gen.17, #Derived_gen.18): + joinpoint List.572 List.159 List.160 List.161 List.162 List.163: + let List.574 : Int1 = CallByName Num.22 List.162 List.163; + if List.574 then + let List.578 : {[C I64, C Decimal], Str} = CallByName List.66 List.159 List.162; + inc List.578; + let List.164 : {Str, Int1} = CallByName Inspect.234 List.160 List.578; + let List.577 : U64 = 1i64; + let List.576 : U64 = CallByName Num.51 List.162 List.577; + jump List.572 List.159 List.164 List.161 List.576 List.163; else - dec List.157; - ret List.158; + dec List.159; + ret List.160; in - jump List.556 #Derived_gen.14 #Derived_gen.15 #Derived_gen.16 #Derived_gen.17 #Derived_gen.18; + jump List.572 #Derived_gen.14 #Derived_gen.15 #Derived_gen.16 #Derived_gen.17 #Derived_gen.18; procedure Num.22 (#Attr.2, #Attr.3): let Num.294 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; @@ -196,9 +201,8 @@ procedure Str.3 (#Attr.2, #Attr.3): ret Str.292; procedure Test.0 (): - let Test.4 : Decimal = 3dec; - let Test.5 : I64 = 7i64; - let Test.3 : {Decimal, I64} = Struct {Test.4, Test.5}; - let Test.2 : Str = CallByName Inspect.5 Test.3; - let Test.1 : Str = CallByName Inspect.35 Test.2; + let Test.3 : Decimal = 3dec; + let Test.4 : I64 = 7i64; + let Test.2 : {Decimal, I64} = Struct {Test.3, Test.4}; + let Test.1 : Str = CallByName Inspect.34 Test.2; ret Test.1; diff --git a/crates/compiler/test_mono/generated/inspect_derived_record_one_field_string.txt b/crates/compiler/test_mono/generated/inspect_derived_record_one_field_string.txt index 1c78bb0240..789513140d 100644 --- a/crates/compiler/test_mono/generated/inspect_derived_record_one_field_string.txt +++ b/crates/compiler/test_mono/generated/inspect_derived_record_one_field_string.txt @@ -19,138 +19,143 @@ procedure Bool.2 (): let Bool.23 : Int1 = true; ret Bool.23; -procedure Inspect.228 (Inspect.229, Inspect.227): - let Inspect.352 : Str = "{"; - let Inspect.328 : Str = CallByName Inspect.61 Inspect.229 Inspect.352; - let Inspect.324 : {Str, Int1} = CallByName Inspect.230 Inspect.328 Inspect.227; - let Inspect.325 : {} = Struct {}; - let Inspect.320 : Str = CallByName Inspect.242 Inspect.324; - let Inspect.321 : Str = "}"; - let Inspect.319 : Str = CallByName Inspect.61 Inspect.320 Inspect.321; - ret Inspect.319; - -procedure Inspect.230 (Inspect.231, Inspect.227): - let Inspect.351 : Int1 = CallByName Bool.1; - let Inspect.332 : {Str, Int1} = Struct {Inspect.231, Inspect.351}; - let Inspect.333 : {} = Struct {}; - let Inspect.331 : {Str, Int1} = CallByName List.18 Inspect.227 Inspect.332 Inspect.333; - ret Inspect.331; - -procedure Inspect.232 (Inspect.334, Inspect.335): - let Inspect.235 : Str = StructAtIndex 0 Inspect.335; - let Inspect.236 : Str = StructAtIndex 1 Inspect.335; - let Inspect.233 : Str = StructAtIndex 0 Inspect.334; - let Inspect.234 : Int1 = StructAtIndex 1 Inspect.334; - joinpoint Inspect.349 Inspect.237: - let Inspect.346 : Str = CallByName Inspect.61 Inspect.237 Inspect.235; - let Inspect.347 : Str = ": "; - let Inspect.341 : Str = CallByName Inspect.61 Inspect.346 Inspect.347; - let Inspect.337 : Str = CallByName Inspect.238 Inspect.341 Inspect.236; - let Inspect.338 : {} = Struct {}; - let Inspect.336 : {Str, Int1} = CallByName Inspect.240 Inspect.337; - ret Inspect.336; - in - if Inspect.234 then - let Inspect.350 : Str = ", "; - let Inspect.348 : Str = CallByName Inspect.61 Inspect.233 Inspect.350; - jump Inspect.349 Inspect.348; - else - jump Inspect.349 Inspect.233; - -procedure Inspect.238 (Inspect.239, Inspect.236): - let Inspect.344 : Str = CallByName Inspect.31 Inspect.236 Inspect.239; - ret Inspect.344; - -procedure Inspect.240 (Inspect.241): - let Inspect.340 : Int1 = CallByName Bool.2; - let Inspect.339 : {Str, Int1} = Struct {Inspect.241, Inspect.340}; - ret Inspect.339; - -procedure Inspect.242 (Inspect.326): - let Inspect.327 : Str = StructAtIndex 0 Inspect.326; - ret Inspect.327; - -procedure Inspect.249 (Inspect.250, Inspect.248): - let Inspect.361 : Str = "\""; - let Inspect.360 : Str = CallByName Inspect.61 Inspect.250 Inspect.361; - let Inspect.358 : Str = CallByName Inspect.61 Inspect.360 Inspect.248; - let Inspect.359 : Str = "\""; - let Inspect.357 : Str = CallByName Inspect.61 Inspect.358 Inspect.359; - ret Inspect.357; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.31 (Inspect.305, Inspect.149): - let Inspect.314 : Str = CallByName Inspect.228 Inspect.149 Inspect.305; - ret Inspect.314; - -procedure Inspect.31 (Inspect.305, Inspect.149): - let Inspect.345 : Str = CallByName Inspect.249 Inspect.149 Inspect.305; - ret Inspect.345; - -procedure Inspect.35 (Inspect.300): - ret Inspect.300; - -procedure Inspect.36 (Inspect.304): - let Inspect.311 : Str = ""; - ret Inspect.311; - -procedure Inspect.42 (Inspect.227): - let Inspect.315 : List {Str, Str} = CallByName Inspect.30 Inspect.227; - ret Inspect.315; - -procedure Inspect.44 (Inspect.248): - let Inspect.353 : Str = CallByName Inspect.30 Inspect.248; - ret Inspect.353; - -procedure Inspect.5 (Inspect.150): - let Inspect.312 : Str = CallByName #Derived.0 Inspect.150; - let Inspect.309 : {} = Struct {}; - let Inspect.308 : Str = CallByName Inspect.36 Inspect.309; - let Inspect.307 : Str = CallByName #Derived.2 Inspect.308 Inspect.312; - ret Inspect.307; - -procedure Inspect.61 (Inspect.303, Inspect.298): - let Inspect.323 : Str = CallByName Str.3 Inspect.303 Inspect.298; - dec Inspect.298; +procedure Inspect.230 (Inspect.231, Inspect.229): + let Inspect.356 : Str = "{"; + let Inspect.332 : Str = CallByName Inspect.61 Inspect.231 Inspect.356; + let Inspect.328 : {Str, Int1} = CallByName Inspect.232 Inspect.332 Inspect.229; + let Inspect.329 : {} = Struct {}; + let Inspect.324 : Str = CallByName Inspect.244 Inspect.328; + let Inspect.325 : Str = "}"; + let Inspect.323 : Str = CallByName Inspect.61 Inspect.324 Inspect.325; ret Inspect.323; -procedure List.18 (List.154, List.155, List.156): - let List.554 : U64 = 0i64; - let List.555 : U64 = CallByName List.6 List.154; - let List.553 : {Str, Int1} = CallByName List.88 List.154 List.155 List.156 List.554 List.555; - ret List.553; +procedure Inspect.232 (Inspect.233, Inspect.229): + let Inspect.355 : Int1 = CallByName Bool.1; + let Inspect.336 : {Str, Int1} = Struct {Inspect.233, Inspect.355}; + let Inspect.337 : {} = Struct {}; + let Inspect.335 : {Str, Int1} = CallByName List.18 Inspect.229 Inspect.336 Inspect.337; + ret Inspect.335; + +procedure Inspect.234 (Inspect.338, Inspect.339): + let Inspect.237 : Str = StructAtIndex 0 Inspect.339; + let Inspect.238 : Str = StructAtIndex 1 Inspect.339; + let Inspect.235 : Str = StructAtIndex 0 Inspect.338; + let Inspect.236 : Int1 = StructAtIndex 1 Inspect.338; + joinpoint Inspect.353 Inspect.239: + let Inspect.350 : Str = CallByName Inspect.61 Inspect.239 Inspect.237; + let Inspect.351 : Str = ": "; + let Inspect.345 : Str = CallByName Inspect.61 Inspect.350 Inspect.351; + let Inspect.341 : Str = CallByName Inspect.240 Inspect.345 Inspect.238; + let Inspect.342 : {} = Struct {}; + let Inspect.340 : {Str, Int1} = CallByName Inspect.242 Inspect.341; + ret Inspect.340; + in + if Inspect.236 then + let Inspect.354 : Str = ", "; + let Inspect.352 : Str = CallByName Inspect.61 Inspect.235 Inspect.354; + jump Inspect.353 Inspect.352; + else + jump Inspect.353 Inspect.235; + +procedure Inspect.240 (Inspect.241, Inspect.238): + let Inspect.348 : Str = CallByName Inspect.31 Inspect.238 Inspect.241; + ret Inspect.348; + +procedure Inspect.242 (Inspect.243): + let Inspect.344 : Int1 = CallByName Bool.2; + let Inspect.343 : {Str, Int1} = Struct {Inspect.243, Inspect.344}; + ret Inspect.343; + +procedure Inspect.244 (Inspect.330): + let Inspect.331 : Str = StructAtIndex 0 Inspect.330; + ret Inspect.331; + +procedure Inspect.251 (Inspect.252, Inspect.250): + let Inspect.365 : Str = "\""; + let Inspect.364 : Str = CallByName Inspect.61 Inspect.252 Inspect.365; + let Inspect.362 : Str = CallByName Inspect.61 Inspect.364 Inspect.250; + let Inspect.363 : Str = "\""; + let Inspect.361 : Str = CallByName Inspect.61 Inspect.362 Inspect.363; + ret Inspect.361; + +procedure Inspect.30 (Inspect.148): + ret Inspect.148; + +procedure Inspect.30 (Inspect.148): + ret Inspect.148; + +procedure Inspect.30 (Inspect.148): + ret Inspect.148; + +procedure Inspect.31 (Inspect.307, Inspect.150): + let Inspect.318 : Str = CallByName Inspect.230 Inspect.150 Inspect.307; + ret Inspect.318; + +procedure Inspect.31 (Inspect.307, Inspect.150): + let Inspect.349 : Str = CallByName Inspect.251 Inspect.150 Inspect.307; + ret Inspect.349; + +procedure Inspect.34 (Inspect.153): + let Inspect.309 : Str = CallByName Inspect.5 Inspect.153; + let Inspect.308 : Str = CallByName Inspect.62 Inspect.309; + ret Inspect.308; + +procedure Inspect.36 (Inspect.305): + let Inspect.315 : Str = ""; + ret Inspect.315; + +procedure Inspect.42 (Inspect.229): + let Inspect.319 : List {Str, Str} = CallByName Inspect.30 Inspect.229; + ret Inspect.319; + +procedure Inspect.44 (Inspect.250): + let Inspect.357 : Str = CallByName Inspect.30 Inspect.250; + ret Inspect.357; + +procedure Inspect.5 (Inspect.151): + let Inspect.316 : Str = CallByName #Derived.0 Inspect.151; + let Inspect.313 : {} = Struct {}; + let Inspect.312 : Str = CallByName Inspect.36 Inspect.313; + let Inspect.311 : Str = CallByName #Derived.2 Inspect.312 Inspect.316; + ret Inspect.311; + +procedure Inspect.61 (Inspect.304, Inspect.300): + let Inspect.327 : Str = CallByName Str.3 Inspect.304 Inspect.300; + dec Inspect.300; + ret Inspect.327; + +procedure Inspect.62 (Inspect.306): + ret Inspect.306; + +procedure List.18 (List.156, List.157, List.158): + let List.570 : U64 = 0i64; + let List.571 : U64 = CallByName List.6 List.156; + let List.569 : {Str, Int1} = CallByName List.89 List.156 List.157 List.158 List.570 List.571; + ret List.569; procedure List.6 (#Attr.2): - let List.564 : U64 = lowlevel ListLen #Attr.2; - ret List.564; + let List.580 : U64 = lowlevel ListLen #Attr.2; + ret List.580; procedure List.66 (#Attr.2, #Attr.3): - let List.563 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.563; + let List.579 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.579; -procedure List.88 (#Derived_gen.14, #Derived_gen.15, #Derived_gen.16, #Derived_gen.17, #Derived_gen.18): - joinpoint List.556 List.157 List.158 List.159 List.160 List.161: - let List.558 : Int1 = CallByName Num.22 List.160 List.161; - if List.558 then - let List.562 : {Str, Str} = CallByName List.66 List.157 List.160; - inc List.562; - let List.162 : {Str, Int1} = CallByName Inspect.232 List.158 List.562; - let List.561 : U64 = 1i64; - let List.560 : U64 = CallByName Num.51 List.160 List.561; - jump List.556 List.157 List.162 List.159 List.560 List.161; +procedure List.89 (#Derived_gen.12, #Derived_gen.13, #Derived_gen.14, #Derived_gen.15, #Derived_gen.16): + joinpoint List.572 List.159 List.160 List.161 List.162 List.163: + let List.574 : Int1 = CallByName Num.22 List.162 List.163; + if List.574 then + let List.578 : {Str, Str} = CallByName List.66 List.159 List.162; + inc List.578; + let List.164 : {Str, Int1} = CallByName Inspect.234 List.160 List.578; + let List.577 : U64 = 1i64; + let List.576 : U64 = CallByName Num.51 List.162 List.577; + jump List.572 List.159 List.164 List.161 List.576 List.163; else - dec List.157; - ret List.158; + dec List.159; + ret List.160; in - jump List.556 #Derived_gen.14 #Derived_gen.15 #Derived_gen.16 #Derived_gen.17 #Derived_gen.18; + jump List.572 #Derived_gen.12 #Derived_gen.13 #Derived_gen.14 #Derived_gen.15 #Derived_gen.16; procedure Num.22 (#Attr.2, #Attr.3): let Num.292 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; @@ -165,7 +170,6 @@ procedure Str.3 (#Attr.2, #Attr.3): ret Str.292; procedure Test.0 (): - let Test.4 : Str = "foo"; - let Test.2 : Str = CallByName Inspect.5 Test.4; - let Test.1 : Str = CallByName Inspect.35 Test.2; + let Test.3 : Str = "foo"; + let Test.1 : Str = CallByName Inspect.34 Test.3; ret Test.1; diff --git a/crates/compiler/test_mono/generated/inspect_derived_record_two_field_strings.txt b/crates/compiler/test_mono/generated/inspect_derived_record_two_field_strings.txt index 76a867481b..f368c1ab16 100644 --- a/crates/compiler/test_mono/generated/inspect_derived_record_two_field_strings.txt +++ b/crates/compiler/test_mono/generated/inspect_derived_record_two_field_strings.txt @@ -26,138 +26,143 @@ procedure Bool.2 (): let Bool.23 : Int1 = true; ret Bool.23; -procedure Inspect.228 (Inspect.229, Inspect.227): - let Inspect.352 : Str = "{"; - let Inspect.328 : Str = CallByName Inspect.61 Inspect.229 Inspect.352; - let Inspect.324 : {Str, Int1} = CallByName Inspect.230 Inspect.328 Inspect.227; - let Inspect.325 : {} = Struct {}; - let Inspect.320 : Str = CallByName Inspect.242 Inspect.324; - let Inspect.321 : Str = "}"; - let Inspect.319 : Str = CallByName Inspect.61 Inspect.320 Inspect.321; - ret Inspect.319; - -procedure Inspect.230 (Inspect.231, Inspect.227): - let Inspect.351 : Int1 = CallByName Bool.1; - let Inspect.332 : {Str, Int1} = Struct {Inspect.231, Inspect.351}; - let Inspect.333 : {} = Struct {}; - let Inspect.331 : {Str, Int1} = CallByName List.18 Inspect.227 Inspect.332 Inspect.333; - ret Inspect.331; - -procedure Inspect.232 (Inspect.334, Inspect.335): - let Inspect.235 : Str = StructAtIndex 0 Inspect.335; - let Inspect.236 : Str = StructAtIndex 1 Inspect.335; - let Inspect.233 : Str = StructAtIndex 0 Inspect.334; - let Inspect.234 : Int1 = StructAtIndex 1 Inspect.334; - joinpoint Inspect.349 Inspect.237: - let Inspect.346 : Str = CallByName Inspect.61 Inspect.237 Inspect.235; - let Inspect.347 : Str = ": "; - let Inspect.341 : Str = CallByName Inspect.61 Inspect.346 Inspect.347; - let Inspect.337 : Str = CallByName Inspect.238 Inspect.341 Inspect.236; - let Inspect.338 : {} = Struct {}; - let Inspect.336 : {Str, Int1} = CallByName Inspect.240 Inspect.337; - ret Inspect.336; - in - if Inspect.234 then - let Inspect.350 : Str = ", "; - let Inspect.348 : Str = CallByName Inspect.61 Inspect.233 Inspect.350; - jump Inspect.349 Inspect.348; - else - jump Inspect.349 Inspect.233; - -procedure Inspect.238 (Inspect.239, Inspect.236): - let Inspect.344 : Str = CallByName Inspect.31 Inspect.236 Inspect.239; - ret Inspect.344; - -procedure Inspect.240 (Inspect.241): - let Inspect.340 : Int1 = CallByName Bool.2; - let Inspect.339 : {Str, Int1} = Struct {Inspect.241, Inspect.340}; - ret Inspect.339; - -procedure Inspect.242 (Inspect.326): - let Inspect.327 : Str = StructAtIndex 0 Inspect.326; - ret Inspect.327; - -procedure Inspect.249 (Inspect.250, Inspect.248): - let Inspect.361 : Str = "\""; - let Inspect.360 : Str = CallByName Inspect.61 Inspect.250 Inspect.361; - let Inspect.358 : Str = CallByName Inspect.61 Inspect.360 Inspect.248; - let Inspect.359 : Str = "\""; - let Inspect.357 : Str = CallByName Inspect.61 Inspect.358 Inspect.359; - ret Inspect.357; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.31 (Inspect.305, Inspect.149): - let Inspect.314 : Str = CallByName Inspect.228 Inspect.149 Inspect.305; - ret Inspect.314; - -procedure Inspect.31 (Inspect.305, Inspect.149): - let Inspect.345 : Str = CallByName Inspect.249 Inspect.149 Inspect.305; - ret Inspect.345; - -procedure Inspect.35 (Inspect.300): - ret Inspect.300; - -procedure Inspect.36 (Inspect.304): - let Inspect.311 : Str = ""; - ret Inspect.311; - -procedure Inspect.42 (Inspect.227): - let Inspect.315 : List {Str, Str} = CallByName Inspect.30 Inspect.227; - ret Inspect.315; - -procedure Inspect.44 (Inspect.248): - let Inspect.362 : Str = CallByName Inspect.30 Inspect.248; - ret Inspect.362; - -procedure Inspect.5 (Inspect.150): - let Inspect.312 : {Str, Str} = CallByName #Derived.0 Inspect.150; - let Inspect.309 : {} = Struct {}; - let Inspect.308 : Str = CallByName Inspect.36 Inspect.309; - let Inspect.307 : Str = CallByName #Derived.2 Inspect.308 Inspect.312; - ret Inspect.307; - -procedure Inspect.61 (Inspect.303, Inspect.298): - let Inspect.323 : Str = CallByName Str.3 Inspect.303 Inspect.298; - dec Inspect.298; +procedure Inspect.230 (Inspect.231, Inspect.229): + let Inspect.356 : Str = "{"; + let Inspect.332 : Str = CallByName Inspect.61 Inspect.231 Inspect.356; + let Inspect.328 : {Str, Int1} = CallByName Inspect.232 Inspect.332 Inspect.229; + let Inspect.329 : {} = Struct {}; + let Inspect.324 : Str = CallByName Inspect.244 Inspect.328; + let Inspect.325 : Str = "}"; + let Inspect.323 : Str = CallByName Inspect.61 Inspect.324 Inspect.325; ret Inspect.323; -procedure List.18 (List.154, List.155, List.156): - let List.554 : U64 = 0i64; - let List.555 : U64 = CallByName List.6 List.154; - let List.553 : {Str, Int1} = CallByName List.88 List.154 List.155 List.156 List.554 List.555; - ret List.553; +procedure Inspect.232 (Inspect.233, Inspect.229): + let Inspect.355 : Int1 = CallByName Bool.1; + let Inspect.336 : {Str, Int1} = Struct {Inspect.233, Inspect.355}; + let Inspect.337 : {} = Struct {}; + let Inspect.335 : {Str, Int1} = CallByName List.18 Inspect.229 Inspect.336 Inspect.337; + ret Inspect.335; + +procedure Inspect.234 (Inspect.338, Inspect.339): + let Inspect.237 : Str = StructAtIndex 0 Inspect.339; + let Inspect.238 : Str = StructAtIndex 1 Inspect.339; + let Inspect.235 : Str = StructAtIndex 0 Inspect.338; + let Inspect.236 : Int1 = StructAtIndex 1 Inspect.338; + joinpoint Inspect.353 Inspect.239: + let Inspect.350 : Str = CallByName Inspect.61 Inspect.239 Inspect.237; + let Inspect.351 : Str = ": "; + let Inspect.345 : Str = CallByName Inspect.61 Inspect.350 Inspect.351; + let Inspect.341 : Str = CallByName Inspect.240 Inspect.345 Inspect.238; + let Inspect.342 : {} = Struct {}; + let Inspect.340 : {Str, Int1} = CallByName Inspect.242 Inspect.341; + ret Inspect.340; + in + if Inspect.236 then + let Inspect.354 : Str = ", "; + let Inspect.352 : Str = CallByName Inspect.61 Inspect.235 Inspect.354; + jump Inspect.353 Inspect.352; + else + jump Inspect.353 Inspect.235; + +procedure Inspect.240 (Inspect.241, Inspect.238): + let Inspect.348 : Str = CallByName Inspect.31 Inspect.238 Inspect.241; + ret Inspect.348; + +procedure Inspect.242 (Inspect.243): + let Inspect.344 : Int1 = CallByName Bool.2; + let Inspect.343 : {Str, Int1} = Struct {Inspect.243, Inspect.344}; + ret Inspect.343; + +procedure Inspect.244 (Inspect.330): + let Inspect.331 : Str = StructAtIndex 0 Inspect.330; + ret Inspect.331; + +procedure Inspect.251 (Inspect.252, Inspect.250): + let Inspect.365 : Str = "\""; + let Inspect.364 : Str = CallByName Inspect.61 Inspect.252 Inspect.365; + let Inspect.362 : Str = CallByName Inspect.61 Inspect.364 Inspect.250; + let Inspect.363 : Str = "\""; + let Inspect.361 : Str = CallByName Inspect.61 Inspect.362 Inspect.363; + ret Inspect.361; + +procedure Inspect.30 (Inspect.148): + ret Inspect.148; + +procedure Inspect.30 (Inspect.148): + ret Inspect.148; + +procedure Inspect.30 (Inspect.148): + ret Inspect.148; + +procedure Inspect.31 (Inspect.307, Inspect.150): + let Inspect.318 : Str = CallByName Inspect.230 Inspect.150 Inspect.307; + ret Inspect.318; + +procedure Inspect.31 (Inspect.307, Inspect.150): + let Inspect.349 : Str = CallByName Inspect.251 Inspect.150 Inspect.307; + ret Inspect.349; + +procedure Inspect.34 (Inspect.153): + let Inspect.309 : Str = CallByName Inspect.5 Inspect.153; + let Inspect.308 : Str = CallByName Inspect.62 Inspect.309; + ret Inspect.308; + +procedure Inspect.36 (Inspect.305): + let Inspect.315 : Str = ""; + ret Inspect.315; + +procedure Inspect.42 (Inspect.229): + let Inspect.319 : List {Str, Str} = CallByName Inspect.30 Inspect.229; + ret Inspect.319; + +procedure Inspect.44 (Inspect.250): + let Inspect.366 : Str = CallByName Inspect.30 Inspect.250; + ret Inspect.366; + +procedure Inspect.5 (Inspect.151): + let Inspect.316 : {Str, Str} = CallByName #Derived.0 Inspect.151; + let Inspect.313 : {} = Struct {}; + let Inspect.312 : Str = CallByName Inspect.36 Inspect.313; + let Inspect.311 : Str = CallByName #Derived.2 Inspect.312 Inspect.316; + ret Inspect.311; + +procedure Inspect.61 (Inspect.304, Inspect.300): + let Inspect.327 : Str = CallByName Str.3 Inspect.304 Inspect.300; + dec Inspect.300; + ret Inspect.327; + +procedure Inspect.62 (Inspect.306): + ret Inspect.306; + +procedure List.18 (List.156, List.157, List.158): + let List.570 : U64 = 0i64; + let List.571 : U64 = CallByName List.6 List.156; + let List.569 : {Str, Int1} = CallByName List.89 List.156 List.157 List.158 List.570 List.571; + ret List.569; procedure List.6 (#Attr.2): - let List.564 : U64 = lowlevel ListLen #Attr.2; - ret List.564; + let List.580 : U64 = lowlevel ListLen #Attr.2; + ret List.580; procedure List.66 (#Attr.2, #Attr.3): - let List.563 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.563; + let List.579 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.579; -procedure List.88 (#Derived_gen.18, #Derived_gen.19, #Derived_gen.20, #Derived_gen.21, #Derived_gen.22): - joinpoint List.556 List.157 List.158 List.159 List.160 List.161: - let List.558 : Int1 = CallByName Num.22 List.160 List.161; - if List.558 then - let List.562 : {Str, Str} = CallByName List.66 List.157 List.160; - inc List.562; - let List.162 : {Str, Int1} = CallByName Inspect.232 List.158 List.562; - let List.561 : U64 = 1i64; - let List.560 : U64 = CallByName Num.51 List.160 List.561; - jump List.556 List.157 List.162 List.159 List.560 List.161; +procedure List.89 (#Derived_gen.16, #Derived_gen.17, #Derived_gen.18, #Derived_gen.19, #Derived_gen.20): + joinpoint List.572 List.159 List.160 List.161 List.162 List.163: + let List.574 : Int1 = CallByName Num.22 List.162 List.163; + if List.574 then + let List.578 : {Str, Str} = CallByName List.66 List.159 List.162; + inc List.578; + let List.164 : {Str, Int1} = CallByName Inspect.234 List.160 List.578; + let List.577 : U64 = 1i64; + let List.576 : U64 = CallByName Num.51 List.162 List.577; + jump List.572 List.159 List.164 List.161 List.576 List.163; else - dec List.157; - ret List.158; + dec List.159; + ret List.160; in - jump List.556 #Derived_gen.18 #Derived_gen.19 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22; + jump List.572 #Derived_gen.16 #Derived_gen.17 #Derived_gen.18 #Derived_gen.19 #Derived_gen.20; procedure Num.22 (#Attr.2, #Attr.3): let Num.292 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; @@ -172,9 +177,8 @@ procedure Str.3 (#Attr.2, #Attr.3): ret Str.292; procedure Test.0 (): - let Test.4 : Str = "foo"; - let Test.5 : Str = "bar"; - let Test.3 : {Str, Str} = Struct {Test.4, Test.5}; - let Test.2 : Str = CallByName Inspect.5 Test.3; - let Test.1 : Str = CallByName Inspect.35 Test.2; + let Test.3 : Str = "foo"; + let Test.4 : Str = "bar"; + let Test.2 : {Str, Str} = Struct {Test.3, Test.4}; + let Test.1 : Str = CallByName Inspect.34 Test.2; ret Test.1; diff --git a/crates/compiler/test_mono/generated/inspect_derived_string.txt b/crates/compiler/test_mono/generated/inspect_derived_string.txt index 8b22e27efe..af0f8f01dc 100644 --- a/crates/compiler/test_mono/generated/inspect_derived_string.txt +++ b/crates/compiler/test_mono/generated/inspect_derived_string.txt @@ -1,43 +1,47 @@ -procedure Inspect.249 (Inspect.250, Inspect.248): +procedure Inspect.251 (Inspect.252, Inspect.250): + let Inspect.327 : Str = "\""; + let Inspect.326 : Str = CallByName Inspect.61 Inspect.252 Inspect.327; + let Inspect.322 : Str = CallByName Inspect.61 Inspect.326 Inspect.250; let Inspect.323 : Str = "\""; - let Inspect.322 : Str = CallByName Inspect.61 Inspect.250 Inspect.323; - let Inspect.318 : Str = CallByName Inspect.61 Inspect.322 Inspect.248; - let Inspect.319 : Str = "\""; - let Inspect.317 : Str = CallByName Inspect.61 Inspect.318 Inspect.319; + let Inspect.321 : Str = CallByName Inspect.61 Inspect.322 Inspect.323; + ret Inspect.321; + +procedure Inspect.30 (Inspect.148): + ret Inspect.148; + +procedure Inspect.34 (Inspect.153): + let Inspect.309 : Str = CallByName Inspect.5 Inspect.153; + let Inspect.308 : Str = CallByName Inspect.62 Inspect.309; + ret Inspect.308; + +procedure Inspect.36 (Inspect.305): + let Inspect.315 : Str = ""; + ret Inspect.315; + +procedure Inspect.44 (Inspect.250): + let Inspect.317 : Str = CallByName Inspect.30 Inspect.250; ret Inspect.317; -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.35 (Inspect.300): - ret Inspect.300; - -procedure Inspect.36 (Inspect.304): - let Inspect.311 : Str = ""; +procedure Inspect.5 (Inspect.151): + let Inspect.316 : Str = CallByName Inspect.44 Inspect.151; + let Inspect.313 : {} = Struct {}; + let Inspect.312 : Str = CallByName Inspect.36 Inspect.313; + let Inspect.311 : Str = CallByName Inspect.251 Inspect.312 Inspect.316; ret Inspect.311; -procedure Inspect.44 (Inspect.248): - let Inspect.313 : Str = CallByName Inspect.30 Inspect.248; - ret Inspect.313; +procedure Inspect.61 (Inspect.304, Inspect.300): + let Inspect.325 : Str = CallByName Str.3 Inspect.304 Inspect.300; + dec Inspect.300; + ret Inspect.325; -procedure Inspect.5 (Inspect.150): - let Inspect.312 : Str = CallByName Inspect.44 Inspect.150; - let Inspect.309 : {} = Struct {}; - let Inspect.308 : Str = CallByName Inspect.36 Inspect.309; - let Inspect.307 : Str = CallByName Inspect.249 Inspect.308 Inspect.312; - ret Inspect.307; - -procedure Inspect.61 (Inspect.303, Inspect.298): - let Inspect.321 : Str = CallByName Str.3 Inspect.303 Inspect.298; - dec Inspect.298; - ret Inspect.321; +procedure Inspect.62 (Inspect.306): + ret Inspect.306; procedure Str.3 (#Attr.2, #Attr.3): let Str.292 : Str = lowlevel StrConcat #Attr.2 #Attr.3; ret Str.292; procedure Test.0 (): - let Test.3 : Str = "abc"; - let Test.2 : Str = CallByName Inspect.5 Test.3; - let Test.1 : Str = CallByName Inspect.35 Test.2; + let Test.2 : Str = "abc"; + let Test.1 : Str = CallByName Inspect.34 Test.2; ret Test.1; diff --git a/crates/compiler/test_mono/generated/inspect_derived_tag_one_field_string.txt b/crates/compiler/test_mono/generated/inspect_derived_tag_one_field_string.txt index 6f59ae05e1..71e668f88d 100644 --- a/crates/compiler/test_mono/generated/inspect_derived_tag_one_field_string.txt +++ b/crates/compiler/test_mono/generated/inspect_derived_tag_one_field_string.txt @@ -17,142 +17,147 @@ procedure Bool.11 (#Attr.2, #Attr.3): let Bool.23 : Int1 = lowlevel Eq #Attr.2 #Attr.3; ret Bool.23; -procedure Inspect.203 (Inspect.204, #Attr.12): - let Inspect.346 : Str = UnionAtIndex (Id 0) (Index 0) #Attr.12; - let Inspect.345 : Str = CallByName Inspect.61 Inspect.204 Inspect.346; - ret Inspect.345; - procedure Inspect.205 (Inspect.206, #Attr.12): - let Inspect.340 : List Str = UnionAtIndex (Id 1) (Index 1) #Attr.12; - let Inspect.339 : Str = UnionAtIndex (Id 1) (Index 0) #Attr.12; - let Inspect.338 : Str = "("; - let Inspect.337 : Str = CallByName Inspect.61 Inspect.206 Inspect.338; - let Inspect.325 : Str = CallByName Inspect.61 Inspect.337 Inspect.339; - let Inspect.321 : Str = CallByName Inspect.207 Inspect.325 Inspect.340; - let Inspect.322 : Str = ")"; - let Inspect.320 : Str = CallByName Inspect.61 Inspect.321 Inspect.322; - ret Inspect.320; + let Inspect.350 : Str = UnionAtIndex (Id 0) (Index 0) #Attr.12; + let Inspect.349 : Str = CallByName Inspect.61 Inspect.206 Inspect.350; + ret Inspect.349; -procedure Inspect.207 (Inspect.208, Inspect.202): - let Inspect.329 : {} = Struct {}; - let Inspect.328 : Str = CallByName List.18 Inspect.202 Inspect.208 Inspect.329; - ret Inspect.328; - -procedure Inspect.209 (Inspect.210, Inspect.211): - let Inspect.336 : Str = " "; - let Inspect.331 : Str = CallByName Inspect.61 Inspect.210 Inspect.336; - let Inspect.330 : Str = CallByName Inspect.212 Inspect.331 Inspect.211; - ret Inspect.330; - -procedure Inspect.212 (Inspect.213, Inspect.211): - let Inspect.334 : Str = CallByName Inspect.31 Inspect.211 Inspect.213; - ret Inspect.334; - -procedure Inspect.249 (Inspect.250, Inspect.248): - let Inspect.355 : Str = "\""; - let Inspect.354 : Str = CallByName Inspect.61 Inspect.250 Inspect.355; - let Inspect.352 : Str = CallByName Inspect.61 Inspect.354 Inspect.248; - let Inspect.353 : Str = "\""; - let Inspect.351 : Str = CallByName Inspect.61 Inspect.352 Inspect.353; - ret Inspect.351; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.31 (Inspect.305, Inspect.149): - let Inspect.315 : U8 = GetTagId Inspect.305; - switch Inspect.315: - case 0: - let Inspect.314 : Str = CallByName Inspect.203 Inspect.149 Inspect.305; - ret Inspect.314; - - default: - let Inspect.314 : Str = CallByName Inspect.205 Inspect.149 Inspect.305; - ret Inspect.314; - - -procedure Inspect.31 (Inspect.305, Inspect.149): - let Inspect.335 : Str = CallByName Inspect.249 Inspect.149 Inspect.305; - ret Inspect.335; - -procedure Inspect.35 (Inspect.300): - ret Inspect.300; - -procedure Inspect.36 (Inspect.304): - let Inspect.311 : Str = ""; - ret Inspect.311; - -procedure Inspect.40 (Inspect.201, Inspect.202): - inc Inspect.202; - let Inspect.341 : Int1 = CallByName List.1 Inspect.202; - if Inspect.341 then - dec Inspect.202; - let Inspect.343 : [C Str, C Str List Str] = TagId(0) Inspect.201; - let Inspect.342 : [C Str, C Str List Str] = CallByName Inspect.30 Inspect.343; - ret Inspect.342; - else - let Inspect.317 : [C Str, C Str List Str] = TagId(1) Inspect.201 Inspect.202; - let Inspect.316 : [C Str, C Str List Str] = CallByName Inspect.30 Inspect.317; - ret Inspect.316; - -procedure Inspect.44 (Inspect.248): - let Inspect.347 : Str = CallByName Inspect.30 Inspect.248; - ret Inspect.347; - -procedure Inspect.5 (Inspect.150): - let Inspect.312 : Str = CallByName #Derived.0 Inspect.150; - let Inspect.309 : {} = Struct {}; - let Inspect.308 : Str = CallByName Inspect.36 Inspect.309; - let Inspect.307 : Str = CallByName #Derived.3 Inspect.308 Inspect.312; - ret Inspect.307; - -procedure Inspect.61 (Inspect.303, Inspect.298): - let Inspect.324 : Str = CallByName Str.3 Inspect.303 Inspect.298; - dec Inspect.298; +procedure Inspect.207 (Inspect.208, #Attr.12): + let Inspect.344 : List Str = UnionAtIndex (Id 1) (Index 1) #Attr.12; + let Inspect.343 : Str = UnionAtIndex (Id 1) (Index 0) #Attr.12; + let Inspect.342 : Str = "("; + let Inspect.341 : Str = CallByName Inspect.61 Inspect.208 Inspect.342; + let Inspect.329 : Str = CallByName Inspect.61 Inspect.341 Inspect.343; + let Inspect.325 : Str = CallByName Inspect.209 Inspect.329 Inspect.344; + let Inspect.326 : Str = ")"; + let Inspect.324 : Str = CallByName Inspect.61 Inspect.325 Inspect.326; ret Inspect.324; -procedure List.1 (List.102): - let List.566 : U64 = CallByName List.6 List.102; - dec List.102; - let List.567 : U64 = 0i64; - let List.565 : Int1 = CallByName Bool.11 List.566 List.567; - ret List.565; +procedure Inspect.209 (Inspect.210, Inspect.204): + let Inspect.333 : {} = Struct {}; + let Inspect.332 : Str = CallByName List.18 Inspect.204 Inspect.210 Inspect.333; + ret Inspect.332; -procedure List.18 (List.154, List.155, List.156): - let List.554 : U64 = 0i64; - let List.555 : U64 = CallByName List.6 List.154; - let List.553 : Str = CallByName List.88 List.154 List.155 List.156 List.554 List.555; - ret List.553; +procedure Inspect.211 (Inspect.212, Inspect.213): + let Inspect.340 : Str = " "; + let Inspect.335 : Str = CallByName Inspect.61 Inspect.212 Inspect.340; + let Inspect.334 : Str = CallByName Inspect.214 Inspect.335 Inspect.213; + ret Inspect.334; + +procedure Inspect.214 (Inspect.215, Inspect.213): + let Inspect.338 : Str = CallByName Inspect.31 Inspect.213 Inspect.215; + ret Inspect.338; + +procedure Inspect.251 (Inspect.252, Inspect.250): + let Inspect.359 : Str = "\""; + let Inspect.358 : Str = CallByName Inspect.61 Inspect.252 Inspect.359; + let Inspect.356 : Str = CallByName Inspect.61 Inspect.358 Inspect.250; + let Inspect.357 : Str = "\""; + let Inspect.355 : Str = CallByName Inspect.61 Inspect.356 Inspect.357; + ret Inspect.355; + +procedure Inspect.30 (Inspect.148): + ret Inspect.148; + +procedure Inspect.30 (Inspect.148): + ret Inspect.148; + +procedure Inspect.30 (Inspect.148): + ret Inspect.148; + +procedure Inspect.31 (Inspect.307, Inspect.150): + let Inspect.319 : U8 = GetTagId Inspect.307; + switch Inspect.319: + case 0: + let Inspect.318 : Str = CallByName Inspect.205 Inspect.150 Inspect.307; + ret Inspect.318; + + default: + let Inspect.318 : Str = CallByName Inspect.207 Inspect.150 Inspect.307; + ret Inspect.318; + + +procedure Inspect.31 (Inspect.307, Inspect.150): + let Inspect.339 : Str = CallByName Inspect.251 Inspect.150 Inspect.307; + ret Inspect.339; + +procedure Inspect.34 (Inspect.153): + let Inspect.309 : Str = CallByName Inspect.5 Inspect.153; + let Inspect.308 : Str = CallByName Inspect.62 Inspect.309; + ret Inspect.308; + +procedure Inspect.36 (Inspect.305): + let Inspect.315 : Str = ""; + ret Inspect.315; + +procedure Inspect.40 (Inspect.203, Inspect.204): + inc Inspect.204; + let Inspect.345 : Int1 = CallByName List.1 Inspect.204; + if Inspect.345 then + dec Inspect.204; + let Inspect.347 : [C Str, C Str List Str] = TagId(0) Inspect.203; + let Inspect.346 : [C Str, C Str List Str] = CallByName Inspect.30 Inspect.347; + ret Inspect.346; + else + let Inspect.321 : [C Str, C Str List Str] = TagId(1) Inspect.203 Inspect.204; + let Inspect.320 : [C Str, C Str List Str] = CallByName Inspect.30 Inspect.321; + ret Inspect.320; + +procedure Inspect.44 (Inspect.250): + let Inspect.351 : Str = CallByName Inspect.30 Inspect.250; + ret Inspect.351; + +procedure Inspect.5 (Inspect.151): + let Inspect.316 : Str = CallByName #Derived.0 Inspect.151; + let Inspect.313 : {} = Struct {}; + let Inspect.312 : Str = CallByName Inspect.36 Inspect.313; + let Inspect.311 : Str = CallByName #Derived.3 Inspect.312 Inspect.316; + ret Inspect.311; + +procedure Inspect.61 (Inspect.304, Inspect.300): + let Inspect.328 : Str = CallByName Str.3 Inspect.304 Inspect.300; + dec Inspect.300; + ret Inspect.328; + +procedure Inspect.62 (Inspect.306): + ret Inspect.306; + +procedure List.1 (List.104): + let List.582 : U64 = CallByName List.6 List.104; + dec List.104; + let List.583 : U64 = 0i64; + let List.581 : Int1 = CallByName Bool.11 List.582 List.583; + ret List.581; + +procedure List.18 (List.156, List.157, List.158): + let List.570 : U64 = 0i64; + let List.571 : U64 = CallByName List.6 List.156; + let List.569 : Str = CallByName List.89 List.156 List.157 List.158 List.570 List.571; + ret List.569; procedure List.6 (#Attr.2): - let List.564 : U64 = lowlevel ListLen #Attr.2; - ret List.564; + let List.580 : U64 = lowlevel ListLen #Attr.2; + ret List.580; procedure List.66 (#Attr.2, #Attr.3): - let List.563 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.563; + let List.579 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.579; -procedure List.88 (#Derived_gen.18, #Derived_gen.19, #Derived_gen.20, #Derived_gen.21, #Derived_gen.22): - joinpoint List.556 List.157 List.158 List.159 List.160 List.161: - let List.558 : Int1 = CallByName Num.22 List.160 List.161; - if List.558 then - let List.562 : Str = CallByName List.66 List.157 List.160; - inc List.562; - let List.162 : Str = CallByName Inspect.209 List.158 List.562; - let List.561 : U64 = 1i64; - let List.560 : U64 = CallByName Num.51 List.160 List.561; - jump List.556 List.157 List.162 List.159 List.560 List.161; +procedure List.89 (#Derived_gen.20, #Derived_gen.21, #Derived_gen.22, #Derived_gen.23, #Derived_gen.24): + joinpoint List.572 List.159 List.160 List.161 List.162 List.163: + let List.574 : Int1 = CallByName Num.22 List.162 List.163; + if List.574 then + let List.578 : Str = CallByName List.66 List.159 List.162; + inc List.578; + let List.164 : Str = CallByName Inspect.211 List.160 List.578; + let List.577 : U64 = 1i64; + let List.576 : U64 = CallByName Num.51 List.162 List.577; + jump List.572 List.159 List.164 List.161 List.576 List.163; else - dec List.157; - ret List.158; + dec List.159; + ret List.160; in - jump List.556 #Derived_gen.18 #Derived_gen.19 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22; + jump List.572 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22 #Derived_gen.23 #Derived_gen.24; procedure Num.22 (#Attr.2, #Attr.3): let Num.292 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; @@ -167,7 +172,6 @@ procedure Str.3 (#Attr.2, #Attr.3): ret Str.292; procedure Test.0 (): - let Test.5 : Str = "foo"; - let Test.4 : Str = CallByName Inspect.5 Test.5; - let Test.3 : Str = CallByName Inspect.35 Test.4; + let Test.4 : Str = "foo"; + let Test.3 : Str = CallByName Inspect.34 Test.4; ret Test.3; diff --git a/crates/compiler/test_mono/generated/inspect_derived_tag_two_payloads_string.txt b/crates/compiler/test_mono/generated/inspect_derived_tag_two_payloads_string.txt index 81517e7e3f..6fe588ef1a 100644 --- a/crates/compiler/test_mono/generated/inspect_derived_tag_two_payloads_string.txt +++ b/crates/compiler/test_mono/generated/inspect_derived_tag_two_payloads_string.txt @@ -20,142 +20,147 @@ procedure Bool.11 (#Attr.2, #Attr.3): let Bool.23 : Int1 = lowlevel Eq #Attr.2 #Attr.3; ret Bool.23; -procedure Inspect.203 (Inspect.204, #Attr.12): - let Inspect.346 : Str = UnionAtIndex (Id 0) (Index 0) #Attr.12; - let Inspect.345 : Str = CallByName Inspect.61 Inspect.204 Inspect.346; - ret Inspect.345; - procedure Inspect.205 (Inspect.206, #Attr.12): - let Inspect.340 : List Str = UnionAtIndex (Id 1) (Index 1) #Attr.12; - let Inspect.339 : Str = UnionAtIndex (Id 1) (Index 0) #Attr.12; - let Inspect.338 : Str = "("; - let Inspect.337 : Str = CallByName Inspect.61 Inspect.206 Inspect.338; - let Inspect.325 : Str = CallByName Inspect.61 Inspect.337 Inspect.339; - let Inspect.321 : Str = CallByName Inspect.207 Inspect.325 Inspect.340; - let Inspect.322 : Str = ")"; - let Inspect.320 : Str = CallByName Inspect.61 Inspect.321 Inspect.322; - ret Inspect.320; + let Inspect.350 : Str = UnionAtIndex (Id 0) (Index 0) #Attr.12; + let Inspect.349 : Str = CallByName Inspect.61 Inspect.206 Inspect.350; + ret Inspect.349; -procedure Inspect.207 (Inspect.208, Inspect.202): - let Inspect.329 : {} = Struct {}; - let Inspect.328 : Str = CallByName List.18 Inspect.202 Inspect.208 Inspect.329; - ret Inspect.328; - -procedure Inspect.209 (Inspect.210, Inspect.211): - let Inspect.336 : Str = " "; - let Inspect.331 : Str = CallByName Inspect.61 Inspect.210 Inspect.336; - let Inspect.330 : Str = CallByName Inspect.212 Inspect.331 Inspect.211; - ret Inspect.330; - -procedure Inspect.212 (Inspect.213, Inspect.211): - let Inspect.334 : Str = CallByName Inspect.31 Inspect.211 Inspect.213; - ret Inspect.334; - -procedure Inspect.249 (Inspect.250, Inspect.248): - let Inspect.355 : Str = "\""; - let Inspect.354 : Str = CallByName Inspect.61 Inspect.250 Inspect.355; - let Inspect.352 : Str = CallByName Inspect.61 Inspect.354 Inspect.248; - let Inspect.353 : Str = "\""; - let Inspect.351 : Str = CallByName Inspect.61 Inspect.352 Inspect.353; - ret Inspect.351; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.30 (Inspect.147): - ret Inspect.147; - -procedure Inspect.31 (Inspect.305, Inspect.149): - let Inspect.315 : U8 = GetTagId Inspect.305; - switch Inspect.315: - case 0: - let Inspect.314 : Str = CallByName Inspect.203 Inspect.149 Inspect.305; - ret Inspect.314; - - default: - let Inspect.314 : Str = CallByName Inspect.205 Inspect.149 Inspect.305; - ret Inspect.314; - - -procedure Inspect.31 (Inspect.305, Inspect.149): - let Inspect.335 : Str = CallByName Inspect.249 Inspect.149 Inspect.305; - ret Inspect.335; - -procedure Inspect.35 (Inspect.300): - ret Inspect.300; - -procedure Inspect.36 (Inspect.304): - let Inspect.311 : Str = ""; - ret Inspect.311; - -procedure Inspect.40 (Inspect.201, Inspect.202): - inc Inspect.202; - let Inspect.341 : Int1 = CallByName List.1 Inspect.202; - if Inspect.341 then - dec Inspect.202; - let Inspect.343 : [C Str, C Str List Str] = TagId(0) Inspect.201; - let Inspect.342 : [C Str, C Str List Str] = CallByName Inspect.30 Inspect.343; - ret Inspect.342; - else - let Inspect.317 : [C Str, C Str List Str] = TagId(1) Inspect.201 Inspect.202; - let Inspect.316 : [C Str, C Str List Str] = CallByName Inspect.30 Inspect.317; - ret Inspect.316; - -procedure Inspect.44 (Inspect.248): - let Inspect.356 : Str = CallByName Inspect.30 Inspect.248; - ret Inspect.356; - -procedure Inspect.5 (Inspect.150): - let Inspect.312 : {Str, Str} = CallByName #Derived.0 Inspect.150; - let Inspect.309 : {} = Struct {}; - let Inspect.308 : Str = CallByName Inspect.36 Inspect.309; - let Inspect.307 : Str = CallByName #Derived.4 Inspect.308 Inspect.312; - ret Inspect.307; - -procedure Inspect.61 (Inspect.303, Inspect.298): - let Inspect.324 : Str = CallByName Str.3 Inspect.303 Inspect.298; - dec Inspect.298; +procedure Inspect.207 (Inspect.208, #Attr.12): + let Inspect.344 : List Str = UnionAtIndex (Id 1) (Index 1) #Attr.12; + let Inspect.343 : Str = UnionAtIndex (Id 1) (Index 0) #Attr.12; + let Inspect.342 : Str = "("; + let Inspect.341 : Str = CallByName Inspect.61 Inspect.208 Inspect.342; + let Inspect.329 : Str = CallByName Inspect.61 Inspect.341 Inspect.343; + let Inspect.325 : Str = CallByName Inspect.209 Inspect.329 Inspect.344; + let Inspect.326 : Str = ")"; + let Inspect.324 : Str = CallByName Inspect.61 Inspect.325 Inspect.326; ret Inspect.324; -procedure List.1 (List.102): - let List.566 : U64 = CallByName List.6 List.102; - dec List.102; - let List.567 : U64 = 0i64; - let List.565 : Int1 = CallByName Bool.11 List.566 List.567; - ret List.565; +procedure Inspect.209 (Inspect.210, Inspect.204): + let Inspect.333 : {} = Struct {}; + let Inspect.332 : Str = CallByName List.18 Inspect.204 Inspect.210 Inspect.333; + ret Inspect.332; -procedure List.18 (List.154, List.155, List.156): - let List.554 : U64 = 0i64; - let List.555 : U64 = CallByName List.6 List.154; - let List.553 : Str = CallByName List.88 List.154 List.155 List.156 List.554 List.555; - ret List.553; +procedure Inspect.211 (Inspect.212, Inspect.213): + let Inspect.340 : Str = " "; + let Inspect.335 : Str = CallByName Inspect.61 Inspect.212 Inspect.340; + let Inspect.334 : Str = CallByName Inspect.214 Inspect.335 Inspect.213; + ret Inspect.334; + +procedure Inspect.214 (Inspect.215, Inspect.213): + let Inspect.338 : Str = CallByName Inspect.31 Inspect.213 Inspect.215; + ret Inspect.338; + +procedure Inspect.251 (Inspect.252, Inspect.250): + let Inspect.359 : Str = "\""; + let Inspect.358 : Str = CallByName Inspect.61 Inspect.252 Inspect.359; + let Inspect.356 : Str = CallByName Inspect.61 Inspect.358 Inspect.250; + let Inspect.357 : Str = "\""; + let Inspect.355 : Str = CallByName Inspect.61 Inspect.356 Inspect.357; + ret Inspect.355; + +procedure Inspect.30 (Inspect.148): + ret Inspect.148; + +procedure Inspect.30 (Inspect.148): + ret Inspect.148; + +procedure Inspect.30 (Inspect.148): + ret Inspect.148; + +procedure Inspect.31 (Inspect.307, Inspect.150): + let Inspect.319 : U8 = GetTagId Inspect.307; + switch Inspect.319: + case 0: + let Inspect.318 : Str = CallByName Inspect.205 Inspect.150 Inspect.307; + ret Inspect.318; + + default: + let Inspect.318 : Str = CallByName Inspect.207 Inspect.150 Inspect.307; + ret Inspect.318; + + +procedure Inspect.31 (Inspect.307, Inspect.150): + let Inspect.339 : Str = CallByName Inspect.251 Inspect.150 Inspect.307; + ret Inspect.339; + +procedure Inspect.34 (Inspect.153): + let Inspect.309 : Str = CallByName Inspect.5 Inspect.153; + let Inspect.308 : Str = CallByName Inspect.62 Inspect.309; + ret Inspect.308; + +procedure Inspect.36 (Inspect.305): + let Inspect.315 : Str = ""; + ret Inspect.315; + +procedure Inspect.40 (Inspect.203, Inspect.204): + inc Inspect.204; + let Inspect.345 : Int1 = CallByName List.1 Inspect.204; + if Inspect.345 then + dec Inspect.204; + let Inspect.347 : [C Str, C Str List Str] = TagId(0) Inspect.203; + let Inspect.346 : [C Str, C Str List Str] = CallByName Inspect.30 Inspect.347; + ret Inspect.346; + else + let Inspect.321 : [C Str, C Str List Str] = TagId(1) Inspect.203 Inspect.204; + let Inspect.320 : [C Str, C Str List Str] = CallByName Inspect.30 Inspect.321; + ret Inspect.320; + +procedure Inspect.44 (Inspect.250): + let Inspect.360 : Str = CallByName Inspect.30 Inspect.250; + ret Inspect.360; + +procedure Inspect.5 (Inspect.151): + let Inspect.316 : {Str, Str} = CallByName #Derived.0 Inspect.151; + let Inspect.313 : {} = Struct {}; + let Inspect.312 : Str = CallByName Inspect.36 Inspect.313; + let Inspect.311 : Str = CallByName #Derived.4 Inspect.312 Inspect.316; + ret Inspect.311; + +procedure Inspect.61 (Inspect.304, Inspect.300): + let Inspect.328 : Str = CallByName Str.3 Inspect.304 Inspect.300; + dec Inspect.300; + ret Inspect.328; + +procedure Inspect.62 (Inspect.306): + ret Inspect.306; + +procedure List.1 (List.104): + let List.582 : U64 = CallByName List.6 List.104; + dec List.104; + let List.583 : U64 = 0i64; + let List.581 : Int1 = CallByName Bool.11 List.582 List.583; + ret List.581; + +procedure List.18 (List.156, List.157, List.158): + let List.570 : U64 = 0i64; + let List.571 : U64 = CallByName List.6 List.156; + let List.569 : Str = CallByName List.89 List.156 List.157 List.158 List.570 List.571; + ret List.569; procedure List.6 (#Attr.2): - let List.564 : U64 = lowlevel ListLen #Attr.2; - ret List.564; + let List.580 : U64 = lowlevel ListLen #Attr.2; + ret List.580; procedure List.66 (#Attr.2, #Attr.3): - let List.563 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.563; + let List.579 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.579; -procedure List.88 (#Derived_gen.19, #Derived_gen.20, #Derived_gen.21, #Derived_gen.22, #Derived_gen.23): - joinpoint List.556 List.157 List.158 List.159 List.160 List.161: - let List.558 : Int1 = CallByName Num.22 List.160 List.161; - if List.558 then - let List.562 : Str = CallByName List.66 List.157 List.160; - inc List.562; - let List.162 : Str = CallByName Inspect.209 List.158 List.562; - let List.561 : U64 = 1i64; - let List.560 : U64 = CallByName Num.51 List.160 List.561; - jump List.556 List.157 List.162 List.159 List.560 List.161; +procedure List.89 (#Derived_gen.13, #Derived_gen.14, #Derived_gen.15, #Derived_gen.16, #Derived_gen.17): + joinpoint List.572 List.159 List.160 List.161 List.162 List.163: + let List.574 : Int1 = CallByName Num.22 List.162 List.163; + if List.574 then + let List.578 : Str = CallByName List.66 List.159 List.162; + inc List.578; + let List.164 : Str = CallByName Inspect.211 List.160 List.578; + let List.577 : U64 = 1i64; + let List.576 : U64 = CallByName Num.51 List.162 List.577; + jump List.572 List.159 List.164 List.161 List.576 List.163; else - dec List.157; - ret List.158; + dec List.159; + ret List.160; in - jump List.556 #Derived_gen.19 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22 #Derived_gen.23; + jump List.572 #Derived_gen.13 #Derived_gen.14 #Derived_gen.15 #Derived_gen.16 #Derived_gen.17; procedure Num.22 (#Attr.2, #Attr.3): let Num.292 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; @@ -170,9 +175,8 @@ procedure Str.3 (#Attr.2, #Attr.3): ret Str.292; procedure Test.0 (): - let Test.6 : Str = "foo"; let Test.5 : Str = "foo"; - let Test.1 : {Str, Str} = Struct {Test.5, Test.6}; - let Test.4 : Str = CallByName Inspect.5 Test.1; - let Test.3 : Str = CallByName Inspect.35 Test.4; + let Test.4 : Str = "foo"; + let Test.1 : {Str, Str} = Struct {Test.4, Test.5}; + let Test.3 : Str = CallByName Inspect.34 Test.1; ret Test.3; diff --git a/crates/compiler/test_mono/generated/ir_int_add.txt b/crates/compiler/test_mono/generated/ir_int_add.txt index 0a5abcf8e0..d60f7829b8 100644 --- a/crates/compiler/test_mono/generated/ir_int_add.txt +++ b/crates/compiler/test_mono/generated/ir_int_add.txt @@ -1,6 +1,6 @@ procedure List.6 (#Attr.2): - let List.553 : U64 = lowlevel ListLen #Attr.2; - ret List.553; + let List.569 : U64 = lowlevel ListLen #Attr.2; + ret List.569; procedure Num.19 (#Attr.2, #Attr.3): let Num.293 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; 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 a3a0659c20..b332177e71 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 @@ -6,42 +6,42 @@ procedure Bool.2 (): let Bool.23 : Int1 = true; ret Bool.23; -procedure List.2 (List.103, List.104): - let List.567 : U64 = CallByName List.6 List.103; - let List.563 : Int1 = CallByName Num.22 List.104 List.567; - if List.563 then - let List.565 : I64 = CallByName List.66 List.103 List.104; - dec List.103; - let List.564 : [C {}, C I64] = TagId(1) List.565; - ret List.564; +procedure List.2 (List.105, List.106): + let List.583 : U64 = CallByName List.6 List.105; + let List.579 : Int1 = CallByName Num.22 List.106 List.583; + if List.579 then + let List.581 : I64 = CallByName List.66 List.105 List.106; + dec List.105; + let List.580 : [C {}, C I64] = TagId(1) List.581; + ret List.580; else - dec List.103; - let List.562 : {} = Struct {}; - let List.561 : [C {}, C I64] = TagId(0) List.562; - ret List.561; + dec List.105; + let List.578 : {} = Struct {}; + let List.577 : [C {}, C I64] = TagId(0) List.578; + ret List.577; procedure List.6 (#Attr.2): - let List.568 : U64 = lowlevel ListLen #Attr.2; - ret List.568; + let List.584 : U64 = lowlevel ListLen #Attr.2; + ret List.584; procedure List.66 (#Attr.2, #Attr.3): - let List.566 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.566; + let List.582 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.582; -procedure List.9 (List.315): - let List.560 : U64 = 0i64; - let List.553 : [C {}, C I64] = CallByName List.2 List.315 List.560; - let List.557 : U8 = 1i64; - let List.558 : U8 = GetTagId List.553; - let List.559 : Int1 = lowlevel Eq List.557 List.558; - if List.559 then - let List.316 : I64 = UnionAtIndex (Id 1) (Index 0) List.553; - let List.554 : [C Int1, C I64] = TagId(1) List.316; - ret List.554; +procedure List.9 (List.331): + let List.576 : U64 = 0i64; + let List.569 : [C {}, C I64] = CallByName List.2 List.331 List.576; + let List.573 : U8 = 1i64; + let List.574 : U8 = GetTagId List.569; + let List.575 : Int1 = lowlevel Eq List.573 List.574; + if List.575 then + let List.332 : I64 = UnionAtIndex (Id 1) (Index 0) List.569; + let List.570 : [C Int1, C I64] = TagId(1) List.332; + ret List.570; else - let List.556 : Int1 = true; - let List.555 : [C Int1, C I64] = TagId(0) List.556; - ret List.555; + let List.572 : Int1 = true; + let List.571 : [C Int1, C I64] = TagId(0) List.572; + ret List.571; procedure Num.22 (#Attr.2, #Attr.3): let Num.291 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/issue_4749.txt b/crates/compiler/test_mono/generated/issue_4749.txt index d72ad5c1a0..8735610956 100644 --- a/crates/compiler/test_mono/generated/issue_4749.txt +++ b/crates/compiler/test_mono/generated/issue_4749.txt @@ -64,119 +64,119 @@ procedure Decode.27 (Decode.107, Decode.108): let Decode.123 : [C [C List U8, C ], C Str] = TagId(0) Decode.124; ret Decode.123; -procedure List.1 (List.102): - let List.607 : U64 = CallByName List.6 List.102; - dec List.102; - let List.608 : U64 = 0i64; - let List.606 : Int1 = CallByName Bool.11 List.607 List.608; - ret List.606; +procedure List.1 (List.104): + let List.623 : U64 = CallByName List.6 List.104; + dec List.104; + let List.624 : U64 = 0i64; + let List.622 : Int1 = CallByName Bool.11 List.623 List.624; + ret List.622; -procedure List.2 (List.103, List.104): - let List.598 : U64 = CallByName List.6 List.103; - let List.595 : Int1 = CallByName Num.22 List.104 List.598; - if List.595 then - let List.597 : U8 = CallByName List.66 List.103 List.104; - dec List.103; - let List.596 : [C {}, C U8] = TagId(1) List.597; - ret List.596; +procedure List.101 (List.484, List.485, List.486): + let List.632 : U64 = 0i64; + let List.633 : U64 = CallByName List.6 List.484; + let List.631 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName List.80 List.484 List.485 List.486 List.632 List.633; + ret List.631; + +procedure List.2 (List.105, List.106): + let List.614 : U64 = CallByName List.6 List.105; + let List.611 : Int1 = CallByName Num.22 List.106 List.614; + if List.611 then + let List.613 : U8 = CallByName List.66 List.105 List.106; + dec List.105; + let List.612 : [C {}, C U8] = TagId(1) List.613; + ret List.612; else - dec List.103; - let List.594 : {} = Struct {}; - let List.593 : [C {}, C U8] = TagId(0) List.594; - ret List.593; + dec List.105; + let List.610 : {} = Struct {}; + let List.609 : [C {}, C U8] = TagId(0) List.610; + ret List.609; -procedure List.26 (List.181, List.182, List.183): - let List.609 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName List.99 List.181 List.182 List.183; - let List.612 : U8 = 1i64; - let List.613 : U8 = GetTagId List.609; - let List.614 : Int1 = lowlevel Eq List.612 List.613; - if List.614 then - let List.184 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 1) (Index 0) List.609; - ret List.184; +procedure List.26 (List.197, List.198, List.199): + let List.625 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName List.101 List.197 List.198 List.199; + let List.628 : U8 = 1i64; + let List.629 : U8 = GetTagId List.625; + let List.630 : Int1 = lowlevel Eq List.628 List.629; + if List.630 then + let List.200 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 1) (Index 0) List.625; + ret List.200; else - let List.185 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 0) (Index 0) List.609; - ret List.185; + let List.201 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 0) (Index 0) List.625; + ret List.201; -procedure List.38 (List.324, List.325): - let List.575 : U64 = CallByName List.6 List.324; - let List.326 : U64 = CallByName Num.77 List.575 List.325; - let List.574 : List U8 = CallByName List.43 List.324 List.326; +procedure List.38 (List.340, List.341): + let List.591 : U64 = CallByName List.6 List.340; + let List.342 : U64 = CallByName Num.77 List.591 List.341; + let List.590 : List U8 = CallByName List.43 List.340 List.342; + ret List.590; + +procedure List.4 (List.121, List.122): + let List.601 : U64 = 1i64; + let List.600 : List U8 = CallByName List.70 List.121 List.601; + let List.599 : List U8 = CallByName List.71 List.600 List.122; + ret List.599; + +procedure List.43 (List.338, List.339): + let List.581 : U64 = CallByName List.6 List.338; + let List.580 : U64 = CallByName Num.77 List.581 List.339; + let List.575 : {U64, U64} = Struct {List.339, List.580}; + let List.574 : List U8 = CallByName List.49 List.338 List.575; ret List.574; -procedure List.4 (List.119, List.120): - let List.585 : U64 = 1i64; - let List.584 : List U8 = CallByName List.70 List.119 List.585; - let List.583 : List U8 = CallByName List.71 List.584 List.120; - ret List.583; - -procedure List.43 (List.322, List.323): - let List.565 : U64 = CallByName List.6 List.322; - let List.564 : U64 = CallByName Num.77 List.565 List.323; - let List.559 : {U64, U64} = Struct {List.323, List.564}; - let List.558 : List U8 = CallByName List.49 List.322 List.559; - ret List.558; - -procedure List.49 (List.400, List.401): - let List.603 : U64 = StructAtIndex 1 List.401; - let List.604 : U64 = StructAtIndex 0 List.401; - let List.602 : List U8 = CallByName List.72 List.400 List.603 List.604; - ret List.602; +procedure List.49 (List.416, List.417): + let List.619 : U64 = StructAtIndex 1 List.417; + let List.620 : U64 = StructAtIndex 0 List.417; + let List.618 : List U8 = CallByName List.72 List.416 List.619 List.620; + ret List.618; procedure List.6 (#Attr.2): - let List.630 : U64 = lowlevel ListLen #Attr.2; - ret List.630; + let List.646 : U64 = lowlevel ListLen #Attr.2; + ret List.646; procedure List.66 (#Attr.2, #Attr.3): - let List.591 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.591; + let List.607 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.607; procedure List.70 (#Attr.2, #Attr.3): - let List.582 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.582; + let List.598 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.598; procedure List.71 (#Attr.2, #Attr.3): - let List.580 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.580; + let List.596 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.596; procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.563 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.563; + let List.579 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.579; procedure List.8 (#Attr.2, #Attr.3): - let List.577 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.577; + let List.593 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.593; procedure List.80 (#Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4, #Derived_gen.5): - joinpoint List.618 List.471 List.472 List.473 List.474 List.475: - let List.620 : Int1 = CallByName Num.22 List.474 List.475; - if List.620 then - let List.629 : U8 = CallByName List.66 List.471 List.474; - let List.621 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName TotallyNotJson.62 List.472 List.629; - let List.626 : U8 = 1i64; - let List.627 : U8 = GetTagId List.621; - let List.628 : Int1 = lowlevel Eq List.626 List.627; - if List.628 then - let List.476 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 1) (Index 0) List.621; - let List.624 : U64 = 1i64; - let List.623 : U64 = CallByName Num.51 List.474 List.624; - jump List.618 List.471 List.476 List.473 List.623 List.475; + joinpoint List.634 List.487 List.488 List.489 List.490 List.491: + let List.636 : Int1 = CallByName Num.22 List.490 List.491; + if List.636 then + let List.645 : U8 = CallByName List.66 List.487 List.490; + let List.637 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName TotallyNotJson.62 List.488 List.645; + let List.642 : U8 = 1i64; + let List.643 : U8 = GetTagId List.637; + let List.644 : Int1 = lowlevel Eq List.642 List.643; + if List.644 then + let List.492 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 1) (Index 0) List.637; + let List.640 : U64 = 1i64; + let List.639 : U64 = CallByName Num.51 List.490 List.640; + jump List.634 List.487 List.492 List.489 List.639 List.491; else - dec List.471; - let List.477 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 0) (Index 0) List.621; - let List.625 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = TagId(0) List.477; - ret List.625; + dec List.487; + let List.493 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 0) (Index 0) List.637; + let List.641 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = TagId(0) List.493; + ret List.641; else - dec List.471; - let List.619 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = TagId(1) List.472; - ret List.619; + dec List.487; + let List.635 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = TagId(1) List.488; + ret List.635; in - jump List.618 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4 #Derived_gen.5; - -procedure List.99 (List.468, List.469, List.470): - let List.616 : U64 = 0i64; - let List.617 : U64 = CallByName List.6 List.468; - let List.615 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName List.80 List.468 List.469 List.470 List.616 List.617; - ret List.615; + jump List.634 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4 #Derived_gen.5; procedure Num.19 (#Attr.2, #Attr.3): let Num.294 : U8 = lowlevel NumAdd #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/issue_4770.txt b/crates/compiler/test_mono/generated/issue_4770.txt index 9cd75dd441..d1d59b8a8f 100644 --- a/crates/compiler/test_mono/generated/issue_4770.txt +++ b/crates/compiler/test_mono/generated/issue_4770.txt @@ -6,80 +6,80 @@ procedure Bool.2 (): let Bool.24 : Int1 = true; ret Bool.24; -procedure List.216 (List.555, List.217, List.215): - let List.585 : Int1 = CallByName Test.1 List.217; - if List.585 then - let List.587 : {} = Struct {}; - let List.586 : [C {}, C {}] = TagId(1) List.587; - ret List.586; - else - let List.584 : {} = Struct {}; - let List.583 : [C {}, C {}] = TagId(0) List.584; - ret List.583; - -procedure List.23 (#Attr.2, #Attr.3, #Attr.4): - let List.588 : List {[C I64, C List *self], [C I64, C List *self]} = lowlevel ListMap2 { xs: `#Attr.#arg1`, ys: `#Attr.#arg2` } #Attr.2 #Attr.3 Test.15 #Attr.4; - decref #Attr.3; - decref #Attr.2; - ret List.588; - -procedure List.56 (List.214, List.215): - let List.564 : {} = Struct {}; - let List.556 : [C {}, C {}] = CallByName List.99 List.214 List.564 List.215; - let List.561 : U8 = 1i64; - let List.562 : U8 = GetTagId List.556; - let List.563 : Int1 = lowlevel Eq List.561 List.562; - if List.563 then - let List.557 : Int1 = CallByName Bool.2; - ret List.557; - else - let List.558 : Int1 = CallByName Bool.1; - ret List.558; - -procedure List.6 (#Attr.2): - let List.554 : U64 = lowlevel ListLen #Attr.2; - ret List.554; - -procedure List.6 (#Attr.2): - let List.582 : U64 = lowlevel ListLen #Attr.2; +procedure List.101 (List.484, List.485, List.486): + let List.583 : U64 = 0i64; + let List.584 : U64 = CallByName List.6 List.484; + let List.582 : [C {}, C {}] = CallByName List.80 List.484 List.485 List.486 List.583 List.584; ret List.582; +procedure List.23 (#Attr.2, #Attr.3, #Attr.4): + let List.604 : List {[C I64, C List *self], [C I64, C List *self]} = lowlevel ListMap2 { xs: `#Attr.#arg1`, ys: `#Attr.#arg2` } #Attr.2 #Attr.3 Test.15 #Attr.4; + decref #Attr.3; + decref #Attr.2; + ret List.604; + +procedure List.232 (List.571, List.233, List.231): + let List.601 : Int1 = CallByName Test.1 List.233; + if List.601 then + let List.603 : {} = Struct {}; + let List.602 : [C {}, C {}] = TagId(1) List.603; + ret List.602; + else + let List.600 : {} = Struct {}; + let List.599 : [C {}, C {}] = TagId(0) List.600; + ret List.599; + +procedure List.56 (List.230, List.231): + let List.580 : {} = Struct {}; + let List.572 : [C {}, C {}] = CallByName List.101 List.230 List.580 List.231; + let List.577 : U8 = 1i64; + let List.578 : U8 = GetTagId List.572; + let List.579 : Int1 = lowlevel Eq List.577 List.578; + if List.579 then + let List.573 : Int1 = CallByName Bool.2; + ret List.573; + else + let List.574 : Int1 = CallByName Bool.1; + ret List.574; + +procedure List.6 (#Attr.2): + let List.570 : U64 = lowlevel ListLen #Attr.2; + ret List.570; + +procedure List.6 (#Attr.2): + let List.598 : U64 = lowlevel ListLen #Attr.2; + ret List.598; + procedure List.66 (#Attr.2, #Attr.3): - let List.581 : {[C I64, C List *self], [C I64, C List *self]} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.581; + let List.597 : {[C I64, C List *self], [C I64, C List *self]} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.597; procedure List.80 (#Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4, #Derived_gen.5): - joinpoint List.569 List.471 List.472 List.473 List.474 List.475: - let List.571 : Int1 = CallByName Num.22 List.474 List.475; - if List.571 then - let List.580 : {[C I64, C List *self], [C I64, C List *self]} = CallByName List.66 List.471 List.474; - inc List.580; - let List.572 : [C {}, C {}] = CallByName List.216 List.472 List.580 List.473; - let List.577 : U8 = 1i64; - let List.578 : U8 = GetTagId List.572; - let List.579 : Int1 = lowlevel Eq List.577 List.578; - if List.579 then - let List.476 : {} = UnionAtIndex (Id 1) (Index 0) List.572; - let List.575 : U64 = 1i64; - let List.574 : U64 = CallByName Num.51 List.474 List.575; - jump List.569 List.471 List.476 List.473 List.574 List.475; + joinpoint List.585 List.487 List.488 List.489 List.490 List.491: + let List.587 : Int1 = CallByName Num.22 List.490 List.491; + if List.587 then + let List.596 : {[C I64, C List *self], [C I64, C List *self]} = CallByName List.66 List.487 List.490; + inc List.596; + let List.588 : [C {}, C {}] = CallByName List.232 List.488 List.596 List.489; + let List.593 : U8 = 1i64; + let List.594 : U8 = GetTagId List.588; + let List.595 : Int1 = lowlevel Eq List.593 List.594; + if List.595 then + let List.492 : {} = UnionAtIndex (Id 1) (Index 0) List.588; + let List.591 : U64 = 1i64; + let List.590 : U64 = CallByName Num.51 List.490 List.591; + jump List.585 List.487 List.492 List.489 List.590 List.491; else - dec List.471; - let List.477 : {} = UnionAtIndex (Id 0) (Index 0) List.572; - let List.576 : [C {}, C {}] = TagId(0) List.477; - ret List.576; + dec List.487; + let List.493 : {} = UnionAtIndex (Id 0) (Index 0) List.588; + let List.592 : [C {}, C {}] = TagId(0) List.493; + ret List.592; else - dec List.471; - let List.570 : [C {}, C {}] = TagId(1) List.472; - ret List.570; + dec List.487; + let List.586 : [C {}, C {}] = TagId(1) List.488; + ret List.586; in - jump List.569 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4 #Derived_gen.5; - -procedure List.99 (List.468, List.469, List.470): - let List.567 : U64 = 0i64; - let List.568 : U64 = CallByName List.6 List.468; - let List.566 : [C {}, C {}] = CallByName List.80 List.468 List.469 List.470 List.567 List.568; - ret List.566; + jump List.585 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4 #Derived_gen.5; procedure Num.22 (#Attr.2, #Attr.3): let Num.291 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; 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 0d16b9f45a..449451bdf7 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 @@ -38,119 +38,119 @@ procedure Decode.26 (Decode.105, Decode.106): let Decode.122 : {List U8, [C {}, C Str]} = CallByName Decode.25 Decode.105 Decode.123 Decode.106; ret Decode.122; -procedure List.1 (List.102): - let List.603 : U64 = CallByName List.6 List.102; - dec List.102; - let List.604 : U64 = 0i64; - let List.602 : Int1 = CallByName Bool.11 List.603 List.604; - ret List.602; +procedure List.1 (List.104): + let List.619 : U64 = CallByName List.6 List.104; + dec List.104; + let List.620 : U64 = 0i64; + let List.618 : Int1 = CallByName Bool.11 List.619 List.620; + ret List.618; -procedure List.2 (List.103, List.104): - let List.594 : U64 = CallByName List.6 List.103; - let List.591 : Int1 = CallByName Num.22 List.104 List.594; - if List.591 then - let List.593 : U8 = CallByName List.66 List.103 List.104; - dec List.103; - let List.592 : [C {}, C U8] = TagId(1) List.593; - ret List.592; +procedure List.101 (List.484, List.485, List.486): + let List.628 : U64 = 0i64; + let List.629 : U64 = CallByName List.6 List.484; + let List.627 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName List.80 List.484 List.485 List.486 List.628 List.629; + ret List.627; + +procedure List.2 (List.105, List.106): + let List.610 : U64 = CallByName List.6 List.105; + let List.607 : Int1 = CallByName Num.22 List.106 List.610; + if List.607 then + let List.609 : U8 = CallByName List.66 List.105 List.106; + dec List.105; + let List.608 : [C {}, C U8] = TagId(1) List.609; + ret List.608; else - dec List.103; - let List.590 : {} = Struct {}; - let List.589 : [C {}, C U8] = TagId(0) List.590; - ret List.589; + dec List.105; + let List.606 : {} = Struct {}; + let List.605 : [C {}, C U8] = TagId(0) List.606; + ret List.605; -procedure List.26 (List.181, List.182, List.183): - let List.605 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName List.99 List.181 List.182 List.183; - let List.608 : U8 = 1i64; - let List.609 : U8 = GetTagId List.605; - let List.610 : Int1 = lowlevel Eq List.608 List.609; - if List.610 then - let List.184 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 1) (Index 0) List.605; - ret List.184; +procedure List.26 (List.197, List.198, List.199): + let List.621 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName List.101 List.197 List.198 List.199; + let List.624 : U8 = 1i64; + let List.625 : U8 = GetTagId List.621; + let List.626 : Int1 = lowlevel Eq List.624 List.625; + if List.626 then + let List.200 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 1) (Index 0) List.621; + ret List.200; else - let List.185 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 0) (Index 0) List.605; - ret List.185; + let List.201 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 0) (Index 0) List.621; + ret List.201; -procedure List.38 (List.324, List.325): - let List.571 : U64 = CallByName List.6 List.324; - let List.326 : U64 = CallByName Num.77 List.571 List.325; - let List.570 : List U8 = CallByName List.43 List.324 List.326; +procedure List.38 (List.340, List.341): + let List.587 : U64 = CallByName List.6 List.340; + let List.342 : U64 = CallByName Num.77 List.587 List.341; + let List.586 : List U8 = CallByName List.43 List.340 List.342; + ret List.586; + +procedure List.4 (List.121, List.122): + let List.597 : U64 = 1i64; + let List.596 : List U8 = CallByName List.70 List.121 List.597; + let List.595 : List U8 = CallByName List.71 List.596 List.122; + ret List.595; + +procedure List.43 (List.338, List.339): + let List.577 : U64 = CallByName List.6 List.338; + let List.576 : U64 = CallByName Num.77 List.577 List.339; + let List.571 : {U64, U64} = Struct {List.339, List.576}; + let List.570 : List U8 = CallByName List.49 List.338 List.571; ret List.570; -procedure List.4 (List.119, List.120): - let List.581 : U64 = 1i64; - let List.580 : List U8 = CallByName List.70 List.119 List.581; - let List.579 : List U8 = CallByName List.71 List.580 List.120; - ret List.579; - -procedure List.43 (List.322, List.323): - let List.561 : U64 = CallByName List.6 List.322; - let List.560 : U64 = CallByName Num.77 List.561 List.323; - let List.555 : {U64, U64} = Struct {List.323, List.560}; - let List.554 : List U8 = CallByName List.49 List.322 List.555; - ret List.554; - -procedure List.49 (List.400, List.401): - let List.599 : U64 = StructAtIndex 1 List.401; - let List.600 : U64 = StructAtIndex 0 List.401; - let List.598 : List U8 = CallByName List.72 List.400 List.599 List.600; - ret List.598; +procedure List.49 (List.416, List.417): + let List.615 : U64 = StructAtIndex 1 List.417; + let List.616 : U64 = StructAtIndex 0 List.417; + let List.614 : List U8 = CallByName List.72 List.416 List.615 List.616; + ret List.614; procedure List.6 (#Attr.2): - let List.626 : U64 = lowlevel ListLen #Attr.2; - ret List.626; + let List.642 : U64 = lowlevel ListLen #Attr.2; + ret List.642; procedure List.66 (#Attr.2, #Attr.3): - let List.587 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.587; + let List.603 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.603; procedure List.70 (#Attr.2, #Attr.3): - let List.578 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.578; + let List.594 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.594; procedure List.71 (#Attr.2, #Attr.3): - let List.576 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.576; + let List.592 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.592; procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.559 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.559; + let List.575 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.575; procedure List.8 (#Attr.2, #Attr.3): - let List.573 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.573; + let List.589 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.589; procedure List.80 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): - joinpoint List.614 List.471 List.472 List.473 List.474 List.475: - let List.616 : Int1 = CallByName Num.22 List.474 List.475; - if List.616 then - let List.625 : U8 = CallByName List.66 List.471 List.474; - let List.617 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName TotallyNotJson.62 List.472 List.625; - let List.622 : U8 = 1i64; - let List.623 : U8 = GetTagId List.617; - let List.624 : Int1 = lowlevel Eq List.622 List.623; - if List.624 then - let List.476 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 1) (Index 0) List.617; - let List.620 : U64 = 1i64; - let List.619 : U64 = CallByName Num.51 List.474 List.620; - jump List.614 List.471 List.476 List.473 List.619 List.475; + joinpoint List.630 List.487 List.488 List.489 List.490 List.491: + let List.632 : Int1 = CallByName Num.22 List.490 List.491; + if List.632 then + let List.641 : U8 = CallByName List.66 List.487 List.490; + let List.633 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName TotallyNotJson.62 List.488 List.641; + let List.638 : U8 = 1i64; + let List.639 : U8 = GetTagId List.633; + let List.640 : Int1 = lowlevel Eq List.638 List.639; + if List.640 then + let List.492 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 1) (Index 0) List.633; + let List.636 : U64 = 1i64; + let List.635 : U64 = CallByName Num.51 List.490 List.636; + jump List.630 List.487 List.492 List.489 List.635 List.491; else - dec List.471; - let List.477 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 0) (Index 0) List.617; - let List.621 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = TagId(0) List.477; - ret List.621; + dec List.487; + let List.493 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 0) (Index 0) List.633; + let List.637 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = TagId(0) List.493; + ret List.637; else - dec List.471; - let List.615 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = TagId(1) List.472; - ret List.615; + dec List.487; + let List.631 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = TagId(1) List.488; + ret List.631; in - jump List.614 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; - -procedure List.99 (List.468, List.469, List.470): - let List.612 : U64 = 0i64; - let List.613 : U64 = CallByName List.6 List.468; - let List.611 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName List.80 List.468 List.469 List.470 List.612 List.613; - ret List.611; + jump List.630 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; procedure Num.19 (#Attr.2, #Attr.3): let Num.294 : U8 = lowlevel NumAdd #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/issue_6196.txt b/crates/compiler/test_mono/generated/issue_6196.txt new file mode 100644 index 0000000000..c360b15845 --- /dev/null +++ b/crates/compiler/test_mono/generated/issue_6196.txt @@ -0,0 +1,47 @@ +procedure Num.20 (#Attr.2, #Attr.3): + let Num.291 : U64 = lowlevel NumSub #Attr.2 #Attr.3; + ret Num.291; + +procedure Test.1 (#Derived_gen.0, #Derived_gen.1): + joinpoint Test.12 Test.2 Test.3: + let Test.13 : {List Str, U64} = Struct {Test.2, Test.3}; + let Test.31 : List Str = StructAtIndex 0 Test.13; + let Test.32 : U64 = lowlevel ListLen Test.31; + let Test.33 : U64 = 1i64; + let Test.34 : Int1 = lowlevel NumGte Test.32 Test.33; + if Test.34 then + let Test.28 : U64 = StructAtIndex 1 Test.13; + let Test.29 : U64 = 0i64; + let Test.30 : Int1 = lowlevel Eq Test.29 Test.28; + if Test.30 then + let Test.21 : List Str = StructAtIndex 0 Test.13; + let Test.22 : U64 = 0i64; + let Test.6 : Str = lowlevel ListGetUnsafe Test.21 Test.22; + inc Test.6; + dec Test.21; + let Test.16 : [C {}, C Str] = TagId(1) Test.6; + ret Test.16; + else + let Test.23 : List Str = StructAtIndex 0 Test.13; + let Test.24 : U64 = 1i64; + let Test.25 : U64 = lowlevel ListLen Test.23; + let Test.26 : U64 = lowlevel NumSub Test.25 Test.24; + let Test.27 : U64 = 1i64; + let Test.8 : List Str = lowlevel ListSublist Test.23 Test.27 Test.26; + let Test.19 : U64 = 1i64; + let Test.18 : U64 = CallByName Num.20 Test.3 Test.19; + jump Test.12 Test.8 Test.18; + else + dec Test.31; + let Test.15 : {} = Struct {}; + let Test.14 : [C {}, C Str] = TagId(0) Test.15; + ret Test.14; + in + jump Test.12 #Derived_gen.0 #Derived_gen.1; + +procedure Test.0 (): + let Test.35 : Str = "a"; + let Test.10 : List Str = Array [Test.35]; + let Test.11 : U64 = 0i64; + let Test.9 : [C {}, C Str] = CallByName Test.1 Test.10 Test.11; + ret Test.9; diff --git a/crates/compiler/test_mono/generated/layout_cache_structure_with_multiple_recursive_structures.txt b/crates/compiler/test_mono/generated/layout_cache_structure_with_multiple_recursive_structures.txt index 02aa6f86cc..169634192e 100644 --- a/crates/compiler/test_mono/generated/layout_cache_structure_with_multiple_recursive_structures.txt +++ b/crates/compiler/test_mono/generated/layout_cache_structure_with_multiple_recursive_structures.txt @@ -1,32 +1,32 @@ -procedure List.18 (List.154, List.155, List.156): - let List.554 : U64 = 0i64; - let List.555 : U64 = CallByName List.6 List.154; - let List.553 : [, C {[C *self, ], *self}] = CallByName List.88 List.154 List.155 List.156 List.554 List.555; - ret List.553; +procedure List.18 (List.156, List.157, List.158): + let List.570 : U64 = 0i64; + let List.571 : U64 = CallByName List.6 List.156; + let List.569 : [, C {[C *self, ], *self}] = CallByName List.89 List.156 List.157 List.158 List.570 List.571; + ret List.569; procedure List.6 (#Attr.2): - let List.564 : U64 = lowlevel ListLen #Attr.2; - ret List.564; + let List.580 : U64 = lowlevel ListLen #Attr.2; + ret List.580; procedure List.66 (#Attr.2, #Attr.3): - let List.563 : [C *self, ] = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.563; + let List.579 : [C *self, ] = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.579; -procedure List.88 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): - joinpoint List.556 List.157 List.158 List.159 List.160 List.161: - let List.558 : Int1 = CallByName Num.22 List.160 List.161; - if List.558 then - let List.562 : [C *self, ] = CallByName List.66 List.157 List.160; - inc List.562; - let List.162 : [, C {[C *self, ], *self}] = CallByName Test.7 List.158 List.562; - let List.561 : U64 = 1i64; - let List.560 : U64 = CallByName Num.51 List.160 List.561; - jump List.556 List.157 List.162 List.159 List.560 List.161; +procedure List.89 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): + joinpoint List.572 List.159 List.160 List.161 List.162 List.163: + let List.574 : Int1 = CallByName Num.22 List.162 List.163; + if List.574 then + let List.578 : [C *self, ] = CallByName List.66 List.159 List.162; + inc List.578; + let List.164 : [, C {[C *self, ], *self}] = CallByName Test.7 List.160 List.578; + let List.577 : U64 = 1i64; + let List.576 : U64 = CallByName Num.51 List.162 List.577; + jump List.572 List.159 List.164 List.161 List.576 List.163; else - dec List.157; - ret List.158; + dec List.159; + ret List.160; in - jump List.556 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; + jump List.572 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; procedure Num.22 (#Attr.2, #Attr.3): let Num.292 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/list_append.txt b/crates/compiler/test_mono/generated/list_append.txt index 68165ad865..e8fcc57811 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.119, List.120): - let List.556 : U64 = 1i64; - let List.554 : List I64 = CallByName List.70 List.119 List.556; - let List.553 : List I64 = CallByName List.71 List.554 List.120; - ret List.553; +procedure List.4 (List.121, List.122): + let List.572 : U64 = 1i64; + let List.570 : List I64 = CallByName List.70 List.121 List.572; + let List.569 : List I64 = CallByName List.71 List.570 List.122; + ret List.569; procedure List.70 (#Attr.2, #Attr.3): - let List.557 : List I64 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.557; + let List.573 : List I64 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.573; procedure List.71 (#Attr.2, #Attr.3): - let List.555 : List I64 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.555; + let List.571 : List I64 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.571; 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 11a5ca5b96..c635c46e0d 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.119, List.120): - let List.556 : U64 = 1i64; - let List.554 : List I64 = CallByName List.70 List.119 List.556; - let List.553 : List I64 = CallByName List.71 List.554 List.120; - ret List.553; +procedure List.4 (List.121, List.122): + let List.572 : U64 = 1i64; + let List.570 : List I64 = CallByName List.70 List.121 List.572; + let List.569 : List I64 = CallByName List.71 List.570 List.122; + ret List.569; procedure List.70 (#Attr.2, #Attr.3): - let List.557 : List I64 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.557; + let List.573 : List I64 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.573; procedure List.71 (#Attr.2, #Attr.3): - let List.555 : List I64 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.555; + let List.571 : List I64 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.571; 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 6038c09534..ac188ff54a 100644 --- a/crates/compiler/test_mono/generated/list_cannot_update_inplace.txt +++ b/crates/compiler/test_mono/generated/list_cannot_update_inplace.txt @@ -1,25 +1,25 @@ -procedure List.3 (List.111, List.112, List.113): - let List.556 : {List I64, I64} = CallByName List.64 List.111 List.112 List.113; - let List.555 : List I64 = StructAtIndex 0 List.556; - ret List.555; +procedure List.3 (List.113, List.114, List.115): + let List.572 : {List I64, I64} = CallByName List.64 List.113 List.114 List.115; + let List.571 : List I64 = StructAtIndex 0 List.572; + ret List.571; procedure List.6 (#Attr.2): - let List.554 : U64 = lowlevel ListLen #Attr.2; - ret List.554; + let List.570 : U64 = lowlevel ListLen #Attr.2; + ret List.570; -procedure List.64 (List.108, List.109, List.110): - let List.561 : U64 = CallByName List.6 List.108; - let List.558 : Int1 = CallByName Num.22 List.109 List.561; - if List.558 then - let List.559 : {List I64, I64} = CallByName List.67 List.108 List.109 List.110; - ret List.559; +procedure List.64 (List.110, List.111, List.112): + let List.577 : U64 = CallByName List.6 List.110; + let List.574 : Int1 = CallByName Num.22 List.111 List.577; + if List.574 then + let List.575 : {List I64, I64} = CallByName List.67 List.110 List.111 List.112; + ret List.575; else - let List.557 : {List I64, I64} = Struct {List.108, List.110}; - ret List.557; + let List.573 : {List I64, I64} = Struct {List.110, List.112}; + ret List.573; procedure List.67 (#Attr.2, #Attr.3, #Attr.4): - let List.560 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; - ret List.560; + let List.576 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; + ret List.576; procedure Num.19 (#Attr.2, #Attr.3): let Num.291 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/list_get.txt b/crates/compiler/test_mono/generated/list_get.txt index 8c1e4b395a..bf50499e0a 100644 --- a/crates/compiler/test_mono/generated/list_get.txt +++ b/crates/compiler/test_mono/generated/list_get.txt @@ -1,24 +1,24 @@ -procedure List.2 (List.103, List.104): - let List.559 : U64 = CallByName List.6 List.103; - let List.555 : Int1 = CallByName Num.22 List.104 List.559; - if List.555 then - let List.557 : I64 = CallByName List.66 List.103 List.104; - dec List.103; - let List.556 : [C {}, C I64] = TagId(1) List.557; - ret List.556; +procedure List.2 (List.105, List.106): + let List.575 : U64 = CallByName List.6 List.105; + let List.571 : Int1 = CallByName Num.22 List.106 List.575; + if List.571 then + let List.573 : I64 = CallByName List.66 List.105 List.106; + dec List.105; + let List.572 : [C {}, C I64] = TagId(1) List.573; + ret List.572; else - dec List.103; - let List.554 : {} = Struct {}; - let List.553 : [C {}, C I64] = TagId(0) List.554; - ret List.553; + dec List.105; + let List.570 : {} = Struct {}; + let List.569 : [C {}, C I64] = TagId(0) List.570; + ret List.569; procedure List.6 (#Attr.2): - let List.560 : U64 = lowlevel ListLen #Attr.2; - ret List.560; + let List.576 : U64 = lowlevel ListLen #Attr.2; + ret List.576; procedure List.66 (#Attr.2, #Attr.3): - let List.558 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.558; + let List.574 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.574; procedure Num.22 (#Attr.2, #Attr.3): let Num.291 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/list_len.txt b/crates/compiler/test_mono/generated/list_len.txt index 8d011e3bb8..e51c03489a 100644 --- a/crates/compiler/test_mono/generated/list_len.txt +++ b/crates/compiler/test_mono/generated/list_len.txt @@ -1,10 +1,10 @@ procedure List.6 (#Attr.2): - let List.553 : U64 = lowlevel ListLen #Attr.2; - ret List.553; + let List.569 : U64 = lowlevel ListLen #Attr.2; + ret List.569; procedure List.6 (#Attr.2): - let List.554 : U64 = lowlevel ListLen #Attr.2; - ret List.554; + let List.570 : U64 = lowlevel ListLen #Attr.2; + ret List.570; procedure Num.19 (#Attr.2, #Attr.3): let Num.291 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; 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 92ed7cb7f8..f3eee0fa87 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.103, List.104): - let List.559 : U64 = CallByName List.6 List.103; - let List.555 : Int1 = CallByName Num.22 List.104 List.559; - if List.555 then - let List.557 : Str = CallByName List.66 List.103 List.104; - inc List.557; - dec List.103; - let List.556 : [C {}, C Str] = TagId(1) List.557; - ret List.556; +procedure List.2 (List.105, List.106): + let List.575 : U64 = CallByName List.6 List.105; + let List.571 : Int1 = CallByName Num.22 List.106 List.575; + if List.571 then + let List.573 : Str = CallByName List.66 List.105 List.106; + inc List.573; + dec List.105; + let List.572 : [C {}, C Str] = TagId(1) List.573; + ret List.572; else - dec List.103; - let List.554 : {} = Struct {}; - let List.553 : [C {}, C Str] = TagId(0) List.554; - ret List.553; + dec List.105; + let List.570 : {} = Struct {}; + let List.569 : [C {}, C Str] = TagId(0) List.570; + ret List.569; procedure List.5 (#Attr.2, #Attr.3): - let List.561 : List Str = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.3 #Attr.3; + let List.577 : List Str = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.3 #Attr.3; decref #Attr.2; - ret List.561; + ret List.577; procedure List.6 (#Attr.2): - let List.560 : U64 = lowlevel ListLen #Attr.2; - ret List.560; + let List.576 : U64 = lowlevel ListLen #Attr.2; + ret List.576; procedure List.66 (#Attr.2, #Attr.3): - let List.558 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.558; + let List.574 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.574; procedure Num.22 (#Attr.2, #Attr.3): let Num.291 : Int1 = lowlevel NumLt #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 ce29fe588d..876f2b41c2 100644 --- a/crates/compiler/test_mono/generated/list_map_closure_owns.txt +++ b/crates/compiler/test_mono/generated/list_map_closure_owns.txt @@ -1,30 +1,30 @@ -procedure List.2 (List.103, List.104): - let List.559 : U64 = CallByName List.6 List.103; - let List.555 : Int1 = CallByName Num.22 List.104 List.559; - if List.555 then - let List.557 : Str = CallByName List.66 List.103 List.104; - inc List.557; - dec List.103; - let List.556 : [C {}, C Str] = TagId(1) List.557; - ret List.556; +procedure List.2 (List.105, List.106): + let List.575 : U64 = CallByName List.6 List.105; + let List.571 : Int1 = CallByName Num.22 List.106 List.575; + if List.571 then + let List.573 : Str = CallByName List.66 List.105 List.106; + inc List.573; + dec List.105; + let List.572 : [C {}, C Str] = TagId(1) List.573; + ret List.572; else - dec List.103; - let List.554 : {} = Struct {}; - let List.553 : [C {}, C Str] = TagId(0) List.554; - ret List.553; + dec List.105; + let List.570 : {} = Struct {}; + let List.569 : [C {}, C Str] = TagId(0) List.570; + ret List.569; procedure List.5 (#Attr.2, #Attr.3): - let List.561 : List Str = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.3 #Attr.3; + let List.577 : List Str = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.3 #Attr.3; decref #Attr.2; - ret List.561; + ret List.577; procedure List.6 (#Attr.2): - let List.560 : U64 = lowlevel ListLen #Attr.2; - ret List.560; + let List.576 : U64 = lowlevel ListLen #Attr.2; + ret List.576; procedure List.66 (#Attr.2, #Attr.3): - let List.558 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.558; + let List.574 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.574; procedure Num.22 (#Attr.2, #Attr.3): let Num.291 : Int1 = lowlevel NumLt #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 149fc14bbf..7dc61e3768 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,23 +1,23 @@ procedure List.5 (#Attr.2, #Attr.3): - let List.554 : U8 = GetTagId #Attr.3; - joinpoint List.555 List.553: - ret List.553; + let List.570 : U8 = GetTagId #Attr.3; + joinpoint List.571 List.569: + ret List.569; in - switch List.554: + switch List.570: case 0: - let List.556 : List U8 = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.4 #Attr.3; + let List.572 : List U8 = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.4 #Attr.3; decref #Attr.2; - jump List.555 List.556; + jump List.571 List.572; case 1: - let List.557 : List U8 = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.6 #Attr.3; + let List.573 : List U8 = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.6 #Attr.3; decref #Attr.2; - jump List.555 List.557; + jump List.571 List.573; default: - let List.558 : List U8 = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.8 #Attr.3; + let List.574 : List U8 = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.8 #Attr.3; decref #Attr.2; - jump List.555 List.558; + jump List.571 List.574; procedure Num.19 (#Attr.2, #Attr.3): 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 1e8fb3e67e..37faccea1f 100644 --- a/crates/compiler/test_mono/generated/list_pass_to_function.txt +++ b/crates/compiler/test_mono/generated/list_pass_to_function.txt @@ -1,25 +1,25 @@ -procedure List.3 (List.111, List.112, List.113): - let List.554 : {List I64, I64} = CallByName List.64 List.111 List.112 List.113; - let List.553 : List I64 = StructAtIndex 0 List.554; - ret List.553; +procedure List.3 (List.113, List.114, List.115): + let List.570 : {List I64, I64} = CallByName List.64 List.113 List.114 List.115; + let List.569 : List I64 = StructAtIndex 0 List.570; + ret List.569; procedure List.6 (#Attr.2): - let List.560 : U64 = lowlevel ListLen #Attr.2; - ret List.560; + let List.576 : U64 = lowlevel ListLen #Attr.2; + ret List.576; -procedure List.64 (List.108, List.109, List.110): - let List.559 : U64 = CallByName List.6 List.108; - let List.556 : Int1 = CallByName Num.22 List.109 List.559; - if List.556 then - let List.557 : {List I64, I64} = CallByName List.67 List.108 List.109 List.110; - ret List.557; +procedure List.64 (List.110, List.111, List.112): + let List.575 : U64 = CallByName List.6 List.110; + let List.572 : Int1 = CallByName Num.22 List.111 List.575; + if List.572 then + let List.573 : {List I64, I64} = CallByName List.67 List.110 List.111 List.112; + ret List.573; else - let List.555 : {List I64, I64} = Struct {List.108, List.110}; - ret List.555; + let List.571 : {List I64, I64} = Struct {List.110, List.112}; + ret List.571; procedure List.67 (#Attr.2, #Attr.3, #Attr.4): - let List.558 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; - ret List.558; + let List.574 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; + ret List.574; procedure Num.22 (#Attr.2, #Attr.3): let Num.291 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/list_sort_asc.txt b/crates/compiler/test_mono/generated/list_sort_asc.txt index 30ce74da82..48800b0b1c 100644 --- a/crates/compiler/test_mono/generated/list_sort_asc.txt +++ b/crates/compiler/test_mono/generated/list_sort_asc.txt @@ -1,11 +1,11 @@ procedure List.28 (#Attr.2, #Attr.3): - let List.555 : List I64 = lowlevel ListSortWith { xs: `#Attr.#arg1` } #Attr.2 Num.46 #Attr.3; - ret List.555; + let List.571 : List I64 = lowlevel ListSortWith { xs: `#Attr.#arg1` } #Attr.2 Num.46 #Attr.3; + ret List.571; -procedure List.59 (List.310): - let List.554 : {} = Struct {}; - let List.553 : List I64 = CallByName List.28 List.310 List.554; - ret List.553; +procedure List.59 (List.326): + let List.570 : {} = Struct {}; + let List.569 : List I64 = CallByName List.28 List.326 List.570; + ret List.569; procedure Num.46 (#Attr.2, #Attr.3): let Num.291 : U8 = lowlevel NumCompare #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/quicksort_swap.txt b/crates/compiler/test_mono/generated/quicksort_swap.txt index b22f35c6aa..176c1a7a5c 100644 --- a/crates/compiler/test_mono/generated/quicksort_swap.txt +++ b/crates/compiler/test_mono/generated/quicksort_swap.txt @@ -1,43 +1,43 @@ -procedure List.2 (List.103, List.104): - let List.575 : U64 = CallByName List.6 List.103; - let List.572 : Int1 = CallByName Num.22 List.104 List.575; - if List.572 then - let List.574 : I64 = CallByName List.66 List.103 List.104; - dec List.103; - let List.573 : [C {}, C I64] = TagId(1) List.574; - ret List.573; +procedure List.2 (List.105, List.106): + let List.591 : U64 = CallByName List.6 List.105; + let List.588 : Int1 = CallByName Num.22 List.106 List.591; + if List.588 then + let List.590 : I64 = CallByName List.66 List.105 List.106; + dec List.105; + let List.589 : [C {}, C I64] = TagId(1) List.590; + ret List.589; else - dec List.103; - let List.571 : {} = Struct {}; - let List.570 : [C {}, C I64] = TagId(0) List.571; - ret List.570; + dec List.105; + let List.587 : {} = Struct {}; + let List.586 : [C {}, C I64] = TagId(0) List.587; + ret List.586; -procedure List.3 (List.111, List.112, List.113): - let List.562 : {List I64, I64} = CallByName List.64 List.111 List.112 List.113; - let List.561 : List I64 = StructAtIndex 0 List.562; - ret List.561; +procedure List.3 (List.113, List.114, List.115): + let List.578 : {List I64, I64} = CallByName List.64 List.113 List.114 List.115; + let List.577 : List I64 = StructAtIndex 0 List.578; + ret List.577; procedure List.6 (#Attr.2): - let List.560 : U64 = lowlevel ListLen #Attr.2; - ret List.560; + let List.576 : U64 = lowlevel ListLen #Attr.2; + ret List.576; -procedure List.64 (List.108, List.109, List.110): - let List.559 : U64 = CallByName List.6 List.108; - let List.556 : Int1 = CallByName Num.22 List.109 List.559; - if List.556 then - let List.557 : {List I64, I64} = CallByName List.67 List.108 List.109 List.110; - ret List.557; +procedure List.64 (List.110, List.111, List.112): + let List.575 : U64 = CallByName List.6 List.110; + let List.572 : Int1 = CallByName Num.22 List.111 List.575; + if List.572 then + let List.573 : {List I64, I64} = CallByName List.67 List.110 List.111 List.112; + ret List.573; else - let List.555 : {List I64, I64} = Struct {List.108, List.110}; - ret List.555; + let List.571 : {List I64, I64} = Struct {List.110, List.112}; + ret List.571; procedure List.66 (#Attr.2, #Attr.3): - let List.568 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.568; + let List.584 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.584; procedure List.67 (#Attr.2, #Attr.3, #Attr.4): - let List.558 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; - ret List.558; + let List.574 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; + ret List.574; procedure Num.22 (#Attr.2, #Attr.3): let Num.293 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/record_update.txt b/crates/compiler/test_mono/generated/record_update.txt index a6b9900def..3b23383988 100644 --- a/crates/compiler/test_mono/generated/record_update.txt +++ b/crates/compiler/test_mono/generated/record_update.txt @@ -1,25 +1,25 @@ -procedure List.3 (List.111, List.112, List.113): - let List.562 : {List U64, U64} = CallByName List.64 List.111 List.112 List.113; - let List.561 : List U64 = StructAtIndex 0 List.562; - ret List.561; +procedure List.3 (List.113, List.114, List.115): + let List.578 : {List U64, U64} = CallByName List.64 List.113 List.114 List.115; + let List.577 : List U64 = StructAtIndex 0 List.578; + ret List.577; procedure List.6 (#Attr.2): - let List.560 : U64 = lowlevel ListLen #Attr.2; - ret List.560; + let List.576 : U64 = lowlevel ListLen #Attr.2; + ret List.576; -procedure List.64 (List.108, List.109, List.110): - let List.559 : U64 = CallByName List.6 List.108; - let List.556 : Int1 = CallByName Num.22 List.109 List.559; - if List.556 then - let List.557 : {List U64, U64} = CallByName List.67 List.108 List.109 List.110; - ret List.557; +procedure List.64 (List.110, List.111, List.112): + let List.575 : U64 = CallByName List.6 List.110; + let List.572 : Int1 = CallByName Num.22 List.111 List.575; + if List.572 then + let List.573 : {List U64, U64} = CallByName List.67 List.110 List.111 List.112; + ret List.573; else - let List.555 : {List U64, U64} = Struct {List.108, List.110}; - ret List.555; + let List.571 : {List U64, U64} = Struct {List.110, List.112}; + ret List.571; procedure List.67 (#Attr.2, #Attr.3, #Attr.4): - let List.558 : {List U64, U64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; - ret List.558; + let List.574 : {List U64, U64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; + ret List.574; procedure Num.22 (#Attr.2, #Attr.3): let Num.291 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/recursive_function_and_union_with_inference_hole.txt b/crates/compiler/test_mono/generated/recursive_function_and_union_with_inference_hole.txt index 28ab73bf6d..1d8626f04d 100644 --- a/crates/compiler/test_mono/generated/recursive_function_and_union_with_inference_hole.txt +++ b/crates/compiler/test_mono/generated/recursive_function_and_union_with_inference_hole.txt @@ -1,7 +1,7 @@ procedure List.5 (#Attr.2, #Attr.3): - let List.553 : List [C List *self] = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.2 #Attr.3; + let List.569 : List [C List *self] = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.2 #Attr.3; decref #Attr.2; - ret List.553; + ret List.569; procedure Test.2 (Test.5): let Test.6 : List [C List *self] = UnionAtIndex (Id 0) (Index 0) Test.5; diff --git a/crates/compiler/test_mono/generated/rigids.txt b/crates/compiler/test_mono/generated/rigids.txt index 313ba111dd..12c3f4fcd0 100644 --- a/crates/compiler/test_mono/generated/rigids.txt +++ b/crates/compiler/test_mono/generated/rigids.txt @@ -1,43 +1,43 @@ -procedure List.2 (List.103, List.104): - let List.575 : U64 = CallByName List.6 List.103; - let List.572 : Int1 = CallByName Num.22 List.104 List.575; - if List.572 then - let List.574 : I64 = CallByName List.66 List.103 List.104; - dec List.103; - let List.573 : [C {}, C I64] = TagId(1) List.574; - ret List.573; +procedure List.2 (List.105, List.106): + let List.591 : U64 = CallByName List.6 List.105; + let List.588 : Int1 = CallByName Num.22 List.106 List.591; + if List.588 then + let List.590 : I64 = CallByName List.66 List.105 List.106; + dec List.105; + let List.589 : [C {}, C I64] = TagId(1) List.590; + ret List.589; else - dec List.103; - let List.571 : {} = Struct {}; - let List.570 : [C {}, C I64] = TagId(0) List.571; - ret List.570; + dec List.105; + let List.587 : {} = Struct {}; + let List.586 : [C {}, C I64] = TagId(0) List.587; + ret List.586; -procedure List.3 (List.111, List.112, List.113): - let List.562 : {List I64, I64} = CallByName List.64 List.111 List.112 List.113; - let List.561 : List I64 = StructAtIndex 0 List.562; - ret List.561; +procedure List.3 (List.113, List.114, List.115): + let List.578 : {List I64, I64} = CallByName List.64 List.113 List.114 List.115; + let List.577 : List I64 = StructAtIndex 0 List.578; + ret List.577; procedure List.6 (#Attr.2): - let List.560 : U64 = lowlevel ListLen #Attr.2; - ret List.560; + let List.576 : U64 = lowlevel ListLen #Attr.2; + ret List.576; -procedure List.64 (List.108, List.109, List.110): - let List.559 : U64 = CallByName List.6 List.108; - let List.556 : Int1 = CallByName Num.22 List.109 List.559; - if List.556 then - let List.557 : {List I64, I64} = CallByName List.67 List.108 List.109 List.110; - ret List.557; +procedure List.64 (List.110, List.111, List.112): + let List.575 : U64 = CallByName List.6 List.110; + let List.572 : Int1 = CallByName Num.22 List.111 List.575; + if List.572 then + let List.573 : {List I64, I64} = CallByName List.67 List.110 List.111 List.112; + ret List.573; else - let List.555 : {List I64, I64} = Struct {List.108, List.110}; - ret List.555; + let List.571 : {List I64, I64} = Struct {List.110, List.112}; + ret List.571; procedure List.66 (#Attr.2, #Attr.3): - let List.568 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.568; + let List.584 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.584; procedure List.67 (#Attr.2, #Attr.3, #Attr.4): - let List.558 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; - ret List.558; + let List.574 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; + ret List.574; procedure Num.22 (#Attr.2, #Attr.3): let Num.293 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; 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 index 91c3e884f1..f8b6a8eced 100644 --- 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 @@ -29,159 +29,159 @@ procedure Encode.26 (Encode.105, Encode.106): let Encode.108 : List U8 = CallByName Encode.24 Encode.109 Encode.110 Encode.106; ret Encode.108; -procedure List.18 (List.154, List.155, List.156): - let List.580 : U64 = 0i64; - let List.581 : U64 = CallByName List.6 List.154; - let List.579 : {List U8, U64} = CallByName List.88 List.154 List.155 List.156 List.580 List.581; - ret List.579; +procedure List.101 (List.484, List.485, List.486): + let List.652 : U64 = 0i64; + let List.653 : U64 = CallByName List.6 List.484; + let List.651 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.484 List.485 List.486 List.652 List.653; + ret List.651; -procedure List.18 (List.154, List.155, List.156): - let List.592 : U64 = 0i64; - let List.593 : U64 = CallByName List.6 List.154; - let List.591 : List U8 = CallByName List.88 List.154 List.155 List.156 List.592 List.593; - ret List.591; +procedure List.18 (List.156, List.157, List.158): + let List.596 : U64 = 0i64; + let List.597 : U64 = CallByName List.6 List.156; + let List.595 : {List U8, U64} = CallByName List.89 List.156 List.157 List.158 List.596 List.597; + ret List.595; -procedure List.26 (List.181, List.182, List.183): - let List.629 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.99 List.181 List.182 List.183; - let List.632 : U8 = 1i64; - let List.633 : U8 = GetTagId List.629; - let List.634 : Int1 = lowlevel Eq List.632 List.633; - if List.634 then - let List.184 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.629; - ret List.184; +procedure List.18 (List.156, List.157, List.158): + let List.608 : U64 = 0i64; + let List.609 : U64 = CallByName List.6 List.156; + let List.607 : List U8 = CallByName List.89 List.156 List.157 List.158 List.608 List.609; + ret List.607; + +procedure List.26 (List.197, List.198, List.199): + let List.645 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.101 List.197 List.198 List.199; + let List.648 : U8 = 1i64; + let List.649 : U8 = GetTagId List.645; + let List.650 : Int1 = lowlevel Eq List.648 List.649; + if List.650 then + let List.200 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.645; + ret List.200; else - let List.185 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.629; - ret List.185; + let List.201 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.645; + ret List.201; -procedure List.4 (List.119, List.120): - let List.578 : U64 = 1i64; - let List.577 : List U8 = CallByName List.70 List.119 List.578; - let List.576 : List U8 = CallByName List.71 List.577 List.120; - ret List.576; +procedure List.4 (List.121, List.122): + let List.594 : U64 = 1i64; + let List.593 : List U8 = CallByName List.70 List.121 List.594; + let List.592 : List U8 = CallByName List.71 List.593 List.122; + ret List.592; -procedure List.49 (List.400, List.401): - let List.620 : U64 = StructAtIndex 1 List.401; - let List.621 : U64 = StructAtIndex 0 List.401; - let List.619 : List U8 = CallByName List.72 List.400 List.620 List.621; +procedure List.49 (List.416, List.417): + let List.636 : U64 = StructAtIndex 1 List.417; + let List.637 : U64 = StructAtIndex 0 List.417; + let List.635 : List U8 = CallByName List.72 List.416 List.636 List.637; + ret List.635; + +procedure List.52 (List.431, List.432): + let List.433 : U64 = CallByName List.6 List.431; + joinpoint List.643 List.434: + let List.641 : U64 = 0i64; + let List.640 : {U64, U64} = Struct {List.434, List.641}; + inc List.431; + let List.435 : List U8 = CallByName List.49 List.431 List.640; + let List.639 : U64 = CallByName Num.75 List.433 List.434; + let List.634 : {U64, U64} = Struct {List.639, List.434}; + let List.436 : List U8 = CallByName List.49 List.431 List.634; + let List.633 : {List U8, List U8} = Struct {List.435, List.436}; + ret List.633; + in + let List.644 : Int1 = CallByName Num.24 List.433 List.432; + if List.644 then + jump List.643 List.432; + else + jump List.643 List.433; + +procedure List.6 (#Attr.2): + let List.619 : U64 = lowlevel ListLen #Attr.2; ret List.619; -procedure List.52 (List.415, List.416): - let List.417 : U64 = CallByName List.6 List.415; - joinpoint List.627 List.418: - let List.625 : U64 = 0i64; - let List.624 : {U64, U64} = Struct {List.418, List.625}; - inc List.415; - let List.419 : List U8 = CallByName List.49 List.415 List.624; - let List.623 : U64 = CallByName Num.75 List.417 List.418; - let List.618 : {U64, U64} = Struct {List.623, List.418}; - let List.420 : List U8 = CallByName List.49 List.415 List.618; - let List.617 : {List U8, List U8} = Struct {List.419, List.420}; - ret List.617; - in - let List.628 : Int1 = CallByName Num.24 List.417 List.416; - if List.628 then - jump List.627 List.416; - else - jump List.627 List.417; - procedure List.6 (#Attr.2): - let List.603 : U64 = lowlevel ListLen #Attr.2; - ret List.603; + let List.621 : U64 = lowlevel ListLen #Attr.2; + ret List.621; -procedure List.6 (#Attr.2): - let List.605 : U64 = lowlevel ListLen #Attr.2; +procedure List.66 (#Attr.2, #Attr.3): + let List.605 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; ret List.605; procedure List.66 (#Attr.2, #Attr.3): - let List.589 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.589; - -procedure List.66 (#Attr.2, #Attr.3): - let List.601 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.601; + let List.617 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.617; procedure List.68 (#Attr.2): - let List.616 : List U8 = lowlevel ListWithCapacity #Attr.2; - ret List.616; + let List.632 : List U8 = lowlevel ListWithCapacity #Attr.2; + ret List.632; procedure List.70 (#Attr.2, #Attr.3): - let List.557 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.557; + let List.573 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.573; procedure List.71 (#Attr.2, #Attr.3): - let List.555 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.555; + let List.571 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.571; procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.622 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.622; + let List.638 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.638; procedure List.8 (#Attr.2, #Attr.3): - let List.614 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.614; + let List.630 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.630; -procedure List.80 (#Derived_gen.13, #Derived_gen.14, #Derived_gen.15, #Derived_gen.16, #Derived_gen.17): - joinpoint List.638 List.471 List.472 List.473 List.474 List.475: - let List.640 : Int1 = CallByName Num.22 List.474 List.475; - if List.640 then - let List.649 : U8 = CallByName List.66 List.471 List.474; - let List.641 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.472 List.649; - let List.646 : U8 = 1i64; - let List.647 : U8 = GetTagId List.641; - let List.648 : Int1 = lowlevel Eq List.646 List.647; - if List.648 then - let List.476 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.641; - let List.644 : U64 = 1i64; - let List.643 : U64 = CallByName Num.51 List.474 List.644; - jump List.638 List.471 List.476 List.473 List.643 List.475; +procedure List.80 (#Derived_gen.8, #Derived_gen.9, #Derived_gen.10, #Derived_gen.11, #Derived_gen.12): + joinpoint List.654 List.487 List.488 List.489 List.490 List.491: + let List.656 : Int1 = CallByName Num.22 List.490 List.491; + if List.656 then + let List.665 : U8 = CallByName List.66 List.487 List.490; + let List.657 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.488 List.665; + let List.662 : U8 = 1i64; + let List.663 : U8 = GetTagId List.657; + let List.664 : Int1 = lowlevel Eq List.662 List.663; + if List.664 then + let List.492 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.657; + let List.660 : U64 = 1i64; + let List.659 : U64 = CallByName Num.51 List.490 List.660; + jump List.654 List.487 List.492 List.489 List.659 List.491; else - dec List.471; - let List.477 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.641; - let List.645 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.477; - ret List.645; + dec List.487; + let List.493 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.657; + let List.661 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.493; + ret List.661; else - dec List.471; - let List.639 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.472; - ret List.639; + dec List.487; + let List.655 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.488; + ret List.655; in - jump List.638 #Derived_gen.13 #Derived_gen.14 #Derived_gen.15 #Derived_gen.16 #Derived_gen.17; + jump List.654 #Derived_gen.8 #Derived_gen.9 #Derived_gen.10 #Derived_gen.11 #Derived_gen.12; -procedure List.88 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): - joinpoint List.582 List.157 List.158 List.159 List.160 List.161: - let List.584 : Int1 = CallByName Num.22 List.160 List.161; - if List.584 then - let List.588 : Str = CallByName List.66 List.157 List.160; - inc List.588; - let List.162 : {List U8, U64} = CallByName TotallyNotJson.267 List.158 List.588 List.159; - let List.587 : U64 = 1i64; - let List.586 : U64 = CallByName Num.51 List.160 List.587; - jump List.582 List.157 List.162 List.159 List.586 List.161; +procedure List.89 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): + joinpoint List.598 List.159 List.160 List.161 List.162 List.163: + let List.600 : Int1 = CallByName Num.22 List.162 List.163; + if List.600 then + let List.604 : Str = CallByName List.66 List.159 List.162; + inc List.604; + let List.164 : {List U8, U64} = CallByName TotallyNotJson.267 List.160 List.604 List.161; + let List.603 : U64 = 1i64; + let List.602 : U64 = CallByName Num.51 List.162 List.603; + jump List.598 List.159 List.164 List.161 List.602 List.163; else - dec List.157; - ret List.158; + dec List.159; + ret List.160; in - jump List.582 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; + jump List.598 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; -procedure List.88 (#Derived_gen.8, #Derived_gen.9, #Derived_gen.10, #Derived_gen.11, #Derived_gen.12): - joinpoint List.594 List.157 List.158 List.159 List.160 List.161: - let List.596 : Int1 = CallByName Num.22 List.160 List.161; - if List.596 then - let List.600 : U8 = CallByName List.66 List.157 List.160; - let List.162 : List U8 = CallByName TotallyNotJson.215 List.158 List.600; - let List.599 : U64 = 1i64; - let List.598 : U64 = CallByName Num.51 List.160 List.599; - jump List.594 List.157 List.162 List.159 List.598 List.161; +procedure List.89 (#Derived_gen.13, #Derived_gen.14, #Derived_gen.15, #Derived_gen.16, #Derived_gen.17): + joinpoint List.610 List.159 List.160 List.161 List.162 List.163: + let List.612 : Int1 = CallByName Num.22 List.162 List.163; + if List.612 then + let List.616 : U8 = CallByName List.66 List.159 List.162; + let List.164 : List U8 = CallByName TotallyNotJson.215 List.160 List.616; + let List.615 : U64 = 1i64; + let List.614 : U64 = CallByName Num.51 List.162 List.615; + jump List.610 List.159 List.164 List.161 List.614 List.163; else - dec List.157; - ret List.158; + dec List.159; + ret List.160; in - jump List.594 #Derived_gen.8 #Derived_gen.9 #Derived_gen.10 #Derived_gen.11 #Derived_gen.12; - -procedure List.99 (List.468, List.469, List.470): - let List.636 : U64 = 0i64; - let List.637 : U64 = CallByName List.6 List.468; - let List.635 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.468 List.469 List.470 List.636 List.637; - ret List.635; + jump List.610 #Derived_gen.13 #Derived_gen.14 #Derived_gen.15 #Derived_gen.16 #Derived_gen.17; procedure Num.127 (#Attr.2): let Num.298 : U8 = lowlevel NumIntCast #Attr.2; 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 index c492774c62..9fc42a535d 100644 --- 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 @@ -81,81 +81,81 @@ procedure Encode.26 (Encode.105, Encode.106): let Encode.108 : List U8 = CallByName Encode.24 Encode.109 Encode.110 Encode.106; ret Encode.108; -procedure List.18 (List.154, List.155, List.156): - let List.580 : U64 = 0i64; - let List.581 : U64 = CallByName List.6 List.154; - let List.579 : {List U8, U64} = CallByName List.88 List.154 List.155 List.156 List.580 List.581; - ret List.579; - -procedure List.18 (List.154, List.155, List.156): - let List.620 : U64 = 0i64; - let List.621 : U64 = CallByName List.6 List.154; - let List.619 : {List U8, U64} = CallByName List.88 List.154 List.155 List.156 List.620 List.621; - ret List.619; - -procedure List.4 (List.119, List.120): - let List.618 : U64 = 1i64; - let List.617 : List U8 = CallByName List.70 List.119 List.618; - let List.616 : List U8 = CallByName List.71 List.617 List.120; - ret List.616; - -procedure List.6 (#Attr.2): - let List.591 : U64 = lowlevel ListLen #Attr.2; - ret List.591; - -procedure List.6 (#Attr.2): - let List.631 : U64 = lowlevel ListLen #Attr.2; - ret List.631; - -procedure List.66 (#Attr.2, #Attr.3): - let List.589 : [C {}, C {}] = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.589; - -procedure List.66 (#Attr.2, #Attr.3): - let List.629 : [] = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.629; - -procedure List.70 (#Attr.2, #Attr.3): - let List.597 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.597; - -procedure List.71 (#Attr.2, #Attr.3): - let List.595 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; +procedure List.18 (List.156, List.157, List.158): + let List.596 : U64 = 0i64; + let List.597 : U64 = CallByName List.6 List.156; + let List.595 : {List U8, U64} = CallByName List.89 List.156 List.157 List.158 List.596 List.597; ret List.595; -procedure List.8 (#Attr.2, #Attr.3): - let List.632 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; +procedure List.18 (List.156, List.157, List.158): + let List.636 : U64 = 0i64; + let List.637 : U64 = CallByName List.6 List.156; + let List.635 : {List U8, U64} = CallByName List.89 List.156 List.157 List.158 List.636 List.637; + ret List.635; + +procedure List.4 (List.121, List.122): + let List.634 : U64 = 1i64; + let List.633 : List U8 = CallByName List.70 List.121 List.634; + let List.632 : List U8 = CallByName List.71 List.633 List.122; ret List.632; -procedure List.88 (#Derived_gen.29, #Derived_gen.30, #Derived_gen.31, #Derived_gen.32, #Derived_gen.33): - joinpoint List.622 List.157 List.158 List.159 List.160 List.161: - let List.624 : Int1 = CallByName Num.22 List.160 List.161; - if List.624 then - let List.628 : [] = CallByName List.66 List.157 List.160; - let List.162 : {List U8, U64} = CallByName TotallyNotJson.267 List.158 List.628 List.159; - let List.627 : U64 = 1i64; - let List.626 : U64 = CallByName Num.51 List.160 List.627; - jump List.622 List.157 List.162 List.159 List.626 List.161; - else - dec List.157; - ret List.158; - in - jump List.622 #Derived_gen.29 #Derived_gen.30 #Derived_gen.31 #Derived_gen.32 #Derived_gen.33; +procedure List.6 (#Attr.2): + let List.607 : U64 = lowlevel ListLen #Attr.2; + ret List.607; -procedure List.88 (#Derived_gen.37, #Derived_gen.38, #Derived_gen.39, #Derived_gen.40, #Derived_gen.41): - joinpoint List.582 List.157 List.158 List.159 List.160 List.161: - let List.584 : Int1 = CallByName Num.22 List.160 List.161; - if List.584 then - let List.588 : [C {}, C {}] = CallByName List.66 List.157 List.160; - let List.162 : {List U8, U64} = CallByName TotallyNotJson.267 List.158 List.588 List.159; - let List.587 : U64 = 1i64; - let List.586 : U64 = CallByName Num.51 List.160 List.587; - jump List.582 List.157 List.162 List.159 List.586 List.161; +procedure List.6 (#Attr.2): + let List.647 : U64 = lowlevel ListLen #Attr.2; + ret List.647; + +procedure List.66 (#Attr.2, #Attr.3): + let List.605 : [C {}, C {}] = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.605; + +procedure List.66 (#Attr.2, #Attr.3): + let List.645 : [] = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.645; + +procedure List.70 (#Attr.2, #Attr.3): + let List.613 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.613; + +procedure List.71 (#Attr.2, #Attr.3): + let List.611 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.611; + +procedure List.8 (#Attr.2, #Attr.3): + let List.648 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.648; + +procedure List.89 (#Derived_gen.20, #Derived_gen.21, #Derived_gen.22, #Derived_gen.23, #Derived_gen.24): + joinpoint List.598 List.159 List.160 List.161 List.162 List.163: + let List.600 : Int1 = CallByName Num.22 List.162 List.163; + if List.600 then + let List.604 : [C {}, C {}] = CallByName List.66 List.159 List.162; + let List.164 : {List U8, U64} = CallByName TotallyNotJson.267 List.160 List.604 List.161; + let List.603 : U64 = 1i64; + let List.602 : U64 = CallByName Num.51 List.162 List.603; + jump List.598 List.159 List.164 List.161 List.602 List.163; else - dec List.157; - ret List.158; + dec List.159; + ret List.160; in - jump List.582 #Derived_gen.37 #Derived_gen.38 #Derived_gen.39 #Derived_gen.40 #Derived_gen.41; + jump List.598 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22 #Derived_gen.23 #Derived_gen.24; + +procedure List.89 (#Derived_gen.31, #Derived_gen.32, #Derived_gen.33, #Derived_gen.34, #Derived_gen.35): + joinpoint List.638 List.159 List.160 List.161 List.162 List.163: + let List.640 : Int1 = CallByName Num.22 List.162 List.163; + if List.640 then + let List.644 : [] = CallByName List.66 List.159 List.162; + let List.164 : {List U8, U64} = CallByName TotallyNotJson.267 List.160 List.644 List.161; + let List.643 : U64 = 1i64; + let List.642 : U64 = CallByName Num.51 List.162 List.643; + jump List.638 List.159 List.164 List.161 List.642 List.163; + else + dec List.159; + ret List.160; + in + jump List.638 #Derived_gen.31 #Derived_gen.32 #Derived_gen.33 #Derived_gen.34 #Derived_gen.35; procedure Num.127 (#Attr.2): let Num.310 : U8 = lowlevel NumIntCast #Attr.2; diff --git a/crates/compiler/test_mono/generated/weakening_avoids_overspecialization.txt b/crates/compiler/test_mono/generated/weakening_avoids_overspecialization.txt index 2eff3f8800..7b93e58ad1 100644 --- a/crates/compiler/test_mono/generated/weakening_avoids_overspecialization.txt +++ b/crates/compiler/test_mono/generated/weakening_avoids_overspecialization.txt @@ -2,80 +2,80 @@ procedure Bool.11 (#Attr.2, #Attr.3): let Bool.23 : Int1 = lowlevel Eq #Attr.2 #Attr.3; ret Bool.23; -procedure List.26 (List.181, List.182, List.183): - let List.564 : [C U64, C U64] = CallByName List.99 List.181 List.182 List.183; - let List.567 : U8 = 1i64; - let List.568 : U8 = GetTagId List.564; - let List.569 : Int1 = lowlevel Eq List.567 List.568; - if List.569 then - let List.184 : U64 = UnionAtIndex (Id 1) (Index 0) List.564; - ret List.184; +procedure List.101 (List.484, List.485, List.486): + let List.587 : U64 = 0i64; + let List.588 : U64 = CallByName List.6 List.484; + let List.586 : [C U64, C U64] = CallByName List.80 List.484 List.485 List.486 List.587 List.588; + ret List.586; + +procedure List.26 (List.197, List.198, List.199): + let List.580 : [C U64, C U64] = CallByName List.101 List.197 List.198 List.199; + let List.583 : U8 = 1i64; + let List.584 : U8 = GetTagId List.580; + let List.585 : Int1 = lowlevel Eq List.583 List.584; + if List.585 then + let List.200 : U64 = UnionAtIndex (Id 1) (Index 0) List.580; + ret List.200; else - let List.185 : U64 = UnionAtIndex (Id 0) (Index 0) List.564; - ret List.185; + let List.201 : U64 = UnionAtIndex (Id 0) (Index 0) List.580; + ret List.201; -procedure List.38 (List.324, List.325): - let List.563 : U64 = CallByName List.6 List.324; - let List.326 : U64 = CallByName Num.77 List.563 List.325; - let List.553 : List U8 = CallByName List.43 List.324 List.326; - ret List.553; +procedure List.38 (List.340, List.341): + let List.579 : U64 = CallByName List.6 List.340; + let List.342 : U64 = CallByName Num.77 List.579 List.341; + let List.569 : List U8 = CallByName List.43 List.340 List.342; + ret List.569; -procedure List.43 (List.322, List.323): - let List.561 : U64 = CallByName List.6 List.322; - let List.560 : U64 = CallByName Num.77 List.561 List.323; - let List.555 : {U64, U64} = Struct {List.323, List.560}; - let List.554 : List U8 = CallByName List.49 List.322 List.555; - ret List.554; +procedure List.43 (List.338, List.339): + let List.577 : U64 = CallByName List.6 List.338; + let List.576 : U64 = CallByName Num.77 List.577 List.339; + let List.571 : {U64, U64} = Struct {List.339, List.576}; + let List.570 : List U8 = CallByName List.49 List.338 List.571; + ret List.570; -procedure List.49 (List.400, List.401): - let List.557 : U64 = StructAtIndex 1 List.401; - let List.558 : U64 = StructAtIndex 0 List.401; - let List.556 : List U8 = CallByName List.72 List.400 List.557 List.558; - ret List.556; +procedure List.49 (List.416, List.417): + let List.573 : U64 = StructAtIndex 1 List.417; + let List.574 : U64 = StructAtIndex 0 List.417; + let List.572 : List U8 = CallByName List.72 List.416 List.573 List.574; + ret List.572; procedure List.6 (#Attr.2): - let List.562 : U64 = lowlevel ListLen #Attr.2; - ret List.562; + let List.578 : U64 = lowlevel ListLen #Attr.2; + ret List.578; procedure List.66 (#Attr.2, #Attr.3): - let List.585 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.585; + let List.601 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.601; procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.559 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.559; + let List.575 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.575; procedure List.80 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): - joinpoint List.573 List.471 List.472 List.473 List.474 List.475: - let List.575 : Int1 = CallByName Num.22 List.474 List.475; - if List.575 then - let List.584 : U8 = CallByName List.66 List.471 List.474; - let List.576 : [C U64, C U64] = CallByName Test.3 List.472 List.584; - let List.581 : U8 = 1i64; - let List.582 : U8 = GetTagId List.576; - let List.583 : Int1 = lowlevel Eq List.581 List.582; - if List.583 then - let List.476 : U64 = UnionAtIndex (Id 1) (Index 0) List.576; - let List.579 : U64 = 1i64; - let List.578 : U64 = CallByName Num.51 List.474 List.579; - jump List.573 List.471 List.476 List.473 List.578 List.475; + joinpoint List.589 List.487 List.488 List.489 List.490 List.491: + let List.591 : Int1 = CallByName Num.22 List.490 List.491; + if List.591 then + let List.600 : U8 = CallByName List.66 List.487 List.490; + let List.592 : [C U64, C U64] = CallByName Test.3 List.488 List.600; + let List.597 : U8 = 1i64; + let List.598 : U8 = GetTagId List.592; + let List.599 : Int1 = lowlevel Eq List.597 List.598; + if List.599 then + let List.492 : U64 = UnionAtIndex (Id 1) (Index 0) List.592; + let List.595 : U64 = 1i64; + let List.594 : U64 = CallByName Num.51 List.490 List.595; + jump List.589 List.487 List.492 List.489 List.594 List.491; else - dec List.471; - let List.477 : U64 = UnionAtIndex (Id 0) (Index 0) List.576; - let List.580 : [C U64, C U64] = TagId(0) List.477; - ret List.580; + dec List.487; + let List.493 : U64 = UnionAtIndex (Id 0) (Index 0) List.592; + let List.596 : [C U64, C U64] = TagId(0) List.493; + ret List.596; else - dec List.471; - let List.574 : [C U64, C U64] = TagId(1) List.472; - ret List.574; + dec List.487; + let List.590 : [C U64, C U64] = TagId(1) List.488; + ret List.590; in - jump List.573 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; - -procedure List.99 (List.468, List.469, List.470): - let List.571 : U64 = 0i64; - let List.572 : U64 = CallByName List.6 List.468; - let List.570 : [C U64, C U64] = CallByName List.80 List.468 List.469 List.470 List.571 List.572; - ret List.570; + jump List.589 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; procedure Num.22 (#Attr.2, #Attr.3): let Num.294 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/src/tests.rs b/crates/compiler/test_mono/src/tests.rs index 091e20565e..2f99efe3a3 100644 --- a/crates/compiler/test_mono/src/tests.rs +++ b/crates/compiler/test_mono/src/tests.rs @@ -234,7 +234,19 @@ fn verify_procedures<'a>( if !has_changes.stdout.is_empty() { println!("{}", std::str::from_utf8(&has_changes.stdout).unwrap()); - panic!("Output changed: resolve conflicts and `git add` the file."); + panic!(indoc!( + r#" + + Mono output has changed! This is normal when making changes to the builtins. + To fix it; run these commands locally: + + cargo test -p test_mono -p uitest --no-fail-fast + git add -u + git commit -S -m "update mono tests" + git push origin YOUR_BRANCH_NAME + + "# + )); } } @@ -3320,7 +3332,7 @@ fn inspect_derived_string() { imports [] provides [main] to "./platform" - main = Inspect.inspect "abc" |> Inspect.toDbgStr + main = Inspect.toStr "abc" "# ) } @@ -3333,7 +3345,7 @@ fn inspect_derived_record() { imports [] provides [main] to "./platform" - main = Inspect.inspect {a: 7, b: 3dec} |> Inspect.toDbgStr + main = Inspect.toStr {a: 7, b: 3dec} "# ) } @@ -3345,7 +3357,7 @@ fn inspect_derived_record_one_field_string() { imports [] provides [main] to "./platform" - main = Inspect.inspect {a: "foo"} |> Inspect.toDbgStr + main = Inspect.toStr {a: "foo"} "# ) } @@ -3358,7 +3370,7 @@ fn inspect_derived_record_two_field_strings() { imports [] provides [main] to "./platform" - main = Inspect.inspect {a: "foo", b: "bar"} |> Inspect.toDbgStr + main = Inspect.toStr {a: "foo", b: "bar"} "# ) } @@ -3371,7 +3383,7 @@ fn inspect_derived_nested_record_string() { imports [] provides [main] to "./platform" - main = Inspect.inspect {a: {b: "bar"}} |> Inspect.toDbgStr + main = Inspect.toStr {a: {b: "bar"}} "# ) } @@ -3387,7 +3399,7 @@ fn inspect_derived_tag_one_field_string() { main = x : [A Str] x = A "foo" - Inspect.inspect x |> Inspect.toDbgStr + Inspect.toStr x "# ) } @@ -3403,7 +3415,7 @@ fn inspect_derived_tag_two_payloads_string() { main = x : [A Str Str] x = A "foo" "foo" - Inspect.inspect x |> Inspect.toDbgStr + Inspect.toStr x "# ) } @@ -3416,7 +3428,7 @@ fn inspect_derived_list() { imports [] provides [main] to "./platform" - main = Inspect.inspect [1, 2, 3] |> Inspect.toDbgStr + main = Inspect.toStr [1, 2, 3] "# ) } @@ -3431,8 +3443,23 @@ fn inspect_derived_dict() { main = Dict.fromList [("a", 1), ("b", 2)] - |> Inspect.inspect - |> Inspect.toDbgStr + |> Inspect.toStr + "# + ) +} + +#[mono_test] +fn issue_6196() { + indoc!( + r#" + nth : List a, Nat -> Result a [OutOfBounds] + nth = \l, i -> + when (l, i) is + ([], _) -> Err OutOfBounds + ([e, ..], 0) -> Ok e + ([_, .. as rest], _) -> nth rest (i - 1) + + nth ["a"] 0 "# ) } diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/dbg.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/dbg.expr.formatted.roc deleted file mode 100644 index 78c37e5eb4..0000000000 --- a/crates/compiler/test_syntax/tests/snapshots/pass/dbg.expr.formatted.roc +++ /dev/null @@ -1,4 +0,0 @@ -dbg - 1 == 1 - -4 \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/dbg_multiline.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/dbg_multiline.expr.formatted.roc new file mode 100644 index 0000000000..f6e349bd30 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/dbg_multiline.expr.formatted.roc @@ -0,0 +1,6 @@ +dbg ( + 5, + 666, +) + +4 \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/dbg_multiline.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/dbg_multiline.expr.result-ast new file mode 100644 index 0000000000..5ec65c119d --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/dbg_multiline.expr.result-ast @@ -0,0 +1,26 @@ +Dbg( + @4-16 Tuple( + [ + @5-6 Num( + "5", + ), + @12-15 SpaceBefore( + Num( + "666", + ), + [ + Newline, + ], + ), + ], + ), + @18-19 SpaceBefore( + Num( + "4", + ), + [ + Newline, + Newline, + ], + ), +) diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/dbg_multiline.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/dbg_multiline.expr.roc new file mode 100644 index 0000000000..baf805964f --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/dbg_multiline.expr.roc @@ -0,0 +1,4 @@ +dbg (5, + 666) + +4 diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/newline_in_packages.full.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/newline_in_packages.full.formatted.roc index 156b704272..89ebd0eed2 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/newline_in_packages.full.formatted.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/newline_in_packages.full.formatted.roc @@ -1,7 +1,7 @@ app "hello" packages { pf: - "https://github.com/roc-lang/basic-cli/releases/download/0.7.0/bkGby8jb0tmZYsy2hg1E_B2QrCgcSTxdUlHtETwm5m4.tar.br", + "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br", } imports [pf.Stdout] provides [main] to pf diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/newline_in_packages.full.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/newline_in_packages.full.result-ast index d06a77cd4c..b7cc7c7b27 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/newline_in_packages.full.result-ast +++ b/crates/compiler/test_syntax/tests/snapshots/pass/newline_in_packages.full.result-ast @@ -24,7 +24,7 @@ Full { Newline, ], package_name: @31-145 PackageName( - "https://github.com/roc-lang/basic-cli/releases/download/0.7.0/bkGby8jb0tmZYsy2hg1E_B2QrCgcSTxdUlHtETwm5m4.tar.br", + "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br", ), }, [ diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/newline_in_packages.full.roc b/crates/compiler/test_syntax/tests/snapshots/pass/newline_in_packages.full.roc index 3fb360020d..e778a2c8fc 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/newline_in_packages.full.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/newline_in_packages.full.roc @@ -1,6 +1,6 @@ app "hello" packages { pf: -"https://github.com/roc-lang/basic-cli/releases/download/0.7.0/bkGby8jb0tmZYsy2hg1E_B2QrCgcSTxdUlHtETwm5m4.tar.br" +"https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br" } imports [pf.Stdout] provides [main] to pf diff --git a/crates/compiler/test_syntax/tests/test_fmt.rs b/crates/compiler/test_syntax/tests/test_fmt.rs index f824a22065..13d9941fab 100644 --- a/crates/compiler/test_syntax/tests/test_fmt.rs +++ b/crates/compiler/test_syntax/tests/test_fmt.rs @@ -6003,6 +6003,33 @@ mod test_fmt { ); } + #[test] + fn issue_6197() { + expr_formats_to( + indoc!( + r#" + when l1 is + [ + .. + as + rest + ] + as + l2 + -> + f rest + "# + ), + indoc!( + r#" + when l1 is + [.. as rest] as l2 -> + f rest + "# + ), + ); + } + // this is a parse error atm // #[test] // fn multiline_apply() { diff --git a/crates/compiler/test_syntax/tests/test_snapshots.rs b/crates/compiler/test_syntax/tests/test_snapshots.rs index 0d78aa3ee9..81f398d1d4 100644 --- a/crates/compiler/test_syntax/tests/test_snapshots.rs +++ b/crates/compiler/test_syntax/tests/test_snapshots.rs @@ -246,8 +246,8 @@ mod test_snapshots { fail/when_outdented_branch.expr, fail/when_over_indented_int.expr, fail/when_over_indented_underscore.expr, - fail/wild_case_arrow.expr, fail/where_type_variable.expr, + fail/wild_case_arrow.expr, malformed/bad_opaque_ref.expr, malformed/malformed_ident_due_to_underscore.expr, malformed/malformed_pattern_field_access.expr, // See https://github.com/roc-lang/roc/issues/399 @@ -296,6 +296,7 @@ mod test_snapshots { pass/control_characters_in_scalar.expr, pass/crash.expr, pass/dbg.expr, + pass/dbg_multiline.expr, pass/def_without_newline.expr, pass/destructure_tag_assignment.expr, pass/empty_app_header.header, @@ -489,9 +490,9 @@ mod test_snapshots { pass/where_clause_multiple_has_across_newlines.expr, pass/where_clause_non_function.expr, pass/where_clause_on_newline.expr, + pass/where_ident.expr, pass/zero_float.expr, pass/zero_int.expr, - pass/where_ident.expr, // END SNAPSHOTS (for automatic test detection via `env ROC_SNAPSHOT_TEST_OVERWRITE=1 cargo test`) } diff --git a/crates/compiler/uitest/tests/ability/specialize/inspect/bool.txt b/crates/compiler/uitest/tests/ability/specialize/inspect/bool.txt index 50661600b3..27668f3513 100644 --- a/crates/compiler/uitest/tests/ability/specialize/inspect/bool.txt +++ b/crates/compiler/uitest/tests/ability/specialize/inspect/bool.txt @@ -1,4 +1,4 @@ app "test" provides [main] to "./platform" -main = Inspect.toInspector Bool.true |> Inspect.apply (Inspect.init {}) |> Inspect.toDbgStr -# ^^^^^^^^^^^^^^^^^^^ Inspect#Inspect.toInspector(32): Bool -[[Inspect.dbgBool(43)]]-> Inspector DbgFormatter +main = Inspect.toInspector Bool.true |> Inspect.apply (Inspect.init {}) +# ^^^^^^^^^^^^^^^^^^^ Inspect#Inspect.toInspector(32): Bool -[[] + f:Inspect.bool(13):1]-> Inspector f where f implements InspectFormatter diff --git a/crates/compiler/uitest/tests/ability/specialize/inspect/dec.txt b/crates/compiler/uitest/tests/ability/specialize/inspect/dec.txt index 839ebc1cba..57a77a0659 100644 --- a/crates/compiler/uitest/tests/ability/specialize/inspect/dec.txt +++ b/crates/compiler/uitest/tests/ability/specialize/inspect/dec.txt @@ -1,4 +1,4 @@ app "test" provides [main] to "./platform" -main = Inspect.toInspector 7dec |> Inspect.apply (Inspect.init {}) |> Inspect.toDbgStr -# ^^^^^^^^^^^^^^^^^^^ Inspect#Inspect.toInspector(32): Dec -[[Inspect.dbgDec(60)]]-> Inspector DbgFormatter +main = Inspect.toInspector 7dec |> Inspect.apply (Inspect.init {}) +# ^^^^^^^^^^^^^^^^^^^ Inspect#Inspect.toInspector(32): Dec -[[] + f:Inspect.dec(29):1]-> Inspector f where f implements InspectFormatter diff --git a/crates/compiler/uitest/tests/ability/specialize/inspect/non_implementing_opaque.txt b/crates/compiler/uitest/tests/ability/specialize/inspect/non_implementing_opaque.txt index d27232f296..e1946cb50c 100644 --- a/crates/compiler/uitest/tests/ability/specialize/inspect/non_implementing_opaque.txt +++ b/crates/compiler/uitest/tests/ability/specialize/inspect/non_implementing_opaque.txt @@ -2,5 +2,5 @@ app "test" provides [main] to "./platform" Op := {} -main = Inspect.toInspector (@Op {}) |> Inspect.apply (Inspect.init {}) |> Inspect.toDbgStr -# ^^^^^^^^^^^^^^^^^^^ Inspect#Inspect.toInspector(32): Op -[[Inspect.dbgOpaque(45)]]-> Inspector DbgFormatter +main = Inspect.toInspector (@Op {}) |> Inspect.apply (Inspect.init {}) +# ^^^^^^^^^^^^^^^^^^^ Inspect#Inspect.toInspector(32): Op -[[] + f:Inspect.opaque(15):1]-> Inspector f where f implements InspectFormatter diff --git a/crates/compiler/uitest/tests/ability/specialize/inspect/opaque_automatic.txt b/crates/compiler/uitest/tests/ability/specialize/inspect/opaque_automatic.txt index ffe19f6da3..a415bbc58c 100644 --- a/crates/compiler/uitest/tests/ability/specialize/inspect/opaque_automatic.txt +++ b/crates/compiler/uitest/tests/ability/specialize/inspect/opaque_automatic.txt @@ -8,46 +8,50 @@ main = 1 # -emit:mono -procedure Inspect.251 (Inspect.252): - let Inspect.317 : Str = ""; - let Inspect.316 : Str = CallByName Inspect.61 Inspect.252 Inspect.317; - ret Inspect.316; +procedure Inspect.253 (Inspect.254): + let Inspect.321 : Str = ""; + let Inspect.320 : Str = CallByName Inspect.61 Inspect.254 Inspect.321; + ret Inspect.320; -procedure Inspect.30 (Inspect.147): - ret Inspect.147; +procedure Inspect.30 (Inspect.148): + ret Inspect.148; -procedure Inspect.35 (Inspect.300): - ret Inspect.300; +procedure Inspect.34 (Inspect.153): + let Inspect.309 : Str = CallByName Inspect.5 Inspect.153; + let Inspect.308 : Str = CallByName Inspect.62 Inspect.309; + ret Inspect.308; -procedure Inspect.36 (Inspect.304): - let Inspect.311 : Str = ""; +procedure Inspect.36 (Inspect.305): + let Inspect.315 : Str = ""; + ret Inspect.315; + +procedure Inspect.45 (Inspect.303): + let Inspect.318 : {} = Struct {}; + let Inspect.317 : {} = CallByName Inspect.30 Inspect.318; + ret Inspect.317; + +procedure Inspect.5 (Inspect.151): + let Inspect.316 : {} = CallByName Inspect.45 Inspect.151; + let Inspect.313 : {} = Struct {}; + let Inspect.312 : Str = CallByName Inspect.36 Inspect.313; + let Inspect.311 : Str = CallByName Inspect.253 Inspect.312; ret Inspect.311; -procedure Inspect.45 (Inspect.302): - let Inspect.314 : {} = Struct {}; - let Inspect.313 : {} = CallByName Inspect.30 Inspect.314; - ret Inspect.313; +procedure Inspect.61 (Inspect.304, Inspect.300): + let Inspect.323 : Str = CallByName Str.3 Inspect.304 Inspect.300; + dec Inspect.300; + ret Inspect.323; -procedure Inspect.5 (Inspect.150): - let Inspect.312 : {} = CallByName Inspect.45 Inspect.150; - let Inspect.309 : {} = Struct {}; - let Inspect.308 : Str = CallByName Inspect.36 Inspect.309; - let Inspect.307 : Str = CallByName Inspect.251 Inspect.308; - ret Inspect.307; - -procedure Inspect.61 (Inspect.303, Inspect.298): - let Inspect.319 : Str = CallByName Str.3 Inspect.303 Inspect.298; - dec Inspect.298; - ret Inspect.319; +procedure Inspect.62 (Inspect.306): + ret Inspect.306; procedure Str.3 (#Attr.2, #Attr.3): let Str.292 : Str = lowlevel StrConcat #Attr.2 #Attr.3; ret Str.292; procedure Test.0 (): - let Test.5 : {} = Struct {}; - let Test.4 : Str = CallByName Inspect.5 Test.5; - let Test.2 : Str = CallByName Inspect.35 Test.4; + let Test.4 : {} = Struct {}; + let Test.2 : Str = CallByName Inspect.34 Test.4; dbg Test.2; dec Test.2; let Test.3 : I64 = 1i64; diff --git a/crates/compiler/uitest/tests/ability/specialize/inspect/opaque_automatic_late.txt b/crates/compiler/uitest/tests/ability/specialize/inspect/opaque_automatic_late.txt index 198b0d15dc..004c4ceb67 100644 --- a/crates/compiler/uitest/tests/ability/specialize/inspect/opaque_automatic_late.txt +++ b/crates/compiler/uitest/tests/ability/specialize/inspect/opaque_automatic_late.txt @@ -11,45 +11,49 @@ main = late (@Op {}) # -emit:mono -procedure Inspect.251 (Inspect.252): - let Inspect.317 : Str = ""; - let Inspect.316 : Str = CallByName Inspect.61 Inspect.252 Inspect.317; - ret Inspect.316; +procedure Inspect.253 (Inspect.254): + let Inspect.321 : Str = ""; + let Inspect.320 : Str = CallByName Inspect.61 Inspect.254 Inspect.321; + ret Inspect.320; -procedure Inspect.30 (Inspect.147): - ret Inspect.147; +procedure Inspect.30 (Inspect.148): + ret Inspect.148; -procedure Inspect.35 (Inspect.300): - ret Inspect.300; +procedure Inspect.34 (Inspect.153): + let Inspect.309 : Str = CallByName Inspect.5 Inspect.153; + let Inspect.308 : Str = CallByName Inspect.62 Inspect.309; + ret Inspect.308; -procedure Inspect.36 (Inspect.304): - let Inspect.311 : Str = ""; +procedure Inspect.36 (Inspect.305): + let Inspect.315 : Str = ""; + ret Inspect.315; + +procedure Inspect.45 (Inspect.303): + let Inspect.318 : {} = Struct {}; + let Inspect.317 : {} = CallByName Inspect.30 Inspect.318; + ret Inspect.317; + +procedure Inspect.5 (Inspect.151): + let Inspect.316 : {} = CallByName Inspect.45 Inspect.151; + let Inspect.313 : {} = Struct {}; + let Inspect.312 : Str = CallByName Inspect.36 Inspect.313; + let Inspect.311 : Str = CallByName Inspect.253 Inspect.312; ret Inspect.311; -procedure Inspect.45 (Inspect.302): - let Inspect.314 : {} = Struct {}; - let Inspect.313 : {} = CallByName Inspect.30 Inspect.314; - ret Inspect.313; +procedure Inspect.61 (Inspect.304, Inspect.300): + let Inspect.323 : Str = CallByName Str.3 Inspect.304 Inspect.300; + dec Inspect.300; + ret Inspect.323; -procedure Inspect.5 (Inspect.150): - let Inspect.312 : {} = CallByName Inspect.45 Inspect.150; - let Inspect.309 : {} = Struct {}; - let Inspect.308 : Str = CallByName Inspect.36 Inspect.309; - let Inspect.307 : Str = CallByName Inspect.251 Inspect.308; - ret Inspect.307; - -procedure Inspect.61 (Inspect.303, Inspect.298): - let Inspect.319 : Str = CallByName Str.3 Inspect.303 Inspect.298; - dec Inspect.298; - ret Inspect.319; +procedure Inspect.62 (Inspect.306): + ret Inspect.306; procedure Str.3 (#Attr.2, #Attr.3): let Str.292 : Str = lowlevel StrConcat #Attr.2 #Attr.3; ret Str.292; procedure Test.2 (Test.3): - let Test.8 : Str = CallByName Inspect.5 Test.3; - let Test.4 : Str = CallByName Inspect.35 Test.8; + let Test.4 : Str = CallByName Inspect.34 Test.3; dbg Test.4; dec Test.4; let Test.7 : I64 = 1i64; diff --git a/crates/compiler/uitest/tests/ability/specialize/inspect/opaque_custom_impl.txt b/crates/compiler/uitest/tests/ability/specialize/inspect/opaque_custom_impl.txt index bdb8f45893..6a3a9f6c62 100644 --- a/crates/compiler/uitest/tests/ability/specialize/inspect/opaque_custom_impl.txt +++ b/crates/compiler/uitest/tests/ability/specialize/inspect/opaque_custom_impl.txt @@ -5,5 +5,5 @@ Op := U8 implements [Inspect { toInspector: myToInspector }] myToInspector : Op -> Inspector f where f implements InspectFormatter myToInspector = \@Op num -> Inspect.u8 num -main = Inspect.toInspector (@Op 1u8) |> Inspect.apply (Inspect.init {}) |> Inspect.toDbgStr -# ^^^^^^^^^^^^^^^^^^^ Op#Inspect.toInspector(2): Op -[[myToInspector(2)]]-> Inspector DbgFormatter +main = Inspect.toInspector (@Op 1u8) |> Inspect.apply (Inspect.init {}) +# ^^^^^^^^^^^^^^^^^^^ Op#Inspect.toInspector(2): Op -[[myToInspector(2)]]-> Inspector f where f implements InspectFormatter diff --git a/crates/compiler/uitest/tests/ability/specialize/inspect/opaque_derived.txt b/crates/compiler/uitest/tests/ability/specialize/inspect/opaque_derived.txt index 1e3569a4fd..b22d8b9b68 100644 --- a/crates/compiler/uitest/tests/ability/specialize/inspect/opaque_derived.txt +++ b/crates/compiler/uitest/tests/ability/specialize/inspect/opaque_derived.txt @@ -2,5 +2,5 @@ app "test" provides [main] to "./platform" Op := U8 implements [Inspect] -main = Inspect.toInspector (@Op 1u8) |> Inspect.apply (Inspect.init {}) |> Inspect.toDbgStr -# ^^^^^^^^^^^^^^^^^^^ Op#Inspect.toInspector(3): Op -[[#Op_toInspector(3)]]-> Inspector DbgFormatter +main = Inspect.toInspector (@Op 1u8) |> Inspect.apply (Inspect.init {}) +# ^^^^^^^^^^^^^^^^^^^ Op#Inspect.toInspector(3): Op -[[#Op_toInspector(3)]]-> Inspector f where f implements InspectFormatter diff --git a/crates/compiler/uitest/tests/ability/specialize/inspect/ranged_num.txt b/crates/compiler/uitest/tests/ability/specialize/inspect/ranged_num.txt index e0112f852b..84b8c5222e 100644 --- a/crates/compiler/uitest/tests/ability/specialize/inspect/ranged_num.txt +++ b/crates/compiler/uitest/tests/ability/specialize/inspect/ranged_num.txt @@ -1,4 +1,4 @@ app "test" provides [main] to "./platform" -main = Inspect.toInspector 7 |> Inspect.apply (Inspect.init {}) |> Inspect.toDbgStr -# ^^^^^^^^^^^^^^^^^^^ Inspect#Inspect.toInspector(32): I64 -[[Inspect.dbgI64(54)]]-> Inspector DbgFormatter +main = Inspect.toInspector 7 |> Inspect.apply (Inspect.init {}) +# ^^^^^^^^^^^^^^^^^^^ Inspect#Inspect.toInspector(32): I64 -[[] + f:Inspect.i64(24):1]-> Inspector f where f implements InspectFormatter diff --git a/crates/compiler/uitest/tests/ability/specialize/inspect/record.txt b/crates/compiler/uitest/tests/ability/specialize/inspect/record.txt index 0094d164f3..3dc0e5f8d1 100644 --- a/crates/compiler/uitest/tests/ability/specialize/inspect/record.txt +++ b/crates/compiler/uitest/tests/ability/specialize/inspect/record.txt @@ -1,4 +1,4 @@ app "test" provides [main] to "./platform" -main = Inspect.toInspector { a: "" } |> Inspect.apply (Inspect.init {}) |> Inspect.toDbgStr -# ^^^^^^^^^^^^^^^^^^^ Inspect#Inspect.toInspector(32): { a : Str } -[[#Derived.toInspector_{a}(0)]]-> Inspector DbgFormatter +main = Inspect.toInspector { a: "" } |> Inspect.apply (Inspect.init {}) +# ^^^^^^^^^^^^^^^^^^^ Inspect#Inspect.toInspector(32): { a : Str } -[[#Derived.toInspector_{a}(0)]]-> Inspector f where f implements InspectFormatter diff --git a/crates/compiler/uitest/tests/ability/specialize/inspect/record_with_nested_custom_impl.txt b/crates/compiler/uitest/tests/ability/specialize/inspect/record_with_nested_custom_impl.txt index 44f741f979..794f97b8b5 100644 --- a/crates/compiler/uitest/tests/ability/specialize/inspect/record_with_nested_custom_impl.txt +++ b/crates/compiler/uitest/tests/ability/specialize/inspect/record_with_nested_custom_impl.txt @@ -5,5 +5,5 @@ Op := U8 implements [Inspect { toInspector: myToInspector }] myToInspector : Op -> Inspector f where f implements InspectFormatter myToInspector = \@Op num -> Inspect.u8 num -main = Inspect.toInspector { op: @Op 1u8 } |> Inspect.apply (Inspect.init {}) |> Inspect.toDbgStr -# ^^^^^^^^^^^^^^^^^^^ Inspect#Inspect.toInspector(32): { op : Op } -[[#Derived.toInspector_{op}(0)]]-> Inspector DbgFormatter +main = Inspect.toInspector { op: @Op 1u8 } |> Inspect.apply (Inspect.init {}) +# ^^^^^^^^^^^^^^^^^^^ Inspect#Inspect.toInspector(32): { op : Op } -[[#Derived.toInspector_{op}(0)]]-> Inspector f where f implements InspectFormatter diff --git a/crates/compiler/uitest/tests/ability/specialize/inspect/u8.txt b/crates/compiler/uitest/tests/ability/specialize/inspect/u8.txt index 59b9a84c1c..f6235fca34 100644 --- a/crates/compiler/uitest/tests/ability/specialize/inspect/u8.txt +++ b/crates/compiler/uitest/tests/ability/specialize/inspect/u8.txt @@ -1,4 +1,4 @@ app "test" provides [main] to "./platform" -main = Inspect.toInspector 7u8 |> Inspect.apply (Inspect.init {}) |> Inspect.toDbgStr -# ^^^^^^^^^^^^^^^^^^^ Inspect#Inspect.toInspector(32): U8 -[[Inspect.dbgU8(47)]]-> Inspector DbgFormatter +main = Inspect.toInspector 7u8 |> Inspect.apply (Inspect.init {}) +# ^^^^^^^^^^^^^^^^^^^ Inspect#Inspect.toInspector(32): U8 -[[] + f:Inspect.u8(17):1]-> Inspector f where f implements InspectFormatter diff --git a/crates/compiler/uitest/tests/ability/specialize/set_eq_issue_4761.txt b/crates/compiler/uitest/tests/ability/specialize/set_eq_issue_4761.txt index b8fa24db29..3173fa4bcc 100644 --- a/crates/compiler/uitest/tests/ability/specialize/set_eq_issue_4761.txt +++ b/crates/compiler/uitest/tests/ability/specialize/set_eq_issue_4761.txt @@ -8,5 +8,5 @@ main = s2 = Set.empty {} Bool.isEq s1 s1 && Bool.isEq s2 s2 -# ^^^^^^^^^ Set#Bool.isEq(20): Set Str, Set Str -[[Set.isEq(20)]]-> Bool -# ^^^^^^^^^ Set#Bool.isEq(20): Set U8, Set U8 -[[Set.isEq(20)]]-> Bool +# ^^^^^^^^^ Set#Bool.isEq(25): Set Str, Set Str -[[Set.isEq(25)]]-> Bool +# ^^^^^^^^^ Set#Bool.isEq(25): Set U8, Set U8 -[[Set.isEq(25)]]-> Bool diff --git a/crates/compiler/uitest/tests/recursion/generalization_among_large_recursive_group.txt b/crates/compiler/uitest/tests/recursion/generalization_among_large_recursive_group.txt index f1f87be404..2070f3f20b 100644 --- a/crates/compiler/uitest/tests/recursion/generalization_among_large_recursive_group.txt +++ b/crates/compiler/uitest/tests/recursion/generalization_among_large_recursive_group.txt @@ -3,22 +3,22 @@ app "test" provides [main] to "./platform" f = \{} -> -#^{-1} <2858><117>{} -<120>[[f(1)]]-> <116>[Ok <2866>{}]<80>* +#^{-1} <2937><117>{} -<120>[[f(1)]]-> <116>[Ok <2945>{}]<80>* when g {} is -# ^ <2848><2866>{} -<2856>[[g(2)]]-> <72>[Ok <2866>{}]<102>* +# ^ <2927><2945>{} -<2935>[[g(2)]]-> <72>[Ok <2945>{}]<102>* _ -> Ok {} g = \{} -> -#^{-1} <2848><2866>{} -<2856>[[g(2)]]-> <72>[Ok <2866>{}]<102>* +#^{-1} <2927><2945>{} -<2935>[[g(2)]]-> <72>[Ok <2945>{}]<102>* when h {} is -# ^ <2853><2866>{} -<2861>[[h(3)]]-> <94>[Ok <2866>{}]<124>* +# ^ <2932><2945>{} -<2940>[[h(3)]]-> <94>[Ok <2945>{}]<124>* _ -> Ok {} h = \{} -> -#^{-1} <2853><2866>{} -<2861>[[h(3)]]-> <94>[Ok <2866>{}]<124>* +#^{-1} <2932><2945>{} -<2940>[[h(3)]]-> <94>[Ok <2945>{}]<124>* when f {} is -# ^ <2858><117>{} -<120>[[f(1)]]-> <116>[Ok <2866>{}]<80>* +# ^ <2937><117>{} -<120>[[f(1)]]-> <116>[Ok <2945>{}]<80>* _ -> Ok {} main = f {} -# ^ <2868><133>{} -<136>[[f(1)]]-> <138>[Ok <2866>{}]<2867>w_a +# ^ <2947><133>{} -<136>[[f(1)]]-> <138>[Ok <2945>{}]<2946>w_a diff --git a/crates/glue/src/ZigGlue.roc b/crates/glue/src/ZigGlue.roc new file mode 100644 index 0000000000..00fee23ce2 --- /dev/null +++ b/crates/glue/src/ZigGlue.roc @@ -0,0 +1,27 @@ +app "zig-glue" + packages { pf: "../platform/main.roc" } + imports [ + pf.Types.{ Types }, + pf.File.{ File }, + "../../compiler/builtins/bitcode/src/list.zig" as rocStdList : Str, + ] + provides [makeGlue] to pf + +makeGlue : List Types -> Result (List File) Str +makeGlue = \typesByArch -> + typesByArch + |> List.map convertTypesToFile + |> List.concat staticFiles + |> Ok + +## These are always included, and don't depend on the specifics of the app. +staticFiles : List File +staticFiles = [ + { name: "list.zig", content: rocStdList }, +] + +convertTypesToFile : Types -> File +convertTypesToFile = \_ -> { + name: "glue.zig", + content: "// Nothing to see yet", +} diff --git a/crates/glue/src/load.rs b/crates/glue/src/load.rs index 93d594aab5..b329d1fefc 100644 --- a/crates/glue/src/load.rs +++ b/crates/glue/src/load.rs @@ -11,8 +11,9 @@ use roc_build::{ }; use roc_collections::MutMap; use roc_error_macros::todo_lambda_erasure; +use roc_gen_llvm::run_roc::RocCallResult; use roc_load::{ExecutionMode, FunctionKind, LoadConfig, LoadedModule, LoadingProblem, Threading}; -use roc_mono::ir::{generate_glue_procs, GlueProc, OptLevel}; +use roc_mono::ir::{generate_glue_procs, CrashTag, GlueProc, OptLevel}; use roc_mono::layout::{GlobalLayoutInterner, LayoutCache, LayoutInterner}; use roc_packaging::cache::{self, RocCacheDir}; use roc_reporting::report::{RenderTarget, DEFAULT_PALETTE}; @@ -55,6 +56,7 @@ pub fn generate( backend, opt_level: OptLevel::Development, emit_debug_info: false, + emit_llvm_ir: false, }; let load_config = standard_load_config( @@ -122,14 +124,16 @@ pub fn generate( if problems.warnings > 0 { problems.print_to_stdout(total_time); println!( - ".\n\nRunning program…\n\n\x1B[36m{}\x1B[39m", + ".\n\nRunning glue despite warnings…\n\n\x1B[36m{}\x1B[39m", "─".repeat(80) ); } let lib = unsafe { Library::new(lib_path) }.unwrap(); + type MakeGlueReturnType = + roc_std::RocResult, roc_std::RocStr>; type MakeGlue = unsafe extern "C" fn( - *mut roc_std::RocResult, roc_std::RocStr>, + *mut RocCallResult, &roc_std::RocList, ); @@ -139,14 +143,22 @@ pub fn generate( }; let roc_types: roc_std::RocList = types.iter().map(|x| x.into()).collect(); - let mut files = roc_std::RocResult::err(roc_std::RocStr::empty()); + let mut files = + RocCallResult::new(roc_std::RocResult::err(roc_std::RocStr::empty())); unsafe { make_glue(&mut files, &roc_types) }; // Roc will free data passed into it. So forget that data. std::mem::forget(roc_types); let files: Result, roc_std::RocStr> = - files.into(); + match Result::from(files) { + Err((msg, tag)) => match tag { + CrashTag::Roc => panic!(r#"Roc failed with message: "{msg}""#), + CrashTag::User => panic!(r#"User crash with message: "{msg}""#), + }, + Ok(x) => x.into(), + }; + let files = files.unwrap_or_else(|err| { eprintln!("Glue generation failed: {err}"); diff --git a/crates/glue/tests/fixtures/advanced-recursive-union/src/lib.rs b/crates/glue/tests/fixtures/advanced-recursive-union/src/lib.rs index 9fa24c4665..bf300bcb9f 100644 --- a/crates/glue/tests/fixtures/advanced-recursive-union/src/lib.rs +++ b/crates/glue/tests/fixtures/advanced-recursive-union/src/lib.rs @@ -77,8 +77,8 @@ pub unsafe extern "C" fn roc_panic(msg: *mut RocStr, tag_id: u32) { } #[no_mangle] -pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr) { - eprintln!("[{}] {}", &*loc, &*msg); +pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut RocStr) { + eprintln!("[{}] {} = {}", &*loc, &*src, &*msg); } #[no_mangle] diff --git a/crates/glue/tests/fixtures/arguments/src/lib.rs b/crates/glue/tests/fixtures/arguments/src/lib.rs index 4f0db9af41..a56170a3cd 100644 --- a/crates/glue/tests/fixtures/arguments/src/lib.rs +++ b/crates/glue/tests/fixtures/arguments/src/lib.rs @@ -49,8 +49,8 @@ pub unsafe extern "C" fn roc_panic(msg: *mut RocStr, tag_id: u32) { } #[no_mangle] -pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr) { - eprintln!("[{}] {}", &*loc, &*msg); +pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut RocStr) { + eprintln!("[{}] {} = {}", &*loc, &*src, &*msg); } #[no_mangle] diff --git a/crates/glue/tests/fixtures/basic-record/src/lib.rs b/crates/glue/tests/fixtures/basic-record/src/lib.rs index cd50e9b76b..015b37a037 100644 --- a/crates/glue/tests/fixtures/basic-record/src/lib.rs +++ b/crates/glue/tests/fixtures/basic-record/src/lib.rs @@ -71,8 +71,8 @@ pub unsafe extern "C" fn roc_panic(msg: *mut RocStr, tag_id: u32) { } #[no_mangle] -pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr) { - eprintln!("[{}] {}", &*loc, &*msg); +pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut RocStr) { + eprintln!("[{}] {} = {}", &*loc, &*src, &*msg); } #[no_mangle] diff --git a/crates/glue/tests/fixtures/basic-recursive-union/src/lib.rs b/crates/glue/tests/fixtures/basic-recursive-union/src/lib.rs index b104cb5a29..1c1658e1fc 100644 --- a/crates/glue/tests/fixtures/basic-recursive-union/src/lib.rs +++ b/crates/glue/tests/fixtures/basic-recursive-union/src/lib.rs @@ -82,8 +82,8 @@ pub unsafe extern "C" fn roc_panic(msg: *mut RocStr, tag_id: u32) { } #[no_mangle] -pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr) { - eprintln!("[{}] {}", &*loc, &*msg); +pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut RocStr) { + eprintln!("[{}] {} = {}", &*loc, &*src, &*msg); } #[no_mangle] diff --git a/crates/glue/tests/fixtures/closures/src/lib.rs b/crates/glue/tests/fixtures/closures/src/lib.rs index 9179f6d02c..1d3be6bda5 100644 --- a/crates/glue/tests/fixtures/closures/src/lib.rs +++ b/crates/glue/tests/fixtures/closures/src/lib.rs @@ -49,8 +49,8 @@ pub unsafe extern "C" fn roc_panic(msg: *mut RocStr, tag_id: u32) { } #[no_mangle] -pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr) { - eprintln!("[{}] {}", &*loc, &*msg); +pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut RocStr) { + eprintln!("[{}] {} = {}", &*loc, &*src, &*msg); } #[no_mangle] diff --git a/crates/glue/tests/fixtures/enumeration/src/lib.rs b/crates/glue/tests/fixtures/enumeration/src/lib.rs index ebe1a45e41..aec7b403a9 100644 --- a/crates/glue/tests/fixtures/enumeration/src/lib.rs +++ b/crates/glue/tests/fixtures/enumeration/src/lib.rs @@ -75,8 +75,8 @@ pub unsafe extern "C" fn roc_panic(msg: *mut RocStr, tag_id: u32) { } #[no_mangle] -pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr) { - eprintln!("[{}] {}", &*loc, &*msg); +pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut RocStr) { + eprintln!("[{}] {} = {}", &*loc, &*src, &*msg); } #[no_mangle] diff --git a/crates/glue/tests/fixtures/list-recursive-union/src/lib.rs b/crates/glue/tests/fixtures/list-recursive-union/src/lib.rs index 7dd435fa73..89ac109ec2 100644 --- a/crates/glue/tests/fixtures/list-recursive-union/src/lib.rs +++ b/crates/glue/tests/fixtures/list-recursive-union/src/lib.rs @@ -77,8 +77,8 @@ pub unsafe extern "C" fn roc_panic(msg: *mut RocStr, tag_id: u32) { } #[no_mangle] -pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr) { - eprintln!("[{}] {}", &*loc, &*msg); +pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut RocStr) { + eprintln!("[{}] {} = {}", &*loc, &*src, &*msg); } #[no_mangle] diff --git a/crates/glue/tests/fixtures/multiple-modules/src/lib.rs b/crates/glue/tests/fixtures/multiple-modules/src/lib.rs index 8f0194fa0d..4750a9a64a 100644 --- a/crates/glue/tests/fixtures/multiple-modules/src/lib.rs +++ b/crates/glue/tests/fixtures/multiple-modules/src/lib.rs @@ -75,8 +75,8 @@ pub unsafe extern "C" fn roc_panic(msg: *mut RocStr, tag_id: u32) { } #[no_mangle] -pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr) { - eprintln!("[{}] {}", &*loc, &*msg); +pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut RocStr) { + eprintln!("[{}] {} = {}", &*loc, &*src, &*msg); } #[no_mangle] diff --git a/crates/glue/tests/fixtures/nested-record/src/lib.rs b/crates/glue/tests/fixtures/nested-record/src/lib.rs index 1263d2341b..d1acc81a34 100644 --- a/crates/glue/tests/fixtures/nested-record/src/lib.rs +++ b/crates/glue/tests/fixtures/nested-record/src/lib.rs @@ -75,8 +75,8 @@ pub unsafe extern "C" fn roc_panic(msg: *mut RocStr, tag_id: u32) { } #[no_mangle] -pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr) { - eprintln!("[{}] {}", &*loc, &*msg); +pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut RocStr) { + eprintln!("[{}] {} = {}", &*loc, &*src, &*msg); } #[no_mangle] diff --git a/crates/glue/tests/fixtures/nonnullable-unwrapped/src/lib.rs b/crates/glue/tests/fixtures/nonnullable-unwrapped/src/lib.rs index ca96c8d6fe..888ec70c84 100644 --- a/crates/glue/tests/fixtures/nonnullable-unwrapped/src/lib.rs +++ b/crates/glue/tests/fixtures/nonnullable-unwrapped/src/lib.rs @@ -90,8 +90,8 @@ pub unsafe extern "C" fn roc_panic(msg: *mut RocStr, tag_id: u32) { } #[no_mangle] -pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr) { - eprintln!("[{}] {}", &*loc, &*msg); +pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut RocStr) { + eprintln!("[{}] {} = {}", &*loc, &*src, &*msg); } #[no_mangle] diff --git a/crates/glue/tests/fixtures/nullable-unwrapped/src/lib.rs b/crates/glue/tests/fixtures/nullable-unwrapped/src/lib.rs index dd2f6a92fd..4a5558012a 100644 --- a/crates/glue/tests/fixtures/nullable-unwrapped/src/lib.rs +++ b/crates/glue/tests/fixtures/nullable-unwrapped/src/lib.rs @@ -82,8 +82,8 @@ pub unsafe extern "C" fn roc_panic(msg: *mut RocStr, tag_id: u32) { } #[no_mangle] -pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr) { - eprintln!("[{}] {}", &*loc, &*msg); +pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut RocStr) { + eprintln!("[{}] {} = {}", &*loc, &*src, &*msg); } #[no_mangle] diff --git a/crates/glue/tests/fixtures/nullable-wrapped/src/lib.rs b/crates/glue/tests/fixtures/nullable-wrapped/src/lib.rs index 0ef35c17c1..542aa904a5 100644 --- a/crates/glue/tests/fixtures/nullable-wrapped/src/lib.rs +++ b/crates/glue/tests/fixtures/nullable-wrapped/src/lib.rs @@ -101,8 +101,8 @@ pub unsafe extern "C" fn roc_panic(msg: *mut RocStr, tag_id: u32) { } #[no_mangle] -pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr) { - eprintln!("[{}] {}", &*loc, &*msg); +pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut RocStr) { + eprintln!("[{}] {} = {}", &*loc, &*src, &*msg); } #[no_mangle] diff --git a/crates/glue/tests/fixtures/option/src/lib.rs b/crates/glue/tests/fixtures/option/src/lib.rs index c5e565c75f..1cd1ec5c26 100644 --- a/crates/glue/tests/fixtures/option/src/lib.rs +++ b/crates/glue/tests/fixtures/option/src/lib.rs @@ -51,8 +51,8 @@ pub unsafe extern "C" fn roc_panic(msg: *mut RocStr, tag_id: u32) { } #[no_mangle] -pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr) { - eprintln!("[{}] {}", &*loc, &*msg); +pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut RocStr) { + eprintln!("[{}] {} = {}", &*loc, &*src, &*msg); } #[no_mangle] diff --git a/crates/glue/tests/fixtures/rocresult/src/lib.rs b/crates/glue/tests/fixtures/rocresult/src/lib.rs index 27092d4d68..8fd4aee837 100644 --- a/crates/glue/tests/fixtures/rocresult/src/lib.rs +++ b/crates/glue/tests/fixtures/rocresult/src/lib.rs @@ -51,8 +51,8 @@ pub unsafe extern "C" fn roc_panic(msg: *mut RocStr, tag_id: u32) { } #[no_mangle] -pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr) { - eprintln!("[{}] {}", &*loc, &*msg); +pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut RocStr) { + eprintln!("[{}] {} = {}", &*loc, &*src, &*msg); } #[no_mangle] diff --git a/crates/glue/tests/fixtures/single-tag-union/src/lib.rs b/crates/glue/tests/fixtures/single-tag-union/src/lib.rs index a59c631a9f..9d3eeb433d 100644 --- a/crates/glue/tests/fixtures/single-tag-union/src/lib.rs +++ b/crates/glue/tests/fixtures/single-tag-union/src/lib.rs @@ -77,8 +77,8 @@ pub unsafe extern "C" fn roc_panic(msg: *mut RocStr, tag_id: u32) { } #[no_mangle] -pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr) { - eprintln!("[{}] {}", &*loc, &*msg); +pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut RocStr) { + eprintln!("[{}] {} = {}", &*loc, &*src, &*msg); } #[no_mangle] diff --git a/crates/glue/tests/fixtures/union-with-padding/src/lib.rs b/crates/glue/tests/fixtures/union-with-padding/src/lib.rs index 42e32770d3..ee8f92f0ff 100644 --- a/crates/glue/tests/fixtures/union-with-padding/src/lib.rs +++ b/crates/glue/tests/fixtures/union-with-padding/src/lib.rs @@ -82,8 +82,8 @@ pub unsafe extern "C" fn roc_panic(msg: *mut RocStr, tag_id: u32) { } #[no_mangle] -pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr) { - eprintln!("[{}] {}", &*loc, &*msg); +pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut RocStr) { + eprintln!("[{}] {} = {}", &*loc, &*src, &*msg); } #[no_mangle] diff --git a/crates/glue/tests/fixtures/union-without-padding/src/lib.rs b/crates/glue/tests/fixtures/union-without-padding/src/lib.rs index f424da0a9f..e5d35357b0 100644 --- a/crates/glue/tests/fixtures/union-without-padding/src/lib.rs +++ b/crates/glue/tests/fixtures/union-without-padding/src/lib.rs @@ -79,8 +79,8 @@ pub unsafe extern "C" fn roc_panic(msg: *mut RocStr, tag_id: u32) { } #[no_mangle] -pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr) { - eprintln!("[{}] {}", &*loc, &*msg); +pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut RocStr) { + eprintln!("[{}] {} = {}", &*loc, &*src, &*msg); } #[no_mangle] diff --git a/crates/glue/tests/test_glue_cli.rs b/crates/glue/tests/test_glue_cli.rs index 86e824b2e9..a41818aea1 100644 --- a/crates/glue/tests/test_glue_cli.rs +++ b/crates/glue/tests/test_glue_cli.rs @@ -78,9 +78,8 @@ mod glue_cli_run { fixtures! { basic_record:"basic-record" => "Record was: MyRcd { b: 42, a: 1995 }\n", - // TODO: re-enable this test. Currently it is flaking on macos x86-64 with a bad exit code. - // nested_record:"nested-record" => "Record was: Outer { y: \"foo\", z: [1, 2], x: Inner { b: 24.0, a: 5 } }\n", - // enumeration:"enumeration" => "tag_union was: MyEnum::Foo, Bar is: MyEnum::Bar, Baz is: MyEnum::Baz\n", + nested_record:"nested-record" => "Record was: Outer { y: \"foo\", z: [1, 2], x: Inner { b: 24.0, a: 5 } }\n", + enumeration:"enumeration" => "tag_union was: MyEnum::Foo, Bar is: MyEnum::Bar, Baz is: MyEnum::Baz\n", single_tag_union:"single-tag-union" => indoc!(r#" tag_union was: SingleTagUnion::OneTag "#), @@ -129,9 +128,13 @@ mod glue_cli_run { multiple_modules:"multiple-modules" => indoc!(r#" combined was: Combined { s1: DepStr1::S("hello"), s2: DepStr2::R("world") } "#), - arguments:"arguments" => indoc!(r#" - Answer was: 84 - "#), + // issue https://github.com/roc-lang/roc/issues/6121 + // TODO: re-enable this test. Currently it is flaking on macos x86-64 with a bad exit code. + // nested_record:"nested-record" => "Record was: Outer { y: \"foo\", z: [1, 2], x: Inner { b: 24.0, a: 5 } }\n", + // enumeration:"enumeration" => "tag_union was: MyEnum::Foo, Bar is: MyEnum::Bar, Baz is: MyEnum::Baz\n", + // arguments:"arguments" => indoc!(r#" + // Answer was: 84 + // "#), closures:"closures" => indoc!(r#" Answer was: 672 "#), diff --git a/crates/lang_srv/README.md b/crates/lang_srv/README.md index 136aa77bc2..a85a1afbac 100644 --- a/crates/lang_srv/README.md +++ b/crates/lang_srv/README.md @@ -1,14 +1,11 @@ # roc_ls -This is a rudimentary language server for supporting basic editor usage in Roc. +This is a basic language server for Roc. Support for the following LSP features are provided: - - - - Inline diagnostics -- Hover support to get types of values +- Hover to view type of value - Go-to-definition -
Example @@ -29,26 +26,28 @@ Support for the following LSP features are provided:
-Semantic highlighting will also be added soon. Additional features require +[Semantic highlighting](https://github.com/microsoft/vscode/wiki/Semantic-Highlighting-Overview#what-is-the-difference-between-syntax-and-semantic-highlighting) will be added soon. Additional features require changes to the compiler infrastructure that are not yet available. -Note that the language server is a bit naive: -- If you make a change in a dependency, you'll need to also make a change in - the dependents' files for the changes to be picked up -- The language server will only operate on changes that are also reflected on - disk (so save often) +Note that the language server is a bit naïve: +- If you make a change in a dependency, you'll also need to make a change in + the dependents' files for the changes to be picked up. +- The language server will only operate on changes on save, auto-saving is recommended. ## Installing -At this time, only from-source installations of the binary are supported. +The roc_lang_server binary is included with the [nightly releases](https://github.com/roc-lang/roc/releases). We recommend using the same version of roc and roc_lang_server. -Follow the [installation from source](https://github.com/roc-lang/roc/tree/main/getting_started#installation) instructions. Then run +### Building from source + +Follow the [building from source](https://github.com/roc-lang/roc/blob/main/BUILDING_FROM_SOURCE.md) instructions for roc. Then run: ``` +# do `nix develop` first if you're using nix! cargo build -p roc_lang_srv --release ``` -which will give you a language server binary at +This will give you the language server binary at: ``` target/release/roc_ls diff --git a/crates/lang_srv/debug_server.sh b/crates/lang_srv/debug_server.sh index 5510f3d8d7..427c81be67 100755 --- a/crates/lang_srv/debug_server.sh +++ b/crates/lang_srv/debug_server.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/bash SCRIPT_DIR=$(cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd) ${SCRIPT_DIR}/../../target/debug/roc_ls "$@" 2> /tmp/roc_ls.err diff --git a/crates/lang_srv/src/analysis/tokens.rs b/crates/lang_srv/src/analysis/tokens.rs index 5649ce1a6d..637f86aeee 100644 --- a/crates/lang_srv/src/analysis/tokens.rs +++ b/crates/lang_srv/src/analysis/tokens.rs @@ -673,7 +673,7 @@ impl IterTokens for Loc> { Expr::Dbg(e1, e2) => (e1.iter_tokens(arena).into_iter()) .chain(e2.iter_tokens(arena)) .collect_in(arena), - Expr::LowLevelDbg(e1, e2) => (e1.iter_tokens(arena).into_iter()) + Expr::LowLevelDbg(_, e1, e2) => (e1.iter_tokens(arena).into_iter()) .chain(e2.iter_tokens(arena)) .collect_in(arena), Expr::Apply(e1, e2, _called_via) => (e1.iter_tokens(arena).into_iter()) diff --git a/crates/linker/src/pe.rs b/crates/linker/src/pe.rs index e7649642e5..711c5b7491 100644 --- a/crates/linker/src/pe.rs +++ b/crates/linker/src/pe.rs @@ -435,17 +435,87 @@ pub(crate) fn surgery_pe(executable_path: &Path, metadata_path: &Path, roc_app_b ); } else { let is_ingested_compiler_rt = [ - "__muloti4", + "__addtf3", + "__ceilx", + "__cmpdf2", + "__cmphf2", + "__cmpsf2", + "__cmptf2", + "__cmpxf2", + "__cosx", + "__divsf3", + "__divtf3", "__divti3", - "__udivti3", - "__modti3", - "__umodti3", + "__exp2x", + "__expx", + "__extendhfsf2", + "__fabsx", "__fixdfti", "__fixsfti", "__fixunsdfti", "__fixunssfti", + "__floorx", + "__fmax", + "__fmaxx", + "__fminx", + "__fmodx", + "__gedf2", + "__gehf2", + "__gesf2", + "__getf2", + "__gexf2", + "__log10x", + "__log2x", + "__logx", "__lshrti3", - "memcpy_decision", + "__modti3", + "__muloti4", + "__multf3", + "__roundx", + "__sincosx", + "__sinx", + "__sqrtx", + "__tanx", + "__truncsfhf2", + "__truncx", + "__udivmoddi4", + "__udivti3", + "__umodti3", + "ceilq", + "cos", + "cosf", + "cosq", + "exp", + "exp2", + "exp2q", + "expf", + "expq", + "floor", + "floorf", + "floorq", + "fmaq", + "fmaxf", + "fmaxl", + "fmodf", + "log10", + "log10q", + "log2", + "log2q", + "logq", + "memcpy", + "roundq", + "sin", + "sincos", + "sincosf", + "sincosq", + "sinf", + "sinq", + "sqrt", + "sqrtf", + "sqrtq", + "tan", + "tanf", + "tanq", ] .contains(&name.as_str()); if *address == 0 && !name.starts_with("roc") && !is_ingested_compiler_rt { diff --git a/crates/packaging/src/https.rs b/crates/packaging/src/https.rs index 5928b23dad..c015e9e442 100644 --- a/crates/packaging/src/https.rs +++ b/crates/packaging/src/https.rs @@ -240,6 +240,7 @@ pub enum Problem { InvalidUrl(UrlProblem), /// The Content-Length header of the response exceeded max_download_bytes DownloadTooBig(u64), + NotFound, } pub fn download_and_hash( @@ -255,6 +256,10 @@ pub fn download_and_hash( .send() .map_err(Problem::HttpErr)?; + if resp.status() == reqwest::StatusCode::NOT_FOUND { + return Err(Problem::NotFound); + } + // Some servers don't return Content-Length - e.g. Netlify seems to only sometimes return it. // If they do, and if it says the file is going to be too big, don't bother downloading it! if let Some(content_len) = resp.content_length() { diff --git a/crates/repl_cli/src/cli_gen.rs b/crates/repl_cli/src/cli_gen.rs index b6e906e155..81c86981fc 100644 --- a/crates/repl_cli/src/cli_gen.rs +++ b/crates/repl_cli/src/cli_gen.rs @@ -255,9 +255,6 @@ fn mono_module_to_dylib_llvm<'a>( env.dibuilder.finalize(); - // we don't use the debug info, and it causes weird errors. - module.strip_debug_info(); - // Uncomment this to see the module's un-optimized LLVM instruction output: // env.module.print_to_stderr(); diff --git a/crates/repl_expect/src/run.rs b/crates/repl_expect/src/run.rs index 202086aae8..8ce24d49ce 100644 --- a/crates/repl_expect/src/run.rs +++ b/crates/repl_expect/src/run.rs @@ -713,9 +713,6 @@ pub fn expect_mono_module_to_dylib<'a>( env.dibuilder.finalize(); - // we don't use the debug info, and it causes weird errors. - module.strip_debug_info(); - // Uncomment this to see the module's un-optimized LLVM instruction output: // env.module.print_to_stderr(); diff --git a/crates/repl_ui/src/repl_state.rs b/crates/repl_ui/src/repl_state.rs index fb93db61bd..6f2e7103f6 100644 --- a/crates/repl_ui/src/repl_state.rs +++ b/crates/repl_ui/src/repl_state.rs @@ -206,7 +206,11 @@ pub fn parse_src<'a>(arena: &'a Bump, line: &'a str) -> ParseOutcome<'a> { match line.trim().to_lowercase().as_str() { "" => ParseOutcome::Empty, ":help" => ParseOutcome::Help, - ":exit" | ":quit" | ":q" => ParseOutcome::Exit, + // These are all common things beginners try. + // Let people exit the repl easily! + // If you really need to evaluate `exit` for some reason, + // you can do `foo = exit` and then evaluate `foo` instead. + ":exit" | ":quit" | ":q" | "exit" | "quit" | "exit()" | "quit()" => ParseOutcome::Exit, _ => { let src_bytes = line.as_bytes(); diff --git a/crates/repl_wasm/README.md b/crates/repl_wasm/README.md index be6731426c..5f4cd8fb58 100644 --- a/crates/repl_wasm/README.md +++ b/crates/repl_wasm/README.md @@ -14,13 +14,14 @@ crates/repl_wasm/build-www.sh ### 2. Make symlinks to the generated Wasm and JS ```bash -cd www/public +mkdir -p www/public/repl +cd www/public/repl ln -s ../../../crates/repl_wasm/build/roc_repl_wasm_bg.wasm ln -s ../../../crates/repl_wasm/build/roc_repl_wasm.js ``` These symlinks are ignored by Git. -> This is a bit different from the production build, where we copy all the files to `www/build/`. But for development, it's convenient to have just one copy of files like `www/public/repl.js`. You can make changes, reload your browser to see them, and commit them to Git, without getting mixed up between different copies of the same file. +> This is a bit different from the production build, where we copy all the files to `www/build/`. But for development, it's convenient to have just one copy of files like `www/public/repl/repl.js`. You can make changes, reload your browser to see them, and commit them to Git, without getting mixed up between different copies of the same file. ### 3. Run a local HTTP server diff --git a/crates/reporting/src/error/canonicalize.rs b/crates/reporting/src/error/canonicalize.rs index cad1da9879..68eb249225 100644 --- a/crates/reporting/src/error/canonicalize.rs +++ b/crates/reporting/src/error/canonicalize.rs @@ -1090,7 +1090,7 @@ pub fn can_problem<'b>( title = "OVERAPPLIED CRASH".to_string(); } Problem::FileProblem { filename, error } => { - let report = to_file_problem_report(alloc, &filename, error); + let report = to_file_problem_report(alloc, filename, error); doc = report.doc; title = report.title; } diff --git a/crates/reporting/src/error/parse.rs b/crates/reporting/src/error/parse.rs index 839da6c2f4..ecbe2cc355 100644 --- a/crates/reporting/src/error/parse.rs +++ b/crates/reporting/src/error/parse.rs @@ -670,6 +670,23 @@ fn to_expr_report<'a>( EExpr::Dbg(e_expect, _position) => { to_dbg_or_expect_report(alloc, lines, filename, context, Node::Dbg, e_expect, start) } + EExpr::TrailingOperator(pos) => { + let surroundings = Region::new(start, *pos); + let region = LineColumnRegion::from_pos(lines.convert_pos(*pos)); + + let doc = alloc.stack([ + alloc.reflow(r"I am partway through parsing an expression, but I got stuck here:"), + alloc.region_with_subregion(lines.convert_region(surroundings), region), + alloc.concat([alloc.reflow("TODO provide more context.")]), + ]); + + Report { + filename, + doc, + title: "TRAILING OPERATOR".to_string(), + severity: Severity::RuntimeError, + } + } _ => todo!("unhandled parse error: {:?}", parse_problem), } } diff --git a/crates/reporting/src/report.rs b/crates/reporting/src/report.rs index cb86c5eac7..7c6a8051c5 100644 --- a/crates/reporting/src/report.rs +++ b/crates/reporting/src/report.rs @@ -1101,7 +1101,11 @@ where } #[cfg(not(target_family = "wasm"))] -pub fn to_https_problem_report_string(url: &str, https_problem: Problem) -> String { +pub fn to_https_problem_report_string( + url: &str, + https_problem: Problem, + filename: PathBuf, +) -> String { let src_lines: Vec<&str> = Vec::new(); let mut module_ids = ModuleIds::default(); @@ -1115,7 +1119,7 @@ pub fn to_https_problem_report_string(url: &str, https_problem: Problem) -> Stri let mut buf = String::new(); let palette = DEFAULT_PALETTE; - let report = to_https_problem_report(&alloc, url, https_problem); + let report = to_https_problem_report(&alloc, url, https_problem, filename); report.render_color_terminal(&mut buf, &alloc, &palette); buf @@ -1126,11 +1130,12 @@ pub fn to_https_problem_report<'b>( alloc: &'b RocDocAllocator<'b>, url: &'b str, https_problem: Problem, + filename: PathBuf, ) -> Report<'b> { match https_problem { Problem::UnsupportedEncoding(not_supported_encoding) => { let doc = alloc.stack([ - alloc.reflow(r"I was trying to download this URL:"), + alloc.reflow(r"I tried to download from this URL:"), alloc.string((&url).to_string()).annotate(Annotation::Url).indent(4), alloc.concat([ alloc.reflow(r"But the server replied with a "), @@ -1154,7 +1159,7 @@ pub fn to_https_problem_report<'b>( ]); Report { - filename: "UNKNOWN.roc".into(), + filename, doc, title: "UNSUPPORTED ENCODING".to_string(), severity: Severity::Fatal, @@ -1162,7 +1167,7 @@ pub fn to_https_problem_report<'b>( } Problem::MultipleEncodings(multiple_encodings) => { let doc = alloc.stack([ - alloc.reflow(r"I was trying to download this URL:"), + alloc.reflow(r"I tried to download from this URL:"), alloc.string((&url).to_string()).annotate(Annotation::Url).indent(4), alloc.concat([ alloc.reflow(r"But the server replied with multiple "), @@ -1189,7 +1194,7 @@ pub fn to_https_problem_report<'b>( ]); Report { - filename: "UNKNOWN.roc".into(), + filename, doc, title: "MULTIPLE ENCODINGS".to_string(), severity: Severity::Fatal, @@ -1224,16 +1229,33 @@ pub fn to_https_problem_report<'b>( ]); Report { - filename: "UNKNOWN.roc".into(), + filename, doc, title: "INVALID CONTENT HASH".to_string(), severity: Severity::Fatal, } } + Problem::NotFound => { + let doc = alloc.stack([ + alloc.reflow(r"I tried to download from this URL:"), + alloc + .string((&url).to_string()) + .annotate(Annotation::Url) + .indent(4), + alloc.concat([alloc.reflow(r"But the file was not found (404).")]), + alloc.concat([alloc.tip(), alloc.reflow(r"Is the URL correct?")]), + ]); + Report { + filename, + doc, + title: "NOTFOUND".to_string(), + severity: Severity::Fatal, + } + } // TODO: The reporting text for IoErr and FsExtraErr could probably be unified Problem::IoErr(io_error) => { let doc = alloc.stack([ - alloc.reflow(r"I was trying to download this URL:"), + alloc.reflow(r"I tried to download from this URL:"), alloc .string((&url).to_string()) .annotate(Annotation::Url) @@ -1251,7 +1273,7 @@ pub fn to_https_problem_report<'b>( ]); Report { - filename: "UNKNOWN.roc".into(), + filename, doc, title: "IO ERROR".to_string(), severity: Severity::Fatal, @@ -1260,7 +1282,7 @@ pub fn to_https_problem_report<'b>( // TODO: The reporting text for IoErr and FsExtraErr could probably be unified Problem::FsExtraErr(fs_extra_error) => { let doc = alloc.stack([ - alloc.reflow(r"I was trying to download this URL:"), + alloc.reflow(r"I tried to download from this URL:"), alloc .string((&url).to_string()) .annotate(Annotation::Url) @@ -1278,7 +1300,7 @@ pub fn to_https_problem_report<'b>( ]); Report { - filename: "UNKNOWN.roc".into(), + filename, doc, title: "IO ERROR".to_string(), severity: Severity::Fatal, @@ -1286,7 +1308,7 @@ pub fn to_https_problem_report<'b>( } Problem::HttpErr(reqwest_error) => { let doc = alloc.stack([ - alloc.reflow(r"I was trying to download this URL:"), + alloc.reflow(r"I tried to download from this URL:"), alloc .string((&url).to_string()) .annotate(Annotation::Url) @@ -1307,7 +1329,7 @@ pub fn to_https_problem_report<'b>( ]); Report { - filename: "UNKNOWN.roc".into(), + filename, doc, title: "HTTP ERROR".to_string(), severity: Severity::Fatal, @@ -1323,7 +1345,7 @@ pub fn to_https_problem_report<'b>( }; let doc = alloc.stack([ - alloc.reflow(r"I was trying to download this URL:"), + alloc.reflow(r"I tried to download from this URL:"), alloc .string((&url).to_string()) .annotate(Annotation::Url) @@ -1348,7 +1370,7 @@ pub fn to_https_problem_report<'b>( ]); Report { - filename: "UNKNOWN.roc".into(), + filename, doc, title: "INVALID EXTENSION SUFFIX".to_string(), severity: Severity::Fatal, @@ -1356,7 +1378,7 @@ pub fn to_https_problem_report<'b>( } Problem::InvalidUrl(roc_packaging::https::UrlProblem::MissingTarExt) => { let doc = alloc.stack([ - alloc.reflow(r"I was trying to download this URL:"), + alloc.reflow(r"I tried to download from this URL:"), alloc .string((&url).to_string()) .annotate(Annotation::Url) @@ -1381,7 +1403,7 @@ pub fn to_https_problem_report<'b>( ]); Report { - filename: "UNKNOWN.roc".into(), + filename, doc, title: "INVALID EXTENSION".to_string(), severity: Severity::Fatal, @@ -1391,7 +1413,7 @@ pub fn to_https_problem_report<'b>( invalid_fragment, )) => { let doc = alloc.stack([ - alloc.reflow(r"I was trying to download this URL:"), + alloc.reflow(r"I tried to download from this URL:"), alloc .string((&url).to_string()) .annotate(Annotation::Url) @@ -1419,7 +1441,7 @@ pub fn to_https_problem_report<'b>( ]); Report { - filename: "UNKNOWN.roc".into(), + filename, doc, title: "INVALID FRAGMENT".to_string(), severity: Severity::Fatal, @@ -1427,7 +1449,7 @@ pub fn to_https_problem_report<'b>( } Problem::InvalidUrl(roc_packaging::https::UrlProblem::MissingHash) => { let doc = alloc.stack([ - alloc.reflow(r"I was trying to download this URL:"), + alloc.reflow(r"I tried to download from this URL:"), alloc .string((&url).to_string()) .annotate(Annotation::Url) @@ -1457,7 +1479,7 @@ pub fn to_https_problem_report<'b>( ]); Report { - filename: "UNKNOWN.roc".into(), + filename, doc, title: "MISSING PACKAGE HASH".to_string(), severity: Severity::Fatal, @@ -1465,7 +1487,7 @@ pub fn to_https_problem_report<'b>( } Problem::InvalidUrl(roc_packaging::https::UrlProblem::MissingHttps) => { let doc = alloc.stack([ - alloc.reflow(r"I was trying to download this URL:"), + alloc.reflow(r"I tried to download from this URL:"), alloc .string((&url).to_string()) .annotate(Annotation::Url) @@ -1483,7 +1505,7 @@ pub fn to_https_problem_report<'b>( ]); Report { - filename: "UNKNOWN.roc".into(), + filename, doc, title: "HTTPS MANDATORY".to_string(), severity: Severity::Fatal, @@ -1491,7 +1513,7 @@ pub fn to_https_problem_report<'b>( } Problem::InvalidUrl(roc_packaging::https::UrlProblem::MisleadingCharacter) => { let doc = alloc.stack([ - alloc.reflow(r"I was trying to download this URL:"), + alloc.reflow(r"I tried to download from this URL:"), alloc .string((&url).to_string()) .annotate(Annotation::Url) @@ -1526,7 +1548,7 @@ pub fn to_https_problem_report<'b>( ]); Report { - filename: "UNKNOWN.roc".into(), + filename, doc, title: "MISLEADING CHARACTERS".to_string(), severity: Severity::Fatal, @@ -1537,7 +1559,7 @@ pub fn to_https_problem_report<'b>( .get_appropriate_unit(false) .format(3); let doc = alloc.stack([ - alloc.reflow(r"I was trying to download this URL:"), + alloc.reflow(r"I tried to download from this URL:"), alloc .string((&url).to_string()) .annotate(Annotation::Url) @@ -1556,7 +1578,7 @@ pub fn to_https_problem_report<'b>( ]); Report { - filename: "UNKNOWN.roc".into(), + filename, doc, title: "FILE TOO LARGE".to_string(), severity: Severity::Fatal, @@ -1565,13 +1587,10 @@ pub fn to_https_problem_report<'b>( } } -pub fn to_file_problem_report_string(filename: &Path, error: io::ErrorKind) -> String { +pub fn to_file_problem_report_string(filename: PathBuf, error: io::ErrorKind) -> String { let src_lines: Vec<&str> = Vec::new(); - let mut module_ids = ModuleIds::default(); - let module_id = module_ids.get_or_insert(&"find module name somehow?".into()); - let interns = Interns::default(); // Report parsing and canonicalization problems @@ -1587,16 +1606,16 @@ pub fn to_file_problem_report_string(filename: &Path, error: io::ErrorKind) -> S pub fn to_file_problem_report<'b>( alloc: &'b RocDocAllocator<'b>, - filename: &Path, + filename: PathBuf, error: io::ErrorKind, ) -> Report<'b> { - let filename: String = filename.to_str().unwrap().to_string(); + let filename_str: String = filename.to_str().unwrap().to_string(); match error { io::ErrorKind::NotFound => { let doc = alloc.stack([ alloc.reflow(r"I am looking for this file, but it's not there:"), alloc - .string(filename) + .string(filename_str) .annotate(Annotation::ParserSuggestion) .indent(4), alloc.concat([ @@ -1606,7 +1625,7 @@ pub fn to_file_problem_report<'b>( ]); Report { - filename: "UNKNOWN.roc".into(), + filename, doc, title: "FILE NOT FOUND".to_string(), severity: Severity::Fatal, @@ -1616,7 +1635,7 @@ pub fn to_file_problem_report<'b>( let doc = alloc.stack([ alloc.reflow(r"I don't have the required permissions to read this file:"), alloc - .string(filename) + .string(filename_str) .annotate(Annotation::ParserSuggestion) .indent(4), alloc @@ -1624,7 +1643,7 @@ pub fn to_file_problem_report<'b>( ]); Report { - filename: "UNKNOWN.roc".into(), + filename, doc, title: "FILE PERMISSION DENIED".to_string(), severity: Severity::Fatal, @@ -1635,13 +1654,16 @@ pub fn to_file_problem_report<'b>( let formatted = format!("{error}"); let doc = alloc.stack([ alloc.reflow(r"I tried to read this file:"), - alloc.string(filename).annotate(Annotation::Error).indent(4), + alloc + .string(filename_str) + .annotate(Annotation::Error) + .indent(4), alloc.reflow(r"But ran into:"), alloc.text(formatted).annotate(Annotation::Error).indent(4), ]); Report { - filename: "UNKNOWN.roc".into(), + filename, doc, title: "FILE PROBLEM".to_string(), severity: Severity::Fatal, diff --git a/crates/roc_std/src/lib.rs b/crates/roc_std/src/lib.rs index 2d88e7d72e..f9c4dfbdb5 100644 --- a/crates/roc_std/src/lib.rs +++ b/crates/roc_std/src/lib.rs @@ -36,7 +36,7 @@ extern "C" { ) -> *mut c_void; pub fn roc_dealloc(ptr: *mut c_void, alignment: u32); pub fn roc_panic(c_ptr: *mut c_void, tag_id: u32); - pub fn roc_dbg(loc: *mut c_void, msg: *mut c_void); + pub fn roc_dbg(loc: *mut c_void, msg: *mut c_void, src: *mut c_void); pub fn roc_memset(dst: *mut c_void, c: i32, n: usize) -> *mut c_void; } diff --git a/crates/roc_std/src/roc_list.rs b/crates/roc_std/src/roc_list.rs index 5d454253de..a7623bb243 100644 --- a/crates/roc_std/src/roc_list.rs +++ b/crates/roc_std/src/roc_list.rs @@ -12,6 +12,7 @@ use core::{ ops::{Deref, DerefMut}, ptr::{self, NonNull}, }; +use std::ops::Range; use crate::{roc_alloc, roc_dealloc, roc_realloc, storage::Storage}; @@ -208,7 +209,7 @@ impl RocList { } /// Useful for doing memcpy on the elements. Returns NULL if list is empty. - pub(crate) unsafe fn ptr_to_first_elem(&self) -> *const T { + pub(crate) fn ptr_to_first_elem(&self) -> *const T { unsafe { core::mem::transmute(self.elements) } } @@ -222,6 +223,15 @@ impl RocList { } } + #[allow(unused)] + pub(crate) fn ptr_to_refcount(&self) -> *mut c_void { + if self.is_seamless_slice() { + ((self.capacity_or_ref_ptr << 1) - std::mem::size_of::()) as *mut _ + } else { + unsafe { self.ptr_to_first_elem().cast::().sub(1) as *mut _ } + } + } + unsafe fn elem_ptr_from_alloc_ptr(alloc_ptr: *mut c_void) -> *mut c_void { unsafe { alloc_ptr @@ -230,6 +240,44 @@ impl RocList { .cast() } } + + pub fn append(&mut self, value: T) { + self.push(value) + } + + pub fn push(&mut self, value: T) { + if self.capacity() <= self.len() { + // reserve space for (at least!) one more element + self.reserve(1); + } + + let elements = self.elements.unwrap().as_ptr(); + let append_ptr = unsafe { elements.add(self.len()) }; + + unsafe { + // Write the element into the slot, without dropping it. + ptr::write(append_ptr, ManuallyDrop::new(value)); + } + + // It's important that the length is increased one by one, to + // make sure that we don't drop uninitialized elements, even when + // a incrementing the reference count panics. + self.length += 1; + } + + /// # Safety + /// + /// - `bytes` must be allocated for `cap` elements + /// - `bytes` must be initialized for `len` elements + /// - `bytes` must be preceded by a correctly-aligned refcount (usize) + /// - `cap` >= `len` + pub unsafe fn from_raw_parts(bytes: *mut T, len: usize, cap: usize) -> Self { + Self { + elements: NonNull::new(bytes.cast()), + length: len, + capacity_or_ref_ptr: cap, + } + } } impl RocList @@ -323,6 +371,38 @@ where } impl RocList { + #[track_caller] + pub fn slice_range(&self, range: Range) -> Self { + match self.try_slice_range(range) { + Some(x) => x, + None => panic!("slice index out of range"), + } + } + + pub fn try_slice_range(&self, range: Range) -> Option { + if self.as_slice().get(range.start..range.end).is_none() { + None + } else { + // increment the refcount + std::mem::forget(self.clone()); + + let element_ptr = self.as_slice()[range.start..] + .as_ptr() + .cast::>(); + + let capacity_or_ref_ptr = + (self.ptr_to_first_elem() as usize) >> 1 | isize::MIN as usize; + + let roc_list = RocList { + elements: NonNull::new(element_ptr as *mut ManuallyDrop), + length: range.end - range.start, + capacity_or_ref_ptr, + }; + + Some(roc_list) + } + } + /// Increase a RocList's capacity by at least the requested number of elements (possibly more). /// /// May return a new RocList, if the provided one was not unique. @@ -333,7 +413,7 @@ impl RocList { match self.elements_and_storage() { Some((elements, storage)) => { - if storage.get().is_unique() { + if storage.get().is_unique() && !self.is_seamless_slice() { unsafe { let old_alloc = self.ptr_to_allocation(); diff --git a/crates/roc_std/src/roc_str.rs b/crates/roc_std/src/roc_str.rs index bf7c83c09f..7a92458013 100644 --- a/crates/roc_std/src/roc_str.rs +++ b/crates/roc_std/src/roc_str.rs @@ -19,8 +19,9 @@ use core::{ #[cfg(feature = "std")] use std::ffi::{CStr, CString}; +use std::{ops::Range, ptr::NonNull}; -use crate::RocList; +use crate::{roc_realloc, RocList}; #[repr(transparent)] pub struct RocStr(RocStrInner); @@ -73,8 +74,34 @@ impl RocStr { Self(RocStrInner { small_string }) } else { let heap_allocated = RocList::from_slice(slice); + let big_string = unsafe { std::mem::transmute(heap_allocated) }; Self(RocStrInner { - heap_allocated: ManuallyDrop::new(heap_allocated), + heap_allocated: ManuallyDrop::new(big_string), + }) + } + } + + /// # Safety + /// + /// - `bytes` must be allocated for `cap` bytes + /// - `bytes` must be initialized for `len` bytes + /// - `bytes` must be preceded by a correctly-aligned refcount (usize) + /// - `bytes` must represent valid UTF-8 + /// - `cap` >= `len` + pub unsafe fn from_raw_parts(bytes: *mut u8, len: usize, cap: usize) -> Self { + if len <= SmallString::CAPACITY { + unsafe { + let slice = std::slice::from_raw_parts(bytes, len); + let small_string = SmallString::try_from_utf8_bytes(slice).unwrap_unchecked(); + Self(RocStrInner { small_string }) + } + } else { + Self(RocStrInner { + heap_allocated: ManuallyDrop::new(BigString { + elements: unsafe { NonNull::new_unchecked(bytes) }, + length: len, + capacity_or_alloc_ptr: cap, + }), }) } } @@ -93,7 +120,7 @@ impl RocStr { pub fn capacity(&self) -> usize { match self.as_enum_ref() { - RocStrInnerRef::HeapAllocated(roc_list) => roc_list.capacity(), + RocStrInnerRef::HeapAllocated(big_string) => big_string.capacity(), RocStrInnerRef::SmallString(_) => SmallString::CAPACITY, } } @@ -137,10 +164,12 @@ impl RocStr { /// There is no way to tell how many references it has and if it is safe to free. /// As such, only values that should have a static lifetime for the entire application run /// should be considered for marking read-only. - pub unsafe fn set_readonly(&self) { - match self.as_enum_ref() { - RocStrInnerRef::HeapAllocated(roc_list) => unsafe { roc_list.set_readonly() }, - RocStrInnerRef::SmallString(_) => {} + pub unsafe fn set_readonly(&mut self) { + if self.is_small_str() { + /* do nothing */ + } else { + let big = unsafe { &mut self.0.heap_allocated }; + big.set_readonly() } } @@ -167,7 +196,7 @@ impl RocStr { } else { // The requested capacity won't fit in a small string; we need to go big. RocStr(RocStrInner { - heap_allocated: ManuallyDrop::new(RocList::with_capacity(bytes)), + heap_allocated: ManuallyDrop::new(BigString::with_capacity(bytes)), }) } } @@ -182,21 +211,33 @@ impl RocStr { if target_cap > SmallString::CAPACITY { // The requested capacity won't fit in a small string; we need to go big. - let mut roc_list = RocList::with_capacity(target_cap); + let mut big_string = BigString::with_capacity(target_cap); - roc_list.extend_from_slice(small_str.as_bytes()); + unsafe { + std::ptr::copy_nonoverlapping( + self.as_bytes().as_ptr(), + big_string.ptr_to_first_elem(), + self.len(), + ) + }; - *self = RocStr(RocStrInner { - heap_allocated: ManuallyDrop::new(roc_list), + big_string.length = self.len(); + big_string.capacity_or_alloc_ptr = target_cap; + + let mut updated = RocStr(RocStrInner { + heap_allocated: ManuallyDrop::new(big_string), }); + + mem::swap(self, &mut updated); + mem::forget(updated); } } else { - let mut roc_list = unsafe { ManuallyDrop::take(&mut self.0.heap_allocated) }; + let mut big_string = unsafe { ManuallyDrop::take(&mut self.0.heap_allocated) }; - roc_list.reserve(bytes); + big_string.reserve(bytes); let mut updated = RocStr(RocStrInner { - heap_allocated: ManuallyDrop::new(roc_list), + heap_allocated: ManuallyDrop::new(big_string), }); mem::swap(self, &mut updated); @@ -204,12 +245,57 @@ impl RocStr { } } + #[track_caller] + pub fn slice_range(&self, range: Range) -> Self { + match self.try_slice_range(range) { + Some(x) => x, + None => panic!("slice index out of range"), + } + } + + pub fn try_slice_range(&self, range: Range) -> Option { + if self.as_str().get(range.start..range.end).is_none() { + None + } else if range.end - range.start <= SmallString::CAPACITY && self.is_small_str() { + let slice = &self.as_bytes()[range]; + let small_string = + unsafe { SmallString::try_from_utf8_bytes(slice).unwrap_unchecked() }; + + // NOTE decrements `self` + Some(RocStr(RocStrInner { small_string })) + } else { + // increment the refcount + std::mem::forget(self.clone()); + + let big = unsafe { &self.0.heap_allocated }; + let ptr = unsafe { (self.as_bytes().as_ptr() as *mut u8).add(range.start) }; + + let heap_allocated = ManuallyDrop::new(BigString { + elements: unsafe { NonNull::new_unchecked(ptr) }, + length: (isize::MIN as usize) | (range.end - range.start), + capacity_or_alloc_ptr: (big.ptr_to_first_elem() as usize) >> 1, + }); + + Some(RocStr(RocStrInner { heap_allocated })) + } + } + + pub fn split_once(&self, delimiter: &str) -> Option<(Self, Self)> { + let (a, b) = self.as_str().split_once(delimiter)?; + + let x = self.slice_range(0..a.len()); + let y = self.slice_range(self.len() - b.len()..self.len()); + + Some((x, y)) + } + + pub fn split_whitespace(&self) -> SplitWhitespace<'_> { + SplitWhitespace(self.as_str().char_indices().peekable(), self) + } + /// Returns the index of the first interior \0 byte in the string, or None if there are none. fn first_nul_byte(&self) -> Option { - match self.as_enum_ref() { - RocStrInnerRef::HeapAllocated(roc_list) => roc_list.iter().position(|byte| *byte == 0), - RocStrInnerRef::SmallString(small_string) => small_string.first_nul_byte(), - } + self.as_bytes().iter().position(|byte| *byte == 0) } // If the string is under this many bytes, the with_terminator family @@ -267,59 +353,48 @@ impl RocStr { }; match self.as_enum_ref() { - RocStrInnerRef::HeapAllocated(roc_list) => { + RocStrInnerRef::HeapAllocated(big_string) => { unsafe { - match roc_list.storage() { - Some(storage) if storage.is_unique() => { - // The backing RocList was unique, so we can mutate it in-place. - let len = roc_list.len(); - let ptr = if len < roc_list.capacity() { - // We happen to have excess capacity already, so we will be able - // to write the terminator into the first byte of excess capacity. - roc_list.ptr_to_first_elem() as *mut u8 - } else { - // We always have an allocation that's even bigger than necessary, - // because the refcount bytes take up more than the 1B needed for - // the terminator. We just need to shift the bytes over on top - // of the refcount. - let alloc_ptr = roc_list.ptr_to_allocation() as *mut u8; + if big_string.is_unique() { + // The backing RocList was unique, so we can mutate it in-place. + let len = big_string.len(); + let ptr = if len < big_string.capacity() { + // We happen to have excess capacity already, so we will be able + // to write the terminator into the first byte of excess capacity. + big_string.ptr_to_first_elem() as *mut u8 + } else { + // We always have an allocation that's even bigger than necessary, + // because the refcount bytes take up more than the 1B needed for + // the terminator. We just need to shift the bytes over on top + // of the refcount. + let alloc_ptr = big_string.ptr_to_allocation() as *mut u8; - // First, copy the bytes over the original allocation - effectively - // shifting everything over by one `usize`. Now we no longer have a - // refcount (but the terminated won't use that anyway), but we do - // have a free `usize` at the end. - // - // IMPORTANT: Must use ptr::copy instead of ptr::copy_nonoverlapping - // because the regions definitely overlap! - ptr::copy(roc_list.ptr_to_first_elem() as *mut u8, alloc_ptr, len); - - alloc_ptr - }; - - terminate(ptr, len) - } - Some(_) => { - let len = roc_list.len(); - - // The backing list was not unique, so we can't mutate it in-place. - // ask for `len + 1` to store the original string and the terminator - with_stack_bytes(len + 1, |alloc_ptr: *mut u8| { - let elem_ptr = roc_list.ptr_to_first_elem() as *mut u8; - - // memcpy the bytes into the stack allocation - ptr::copy_nonoverlapping(elem_ptr, alloc_ptr, len); - - terminate(alloc_ptr, len) - }) - } - None => { - // The backing list was empty. + // First, copy the bytes over the original allocation - effectively + // shifting everything over by one `usize`. Now we no longer have a + // refcount (but the terminated won't use that anyway), but we do + // have a free `usize` at the end. // - // No need to do a heap allocation for an empty string - we - // can just do a stack allocation that will live for the - // duration of the function. - func([terminator].as_mut_ptr(), 0) - } + // IMPORTANT: Must use ptr::copy instead of ptr::copy_nonoverlapping + // because the regions definitely overlap! + ptr::copy(big_string.ptr_to_first_elem() as *mut u8, alloc_ptr, len); + + alloc_ptr + }; + + terminate(ptr, len) + } else { + let len = big_string.len(); + + // The backing list was not unique, so we can't mutate it in-place. + // ask for `len + 1` to store the original string and the terminator + with_stack_bytes(len + 1, |alloc_ptr: *mut u8| { + let elem_ptr = big_string.ptr_to_first_elem() as *mut u8; + + // memcpy the bytes into the stack allocation + std::ptr::copy_nonoverlapping(elem_ptr, alloc_ptr, len); + + terminate(alloc_ptr, len) + }) } } } @@ -484,57 +559,46 @@ impl RocStr { }; match self.as_enum_ref() { - RocStrInnerRef::HeapAllocated(roc_list) => { - let len = roc_list.len(); + RocStrInnerRef::HeapAllocated(big_string) => { + let len = big_string.len(); unsafe { - match roc_list.storage() { - Some(storage) if storage.is_unique() => { - // The backing RocList was unique, so we can mutate it in-place. + if big_string.is_unique() { + // The backing RocList was unique, so we can mutate it in-place. - // We need 1 extra elem for the terminator. It must be an elem, - // not a byte, because we'll be providing a pointer to elems. - let needed_bytes = (len + 1) * size_of::(); + // We need 1 extra elem for the terminator. It must be an elem, + // not a byte, because we'll be providing a pointer to elems. + let needed_bytes = (len + 1) * size_of::(); - // We can use not only the capacity on the heap, but also - // the bytes originally used for the refcount. - let available_bytes = roc_list.capacity() + size_of::(); + // We can use not only the capacity on the heap, but also + // the bytes originally used for the refcount. + let available_bytes = big_string.capacity() + size_of::(); - if needed_bytes < available_bytes { - debug_assert!(align_of::() >= align_of::()); + if needed_bytes < available_bytes { + debug_assert!(align_of::() >= align_of::()); - // We happen to have sufficient excess capacity already, - // so we will be able to write the new elements as well as - // the terminator into the existing allocation. - let ptr = roc_list.ptr_to_allocation() as *mut E; - let answer = terminate(ptr, self.as_str()); + // We happen to have sufficient excess capacity already, + // so we will be able to write the new elements as well as + // the terminator into the existing allocation. + let ptr = big_string.ptr_to_allocation() as *mut E; + let answer = terminate(ptr, self.as_str()); - // We cannot rely on the RocStr::drop implementation, because - // it tries to use the refcount - which we just overwrote - // with string bytes. - mem::forget(self); - crate::roc_dealloc(ptr.cast(), mem::align_of::() as u32); + // We cannot rely on the RocStr::drop implementation, because + // it tries to use the refcount - which we just overwrote + // with string bytes. + mem::forget(self); + crate::roc_dealloc(ptr.cast(), mem::align_of::() as u32); - answer - } else { - // We didn't have sufficient excess capacity already, - // so we need to do either a new stack allocation or a new - // heap allocation. - fallback(self.as_str()) - } - } - Some(_) => { - // The backing list was not unique, so we can't mutate it in-place. + answer + } else { + // We didn't have sufficient excess capacity already, + // so we need to do either a new stack allocation or a new + // heap allocation. fallback(self.as_str()) } - None => { - // The backing list was empty. - // - // No need to do a heap allocation for an empty string - we - // can just do a stack allocation that will live for the - // duration of the function. - func([terminator].as_mut_ptr(), "") - } + } else { + // The backing list was not unique, so we can't mutate it in-place. + fallback(self.as_str()) } } } @@ -557,12 +621,44 @@ impl RocStr { } } +pub struct SplitWhitespace<'a>(std::iter::Peekable>, &'a RocStr); + +impl Iterator for SplitWhitespace<'_> { + type Item = RocStr; + + fn next(&mut self) -> Option { + let start = 'blk: { + while let Some((pos, c)) = self.0.peek() { + if c.is_whitespace() { + self.0.next(); + } else { + break 'blk *pos; + } + } + + return None; + }; + + let end = 'blk: { + for (pos, c) in self.0.by_ref() { + if c.is_whitespace() { + break 'blk pos; + } + } + + break 'blk self.1.len(); + }; + + self.1.try_slice_range(start..end) + } +} + impl Deref for RocStr { type Target = str; fn deref(&self) -> &Self::Target { match self.as_enum_ref() { - RocStrInnerRef::HeapAllocated(h) => unsafe { core::str::from_utf8_unchecked(h) }, + RocStrInnerRef::HeapAllocated(h) => h.as_str(), RocStrInnerRef::SmallString(s) => s, } } @@ -696,6 +792,203 @@ impl From for RocStr { } } +#[repr(C)] +struct BigString { + elements: NonNull, + length: usize, + capacity_or_alloc_ptr: usize, +} + +const SEAMLESS_SLICE_BIT: usize = isize::MIN as usize; + +impl BigString { + fn len(&self) -> usize { + self.length & !SEAMLESS_SLICE_BIT + } + + fn capacity(&self) -> usize { + if self.is_seamless_slice() { + self.len() + } else { + self.capacity_or_alloc_ptr + } + } + + fn is_seamless_slice(&self) -> bool { + (self.length as isize) < 0 + } + + fn ptr_to_first_elem(&self) -> *mut u8 { + unsafe { core::mem::transmute(self.elements) } + } + + fn ptr_to_allocation(&self) -> *mut usize { + // these are the same because the alignment of u8 is just 1 + self.ptr_to_refcount() + } + + fn ptr_to_refcount(&self) -> *mut usize { + if self.is_seamless_slice() { + unsafe { ((self.capacity_or_alloc_ptr << 1) as *mut usize).sub(1) } + } else { + unsafe { self.ptr_to_first_elem().cast::().sub(1) } + } + } + + fn as_bytes(&self) -> &[u8] { + unsafe { std::slice::from_raw_parts(self.ptr_to_first_elem(), self.len()) } + } + + fn as_str(&self) -> &str { + unsafe { std::str::from_utf8_unchecked(self.as_bytes()) } + } + + fn is_unique(&self) -> bool { + if self.capacity() == 0 { + return false; + } + + let ptr = self.ptr_to_refcount(); + let rc = unsafe { std::ptr::read(ptr) as isize }; + + rc == isize::MIN + } + + fn is_readonly(&self) -> bool { + if self.capacity() == 0 { + return true; + } + + let ptr = self.ptr_to_refcount(); + let rc = unsafe { std::ptr::read(ptr) as isize }; + + rc == 0 + } + + fn set_readonly(&mut self) { + assert_ne!(self.capacity(), 0); + + let ptr = self.ptr_to_refcount(); + unsafe { std::ptr::write(ptr, 0) } + } + + fn inc(&mut self, n: usize) { + let ptr = self.ptr_to_refcount(); + unsafe { + let value = std::ptr::read(ptr); + std::ptr::write(ptr, Ord::max(0, ((value as isize) + n as isize) as usize)); + } + } + + fn dec(&mut self) { + if self.capacity() == 0 { + // no valid allocation, elements pointer is dangling + return; + } + + let ptr = self.ptr_to_refcount(); + unsafe { + let value = std::ptr::read(ptr) as isize; + match value { + 0 => { + // static lifetime, do nothing + } + isize::MIN => { + // refcount becomes zero; free allocation + crate::roc_dealloc(self.ptr_to_allocation().cast(), 1); + } + _ => { + std::ptr::write(ptr, (value - 1) as usize); + } + } + } + } + + fn with_capacity(cap: usize) -> Self { + let mut this = Self { + elements: NonNull::dangling(), + length: 0, + capacity_or_alloc_ptr: 0, + }; + + this.reserve(cap); + + this + } + + /// Increase a BigString's capacity by at least the requested number of elements (possibly more). + /// + /// May return a new BigString, if the provided one was not unique. + fn reserve(&mut self, n: usize) { + let align = std::mem::size_of::(); + let desired_cap = self.len() + n; + let desired_alloc = align + desired_cap; + + if self.is_unique() && !self.is_seamless_slice() { + if self.capacity() >= desired_cap { + return; + } + + let new_alloc = unsafe { + roc_realloc( + self.ptr_to_allocation().cast(), + desired_alloc as _, + align + self.capacity(), + align as _, + ) + }; + + let elements = unsafe { NonNull::new_unchecked(new_alloc.cast::().add(align)) }; + + let mut this = Self { + elements, + length: self.len(), + capacity_or_alloc_ptr: desired_cap, + }; + + std::mem::swap(&mut this, self); + std::mem::forget(this); + } else { + let ptr = unsafe { crate::roc_alloc(desired_alloc, align as _) } as *mut u8; + let elements = unsafe { NonNull::new_unchecked(ptr.cast::().add(align)) }; + + unsafe { + // Copy the old elements to the new allocation. + std::ptr::copy_nonoverlapping(self.ptr_to_first_elem(), ptr.add(align), self.len()); + } + + let mut this = Self { + elements, + length: self.len(), + capacity_or_alloc_ptr: desired_cap, + }; + + std::mem::swap(&mut this, self); + std::mem::drop(this); + } + } +} + +impl Clone for BigString { + fn clone(&self) -> Self { + let mut this = Self { + elements: self.elements, + length: self.length, + capacity_or_alloc_ptr: self.capacity_or_alloc_ptr, + }; + + this.inc(1); + + this + } +} + +impl Drop for BigString { + fn drop(&mut self) { + self.dec() + } +} + #[repr(C)] union RocStrInner { // TODO: this really should be separated from the List type. @@ -703,12 +996,12 @@ union RocStrInner { // Currently, there are work arounds in RocList to handle both via removing the highest bit of length in many cases. // With glue changes, we should probably rewrite these cleanly to match what is in the zig bitcode. // It is definitely a bit stale now and I think the storage mechanism can be quite confusing with our extra pieces of state. - heap_allocated: ManuallyDrop>, + heap_allocated: ManuallyDrop, small_string: SmallString, } enum RocStrInnerRef<'a> { - HeapAllocated(&'a RocList), + HeapAllocated(&'a BigString), SmallString(&'a SmallString), } @@ -755,17 +1048,6 @@ impl SmallString { fn len(&self) -> usize { usize::from(self.len & !RocStr::MASK) } - - /// Returns the index of the first interior \0 byte in the string, or None if there are none. - fn first_nul_byte(&self) -> Option { - for (index, byte) in self.bytes[0..self.len()].iter().enumerate() { - if *byte == 0 { - return Some(index); - } - } - - None - } } impl Deref for SmallString { @@ -830,4 +1112,4 @@ impl<'de> Visitor<'de> for RocStrVisitor { { Ok(RocStr::from(value)) } -} +} \ No newline at end of file diff --git a/crates/roc_std/tests/test_roc_std.rs b/crates/roc_std/tests/test_roc_std.rs index 9b1e8fd1f8..f21565ba43 100644 --- a/crates/roc_std/tests/test_roc_std.rs +++ b/crates/roc_std/tests/test_roc_std.rs @@ -38,8 +38,12 @@ pub unsafe extern "C" fn roc_panic(msg: *mut roc_std::RocStr, _tag_id: u32) { #[cfg(test)] #[no_mangle] -pub unsafe extern "C" fn roc_dbg(loc: *mut roc_std::RocStr, msg: *mut roc_std::RocStr) { - eprintln!("[{}] {}", &*loc, &*msg); +pub unsafe extern "C" fn roc_dbg( + loc: *mut roc_std::RocStr, + msg: *mut roc_std::RocStr, + src: *mut roc_std::RocStr, +) { + eprintln!("[{}] {} = {}", &*loc, &*src, &*msg); } #[cfg(test)] @@ -354,6 +358,79 @@ mod test_roc_std { let roc_list = RocList::::empty(); assert!(roc_list.is_unique()); } + + #[test] + fn slicing_and_dicing_list() { + let example = RocList::from_slice(b"chaos is a ladder"); + + // basic slice from the start + assert_eq!(example.slice_range(0..5).as_slice(), b"chaos"); + + // slice in the middle + assert_eq!(example.slice_range(6..10).as_slice(), b"is a"); + + // slice of slice + let first = example.slice_range(0..5); + assert_eq!(first.slice_range(0..3).as_slice(), b"cha"); + } + + #[test] + fn slicing_and_dicing_str() { + let example = RocStr::from("chaos is a ladder"); + + // basic slice from the start + assert_eq!(example.slice_range(0..5).as_str(), "chaos"); + + // slice in the middle + assert_eq!(example.slice_range(6..10).as_str(), "is a"); + + // slice of slice + let first = example.slice_range(0..5); + assert_eq!(first.slice_range(0..3).as_str(), "cha"); + } + + #[test] + fn roc_list_push() { + let mut example = RocList::from_slice(&[1, 2, 3]); + + // basic slice from the start + example.push(4); + assert_eq!(example.as_slice(), &[1, 2, 3, 4]); + + // slice in the middle + let mut sliced = example.slice_range(0..3); + sliced.push(5); + assert_eq!(sliced.as_slice(), &[1, 2, 3, 5]); + + // original did not change + assert_eq!(example.as_slice(), &[1, 2, 3, 4]); + + drop(sliced); + + let mut sliced = example.slice_range(0..3); + // make the slice unique + drop(example); + + sliced.push(5); + assert_eq!(sliced.as_slice(), &[1, 2, 3, 5]); + } + + #[test] + fn split_whitespace() { + let example = RocStr::from("chaos is a ladder"); + + let split: Vec<_> = example.split_whitespace().collect(); + + assert_eq!( + split, + vec![ + RocStr::from("chaos"), + RocStr::from("is"), + RocStr::from("a"), + RocStr::from("ladder"), + ] + ); + } } #[cfg(test)] diff --git a/crates/valgrind/zig-platform/host.zig b/crates/valgrind/zig-platform/host.zig index 84f1ac0117..27df651918 100644 --- a/crates/valgrind/zig-platform/host.zig +++ b/crates/valgrind/zig-platform/host.zig @@ -58,9 +58,9 @@ export fn roc_panic(msg: *RocStr, tag_id: u32) callconv(.C) void { std.process.exit(1); } -export fn roc_dbg(loc: *RocStr, msg: *RocStr) callconv(.C) void { +export fn roc_dbg(loc: *RocStr, msg: *RocStr, src: *RocStr) callconv(.C) void { const stderr = std.io.getStdErr().writer(); - stderr.print("[{s}] {s}\n", .{ loc.asSlice(), msg.asSlice() }) catch unreachable; + stderr.print("[{s}] {s} = {s}\n", .{ loc.asSlice(), src.asSlice(), msg.asSlice() }) catch unreachable; } export fn roc_memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void { diff --git a/examples/cli/argsBROKEN.roc b/examples/cli/argsBROKEN.roc index c2fe7b1d4c..d56b88c582 100644 --- a/examples/cli/argsBROKEN.roc +++ b/examples/cli/argsBROKEN.roc @@ -1,5 +1,5 @@ app "args" - packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.0/bkGby8jb0tmZYsy2hg1E_B2QrCgcSTxdUlHtETwm5m4.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br" } imports [pf.Stdout, pf.Arg, pf.Task.{ Task }] provides [main] to pf diff --git a/examples/cli/countdown.roc b/examples/cli/countdown.roc index 917c30fda8..13ddb94d24 100644 --- a/examples/cli/countdown.roc +++ b/examples/cli/countdown.roc @@ -1,5 +1,5 @@ app "countdown" - packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.0/bkGby8jb0tmZYsy2hg1E_B2QrCgcSTxdUlHtETwm5m4.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br" } imports [pf.Stdin, pf.Stdout, pf.Task.{ await, loop }] provides [main] to pf diff --git a/examples/cli/echo.roc b/examples/cli/echo.roc index 88737ea6cc..034e7fd4c1 100644 --- a/examples/cli/echo.roc +++ b/examples/cli/echo.roc @@ -1,5 +1,5 @@ app "echo" - packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.0/bkGby8jb0tmZYsy2hg1E_B2QrCgcSTxdUlHtETwm5m4.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br" } imports [pf.Stdin, pf.Stdout, pf.Task.{ Task }] provides [main] to pf diff --git a/examples/cli/effects-platform/host.zig b/examples/cli/effects-platform/host.zig index 6d3ea3306e..04b650705f 100644 --- a/examples/cli/effects-platform/host.zig +++ b/examples/cli/effects-platform/host.zig @@ -72,9 +72,9 @@ export fn roc_panic(msg: *RocStr, tag_id: u32) callconv(.C) void { std.process.exit(1); } -export fn roc_dbg(loc: *RocStr, msg: *RocStr) callconv(.C) void { +export fn roc_dbg(loc: *RocStr, msg: *RocStr, src: *RocStr) callconv(.C) void { const stderr = std.io.getStdErr().writer(); - stderr.print("[{s}] {s}\n", .{ loc.asSlice(), msg.asSlice() }) catch unreachable; + stderr.print("[{s}] {s} = {s}\n", .{ loc.asSlice(), src.asSlice(), msg.asSlice() }) catch unreachable; } export fn roc_memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void { diff --git a/examples/cli/env.roc b/examples/cli/env.roc index eb2a6184c9..41fbd6a61e 100644 --- a/examples/cli/env.roc +++ b/examples/cli/env.roc @@ -1,5 +1,5 @@ app "env" - packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.0/bkGby8jb0tmZYsy2hg1E_B2QrCgcSTxdUlHtETwm5m4.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br" } imports [pf.Stdout, pf.Stderr, pf.Env, pf.Task.{ Task }] provides [main] to pf diff --git a/examples/cli/false-interpreter/platform/src/lib.rs b/examples/cli/false-interpreter/platform/src/lib.rs index eb48d41bb3..b889ee3678 100644 --- a/examples/cli/false-interpreter/platform/src/lib.rs +++ b/examples/cli/false-interpreter/platform/src/lib.rs @@ -63,8 +63,8 @@ pub unsafe extern "C" fn roc_panic(msg: *mut RocStr, tag_id: u32) { } #[no_mangle] -pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr) { - eprintln!("[{}] {}", &*loc, &*msg); +pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut RocStr) { + eprintln!("[{}] {} = {}", &*loc, &*src, &*msg); } #[no_mangle] diff --git a/examples/cli/fileBROKEN.roc b/examples/cli/fileBROKEN.roc index bc63e5655a..711c5f4541 100644 --- a/examples/cli/fileBROKEN.roc +++ b/examples/cli/fileBROKEN.roc @@ -1,5 +1,5 @@ app "file-io" - packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.0/bkGby8jb0tmZYsy2hg1E_B2QrCgcSTxdUlHtETwm5m4.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br" } imports [ pf.Stdout, pf.Stderr, diff --git a/examples/cli/form.roc b/examples/cli/form.roc index 3df5cd2d12..3aae9272d8 100644 --- a/examples/cli/form.roc +++ b/examples/cli/form.roc @@ -1,5 +1,5 @@ app "form" - packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.0/bkGby8jb0tmZYsy2hg1E_B2QrCgcSTxdUlHtETwm5m4.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br" } imports [pf.Stdin, pf.Stdout, pf.Task.{ await, Task }] provides [main] to pf diff --git a/examples/cli/http-get.roc b/examples/cli/http-get.roc index a1890bbc27..2664203be8 100644 --- a/examples/cli/http-get.roc +++ b/examples/cli/http-get.roc @@ -1,5 +1,5 @@ app "http-get" - packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.0/bkGby8jb0tmZYsy2hg1E_B2QrCgcSTxdUlHtETwm5m4.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br" } imports [pf.Http, pf.Task.{ Task }, pf.Stdin, pf.Stdout] provides [main] to pf diff --git a/examples/cli/ingested-file-bytes.roc b/examples/cli/ingested-file-bytes.roc index 5f89b21bfa..de29db4d3e 100644 --- a/examples/cli/ingested-file-bytes.roc +++ b/examples/cli/ingested-file-bytes.roc @@ -1,14 +1,14 @@ app "ingested-file-bytes" - packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.0/bkGby8jb0tmZYsy2hg1E_B2QrCgcSTxdUlHtETwm5m4.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br" } imports [ pf.Stdout, - "ingested-file.roc" as ownCode : _, # A type hole can also be used here. + "../../LICENSE" as license : _, # A type hole can also be used here. ] provides [main] to pf main = - # Due to how ownCode is used, it will be a List U8. - ownCode + # Due to how license is used, it will be a List U8. + license |> List.map Num.toNat |> List.sum |> Num.toStr diff --git a/examples/cli/ingested-file.roc b/examples/cli/ingested-file.roc index 8c79c1e22c..361c6cecac 100644 --- a/examples/cli/ingested-file.roc +++ b/examples/cli/ingested-file.roc @@ -1,5 +1,5 @@ app "ingested-file" - packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.0/bkGby8jb0tmZYsy2hg1E_B2QrCgcSTxdUlHtETwm5m4.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br" } imports [ pf.Stdout, "ingested-file.roc" as ownCode : Str, diff --git a/examples/cli/tui-platform/host.zig b/examples/cli/tui-platform/host.zig index 842b3a8833..a9e9c40f50 100644 --- a/examples/cli/tui-platform/host.zig +++ b/examples/cli/tui-platform/host.zig @@ -127,9 +127,9 @@ export fn roc_panic(msg: *RocStr, tag_id: u32) callconv(.C) void { std.process.exit(1); } -export fn roc_dbg(loc: *RocStr, msg: *RocStr) callconv(.C) void { +export fn roc_dbg(loc: *RocStr, msg: *RocStr, src: *RocStr) callconv(.C) void { const stderr = std.io.getStdErr().writer(); - stderr.print("[{s}] {s}\n", .{ loc.asSlice(), msg.asSlice() }) catch unreachable; + stderr.print("[{s}] {s} = {s}\n", .{ loc.asSlice(), src.asSlice(), msg.asSlice() }) catch unreachable; } export fn roc_memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void { diff --git a/examples/glue/rust-platform/src/lib.rs b/examples/glue/rust-platform/src/lib.rs index 3665ed7b43..022ea94a18 100644 --- a/examples/glue/rust-platform/src/lib.rs +++ b/examples/glue/rust-platform/src/lib.rs @@ -44,8 +44,8 @@ pub unsafe extern "C" fn roc_panic(msg: *mut RocStr, tag_id: u32) { } #[no_mangle] -pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr) { - eprintln!("[{}] {}", &*loc, &*msg); +pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut RocStr) { + eprintln!("[{}] {} = {}", &*loc, &*src, &*msg); } #[no_mangle] diff --git a/examples/gui/breakout/platform/src/roc.rs b/examples/gui/breakout/platform/src/roc.rs index fe6cbb4a69..8c651dbd07 100644 --- a/examples/gui/breakout/platform/src/roc.rs +++ b/examples/gui/breakout/platform/src/roc.rs @@ -198,8 +198,8 @@ pub unsafe extern "C" fn roc_panic(msg: *mut RocStr, tag_id: u32) { } #[no_mangle] -pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr) { - eprintln!("[{}] {}", &*loc, &*msg); +pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut RocStr) { + eprintln!("[{}] {} = {}", &*loc, &*src, &*msg); } #[no_mangle] diff --git a/examples/gui/platform/src/roc.rs b/examples/gui/platform/src/roc.rs index f5b8f0480e..14ede5abed 100644 --- a/examples/gui/platform/src/roc.rs +++ b/examples/gui/platform/src/roc.rs @@ -40,8 +40,8 @@ pub unsafe extern "C" fn roc_panic(msg: *mut RocStr, tag_id: u32) { } #[no_mangle] -pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr) { - eprintln!("[{}] {}", &*loc, &*msg); +pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut RocStr) { + eprintln!("[{}] {} = {}", &*loc, &*src, &*msg); } #[no_mangle] diff --git a/examples/helloWorld.roc b/examples/helloWorld.roc index 7a30101ef2..4fbaf85032 100644 --- a/examples/helloWorld.roc +++ b/examples/helloWorld.roc @@ -1,5 +1,5 @@ app "helloWorld" - packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.0/bkGby8jb0tmZYsy2hg1E_B2QrCgcSTxdUlHtETwm5m4.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br" } imports [pf.Stdout] provides [main] to pf diff --git a/examples/inspect-logging.roc b/examples/inspect-logging.roc index f9b9c10c91..0526413cdf 100644 --- a/examples/inspect-logging.roc +++ b/examples/inspect-logging.roc @@ -2,7 +2,7 @@ # Shows how Roc values can be logged # app "inspect-logging" - packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.0/bkGby8jb0tmZYsy2hg1E_B2QrCgcSTxdUlHtETwm5m4.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br" } imports [ pf.Stdout, Community, @@ -34,6 +34,5 @@ main = } |> Community.addFriend 0 2 |> Community.addFriend 1 2 - |> Inspect.inspect - |> Inspect.toDbgStr + |> Inspect.toStr |> Stdout.line diff --git a/examples/jvm-interop/bridge.c b/examples/jvm-interop/bridge.c index 174d0c7cfd..4bd4aafc27 100644 --- a/examples/jvm-interop/bridge.c +++ b/examples/jvm-interop/bridge.c @@ -275,10 +275,11 @@ __attribute__((noreturn)) void roc_panic(struct RocStr *msg, unsigned int tag_id longjmp(exception_buffer, 1); } -void roc_dbg(struct RocStr *loc, struct RocStr *msg) { +void roc_dbg(struct RocStr *loc, struct RocStr *msg, struct RocStr *src) { char* loc_bytes = is_small_str(*loc) ? (char*)loc : (char*)loc->bytes; + char* src_bytes = is_small_str(*src) ? (char*)src : (char*)src->bytes; char* msg_bytes = is_small_str(*msg) ? (char*)msg : (char*)msg->bytes; - fprintf(stderr, "[%s] %s\n", loc_bytes, msg_bytes); + fprintf(stderr, "[%s] %s = %s\n", loc_bytes, src_bytes, msg_bytes); } extern void roc__programForHost_1__InterpolateString_caller(struct RocStr *name, char *closure_data, struct RocStr *ret); diff --git a/examples/nodejs-interop/native-c-api/demo.c b/examples/nodejs-interop/native-c-api/demo.c index 72a3325df4..cd36922bba 100644 --- a/examples/nodejs-interop/native-c-api/demo.c +++ b/examples/nodejs-interop/native-c-api/demo.c @@ -27,8 +27,8 @@ void roc_panic(void *ptr, unsigned int alignment) napi_throw_error(napi_global_env, NULL, (char *)ptr); } -void roc_dbg(char* loc, char* msg) { - fprintf(stderr, "[%s] %s\n", loc, msg); +void roc_dbg(char* loc, char* msg, char* src) { + fprintf(stderr, "[%s] %s = %s\n", loc, src, msg); } void *roc_memset(void *str, int c, size_t n) { return memset(str, c, n); } diff --git a/examples/nodejs-interop/wasm/README.md b/examples/nodejs-interop/wasm/README.md index 26bdf6f37e..9c0b5120a4 100644 --- a/examples/nodejs-interop/wasm/README.md +++ b/examples/nodejs-interop/wasm/README.md @@ -2,7 +2,7 @@ This is an example of calling Roc code from [Node.js](https://nodejs.org/en/). -You'll need to have [Zig](https://zig-lang.org) installed. Run this from the current directory: +You'll need to have [Zig](https://ziglang.org/) installed. Run this from the current directory: ``` roc build --target=wasm32 diff --git a/examples/nodejs-interop/wasm/platform/host.zig b/examples/nodejs-interop/wasm/platform/host.zig index 3f1a176fa6..d6da990e7e 100644 --- a/examples/nodejs-interop/wasm/platform/host.zig +++ b/examples/nodejs-interop/wasm/platform/host.zig @@ -24,13 +24,13 @@ export fn roc_realloc(c_ptr: *anyopaque, new_size: usize, old_size: usize, align _ = old_size; _ = alignment; - return realloc(@as([*]align(Align) u8, @alignCast(@ptrCast(c_ptr))), new_size); + return realloc(@as([*]align(@alignOf(Align)) u8, @alignCast(@ptrCast(c_ptr))), new_size); } export fn roc_dealloc(c_ptr: *anyopaque, alignment: u32) callconv(.C) void { _ = alignment; - free(@as([*]align(Align) u8, @alignCast(@ptrCast(c_ptr)))); + free(@as([*]align(@alignOf(Align)) u8, @alignCast(@ptrCast(c_ptr)))); } // NOTE roc_panic and roc_dbg is provided in the JS file, so it can throw an exception diff --git a/examples/parser/examples/letter-counts.roc b/examples/parser/examples/letter-counts.roc index 22ed5b3956..f65a126c4a 100644 --- a/examples/parser/examples/letter-counts.roc +++ b/examples/parser/examples/letter-counts.roc @@ -1,6 +1,6 @@ app "example" packages { - cli: "https://github.com/roc-lang/basic-cli/releases/download/0.7.0/bkGby8jb0tmZYsy2hg1E_B2QrCgcSTxdUlHtETwm5m4.tar.br", + cli: "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br", parser: "../package/main.roc", } imports [ diff --git a/examples/platform-switching/c-platform/host.c b/examples/platform-switching/c-platform/host.c index 3683afaa98..2b0baf8e15 100644 --- a/examples/platform-switching/c-platform/host.c +++ b/examples/platform-switching/c-platform/host.c @@ -29,8 +29,8 @@ void roc_panic(void* ptr, unsigned int alignment) { exit(1); } -void roc_dbg(char* loc, char* msg) { - fprintf(stderr, "[%s] %s\n", loc, msg); +void roc_dbg(char* loc, char* msg, char* src) { + fprintf(stderr, "[%s] %s = %s\n", loc, src, msg); } void* roc_memset(void* str, int c, size_t n) { return memset(str, c, n); } diff --git a/examples/platform-switching/rust-platform/src/lib.rs b/examples/platform-switching/rust-platform/src/lib.rs index db4490425b..f3c83ed557 100644 --- a/examples/platform-switching/rust-platform/src/lib.rs +++ b/examples/platform-switching/rust-platform/src/lib.rs @@ -46,8 +46,8 @@ pub unsafe extern "C" fn roc_panic(msg: *mut RocStr, tag_id: u32) { } #[no_mangle] -pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr) { - eprintln!("[{}] {}", &*loc, &*msg); +pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut RocStr) { + eprintln!("[{}] {} = {}", &*loc, &*src, &*msg); } #[no_mangle] diff --git a/examples/platform-switching/zig-platform/host.zig b/examples/platform-switching/zig-platform/host.zig index 84f1ac0117..27df651918 100644 --- a/examples/platform-switching/zig-platform/host.zig +++ b/examples/platform-switching/zig-platform/host.zig @@ -58,9 +58,9 @@ export fn roc_panic(msg: *RocStr, tag_id: u32) callconv(.C) void { std.process.exit(1); } -export fn roc_dbg(loc: *RocStr, msg: *RocStr) callconv(.C) void { +export fn roc_dbg(loc: *RocStr, msg: *RocStr, src: *RocStr) callconv(.C) void { const stderr = std.io.getStdErr().writer(); - stderr.print("[{s}] {s}\n", .{ loc.asSlice(), msg.asSlice() }) catch unreachable; + stderr.print("[{s}] {s} = {s}\n", .{ loc.asSlice(), src.asSlice(), msg.asSlice() }) catch unreachable; } export fn roc_memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void { diff --git a/examples/python-interop/demo.c b/examples/python-interop/demo.c index 11c274f001..453adf6028 100644 --- a/examples/python-interop/demo.c +++ b/examples/python-interop/demo.c @@ -27,8 +27,8 @@ __attribute__((noreturn)) void roc_panic(void *ptr, unsigned int alignment) PyErr_SetString(PyExc_RuntimeError, (char *)ptr); } -void roc_dbg(char* loc, char* msg) { - fprintf(stderr, "[%s] %s\n", loc, msg); +void roc_dbg(char* loc, char* msg, char* src) { + fprintf(stderr, "[%s] %s = %s\n", loc, src, msg); } void *roc_memset(void *str, int c, size_t n) { return memset(str, c, n); } diff --git a/examples/python-interop/platform/host.c b/examples/python-interop/platform/host.c index 7560e3d5fd..8d3ab3c39f 100644 --- a/examples/python-interop/platform/host.c +++ b/examples/python-interop/platform/host.c @@ -24,8 +24,8 @@ void roc_panic(void* ptr, unsigned int alignment) { exit(1); } -void roc_dbg(char* loc, char* msg) { - fprintf(stderr, "[%s] %s\n", loc, msg); +void roc_dbg(char* loc, char* msg, char* src) { + fprintf(stderr, "[%s] %s = %s\n", loc, src, msg); } void* roc_memset(void* str, int c, size_t n) { return memset(str, c, n); } diff --git a/examples/ruby-interop/demo.c b/examples/ruby-interop/demo.c index 068d8c5daa..7bbbcf1eb1 100644 --- a/examples/ruby-interop/demo.c +++ b/examples/ruby-interop/demo.c @@ -23,8 +23,8 @@ __attribute__((noreturn)) void roc_panic(void *ptr, unsigned int alignment) rb_raise(rb_eException, "%s", (char *)ptr); } -void roc_dbg(char* loc, char* msg) { - fprintf(stderr, "[%s] %s\n", loc, msg); +void roc_dbg(char* loc, char* msg, char* src) { + fprintf(stderr, "[%s] %s = %s\n", loc, src, msg); } void *roc_memset(void *str, int c, size_t n) { return memset(str, c, n); } diff --git a/examples/ruby-interop/platform/host.c b/examples/ruby-interop/platform/host.c index 1d7b681dbb..10267c6eaa 100644 --- a/examples/ruby-interop/platform/host.c +++ b/examples/ruby-interop/platform/host.c @@ -24,8 +24,8 @@ void roc_panic(void* ptr, unsigned int alignment) { exit(1); } -void roc_dbg(char* loc, char* msg) { - fprintf(stderr, "[%s] %s\n", loc, msg); +void roc_dbg(char* loc, char* msg, char* src) { + fprintf(stderr, "[%s] %s = %s\n", loc, src, msg); } void* roc_memmove(void* dest, const void* src, size_t n){ diff --git a/examples/static-site-gen/platform/src/lib.rs b/examples/static-site-gen/platform/src/lib.rs index acbe32e079..5abff2999b 100644 --- a/examples/static-site-gen/platform/src/lib.rs +++ b/examples/static-site-gen/platform/src/lib.rs @@ -100,8 +100,8 @@ pub unsafe extern "C" fn roc_panic(msg: *mut RocStr, tag_id: u32) { } #[no_mangle] -pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr) { - eprintln!("[{}] {}", &*loc, &*msg); +pub unsafe extern "C" fn roc_dbg(loc: *mut RocStr, msg: *mut RocStr, src: *mut RocStr) { + eprintln!("[{}] {} = {}", &*loc, &*src, &*msg); } #[no_mangle] diff --git a/examples/virtual-dom-wip/platform/src/client-side/host.zig b/examples/virtual-dom-wip/platform/src/client-side/host.zig index eb33420650..029504e4fa 100644 --- a/examples/virtual-dom-wip/platform/src/client-side/host.zig +++ b/examples/virtual-dom-wip/platform/src/client-side/host.zig @@ -42,9 +42,9 @@ export fn roc_panic(msg: *RocStr, tag_id: u32) callconv(.C) void { std.process.exit(1); } -export fn roc_dbg(loc: *RocStr, msg: *RocStr) callconv(.C) void { +export fn roc_dbg(loc: *RocStr, msg: *RocStr, src: *RocStr) callconv(.C) void { const stderr = std.io.getStdErr().writer(); - stderr.print("[{s}] {s}\n", .{ loc.asSlice(), msg.asSlice() }) catch unreachable; + stderr.print("[{s}] {s} = {s}\n", .{ loc.asSlice(), src.asSlice(), msg.asSlice() }) catch unreachable; } const RocList = extern struct { diff --git a/examples/virtual-dom-wip/platform/src/server-side/host.zig b/examples/virtual-dom-wip/platform/src/server-side/host.zig index 4167736ea5..f2dcc9b756 100644 --- a/examples/virtual-dom-wip/platform/src/server-side/host.zig +++ b/examples/virtual-dom-wip/platform/src/server-side/host.zig @@ -42,9 +42,9 @@ export fn roc_panic(msg: *RocStr, tag_id: u32) callconv(.C) void { std.process.exit(1); } -export fn roc_dbg(loc: *RocStr, msg: *RocStr) callconv(.C) void { +export fn roc_dbg(loc: *RocStr, msg: *RocStr, src: *RocStr) callconv(.C) void { const stderr = std.io.getStdErr().writer(); - stderr.print("[{s}] {s}\n", .{ loc.asSlice(), msg.asSlice() }) catch unreachable; + stderr.print("[{s}] {s} = {s}\n", .{ loc.asSlice(), src.asSlice(), msg.asSlice() }) catch unreachable; } const ResultStrStr = extern struct { diff --git a/flake.nix b/flake.nix index cfb5b92855..fa6998ae5e 100644 --- a/flake.nix +++ b/flake.nix @@ -27,11 +27,16 @@ }; outputs = { self, nixpkgs, rust-overlay, flake-utils, nixgl, ... }@inputs: - let supportedSystems = [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" "aarch64-linux" ]; - in flake-utils.lib.eachSystem supportedSystems (system: + let + supportedSystems = [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" "aarch64-linux" ]; + + templates = import ./nix/templates { }; + in + { inherit templates; } // + flake-utils.lib.eachSystem supportedSystems (system: let overlays = [ (import rust-overlay) ] - ++ (if system == "x86_64-linux" then [ nixgl.overlay ] else [ ]); + ++ (if system == "x86_64-linux" then [ nixgl.overlay ] else [ ]); pkgs = import nixpkgs { inherit system overlays; }; rocBuild = import ./nix { inherit pkgs; }; @@ -64,29 +69,6 @@ curl # for wasm-bindgen-cli libcurl (see ./ci/www-repl.sh) ]); - # For debugging LLVM IR - debugir = pkgs.stdenv.mkDerivation { - name = "debugir"; - src = pkgs.fetchFromGitHub { - owner = "vaivaswatha"; - repo = "debugir"; - rev = "b981e0b74872d9896ba447dd6391dfeb63332b80"; - sha256 = "Gzey0SF0NZkpiObk5e29nbc41dn4Olv1dx+6YixaZH0="; - }; - buildInputs = with pkgs; [ cmake libxml2 llvmPkgs.llvm.dev ]; - buildPhase = '' - mkdir build - cd build - cmake -DLLVM_DIR=${llvmPkgs.llvm.dev} -DCMAKE_BUILD_TYPE=Release ../ - cmake --build ../ - cp ../debugir . - ''; - installPhase = '' - mkdir -p $out/bin - cp debugir $out/bin - ''; - }; - sharedInputs = (with pkgs; [ # build libraries cmake @@ -102,6 +84,7 @@ # faster builds - see https://github.com/roc-lang/roc/blob/main/BUILDING_FROM_SOURCE.md#use-lld-for-the-linker llvmPkgs.lld rocBuild.rust-shell + perl # ./ci/update_basic_cli_url.sh ]); sharedDevInputs = (with pkgs; [ @@ -109,13 +92,12 @@ python3 libiconv # for examples/gui libxkbcommon # for examples/gui - # debugir needs to be updated to llvm 15 - # debugir # used in crates/compiler/build/src/program.rs cargo-criterion # for benchmarks simple-http-server # to view roc website when trying out edits wasm-pack # for repl_wasm jq # used in several bash scripts cargo-nextest # used to give more info for segfaults for gen tests + zls # zig language server ]); aliases = '' @@ -129,7 +111,7 @@ devShell = pkgs.mkShell { buildInputs = sharedInputs ++ sharedDevInputs ++ darwinInputs ++ darwinDevInputs ++ linuxDevInputs - ++ (if system == "x86_64-linux" then + ++ (if system == "x86_64-linux" then [ pkgs.nixgl.nixVulkanIntel ] else [ ]); @@ -145,7 +127,7 @@ LD_LIBRARY_PATH = with pkgs; lib.makeLibraryPath ([ pkg-config stdenv.cc.cc.lib libffi ncurses zlib ] - ++ linuxDevInputs); + ++ linuxDevInputs); NIXPKGS_ALLOW_UNFREE = 1; # to run the GUI examples with NVIDIA's closed source drivers @@ -160,12 +142,19 @@ # You can build this package (the roc CLI) with the `nix build` command. packages = { default = rocBuild.roc-cli; - + # all rust crates in workspace.members of Cargo.toml full = rocBuild.roc-full; # only the CLI crate = executable provided in nightly releases cli = rocBuild.roc-cli; lang-server = rocBuild.roc-lang-server; }; + + apps = { + default = { + type = "app"; + program = "${rocBuild.roc-cli}/bin/roc"; + }; + }; }); } diff --git a/getting_started/README.md b/getting_started/README.md index 78cd4b57c3..e4d319225e 100644 --- a/getting_started/README.md +++ b/getting_started/README.md @@ -6,11 +6,12 @@ play around with as long as you have a tolerance for missing features and compil The [tutorial](https://roc-lang.org/tutorial) is the best place to learn about how to use the language - it assumes no prior knowledge of Roc or similar languages. (If you already know [Elm](https://elm-lang.org/), then [Roc for Elm Programmers](https://github.com/roc-lang/roc/blob/main/roc-for-elm-programmers.md) may be of interest.) -If you have a specific question, the [FAQ](../FAQ.md) might have an answer, although [Roc Zulip chat](https://roc.zulipchat.com) is overall the best place to ask questions and get help! It's also where we discuss [ideas](https://roc.zulipchat.com/#narrow/stream/304641-ideas) for the language. If you want to get involved in contributing to the language, Zulip is also a great place to ask about good first projects. +If you have a specific question, the [FAQ](../www/content/faq.md) might have an answer, although [Roc Zulip chat](https://roc.zulipchat.com) is overall the best place to ask questions and get help! It's also where we discuss [ideas](https://roc.zulipchat.com/#narrow/stream/304641-ideas) for the language. If you want to get involved in contributing to the language, Zulip is also a great place to ask about good first projects. ## Installation - [🐧 Linux x86_64](linux_x86_64.md) +- [❄️ Nix Linux/MacOS](nix.md) - [🍏 MacOS Apple Silicon](macos_apple_silicon.md) - [🍏 MacOS x86_64](macos_x86_64.md) - [🟦 Windows](windows.md) diff --git a/getting_started/nix.md b/getting_started/nix.md new file mode 100644 index 0000000000..51bfce7246 --- /dev/null +++ b/getting_started/nix.md @@ -0,0 +1,48 @@ +## Try out + +To quickly try out roc without installing, use `nix run`: +```shell +nix run roc-lang/roc -- +# examples: +# - nix run roc-lang/roc -- repl +# - nix run roc-lang/roc -- dev main.roc +``` + +## Use with Flakes + + +### Start your project with our template + +```shell +# use the template in the current directory +nix flake init --template github:roc-lang/roc#simple --refresh +``` + +### Add roc to existing flake +```nix +{ + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + roc.url = "github:roc-lang/roc"; + }; + + outputs = {nixpkgs, roc, flake-utils, ...}: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = import nixpkgs { inherit system; }; + rocPkgs = roc.packages.${system}; + in + { + devShells = { + default = pkgs.mkShell { + buildInputs = with pkgs; + [ + rocPkgs.cli + ]; + }; + }; + } + ); +} +``` diff --git a/nix/builder.nix b/nix/builder.nix index 4038a1bfbe..265df5a310 100644 --- a/nix/builder.nix +++ b/nix/builder.nix @@ -3,6 +3,8 @@ let inherit (compile-deps) zigPkg llvmPkgs llvmVersion llvmMajorMinorStr glibcPath libGccSPath; subPackagePath = if subPackage != null then "crates/${subPackage}" else null; + + mainBin = if subPackage == "lang_srv" then "roc_ls" else "roc"; in rustPlatform.buildRustPackage { pname = "roc" + lib.optionalString (subPackage != null) "_${subPackage}"; @@ -84,4 +86,11 @@ rustPlatform.buildRustPackage { ${wrapRoc} fi ''; + + # https://ryantm.github.io/nixpkgs/stdenv/meta/ + meta = { + homepage = "https://www.roc-lang.org/"; + license = lib.licenses.upl; + mainProgram = mainBin; + }; } diff --git a/nix/templates/default.nix b/nix/templates/default.nix new file mode 100644 index 0000000000..fe1e7ea98b --- /dev/null +++ b/nix/templates/default.nix @@ -0,0 +1,7 @@ +{ ... }: rec { + default = simple; + simple = { + description = "Basic flake with roc cli + lsp"; + path = ./simple; + }; +} diff --git a/nix/templates/simple/flake.nix b/nix/templates/simple/flake.nix new file mode 100644 index 0000000000..244687c428 --- /dev/null +++ b/nix/templates/simple/flake.nix @@ -0,0 +1,38 @@ +{ + description = "Roc flake template"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + roc.url = "github:roc-lang/roc"; + }; + + outputs = { self, nixpkgs, flake-utils, roc, ... }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = import nixpkgs { inherit system; }; + + # see "packages =" in https://github.com/roc-lang/roc/blob/main/flake.nix + rocPkgs = roc.packages.${system}; + + rocFull = rocPkgs.full; + + in + { + formatter = pkgs.nixpkgs-fmt; + + devShells = { + default = pkgs.mkShell { + buildInputs = with pkgs; + [ + rocFull # includes CLI + ]; + + # For vscode plugin https://github.com/ivan-demchenko/roc-vscode-unofficial + shellHook = '' + export ROC_LSP_PATH=${rocFull}/bin/roc_ls + ''; + }; + }; + }); +} diff --git a/www/.gitignore b/www/.gitignore new file mode 100644 index 0000000000..9bc9fa870c --- /dev/null +++ b/www/.gitignore @@ -0,0 +1,2 @@ +# ignore a symlink to the wasm repl code +public/repl \ No newline at end of file diff --git a/www/build-dev-local.sh b/www/build-dev-local.sh index 37c62eb167..0e21952743 100755 --- a/www/build-dev-local.sh +++ b/www/build-dev-local.sh @@ -15,4 +15,4 @@ cp -r build dist/ cp -r public/* dist/ roc run main.roc -- content/ dist/ -npx http-server dist/ -p 8080 -c-1 --cors +simple-http-server -p 8080 --nocache --cors --index -- dist/ diff --git a/www/build.sh b/www/build.sh index 78a2244682..83a89fae2f 100755 --- a/www/build.sh +++ b/www/build.sh @@ -111,7 +111,7 @@ rm -rf ./downloaded-basic-cli git clone --depth 1 https://github.com/roc-lang/basic-cli.git downloaded-basic-cli -cargo run --bin roc-docs downloaded-basic-cli/src/main.roc +cargo run --bin roc-docs downloaded-basic-cli/platform/main.roc rm -rf ./downloaded-basic-cli diff --git a/www/content/abilities.md b/www/content/abilities.md index 06a8356a65..2eeb025b43 100644 --- a/www/content/abilities.md +++ b/www/content/abilities.md @@ -25,7 +25,7 @@ All types which implement the `Encoding` Ability can therefore use the `Encode.t - [`Decoding` Ability](#decoding-ability) - [`Inspect` Ability](#inspect-ability) - [Opaque Types](#opaque-types) - - [Derived Implementions](#derived-implementions) + - [Derived Implementations](#derived-implementations) - [Custom Implementations ](#custom-implementations) - [Advanced Topic: Defining a new Ability](#defining-a-new-ability) @@ -98,7 +98,7 @@ The `Encoding` Ability defines `toEncoder` which can be used with an Encoder to Functions are not serialisable, therefore Roc does not derive `Encoding` for types that contain functions. -Encoding for `Dict` values **has not been implemened**, see [#5294](https://github.com/roc-lang/roc/issues/5294) for more details. If you would like to help implement this, please let us know. +Encoding for `Dict` values **has not been implemented**, see [#5294](https://github.com/roc-lang/roc/issues/5294) for more details. If you would like to help implement this, please let us know. **Example** showing the use of `Encoding.toBytes` to serialise a Roc `List (Str, U32)` to a [JSON](https://www.json.org/json-en.html) encoded string. @@ -126,9 +126,9 @@ Encoding implements ### [`Decoding` Ability](#decoding-ability) {#decoding-ability} -The `Decoding` Ability defines `decoder` which can be used with an Decoder to de-serialise from bytes to Roc values using the `Decoding.fromBytesPartial` and `Decoding.fromBytes` functions. +The `Decoding` Ability defines `decoder` which can be used with a Decoder to de-serialise from bytes to Roc values using the `Decoding.fromBytesPartial` and `Decoding.fromBytes` functions. -Decoding for `Dict` values **has not been implemened**, see [#5294](https://github.com/roc-lang/roc/issues/5294) for more details. If you would like to help implement this, please let us know. +Decoding for `Dict` values **has not been implemented**, see [#5294](https://github.com/roc-lang/roc/issues/5294) for more details. If you would like to help implement this, please let us know. **Example** showing the use of `Decoding.fromBytes` to decode a Roc `List (U32, Str)` from a [JSON](https://www.json.org/json-en.html) encoded string. @@ -180,9 +180,9 @@ Inspect implements Opaque Types are used to hide implementation details of a type. Modules export functions to define a *public* API for working with a type. -By default abilities are not derieved for Opaque Types. However, [Derived](#derived-implementions) and [Custom](#custom-implementations) implementations are two ways to work with abilities for your Opaque Types. +By default abilities are not derived for Opaque Types. However, [Derived](#derived-implementations) and [Custom](#custom-implementations) implementations are two ways to work with abilities for your Opaque Types. -### [Derived Implementions](#derived-implementions) {#derived-implementions} +### [Derived Implementations](#derived-implementations) {#derived-implementations} Abilities can be automatically derived for Opaque Types where the type is an alias for a builtin, or it is composed of other types which also implement that ability. diff --git a/www/content/community.md b/www/content/community.md index 70a68b1843..3e17190bd0 100644 --- a/www/content/community.md +++ b/www/content/community.md @@ -23,7 +23,7 @@ The project has [many contributors](https://github.com/roc-lang/roc/graphs/contr Roc doesn't have a formal process for managing design proposals. -At the current size of the project, having a formal process (like a [RFC](https://en.wikipedia.org/wiki/Change_request) system) would be more heavyweight than it's worth. Fow now, the guiding principle is that as a community we should all be friendly, supportive, and openly share and discuss ideas without the expectation that they will necessarily be accepted or not. We follow a [BDFN](/bdfn) leadership model today, although this is planned to change someday. +At the current size of the project, having a formal process (like a [RFC](https://en.wikipedia.org/wiki/Change_request) system) would be more heavyweight than it's worth. For now, the guiding principle is that as a community we should all be friendly, supportive, and openly share and discuss ideas without the expectation that they will necessarily be accepted or not. We follow a [BDFN](/bdfn) leadership model today, although this is planned to change someday. There are three loose stages that a design proposal can go through in Roc: idea, proposal, and implementation. These are guidelines, not strict requirements; their goal is to prevent the outcome where someone does a lot of implementation work only to have their contribution never make it into the code base because it's determined that we wanted to go in a different design direction. Confirming ahead of time that the design direction is desired can prevent implementing something that ends up not being used. diff --git a/www/content/docs.md b/www/content/docs.md index 97201f6a2b..bd78c7ad66 100644 --- a/www/content/docs.md +++ b/www/content/docs.md @@ -1,4 +1,3 @@ - # Documentation - [builtins](/builtins) - docs for modules built into the language—`Str`, `Num`, etc. @@ -10,7 +9,7 @@ In the future, a language reference will be on this page too. ## [Guides](#guides) {#guides} -- [Frequently Asked Questions](https://github.com/roc-lang/roc/blob/main/FAQ.md) +- [Frequently Asked Questions](https://www.roc-lang.org/faq.html) - [Roc for Elm Programmers](https://github.com/roc-lang/roc/blob/main/roc-for-elm-programmers.md) - [Tutorial](/tutorial) diff --git a/FAQ.md b/www/content/faq.md similarity index 97% rename from FAQ.md rename to www/content/faq.md index 61a4d5a181..7bdcc7f52a 100644 --- a/FAQ.md +++ b/www/content/faq.md @@ -1,14 +1,16 @@ -Click the ☰ button in the top left to see and search the table of contents. - -# Frequently Asked Questions +# FAQ ## Where did the name Roc come from? -The Roc logo, an origami bird - The Roc programming language is named after [a mythical bird](). -That’s why the logo is a bird. It’s specifically an [_origami_ bird](https://youtu.be/9gni1t1k1uY) as an homage + + + + + + +That's why the logo is a bird. It’s specifically an [_origami_ bird](https://youtu.be/9gni1t1k1uY) as an homage to [Elm](https://elm-lang.org/)’s tangram logo. Roc is a direct descendant of Elm. The languages are similar, but not the same. @@ -55,8 +57,10 @@ Both of these would make revising code riskier across the entire language, which Another option would be to define that function equality always returns `false`. So both of these would evaluate to `false`: -- `(\x -> x + 1) == (\x -> 1 + x)` -- `(\x -> x + 1) == (\x -> x + 1)` +```roc +(\x -> x + 1) == (\x -> 1 + x) #false +(\x -> x + 1) == (\x -> x + 1) #false +``` This makes function equality effectively useless, while still technically allowing it. It has some other downsides: @@ -71,6 +75,9 @@ The first of these problems could be addressed by having function equality alway Each of these designs makes Roc a language that's some combination of more error-prone, more confusing, and more brittle to change. Disallowing function equality at compile time eliminates all of these drawbacks. +Note that you can provide a custom implementation of the `Eq` ability for an opaque type that contains a function, +in any way you like (including ignoring the function for equality). + ## Why is there no way to specify "import everything this module exposes" in `imports`? In [Elm](https://elm-lang.org), it's possible to import a module in a way that brings everything that module @@ -249,11 +256,11 @@ the downsides. In Roc, both of these expressions evaluate to `"Hello, World!"` -```elixir +```roc Str.concat "Hello, " "World!" ``` -```elixir +```roc "Hello, " |> Str.concat "World!" ``` @@ -270,12 +277,12 @@ In Roc, both expressions evaluate to the same thing because Roc's `|>` operator This comes up in other situations besides string concatenation. For example, consider subtraction and division: -```elixir +```roc someNumber |> Num.div 2 ``` -```elixir +```roc someNumber |> Num.sub 1 ``` @@ -289,7 +296,7 @@ experienced users. The way `|>` works in Roc has a second benefit when it comes to higher-order functions. Consider these two examples: -```elixir +```roc answer = List.map numbers \num -> someFunction "some argument" @@ -297,7 +304,7 @@ answer = List.map numbers \num -> anotherArg ``` -```elixir +```roc numbers |> List.map Num.abs ``` @@ -308,7 +315,7 @@ In a curried language, these two examples couldn't both be valid. In order for ` This means the first example would have to change from this... -```elixir +```roc answer = List.map numbers \num -> someFunction "some argument" @@ -318,7 +325,7 @@ answer = List.map numbers \num -> ...to this: -```elixir +```roc answer = List.map (\num -> @@ -367,7 +374,7 @@ And however easy Roc would be to learn if it had currying, the language is certa a new function by composing together two existing functions without naming intermediate arguments. Here's an example: -```elm +```roc reverseSort : List elem -> List elem reverseSort = compose List.reverse List.sort @@ -377,7 +384,7 @@ compose = \f, g, x -> f (g x) Here's a way to write it without pointfree function composition: -```elm +```roc reverseSort : List elem -> List elem reverseSort = \list -> List.reverse (List.sort list) ``` @@ -440,7 +447,3 @@ There were a few reasons for this rewrite. 4. Zig has more tools for working in a memory-unsafe environment, such as reporting memory leaks in tests. These have been helpful in finding bugs that are out of scope for safe Rust. The split of Rust for the compiler and Zig for the standard library has worked well so far, and there are no plans to change it. - -## Why is the website so basic? - -We have a very basic website on purpose, it helps set expectations that roc is a work in progress and not ready yet for a first release. diff --git a/www/content/index.md b/www/content/index.md index d0e2bf8b33..b5addaf0e9 100644 --- a/www/content/index.md +++ b/www/content/index.md @@ -116,7 +116,7 @@ The [tutorial](/tutorial) introduces these gradually and in more depth, but this ## [Sponsors](#sponsors) {#sponsors} -We are very grateful for our corporate sponsors [Vendr](https://www.vendr.com/), [RWX](https://www.rwx.com), [Tweede golf](https://tweedegolf.nl/en), and [ohne-makler](https://www.ohne-makler.net): +We are very grateful for our corporate sponsors! They are: [Vendr](https://www.vendr.com/), [RWX](https://www.rwx.com), [Tweede golf](https://tweedegolf.nl/en), ohne-makler, and [Decem](https://www.decem.com.au). If you would like your organization to become an official sponsor of Roc's development, please [DM Richard Feldman on Zulip](https://roc.zulipchat.com/#narrow/pm-with/281383-user281383)! @@ -153,7 +155,7 @@ We'd also like to express our gratitude to our generous [individual sponsors](ht
  • Lucas Rosa
  • Jonas Schell
  • Christopher Dolan
  • -
  • Nick Gravgaard
  • +
  • Nick Gravgaard
  • Zeljko Nesic
  • Shritesh Bhattarai
  • Richard Feldman
  • diff --git a/www/content/install.md b/www/content/install.md index ddaa322cdf..fb267ef15d 100644 --- a/www/content/install.md +++ b/www/content/install.md @@ -5,7 +5,7 @@ Roc is a very young language with many incomplete features and known bugs. It do There are currently a few known OS-specific issues: * **macOS:** There are no known compatibility issues, but the compiler doesn't run as fast as it does on Linux or Windows, because we don't (yet) do our own linking like we do on those targets. (Linking works similarly on Linux and Windows, but the way macOS does it is both different and significantly more complicated.) * **Windows:** There are some known Windows-specific compiler bugs, and probably some other unknown ones because more people have tried out Roc on Mac and Linux than on Windows. -* **Linux:** The nightlies are built with glibc, so they aren't usable on distros that don't use (dynamically linked) glibc, like Alpine or NixOS. In the future we plan to build Linux releases with [musl libc](https://wiki.musl-libc.org/) to address this, but this requires [building LLVM from source with musl](https://wiki.musl-libc.org/building-llvm.html). +* **Linux:** The nightlies are built with glibc, so they aren't usable on distros that don't use glibc, like Alpine. In the future we plan to build Linux releases with [musl libc](https://wiki.musl-libc.org/) to address this, but this requires [building LLVM from source with musl](https://wiki.musl-libc.org/building-llvm.html). * **Other operating systems:** Roc has not been built on any other operating systems. [Building from source](https://github.com/roc-lang/roc/blob/main/BUILDING_FROM_SOURCE.md) on another OS might work, but you might very well be the first person ever to try it! ### [Getting Started](#getting-started) {#getting-started} @@ -14,6 +14,7 @@ Here are some Getting Started guides for different operating systems: - [Linux x86-64](https://github.com/roc-lang/roc/blob/main/getting_started/linux_x86_64.md) +- [Nix Linux/MacOS](https://github.com/roc-lang/roc/blob/main/getting_started/nix.md) - [MacOS Apple Silicon](https://github.com/roc-lang/roc/blob/main/getting_started/macos_apple_silicon.md) - [MacOS x86-64](https://github.com/roc-lang/roc/blob/main/getting_started/macos_x86_64.md) - [Windows](https://github.com/roc-lang/roc/blob/main/getting_started/windows.md) diff --git a/www/content/plans.md b/www/content/plans.md index 1495a32c8a..dde76d390b 100644 --- a/www/content/plans.md +++ b/www/content/plans.md @@ -30,6 +30,12 @@ Implementing the very important [module params](https://docs.google.com/document Work has not started on this yet, but we'd like to have the project completed sometime in 2024. +### Removal of `Nat` + +We are removing the `Nat` number type in favour of using `U64` as the default. This will further improve the portability of Roc programs, by removing a potential source of different behaviour across architectures. + +You can track progress in [this PR](https://github.com/roc-lang/roc/pull/5923). + ## Planned Non-Breaking Changes These are planned changes to how things work, which should be backwards-compatible and require no code changes. These won't include bugfixes, just changing something that currently works as designed to have a different design. diff --git a/www/content/platforms.md b/www/content/platforms.md index 46943e9afc..e956568da5 100644 --- a/www/content/platforms.md +++ b/www/content/platforms.md @@ -8,7 +8,7 @@ Here is a Roc application that prints `"Hello, World!"` to the command line: ```roc app "hello" - packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.5.0/Cufzl36_SnJ4QbOoEmiJ5dIpUxBvdB3NEySvuH82Wio.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br" } imports [pf.Stdout] provides [main] to pf diff --git a/www/content/tutorial.md b/www/content/tutorial.md index 14a3ddf5ef..fba4399a2e 100644 --- a/www/content/tutorial.md +++ b/www/content/tutorial.md @@ -18,7 +18,6 @@
  • Tests and Expectations
  • Modules
  • Tasks
  • -
  • Abilities
  • Advanced Concepts
  • Reserved Keywords
  • Operator Desugaring Table
  • @@ -165,7 +164,7 @@ Make a file named `main.roc` and put this in it: ```roc app "hello" - packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.5.0/Cufzl36_SnJ4QbOoEmiJ5dIpUxBvdB3NEySvuH82Wio.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br" } imports [pf.Stdout] provides [main] to pf @@ -655,6 +654,7 @@ when myList is [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 + [head, .. as tail] -> 9 # destructure a list into a first element (head) and the rest (tail) ``` 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. @@ -1412,7 +1412,7 @@ Let's take a closer look at the part of `main.roc` above the `main` def: ```roc app "hello" - packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.5.0/Cufzl36_SnJ4QbOoEmiJ5dIpUxBvdB3NEySvuH82Wio.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br" } imports [pf.Stdout] provides [main] to pf ``` @@ -1424,7 +1424,7 @@ The line `app "hello"` shows that this module is a Roc application. The "hello" The remaining lines all involve the [platform](https://github.com/roc-lang/roc/wiki/Roc-concepts-explained#platform) this application is built on: ```roc -packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.5.0/Cufzl36_SnJ4QbOoEmiJ5dIpUxBvdB3NEySvuH82Wio.tar.br" } +packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br" } imports [pf.Stdout] provides [main] to pf ``` @@ -1523,7 +1523,7 @@ Let's start with a basic "Hello World" program. ```roc app "cli-tutorial" - packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.5.0/Cufzl36_SnJ4QbOoEmiJ5dIpUxBvdB3NEySvuH82Wio.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br" } imports [pf.Stdout] provides [main] to pf @@ -1543,26 +1543,34 @@ When we set `main` to be a `Task`, the task will get run when we run our program `Task` has two type parameters: the type of value it produces when it finishes running, and any errors that might happen when running it. `Stdout.line` has the type `Task {} *` because it doesn't produce any values when it finishes (hence the `{}`) and there aren't any errors that can happen when it runs (hence the `*`). -In contrast, `Stdin.line` produces a `Str` when it finishes reading from [standard input](). That `Str` is reflected in its type: +In contrast, when `Stdin.line` finishes reading a line from [standard input](), it produces either a `Str` or else `End` if standard input reached its end (which can happen if the user types Ctrl+D on UNIX systems or Ctrl+Z on Windows). Those two possibilities are reflected in its type: ```roc -Stdin.line : Task Str * +Stdin.line : Task [Input Str, End] * ``` -Let's change `main` to read a line from `stdin`, and then print it back out again: +Once this task runs, we'll end up with the [tag union](https://www.roc-lang.org/tutorial#tags-with-payloads) `[Input Str, End]`. Then we can check whether we got an `End` or some actual `Input`, and print out a message accordingly. + +### [Printing Roc values with `Inspect.toStr`](#inspect) {#inspect} + +Let's change `main` to read a line from `stdin`, and then print what we got: ```roc app "cli-tutorial" - packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.5.0/Cufzl36_SnJ4QbOoEmiJ5dIpUxBvdB3NEySvuH82Wio.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.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)" + Task.await Stdin.line \input -> + Stdout.line "Your input was: \(Inspect.toStr input)" ``` -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. +The [`Inspect.toStr`](https://www.roc-lang.org/builtins/Inspect#toStr) function returns a `Str` representation of any Roc value. It's useful for things like debugging and logging (although [`dbg`](https://www.roc-lang.org/tutorial#debugging) is often nicer for debugging), but its output is almost never something that should be shown to end users! In this case we're just using it for our own learning, but in a real program we'd run a `when` on `answer` and do something different depending on whether we got an `End` or `Input` tag. + +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—either `Your input was: End` or `Your input was: Input ` depending on whether you pressed Enter or the key combination to close stdin (namely Ctrl+D on UNIX or Ctrl+Z on Windows). Try doing it both ways to watch the output change! + +### [Chaining tasks with `Task.await`](#await) {#await} The `Task.await` function combines two tasks into one bigger `Task` which first runs one of the given tasks and then the other. In this case, it's combining a `Stdin.line` task with a `Stdout.line` task into one bigger `Task`, and then setting `main` to be that bigger task. @@ -1572,11 +1580,11 @@ The type of `Task.await` is: 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 `\input -> ...` callback function here: ```roc -\text -> - Stdout.line "You just entered: \(text)" +\input -> + Stdout.line "Your input was: \(Inspect.toStr input)" ``` 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`. @@ -1586,22 +1594,22 @@ For example, we can print a prompt before we pause to read from `stdin`, so it n ```roc main = Task.await (Stdout.line "Type something press Enter:") \_ -> - Task.await Stdin.line \text -> - Stdout.line "You just entered: \(text)" + Task.await Stdin.line \input -> + Stdout.line "Your input was: \(Inspect.toStr input)" ``` This works, but we can make it a little nicer to read. Let's change it to the following: ```roc app "cli-tutorial" - packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.5.0/Cufzl36_SnJ4QbOoEmiJ5dIpUxBvdB3NEySvuH82Wio.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.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)" + await Stdin.line \input -> + Stdout.line "Your input was: \(Inspect.toStr input)" ``` 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`. @@ -1613,9 +1621,9 @@ Speaking of calling `await` repeatedly, if we keep calling it more and more on t ```roc main = _ <- await (Stdout.line "Type something press Enter:") - text <- await Stdin.line + input <- await Stdin.line - Stdout.line "You just entered: \(text)" + Stdout.line "Your input was: \(Inspect.toStr input)" ``` ## [Backpassing](#backpassing) {#backpassing} @@ -1625,16 +1633,16 @@ This `<-` syntax is called _backpassing_. The `<-` is a way to define an anonymo Here, we're using backpassing to define two anonymous functions. Here's one of them: ```roc -text <- +input <- -Stdout.line "You just entered: \(text)" +Stdout.line "Your input was: \(Inspect.toStr input)" ``` 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: ```roc -\text -> - Stdout.line "You just entered: \(text)" +\input -> + Stdout.line "Your input was: \(Inspect.toStr input)" ``` These two anonymous functions are the same, just defined using different syntax. @@ -1646,25 +1654,25 @@ Let's look at these two complete expressions side by side. They are both saying Here's the original: ```roc -await Stdin.line \text -> - Stdout.line "You just entered: \(text)" +await Stdin.line \input -> + Stdout.line "Your input was: \(Inspect.toStr input)" ``` And here's the equivalent expression with backpassing syntax: ```roc -text <- await Stdin.line +input <- await Stdin.line -Stdout.line "You just entered: \(text)" +Stdout.line "Your input was: \(Inspect.toStr input)" ``` Here's the other function we're defining with backpassing: ```roc _ <- -text <- await Stdin.line +input <- await Stdin.line -Stdout.line "You just entered: \(text)" +Stdout.line "Your input was: \(Inspect.toStr input)" ``` We could also have written that function this way if we preferred: @@ -1672,40 +1680,36 @@ 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 \input -> + Stdout.line "Your input was: \(Inspect.toStr input)" ``` -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. +This is using a mix of a backpassing function `_ <-` and a normal function `\input ->`, 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: ```roc main = _ <- await (Stdout.line "Type something press Enter:") - text <- await Stdin.line + input <- await Stdin.line - Stdout.line "You just entered: \(text)" + Stdout.line "Your input was: \(Inspect.toStr input)" ``` This way, it reads like a series of instructions: 1. First, run the `Stdout.line` task and await its completion. Ignore its output (hence the underscore in `_ <-`) -2. Next, run the `Stdin.line` task and await its completion. Name its output `text`. -3. Finally, run the `Stdout.line` task again, using the `text` value we got from the `Stdin.line` effect. +2. Next, run the `Stdin.line` task and await its completion. Name its output `input`. +3. Finally, run the `Stdout.line` task again, using the `input` value we got from the `Stdin.line` effect. Some important things to note about backpassing and `await`: - `await` is not a language keyword in Roc! It's referring to the `Task.await` function, which we imported unqualified by writing `Task.{ await }` in our module imports. (That said, it is playing a similar role here to the `await` keyword in languages that have `async`/`await` keywords, even though in this case it's a function instead of a special keyword.) - Backpassing syntax does not need to be used with `await` in particular. It can be used with any function. -- Roc's compiler treats functions defined with backpassing exactly the same way as functions defined the other way. The only difference between `\text ->` and `text <-` is how they look, so feel free to use whichever looks nicer to you! +- Roc's compiler treats functions defined with backpassing exactly the same way as functions defined the other way. The only difference between `\input ->` and `input <-` is how they look, so feel free to use whichever looks nicer to you! See the [Task & Error Handling example](https://www.roc-lang.org/examples/Tasks/README.html) for a more detailed explanation of how to use tasks to help with error handling in a larger program. -## [Abilities](#abilities) {#abilities} - -\[This part of the tutorial has not been written yet. Coming soon!\] - ## Examples Well done on making it this far! @@ -2072,8 +2076,8 @@ Here are various Roc expressions involving operators, and what they desugar to. | `a && b` | `Bool.and a b` | | a \|\| b | `Bool.or a b` | | `!a` | `Bool.not a` | -| a \|> b | `b a` | -| a b c \|> f x y | `f (a b c) x y` | +| a \|> f | `f a` | +| f a b \|> g x y | `g (f a b) x y` | diff --git a/www/public/site.css b/www/public/site.css index 97591f815b..f03c662803 100644 --- a/www/public/site.css +++ b/www/public/site.css @@ -166,6 +166,10 @@ hr { height: 4.5rem; } +#sponsor-logos .logo-decem .cls-1 { + fill:#04021e; +} + #sponsor-logos + p { margin-bottom: 3em; } @@ -870,6 +874,10 @@ li { .home-goals-content:hover { background-color: #481870 !important; } + + #sponsor-logos .logo-decem .cls-1 { + fill: #fff; + } } /* Comments `#` and Documentation comments `##` */ @@ -1539,4 +1547,4 @@ code .dim { #gh-link-text { margin-left: 8px; vertical-align: middle; -} \ No newline at end of file +}