mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 05:49:08 +00:00
Merge remote-tracking branch 'remote/main' into upgrade-llvm-zig
This commit is contained in:
commit
99e2bc2038
253 changed files with 7403 additions and 4217 deletions
43
.github/workflows/basic_cli_build_release.yml
vendored
43
.github/workflows/basic_cli_build_release.yml
vendored
|
@ -11,7 +11,7 @@ env:
|
||||||
# use .tar.gz for quick testing
|
# use .tar.gz for quick testing
|
||||||
ARCHIVE_FORMAT: .tar.br
|
ARCHIVE_FORMAT: .tar.br
|
||||||
# Make a new basic-cli git tag and set it here before starting this workflow
|
# Make a new basic-cli git tag and set it here before starting this workflow
|
||||||
RELEASE_TAG: 0.12.0
|
RELEASE_TAG: 0.14.0
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
prepare:
|
prepare:
|
||||||
|
@ -34,14 +34,14 @@ jobs:
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# get latest nightly releases
|
# 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_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-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
|
#- run: curl -fOL https://github.com/roc-lang/roc/releases/download/nightly/roc_nightly-macos_x86_64-latest.tar.gz
|
||||||
- run: curl -fOL https://github.com/roc-lang/roc/releases/download/nightly/roc_nightly-macos_apple_silicon-latest.tar.gz
|
#- run: curl -fOL https://github.com/roc-lang/roc/releases/download/nightly/roc_nightly-macos_apple_silicon-latest.tar.gz
|
||||||
#- run: curl -fOL https://github.com/roc-lang/roc/releases/download/nightly/roc_nightly-linux_x86_64-TESTING.tar.gz
|
- run: curl -fOL https://github.com/roc-lang/roc/releases/download/nightly/roc_nightly-linux_x86_64-TESTING.tar.gz
|
||||||
#- run: curl -fOL https://github.com/roc-lang/roc/releases/download/nightly/roc_nightly-linux_arm64-TESTING.tar.gz
|
- run: curl -fOL https://github.com/roc-lang/roc/releases/download/nightly/roc_nightly-linux_arm64-TESTING.tar.gz
|
||||||
#- run: curl -fOL https://github.com/roc-lang/roc/releases/download/nightly/roc_nightly-macos_x86_64-TESTING.tar.gz
|
- run: curl -fOL https://github.com/roc-lang/roc/releases/download/nightly/roc_nightly-macos_x86_64-TESTING.tar.gz
|
||||||
#- run: curl -fOL https://github.com/roc-lang/roc/releases/download/nightly/roc_nightly-macos_apple_silicon-TESTING.tar.gz
|
- run: curl -fOL https://github.com/roc-lang/roc/releases/download/nightly/roc_nightly-macos_apple_silicon-TESTING.tar.gz
|
||||||
|
|
||||||
- name: Save roc_nightly archives
|
- name: Save roc_nightly archives
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
|
@ -60,16 +60,16 @@ jobs:
|
||||||
- name: build basic-cli with surgical linker and also with legacy linker
|
- name: build basic-cli with surgical linker and also with legacy linker
|
||||||
env:
|
env:
|
||||||
CARGO_BUILD_TARGET: x86_64-unknown-linux-musl
|
CARGO_BUILD_TARGET: x86_64-unknown-linux-musl
|
||||||
run: ./ci/build_basic_cli.sh linux_x86_64 "--linker legacy"
|
run: ./ci/build_basic_cli.sh linux_x86_64
|
||||||
|
|
||||||
- name: Save .rh, .rm and .o file
|
- name: Save .rh, .rm and .a file
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: linux-x86_64-files
|
name: linux-x86_64-files
|
||||||
path: |
|
path: |
|
||||||
basic-cli/platform/metadata_linux-x64.rm
|
basic-cli/platform/metadata_linux-x64.rm
|
||||||
basic-cli/platform/linux-x64.rh
|
basic-cli/platform/linux-x64.rh
|
||||||
basic-cli/platform/linux-x64.o
|
basic-cli/platform/linux-x64.a
|
||||||
|
|
||||||
|
|
||||||
build-linux-arm64-files:
|
build-linux-arm64-files:
|
||||||
|
@ -89,12 +89,12 @@ jobs:
|
||||||
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_RUSTFLAGS: "-Clink-self-contained=yes -Clinker=rust-lld"
|
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_RUSTFLAGS: "-Clink-self-contained=yes -Clinker=rust-lld"
|
||||||
run: ./ci/build_basic_cli.sh linux_arm64
|
run: ./ci/build_basic_cli.sh linux_arm64
|
||||||
|
|
||||||
- name: Save .o file
|
- name: Save .a file
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: linux-arm64-files
|
name: linux-arm64-files
|
||||||
path: |
|
path: |
|
||||||
basic-cli/platform/linux-arm64.o
|
basic-cli/platform/linux-arm64.a
|
||||||
|
|
||||||
build-macos-x86_64-files:
|
build-macos-x86_64-files:
|
||||||
runs-on: [macos-12] # I expect the generated files to work on macOS 12 and up
|
runs-on: [macos-12] # I expect the generated files to work on macOS 12 and up
|
||||||
|
@ -107,15 +107,15 @@ jobs:
|
||||||
|
|
||||||
- run: ./ci/build_basic_cli.sh macos_x86_64
|
- run: ./ci/build_basic_cli.sh macos_x86_64
|
||||||
|
|
||||||
- name: Save .o files
|
- name: Save .a file
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: macos-x86_64-files
|
name: macos-x86_64-files
|
||||||
path: |
|
path: |
|
||||||
basic-cli/platform/macos-x64.o
|
basic-cli/platform/macos-x64.a
|
||||||
|
|
||||||
build-macos-apple-silicon-files:
|
build-macos-apple-silicon-files:
|
||||||
name: build apple silicon .o file
|
name: build apple silicon .a file
|
||||||
runs-on: [self-hosted, macOS, ARM64]
|
runs-on: [self-hosted, macOS, ARM64]
|
||||||
needs: [prepare]
|
needs: [prepare]
|
||||||
steps:
|
steps:
|
||||||
|
@ -126,12 +126,12 @@ jobs:
|
||||||
|
|
||||||
- run: ./ci/build_basic_cli.sh macos_apple_silicon
|
- run: ./ci/build_basic_cli.sh macos_apple_silicon
|
||||||
|
|
||||||
- name: Save macos-arm64.o file
|
- name: Save macos-arm64.a file
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: macos-apple-silicon-files
|
name: macos-apple-silicon-files
|
||||||
path: |
|
path: |
|
||||||
basic-cli/platform/macos-arm64.o
|
basic-cli/platform/macos-arm64.a
|
||||||
|
|
||||||
create-release-archive:
|
create-release-archive:
|
||||||
needs: [build-linux-x86_64-files, build-linux-arm64-files, build-macos-x86_64-files, build-macos-apple-silicon-files]
|
needs: [build-linux-x86_64-files, build-linux-arm64-files, build-macos-x86_64-files, build-macos-apple-silicon-files]
|
||||||
|
@ -250,10 +250,11 @@ jobs:
|
||||||
git checkout ${{ env.RELEASE_TAG }}
|
git checkout ${{ env.RELEASE_TAG }}
|
||||||
cp -r examples ../..
|
cp -r examples ../..
|
||||||
cp -r ci ../..
|
cp -r ci ../..
|
||||||
cp -r LICENSE ../..
|
|
||||||
# LICENSE is necessary for command test
|
# LICENSE is necessary for command test
|
||||||
|
cp -r LICENSE ../..
|
||||||
|
|
||||||
- name: run tests
|
- name: run tests
|
||||||
run: |
|
run: |
|
||||||
cd basic-cli-platform
|
cd basic-cli-platform
|
||||||
ROC=./roc_nightly/roc EXAMPLES_DIR=./examples/ ROC_BUILD_FLAGS=--prebuilt-platform ./ci/all_tests.sh
|
# no need to build platform anymore
|
||||||
|
NO_BUILD=1 ROC=./roc_nightly/roc EXAMPLES_DIR=./examples/ ./ci/all_tests.sh
|
||||||
|
|
|
@ -10,7 +10,7 @@ concurrency:
|
||||||
env:
|
env:
|
||||||
# use .tar.gz for quick testing
|
# use .tar.gz for quick testing
|
||||||
ARCHIVE_FORMAT: .tar.br
|
ARCHIVE_FORMAT: .tar.br
|
||||||
BASIC_WEBSERVER_BRANCH: main
|
RELEASE_TAG: 0.8.0
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
fetch-releases:
|
fetch-releases:
|
||||||
|
@ -46,16 +46,16 @@ jobs:
|
||||||
- name: build basic-webserver with legacy linker
|
- name: build basic-webserver with legacy linker
|
||||||
env:
|
env:
|
||||||
CARGO_BUILD_TARGET: x86_64-unknown-linux-musl
|
CARGO_BUILD_TARGET: x86_64-unknown-linux-musl
|
||||||
run: ./ci/build_basic_webserver.sh linux_x86_64 "--linker legacy"
|
run: ./ci/build_basic_webserver.sh linux_x86_64
|
||||||
|
|
||||||
- name: Save .rh, .rm and .o file
|
- name: Save .rh, .rm and .a file
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: linux-x86_64-files
|
name: linux-x86_64-files
|
||||||
path: |
|
path: |
|
||||||
basic-webserver/platform/metadata_linux-x64.rm
|
basic-webserver/platform/metadata_linux-x64.rm
|
||||||
basic-webserver/platform/linux-x64.rh
|
basic-webserver/platform/linux-x64.rh
|
||||||
basic-webserver/platform/linux-x64.o
|
basic-webserver/platform/linux-x64.a
|
||||||
|
|
||||||
|
|
||||||
build-linux-arm64-files:
|
build-linux-arm64-files:
|
||||||
|
@ -75,12 +75,12 @@ jobs:
|
||||||
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_RUSTFLAGS: "-Clink-self-contained=yes -Clinker=rust-lld"
|
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_RUSTFLAGS: "-Clink-self-contained=yes -Clinker=rust-lld"
|
||||||
run: ./ci/build_basic_webserver.sh linux_arm64
|
run: ./ci/build_basic_webserver.sh linux_arm64
|
||||||
|
|
||||||
- name: Save .o file
|
- name: Save .a file
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: linux-arm64-files
|
name: linux-arm64-files
|
||||||
path: |
|
path: |
|
||||||
basic-webserver/platform/linux-arm64.o
|
basic-webserver/platform/linux-arm64.a
|
||||||
|
|
||||||
build-macos-x86_64-files:
|
build-macos-x86_64-files:
|
||||||
runs-on: [macos-12] # I expect the generated files to work on macOS 12 and up
|
runs-on: [macos-12] # I expect the generated files to work on macOS 12 and up
|
||||||
|
@ -93,15 +93,15 @@ jobs:
|
||||||
|
|
||||||
- run: ./ci/build_basic_webserver.sh macos_x86_64
|
- run: ./ci/build_basic_webserver.sh macos_x86_64
|
||||||
|
|
||||||
- name: Save .o files
|
- name: Save .a files
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: macos-x86_64-files
|
name: macos-x86_64-files
|
||||||
path: |
|
path: |
|
||||||
basic-webserver/platform/macos-x64.o
|
basic-webserver/platform/macos-x64.a
|
||||||
|
|
||||||
build-macos-apple-silicon-files:
|
build-macos-apple-silicon-files:
|
||||||
name: build apple silicon .o file
|
name: build apple silicon .a file
|
||||||
runs-on: [self-hosted, macOS, ARM64]
|
runs-on: [self-hosted, macOS, ARM64]
|
||||||
needs: [fetch-releases]
|
needs: [fetch-releases]
|
||||||
steps:
|
steps:
|
||||||
|
@ -112,12 +112,12 @@ jobs:
|
||||||
|
|
||||||
- run: ./ci/build_basic_webserver.sh macos_apple_silicon
|
- run: ./ci/build_basic_webserver.sh macos_apple_silicon
|
||||||
|
|
||||||
- name: Save macos-arm64.o file
|
- name: Save macos-arm64.a file
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: macos-apple-silicon-files
|
name: macos-apple-silicon-files
|
||||||
path: |
|
path: |
|
||||||
basic-webserver/platform/macos-arm64.o
|
basic-webserver/platform/macos-arm64.a
|
||||||
|
|
||||||
create-release-archive:
|
create-release-archive:
|
||||||
needs: [build-linux-x86_64-files, build-linux-arm64-files, build-macos-x86_64-files, build-macos-apple-silicon-files]
|
needs: [build-linux-x86_64-files, build-linux-arm64-files, build-macos-x86_64-files, build-macos-apple-silicon-files]
|
||||||
|
@ -147,7 +147,7 @@ jobs:
|
||||||
- run: |
|
- run: |
|
||||||
git clone https://github.com/roc-lang/basic-webserver.git
|
git clone https://github.com/roc-lang/basic-webserver.git
|
||||||
cd basic-webserver
|
cd basic-webserver
|
||||||
git checkout ${{ env.BASIC_WEBSERVER_BRANCH }}
|
git checkout ${{ env.RELEASE_TAG }}
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
- run: cp macos-apple-silicon-files/* ./basic-webserver/platform
|
- run: cp macos-apple-silicon-files/* ./basic-webserver/platform
|
||||||
|
|
26
.github/workflows/docker.yml
vendored
26
.github/workflows/docker.yml
vendored
|
@ -1,5 +1,7 @@
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
# pull_request:
|
||||||
|
# TODO remove pull_request trigger
|
||||||
|
|
||||||
name: Docker images tests
|
name: Docker images tests
|
||||||
|
|
||||||
|
@ -15,10 +17,10 @@ jobs:
|
||||||
run: cp docker/nightly-ubuntu-latest/docker-compose.example.yml docker/nightly-ubuntu-latest/docker-compose.yml
|
run: cp docker/nightly-ubuntu-latest/docker-compose.example.yml docker/nightly-ubuntu-latest/docker-compose.yml
|
||||||
|
|
||||||
- name: Build image
|
- name: Build image
|
||||||
run: docker-compose -f docker/nightly-ubuntu-latest/docker-compose.yml build
|
run: docker compose -f docker/nightly-ubuntu-latest/docker-compose.yml build
|
||||||
|
|
||||||
- name: Run hello world test
|
- name: Run hello world test
|
||||||
run: docker-compose -f docker/nightly-ubuntu-latest/docker-compose.yml run roc examples/helloWorld.roc
|
run: docker compose -f docker/nightly-ubuntu-latest/docker-compose.yml run roc examples/helloWorld.roc
|
||||||
|
|
||||||
|
|
||||||
nightly-ubuntu-2204:
|
nightly-ubuntu-2204:
|
||||||
|
@ -32,10 +34,10 @@ jobs:
|
||||||
run: cp docker/nightly-ubuntu-2204/docker-compose.example.yml docker/nightly-ubuntu-2204/docker-compose.yml
|
run: cp docker/nightly-ubuntu-2204/docker-compose.example.yml docker/nightly-ubuntu-2204/docker-compose.yml
|
||||||
|
|
||||||
- name: Build image
|
- name: Build image
|
||||||
run: docker-compose -f docker/nightly-ubuntu-2204/docker-compose.yml build
|
run: docker compose -f docker/nightly-ubuntu-2204/docker-compose.yml build
|
||||||
|
|
||||||
- name: Run hello world test
|
- name: Run hello world test
|
||||||
run: docker-compose -f docker/nightly-ubuntu-2204/docker-compose.yml run roc examples/helloWorld.roc
|
run: docker compose -f docker/nightly-ubuntu-2204/docker-compose.yml run roc examples/helloWorld.roc
|
||||||
|
|
||||||
nightly-ubuntu-2004:
|
nightly-ubuntu-2004:
|
||||||
name: nightly-ubuntu-2004
|
name: nightly-ubuntu-2004
|
||||||
|
@ -48,10 +50,10 @@ jobs:
|
||||||
run: cp docker/nightly-ubuntu-2004/docker-compose.example.yml docker/nightly-ubuntu-2004/docker-compose.yml
|
run: cp docker/nightly-ubuntu-2004/docker-compose.example.yml docker/nightly-ubuntu-2004/docker-compose.yml
|
||||||
|
|
||||||
- name: Build image
|
- name: Build image
|
||||||
run: docker-compose -f docker/nightly-ubuntu-2004/docker-compose.yml build
|
run: docker compose -f docker/nightly-ubuntu-2004/docker-compose.yml build
|
||||||
|
|
||||||
- name: Run hello world test
|
- name: Run hello world test
|
||||||
run: docker-compose -f docker/nightly-ubuntu-2004/docker-compose.yml run roc examples/helloWorld.roc
|
run: docker compose -f docker/nightly-ubuntu-2004/docker-compose.yml run roc examples/helloWorld.roc
|
||||||
|
|
||||||
nightly-debian-latest:
|
nightly-debian-latest:
|
||||||
name: nightly-debian-latest
|
name: nightly-debian-latest
|
||||||
|
@ -64,10 +66,10 @@ jobs:
|
||||||
run: cp docker/nightly-debian-latest/docker-compose.example.yml docker/nightly-debian-latest/docker-compose.yml
|
run: cp docker/nightly-debian-latest/docker-compose.example.yml docker/nightly-debian-latest/docker-compose.yml
|
||||||
|
|
||||||
- name: Build image
|
- name: Build image
|
||||||
run: docker-compose -f docker/nightly-debian-latest/docker-compose.yml build
|
run: docker compose -f docker/nightly-debian-latest/docker-compose.yml build
|
||||||
|
|
||||||
- name: Run hello world test
|
- name: Run hello world test
|
||||||
run: docker-compose -f docker/nightly-debian-latest/docker-compose.yml run roc examples/helloWorld.roc
|
run: docker compose -f docker/nightly-debian-latest/docker-compose.yml run roc examples/helloWorld.roc
|
||||||
|
|
||||||
nightly-debian-bookworm:
|
nightly-debian-bookworm:
|
||||||
name: nightly-debian-bookworm
|
name: nightly-debian-bookworm
|
||||||
|
@ -80,10 +82,10 @@ jobs:
|
||||||
run: cp docker/nightly-debian-bookworm/docker-compose.example.yml docker/nightly-debian-bookworm/docker-compose.yml
|
run: cp docker/nightly-debian-bookworm/docker-compose.example.yml docker/nightly-debian-bookworm/docker-compose.yml
|
||||||
|
|
||||||
- name: Build image
|
- name: Build image
|
||||||
run: docker-compose -f docker/nightly-debian-bookworm/docker-compose.yml build
|
run: docker compose -f docker/nightly-debian-bookworm/docker-compose.yml build
|
||||||
|
|
||||||
- name: Run hello world test
|
- name: Run hello world test
|
||||||
run: docker-compose -f docker/nightly-debian-bookworm/docker-compose.yml run roc examples/helloWorld.roc
|
run: docker compose -f docker/nightly-debian-bookworm/docker-compose.yml run roc examples/helloWorld.roc
|
||||||
|
|
||||||
nightly-debian-buster:
|
nightly-debian-buster:
|
||||||
name: nightly-debian-buster
|
name: nightly-debian-buster
|
||||||
|
@ -96,7 +98,7 @@ jobs:
|
||||||
run: cp docker/nightly-debian-buster/docker-compose.example.yml docker/nightly-debian-buster/docker-compose.yml
|
run: cp docker/nightly-debian-buster/docker-compose.example.yml docker/nightly-debian-buster/docker-compose.yml
|
||||||
|
|
||||||
- name: Build image
|
- name: Build image
|
||||||
run: docker-compose -f docker/nightly-debian-buster/docker-compose.yml build
|
run: docker compose -f docker/nightly-debian-buster/docker-compose.yml build
|
||||||
|
|
||||||
- name: Run hello world test
|
- name: Run hello world test
|
||||||
run: docker-compose -f docker/nightly-debian-buster/docker-compose.yml run roc examples/helloWorld.roc
|
run: docker compose -f docker/nightly-debian-buster/docker-compose.yml run roc examples/helloWorld.roc
|
||||||
|
|
2
.github/workflows/test_nightly_many_os.yml
vendored
2
.github/workflows/test_nightly_many_os.yml
vendored
|
@ -9,7 +9,7 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [ macos-12, macos-13, ubuntu-20.04, ubuntu-22.04 ]
|
os: [ macos-12, macos-13, ubuntu-20.04, ubuntu-22.04, ubuntu-24.04]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
timeout-minutes: 90
|
timeout-minutes: 90
|
||||||
steps:
|
steps:
|
||||||
|
|
|
@ -94,6 +94,21 @@ If so, you can fix it like so:
|
||||||
sudo apt-get install libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev
|
sudo apt-get install libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### libz libzstd libraries
|
||||||
|
|
||||||
|
You may see an error like this during builds:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/usr/bin/ld: cannot find -lz: No such file or directory
|
||||||
|
/usr/bin/ld: cannot find -lzstd: No such file or directory
|
||||||
|
```
|
||||||
|
|
||||||
|
If so, you can fix it like so:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo apt-get install libz-dev libzstd-dev
|
||||||
|
```
|
||||||
|
|
||||||
### Zig
|
### Zig
|
||||||
|
|
||||||
**version: 0.11.0**
|
**version: 0.11.0**
|
||||||
|
|
83
Cargo.lock
generated
83
Cargo.lock
generated
|
@ -737,17 +737,6 @@ dependencies = [
|
||||||
"powerfmt",
|
"powerfmt",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "derive_more"
|
|
||||||
version = "0.99.17"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 1.0.109",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "diff"
|
name = "diff"
|
||||||
version = "0.1.13"
|
version = "0.1.13"
|
||||||
|
@ -798,12 +787,6 @@ version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6d9d8664cf849d7d0f3114a3a387d2f5e4303176d746d5a951aaddc66dfe9240"
|
checksum = "6d9d8664cf849d7d0f3114a3a387d2f5e4303176d746d5a951aaddc66dfe9240"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "doc-comment"
|
|
||||||
version = "0.3.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dunce"
|
name = "dunce"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
|
@ -1715,11 +1698,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
|
checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
"flate2",
|
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"memchr",
|
"memchr",
|
||||||
"ruzstd",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2537,7 +2518,6 @@ dependencies = [
|
||||||
"roc_solve",
|
"roc_solve",
|
||||||
"roc_target",
|
"roc_target",
|
||||||
"roc_types",
|
"roc_types",
|
||||||
"snafu",
|
|
||||||
"ven_pretty",
|
"ven_pretty",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2557,9 +2537,6 @@ version = "0.0.1"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "roc_error_utils"
|
name = "roc_error_utils"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
|
||||||
"snafu",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "roc_exhaustive"
|
name = "roc_exhaustive"
|
||||||
|
@ -2650,7 +2627,6 @@ dependencies = [
|
||||||
name = "roc_glue"
|
name = "roc_glue"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"cli_utils",
|
"cli_utils",
|
||||||
"dircpy",
|
"dircpy",
|
||||||
|
@ -2816,6 +2792,7 @@ dependencies = [
|
||||||
"roc_derive_key",
|
"roc_derive_key",
|
||||||
"roc_error_macros",
|
"roc_error_macros",
|
||||||
"roc_late_solve",
|
"roc_late_solve",
|
||||||
|
"roc_lower_params",
|
||||||
"roc_module",
|
"roc_module",
|
||||||
"roc_mono",
|
"roc_mono",
|
||||||
"roc_packaging",
|
"roc_packaging",
|
||||||
|
@ -2836,6 +2813,19 @@ dependencies = [
|
||||||
"ven_pretty",
|
"ven_pretty",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "roc_lower_params"
|
||||||
|
version = "0.0.1"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"roc_can",
|
||||||
|
"roc_collections",
|
||||||
|
"roc_module",
|
||||||
|
"roc_region",
|
||||||
|
"roc_solve_problem",
|
||||||
|
"roc_types",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "roc_module"
|
name = "roc_module"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
|
@ -2845,7 +2835,6 @@ dependencies = [
|
||||||
"roc_error_macros",
|
"roc_error_macros",
|
||||||
"roc_ident",
|
"roc_ident",
|
||||||
"roc_region",
|
"roc_region",
|
||||||
"snafu",
|
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -3377,17 +3366,6 @@ dependencies = [
|
||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ruzstd"
|
|
||||||
version = "0.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "58c4eb8a81997cf040a091d1f7e1938aeab6749d3a0dfa73af43cdc32393483d"
|
|
||||||
dependencies = [
|
|
||||||
"byteorder",
|
|
||||||
"derive_more",
|
|
||||||
"twox-hash",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.15"
|
version = "1.0.15"
|
||||||
|
@ -3620,29 +3598,6 @@ version = "1.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
|
checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "snafu"
|
|
||||||
version = "0.7.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e4de37ad025c587a29e8f3f5605c00f70b98715ef90b9061a815b9e59e9042d6"
|
|
||||||
dependencies = [
|
|
||||||
"backtrace",
|
|
||||||
"doc-comment",
|
|
||||||
"snafu-derive",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "snafu-derive"
|
|
||||||
version = "0.7.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "990079665f075b699031e9c08fd3ab99be5029b96f3b78dc0709e8f77e4efebf"
|
|
||||||
dependencies = [
|
|
||||||
"heck",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 1.0.109",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.4.9"
|
version = "0.4.9"
|
||||||
|
@ -4248,16 +4203,6 @@ version = "0.2.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
|
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "twox-hash"
|
|
||||||
version = "1.6.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"static_assertions",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typed-arena"
|
name = "typed-arena"
|
||||||
version = "2.0.2"
|
version = "2.0.2"
|
||||||
|
|
|
@ -117,7 +117,7 @@ maplit = "1.0.2"
|
||||||
memmap2 = "0.5.10"
|
memmap2 = "0.5.10"
|
||||||
mimalloc = { version = "0.1.34", default-features = false }
|
mimalloc = { version = "0.1.34", default-features = false }
|
||||||
nonempty = "0.8.1"
|
nonempty = "0.8.1"
|
||||||
object = { version = "0.32.2", features = ["read", "write"] }
|
object = { version = "0.32.2", default-features = false, features = ["read", "write"] }
|
||||||
packed_struct = "0.10.1"
|
packed_struct = "0.10.1"
|
||||||
page_size = "0.5.0"
|
page_size = "0.5.0"
|
||||||
palette = "0.6.1"
|
palette = "0.6.1"
|
||||||
|
@ -151,7 +151,6 @@ serde_json = "1.0.94" # update roc_std/Cargo.toml on change
|
||||||
serial_test = "1.0.0"
|
serial_test = "1.0.0"
|
||||||
signal-hook = "0.3.15"
|
signal-hook = "0.3.15"
|
||||||
smallvec = { version = "1.10.0", features = ["const_generics", "const_new"] }
|
smallvec = { version = "1.10.0", features = ["const_generics", "const_new"] }
|
||||||
snafu = { version = "0.7.4", features = ["backtraces"] }
|
|
||||||
static_assertions = "1.1.0" # update roc_std/Cargo.toml on change
|
static_assertions = "1.1.0" # update roc_std/Cargo.toml on change
|
||||||
strip-ansi-escapes = "0.1.1"
|
strip-ansi-escapes = "0.1.1"
|
||||||
strum = { version = "0.24.1", features = ["derive"] }
|
strum = { version = "0.24.1", features = ["derive"] }
|
||||||
|
|
|
@ -17,10 +17,6 @@ if [ -n "$(ls | grep -v "roc_nightly.*tar\.gz" | grep -v "^ci$")" ]; then
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$(uname)" == "Darwin" ]]; then
|
|
||||||
brew install z3 # used by llvm
|
|
||||||
fi
|
|
||||||
|
|
||||||
# decompress the tar
|
# decompress the tar
|
||||||
ls | grep "roc_nightly.*tar\.gz" | xargs tar -xzvf
|
ls | grep "roc_nightly.*tar\.gz" | xargs tar -xzvf
|
||||||
|
|
||||||
|
|
|
@ -37,16 +37,23 @@ rm roc_nightly.tar.gz
|
||||||
mv roc_nightly* roc_nightly
|
mv roc_nightly* roc_nightly
|
||||||
|
|
||||||
cd roc_nightly
|
cd roc_nightly
|
||||||
|
export PATH="$(pwd -P):$PATH"
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
# temp test
|
||||||
|
roc version
|
||||||
|
|
||||||
|
cd basic-cli
|
||||||
|
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
||||||
|
if [[ $(uname -m) == "aarch64" ]]; then
|
||||||
|
target_arch="aarch64-unknown-linux-musl"
|
||||||
|
else
|
||||||
|
target_arch="x86_64-unknown-linux-musl"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
./jump-start.sh
|
||||||
|
|
||||||
# build the basic cli platform
|
# build the basic cli platform
|
||||||
./roc build ../basic-cli/examples/countdown.roc --optimize
|
roc build.roc --prebuilt-platform
|
||||||
|
|
||||||
# We need this extra variable so we can safely check if $2 is empty later
|
|
||||||
EXTRA_ARGS=${2:-}
|
|
||||||
|
|
||||||
# In some rare cases it's nice to be able to use the legacy linker, so we produce the .o file to be able to do that
|
|
||||||
if [ -n "${EXTRA_ARGS}" ];
|
|
||||||
then ./roc build $EXTRA_ARGS ../basic-cli/examples/countdown.roc --optimize
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd ..
|
cd ..
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
set -euxo pipefail
|
set -euxo pipefail
|
||||||
|
|
||||||
git clone https://github.com/roc-lang/basic-webserver.git
|
git clone https://github.com/roc-lang/basic-webserver.git
|
||||||
|
cd basic-webserver
|
||||||
|
git checkout $RELEASE_TAG
|
||||||
|
cd ..
|
||||||
|
|
||||||
OS=$(uname -s)
|
OS=$(uname -s)
|
||||||
ARCH=$(uname -m)
|
ARCH=$(uname -m)
|
||||||
|
@ -37,20 +40,13 @@ rm roc_nightly.tar.gz
|
||||||
# simplify dir name
|
# simplify dir name
|
||||||
mv roc_nightly* roc_nightly
|
mv roc_nightly* roc_nightly
|
||||||
|
|
||||||
|
# add roc to PATH
|
||||||
cd roc_nightly
|
cd roc_nightly
|
||||||
|
export PATH="$(pwd -P):$PATH"
|
||||||
|
cd ..
|
||||||
|
|
||||||
# prevent https://github.com/roc-lang/basic-webserver/issues/9
|
cd basic-webserver
|
||||||
if [ "$OS" != "Linux" ] || [ "$ARCH" != "x86_64" ]; then
|
|
||||||
# build the basic-webserver platform
|
|
||||||
./roc build ../basic-webserver/examples/echo.roc --optimize
|
|
||||||
fi
|
|
||||||
|
|
||||||
# We need this extra variable so we can safely check if $2 is empty later
|
roc build.roc --prebuilt-platform
|
||||||
EXTRA_ARGS=${2:-}
|
|
||||||
|
|
||||||
# In some rare cases it's nice to be able to use the legacy linker, so we produce the .o file to be able to do that
|
|
||||||
if [ -n "${EXTRA_ARGS}" ];
|
|
||||||
then ./roc build $EXTRA_ARGS ../basic-webserver/examples/echo.roc --optimize
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd ..
|
cd ..
|
||||||
|
|
|
@ -263,7 +263,7 @@ mod tests {
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use tempfile::{tempdir, TempDir};
|
use tempfile::{tempdir, TempDir};
|
||||||
|
|
||||||
const FORMATTED_ROC: &str = r#"app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.12.0/Lb8EgiejTUzbggO2HVVuPJFkwvvsfW6LojkLR20kTVE.tar.br" }
|
const FORMATTED_ROC: &str = r#"app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.15.0/SlwdbJ-3GR7uBWQo6zlmYWNYOxnvo8r6YABXD-45UOw.tar.br" }
|
||||||
|
|
||||||
import pf.Stdout
|
import pf.Stdout
|
||||||
import pf.Task
|
import pf.Task
|
||||||
|
@ -271,7 +271,7 @@ import pf.Task
|
||||||
main =
|
main =
|
||||||
Stdout.line! "I'm a Roc application!""#;
|
Stdout.line! "I'm a Roc application!""#;
|
||||||
|
|
||||||
const UNFORMATTED_ROC: &str = r#"app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.12.0/Lb8EgiejTUzbggO2HVVuPJFkwvvsfW6LojkLR20kTVE.tar.br" }
|
const UNFORMATTED_ROC: &str = r#"app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.15.0/SlwdbJ-3GR7uBWQo6zlmYWNYOxnvo8r6YABXD-45UOw.tar.br" }
|
||||||
|
|
||||||
|
|
||||||
import pf.Stdout
|
import pf.Stdout
|
||||||
|
|
|
@ -1279,8 +1279,8 @@ fn roc_dev_native(
|
||||||
break if libc::WIFEXITED(status) {
|
break if libc::WIFEXITED(status) {
|
||||||
libc::WEXITSTATUS(status)
|
libc::WEXITSTATUS(status)
|
||||||
} else {
|
} else {
|
||||||
// we don't have an exit code, so we probably shouldn't make one up
|
// we don't have an exit code, but something went wrong if we're in this else
|
||||||
0
|
1
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
ChildProcessMsg::Expect => {
|
ChildProcessMsg::Expect => {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
interface AStar
|
module [findPath, Model, initialModel, cheapestOpen, reconstructPath]
|
||||||
exposes [findPath, Model, initialModel, cheapestOpen, reconstructPath]
|
|
||||||
imports [Quicksort]
|
import Quicksort
|
||||||
|
|
||||||
findPath = \costFn, moveFn, start, end ->
|
findPath = \costFn, moveFn, start, end ->
|
||||||
astar costFn moveFn end (initialModel start)
|
astar costFn moveFn end (initialModel start)
|
||||||
|
@ -92,9 +92,8 @@ astar = \costFn, moveFn, goal, model ->
|
||||||
|
|
||||||
modelWithNeighbors : Model position
|
modelWithNeighbors : Model position
|
||||||
modelWithNeighbors =
|
modelWithNeighbors =
|
||||||
{ modelPopped &
|
modelPopped
|
||||||
openSet: Set.union modelPopped.openSet newNeighbors,
|
|> &openSet (Set.union modelPopped.openSet newNeighbors)
|
||||||
}
|
|
||||||
|
|
||||||
walker : Model position, position -> Model position
|
walker : Model position, position -> Model position
|
||||||
walker = \amodel, n -> updateCost current n amodel
|
walker = \amodel, n -> updateCost current n amodel
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
interface Base64 exposes [fromBytes, fromStr, toBytes, toStr] imports []
|
module [fromBytes, fromStr, toBytes, toStr]
|
||||||
|
|
||||||
import Base64.Decode
|
import Base64.Decode
|
||||||
import Base64.Encode
|
import Base64.Encode
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
interface Base64.Decode exposes [fromBytes] imports []
|
module [fromBytes]
|
||||||
|
|
||||||
import Bytes.Decode exposing [ByteDecoder, DecodeProblem]
|
import Bytes.Decode exposing [ByteDecoder, DecodeProblem]
|
||||||
|
|
||||||
|
@ -12,40 +12,39 @@ decodeBase64 = \width -> Bytes.Decode.loop loopHelp { remaining: width, string:
|
||||||
loopHelp : { remaining : U64, string : Str } -> ByteDecoder (Bytes.Decode.Step { remaining : U64, string : Str } Str)
|
loopHelp : { remaining : U64, string : Str } -> ByteDecoder (Bytes.Decode.Step { remaining : U64, string : Str } Str)
|
||||||
loopHelp = \{ remaining, string } ->
|
loopHelp = \{ remaining, string } ->
|
||||||
if remaining >= 3 then
|
if remaining >= 3 then
|
||||||
x, y, z <- Bytes.Decode.map3 Bytes.Decode.u8 Bytes.Decode.u8 Bytes.Decode.u8
|
Bytes.Decode.map3 Bytes.Decode.u8 Bytes.Decode.u8 Bytes.Decode.u8 \x, y, z ->
|
||||||
|
a : U32
|
||||||
|
a = Num.intCast x
|
||||||
|
b : U32
|
||||||
|
b = Num.intCast y
|
||||||
|
c : U32
|
||||||
|
c = Num.intCast z
|
||||||
|
combined = Num.bitwiseOr (Num.bitwiseOr (Num.shiftLeftBy a 16) (Num.shiftLeftBy b 8)) c
|
||||||
|
|
||||||
a : U32
|
Loop {
|
||||||
a = Num.intCast x
|
remaining: remaining - 3,
|
||||||
b : U32
|
string: Str.concat string (bitsToChars combined 0),
|
||||||
b = Num.intCast y
|
}
|
||||||
c : U32
|
|
||||||
c = Num.intCast z
|
|
||||||
combined = Num.bitwiseOr (Num.bitwiseOr (Num.shiftLeftBy a 16) (Num.shiftLeftBy b 8)) c
|
|
||||||
|
|
||||||
Loop {
|
|
||||||
remaining: remaining - 3,
|
|
||||||
string: Str.concat string (bitsToChars combined 0),
|
|
||||||
}
|
|
||||||
else if remaining == 0 then
|
else if remaining == 0 then
|
||||||
Bytes.Decode.succeed (Done string)
|
Bytes.Decode.succeed (Done string)
|
||||||
else if remaining == 2 then
|
else if remaining == 2 then
|
||||||
x, y <- Bytes.Decode.map2 Bytes.Decode.u8 Bytes.Decode.u8
|
Bytes.Decode.map2 Bytes.Decode.u8 Bytes.Decode.u8 \x, y ->
|
||||||
|
|
||||||
a : U32
|
a : U32
|
||||||
a = Num.intCast x
|
a = Num.intCast x
|
||||||
b : U32
|
b : U32
|
||||||
b = Num.intCast y
|
b = Num.intCast y
|
||||||
combined = Num.bitwiseOr (Num.shiftLeftBy a 16) (Num.shiftLeftBy b 8)
|
combined = Num.bitwiseOr (Num.shiftLeftBy a 16) (Num.shiftLeftBy b 8)
|
||||||
|
|
||||||
Done (Str.concat string (bitsToChars combined 1))
|
Done (Str.concat string (bitsToChars combined 1))
|
||||||
else
|
else
|
||||||
# remaining = 1
|
# remaining = 1
|
||||||
x <- Bytes.Decode.map Bytes.Decode.u8
|
Bytes.Decode.map Bytes.Decode.u8 \x ->
|
||||||
|
|
||||||
a : U32
|
a : U32
|
||||||
a = Num.intCast x
|
a = Num.intCast x
|
||||||
|
|
||||||
Done (Str.concat string (bitsToChars (Num.shiftLeftBy a 16) 2))
|
Done (Str.concat string (bitsToChars (Num.shiftLeftBy a 16) 2))
|
||||||
|
|
||||||
bitsToChars : U32, Int * -> Str
|
bitsToChars : U32, Int * -> Str
|
||||||
bitsToChars = \bits, missing ->
|
bitsToChars = \bits, missing ->
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
interface Base64.Encode
|
module [toBytes]
|
||||||
exposes [toBytes]
|
|
||||||
imports []
|
|
||||||
|
|
||||||
|
|
||||||
import Bytes.Encode exposing [ByteEncoder]
|
import Bytes.Encode exposing [ByteEncoder]
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
interface Bytes.Decode exposes [ByteDecoder, decode, map, map2, u8, loop, Step, succeed, DecodeProblem, after, map3] imports []
|
module [ByteDecoder, decode, map, map2, u8, loop, Step, succeed, DecodeProblem, after, map3]
|
||||||
|
|
||||||
State : { bytes : List U8, cursor : U64 }
|
State : { bytes : List U8, cursor : U64 }
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
interface Bytes.Encode exposes [ByteEncoder, sequence, u8, u16, bytes, empty, encode] imports []
|
module [ByteEncoder, sequence, u8, u16, bytes, empty, encode]
|
||||||
|
|
||||||
Endianness : [BE, LE]
|
Endianness : [BE, LE]
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
interface Issue2279Help
|
module [text, asText]
|
||||||
exposes [text, asText]
|
|
||||||
imports []
|
|
||||||
|
|
||||||
text = "Hello, world!"
|
text = "Hello, world!"
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
interface Quicksort exposes [sortBy, sortWith, show] imports []
|
module [sortBy, sortWith, show]
|
||||||
|
|
||||||
show : List I64 -> Str
|
show : List I64 -> Str
|
||||||
show = \list ->
|
show = \list ->
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
app "cfold"
|
app [main] { pf: platform "platform/main.roc" }
|
||||||
packages { pf: "platform/main.roc" }
|
|
||||||
imports [pf.Task]
|
import pf.PlatformTasks
|
||||||
provides [main] to pf
|
|
||||||
|
|
||||||
# adapted from https://github.com/koka-lang/koka/blob/master/test/bench/haskell/cfold.hs
|
# adapted from https://github.com/koka-lang/koka/blob/master/test/bench/haskell/cfold.hs
|
||||||
main : Task.Task {} []
|
main : Task {} []
|
||||||
main =
|
main =
|
||||||
inputResult <- Task.attempt Task.getInt
|
{ value, isError } = PlatformTasks.getInt!
|
||||||
|
inputResult =
|
||||||
|
if isError then
|
||||||
|
Err GetIntError
|
||||||
|
else
|
||||||
|
Ok value
|
||||||
|
|
||||||
when inputResult is
|
when inputResult is
|
||||||
Ok n ->
|
Ok n ->
|
||||||
|
@ -18,10 +22,10 @@ main =
|
||||||
|> Num.toStr
|
|> Num.toStr
|
||||||
|> Str.concat " & "
|
|> Str.concat " & "
|
||||||
|> Str.concat (Num.toStr optimized)
|
|> Str.concat (Num.toStr optimized)
|
||||||
|> Task.putLine
|
|> PlatformTasks.putLine
|
||||||
|
|
||||||
Err GetIntError ->
|
Err GetIntError ->
|
||||||
Task.putLine "Error: Failed to get Integer from stdin."
|
PlatformTasks.putLine "Error: Failed to get Integer from stdin."
|
||||||
|
|
||||||
Expr : [
|
Expr : [
|
||||||
Add Expr Expr,
|
Add Expr Expr,
|
||||||
|
|
|
@ -1,18 +1,15 @@
|
||||||
app "closure"
|
app [main] { pf: platform "platform/main.roc" }
|
||||||
packages { pf: "platform/main.roc" }
|
|
||||||
imports [pf.Task]
|
|
||||||
provides [main] to pf
|
|
||||||
|
|
||||||
# see https://github.com/roc-lang/roc/issues/985
|
# see https://github.com/roc-lang/roc/issues/985
|
||||||
main : Task.Task {} []
|
main : Task {} []
|
||||||
main = closure1 {}
|
main = closure1 {}
|
||||||
# |> Task.after (\_ -> closure2 {})
|
# |> Task.after (\_ -> closure2 {})
|
||||||
# |> Task.after (\_ -> closure3 {})
|
# |> Task.after (\_ -> closure3 {})
|
||||||
# |> Task.after (\_ -> closure4 {})
|
# |> Task.after (\_ -> closure4 {})
|
||||||
# ---
|
# ---
|
||||||
closure1 : {} -> Task.Task {} []
|
closure1 : {} -> Task {} []
|
||||||
closure1 = \_ ->
|
closure1 = \_ ->
|
||||||
Task.succeed (foo toUnitBorrowed "a long string such that it's malloced")
|
Task.ok (foo toUnitBorrowed "a long string such that it's malloced")
|
||||||
|> Task.map \_ -> {}
|
|> Task.map \_ -> {}
|
||||||
|
|
||||||
toUnitBorrowed = \x -> Str.countUtf8Bytes x
|
toUnitBorrowed = \x -> Str.countUtf8Bytes x
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
app "deriv"
|
app [main] { pf: platform "platform/main.roc" }
|
||||||
packages { pf: "platform/main.roc" }
|
|
||||||
imports [pf.Task]
|
import pf.PlatformTasks
|
||||||
provides [main] to pf
|
|
||||||
|
|
||||||
# based on: https://github.com/koka-lang/koka/blob/master/test/bench/haskell/deriv.hs
|
# based on: https://github.com/koka-lang/koka/blob/master/test/bench/haskell/deriv.hs
|
||||||
IO a : Task.Task a []
|
IO a : Task a []
|
||||||
|
|
||||||
main : Task.Task {} []
|
main : Task {} []
|
||||||
main =
|
main =
|
||||||
inputResult <- Task.attempt Task.getInt
|
{ value, isError } = PlatformTasks.getInt!
|
||||||
|
inputResult =
|
||||||
|
if isError then
|
||||||
|
Err GetIntError
|
||||||
|
else
|
||||||
|
Ok value
|
||||||
|
|
||||||
when inputResult is
|
when inputResult is
|
||||||
Ok n ->
|
Ok n ->
|
||||||
|
@ -22,14 +26,15 @@ main =
|
||||||
|> Task.map \_ -> {}
|
|> Task.map \_ -> {}
|
||||||
|
|
||||||
Err GetIntError ->
|
Err GetIntError ->
|
||||||
Task.putLine "Error: Failed to get Integer from stdin."
|
PlatformTasks.putLine "Error: Failed to get Integer from stdin."
|
||||||
|
|
||||||
nestHelp : I64, (I64, Expr -> IO Expr), I64, Expr -> IO Expr
|
nestHelp : I64, (I64, Expr -> IO Expr), I64, Expr -> IO Expr
|
||||||
nestHelp = \s, f, m, x -> when m is
|
nestHelp = \s, f, m, x ->
|
||||||
0 -> Task.succeed x
|
when m is
|
||||||
_ ->
|
0 -> Task.ok x
|
||||||
w <- Task.after (f (s - m) x)
|
_ ->
|
||||||
nestHelp s f (m - 1) w
|
w = f! (s - m) x
|
||||||
|
nestHelp s f (m - 1) w
|
||||||
|
|
||||||
nest : (I64, Expr -> IO Expr), I64, Expr -> IO Expr
|
nest : (I64, Expr -> IO Expr), I64, Expr -> IO Expr
|
||||||
nest = \f, n, e -> nestHelp n f n e
|
nest = \f, n, e -> nestHelp n f n e
|
||||||
|
@ -162,6 +167,5 @@ deriv = \i, f ->
|
||||||
Num.toStr (i + 1)
|
Num.toStr (i + 1)
|
||||||
|> Str.concat " count: "
|
|> Str.concat " count: "
|
||||||
|> Str.concat (Num.toStr (count fprime))
|
|> Str.concat (Num.toStr (count fprime))
|
||||||
|
PlatformTasks.putLine! line
|
||||||
Task.putLine line
|
Task.ok fprime
|
||||||
|> Task.after \_ -> Task.succeed fprime
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
app "issue2279"
|
app [main] { pf: platform "platform/main.roc" }
|
||||||
packages { pf: "platform/main.roc" }
|
|
||||||
imports [Issue2279Help, pf.Task]
|
import Issue2279Help
|
||||||
provides [main] to pf
|
import pf.PlatformTasks
|
||||||
|
|
||||||
main =
|
main =
|
||||||
text =
|
text =
|
||||||
|
@ -10,4 +10,4 @@ main =
|
||||||
else
|
else
|
||||||
Issue2279Help.asText 42
|
Issue2279Help.asText 42
|
||||||
|
|
||||||
Task.putLine text
|
PlatformTasks.putLine text
|
||||||
|
|
|
@ -1,20 +1,24 @@
|
||||||
app "nqueens"
|
app [main] { pf: platform "platform/main.roc" }
|
||||||
packages { pf: "platform/main.roc" }
|
|
||||||
imports [pf.Task]
|
|
||||||
provides [main] to pf
|
|
||||||
|
|
||||||
main : Task.Task {} []
|
import pf.PlatformTasks
|
||||||
|
|
||||||
|
main : Task {} []
|
||||||
main =
|
main =
|
||||||
inputResult <- Task.attempt Task.getInt
|
{ value, isError } = PlatformTasks.getInt!
|
||||||
|
inputResult =
|
||||||
|
if isError then
|
||||||
|
Err GetIntError
|
||||||
|
else
|
||||||
|
Ok value
|
||||||
|
|
||||||
when inputResult is
|
when inputResult is
|
||||||
Ok n ->
|
Ok n ->
|
||||||
queens n # original koka 13
|
queens n # original koka 13
|
||||||
|> Num.toStr
|
|> Num.toStr
|
||||||
|> Task.putLine
|
|> PlatformTasks.putLine
|
||||||
|
|
||||||
Err GetIntError ->
|
Err GetIntError ->
|
||||||
Task.putLine "Error: Failed to get Integer from stdin."
|
PlatformTasks.putLine "Error: Failed to get Integer from stdin."
|
||||||
|
|
||||||
ConsList a : [Nil, Cons a (ConsList a)]
|
ConsList a : [Nil, Cons a (ConsList a)]
|
||||||
|
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
hosted Effect
|
|
||||||
exposes [Effect, after, map, always, forever, loop, putLine, putInt, getInt]
|
|
||||||
imports []
|
|
||||||
generates Effect with [after, map, always, forever, loop]
|
|
||||||
|
|
||||||
putLine : Str -> Effect {}
|
|
||||||
|
|
||||||
putInt : I64 -> Effect {}
|
|
||||||
|
|
||||||
getInt : Effect { value : I64, isError : Bool }
|
|
9
crates/cli/tests/benchmarks/platform/PlatformTasks.roc
Normal file
9
crates/cli/tests/benchmarks/platform/PlatformTasks.roc
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
hosted PlatformTasks
|
||||||
|
exposes [putLine, putInt, getInt]
|
||||||
|
imports []
|
||||||
|
|
||||||
|
putLine : Str -> Task {} *
|
||||||
|
|
||||||
|
putInt : I64 -> Task {} *
|
||||||
|
|
||||||
|
getInt : Task { value : I64, isError : Bool } *
|
|
@ -1,88 +0,0 @@
|
||||||
interface Task
|
|
||||||
exposes [Task, succeed, fail, after, map, putLine, putInt, getInt, forever, loop, attempt]
|
|
||||||
imports [pf.Effect]
|
|
||||||
|
|
||||||
Task ok err : Effect.Effect (Result ok err)
|
|
||||||
|
|
||||||
forever : Task val err -> Task * err
|
|
||||||
forever = \task ->
|
|
||||||
looper = \{} ->
|
|
||||||
task
|
|
||||||
|> Effect.map
|
|
||||||
\res ->
|
|
||||||
when res is
|
|
||||||
Ok _ -> Step {}
|
|
||||||
Err e -> Done (Err e)
|
|
||||||
|
|
||||||
Effect.loop {} looper
|
|
||||||
|
|
||||||
loop : state, (state -> Task [Step state, Done done] err) -> Task done err
|
|
||||||
loop = \state, step ->
|
|
||||||
looper = \current ->
|
|
||||||
step current
|
|
||||||
|> Effect.map
|
|
||||||
\res ->
|
|
||||||
when res is
|
|
||||||
Ok (Step newState) -> Step newState
|
|
||||||
Ok (Done result) -> Done (Ok result)
|
|
||||||
Err e -> Done (Err e)
|
|
||||||
|
|
||||||
Effect.loop state looper
|
|
||||||
|
|
||||||
succeed : val -> Task val *
|
|
||||||
succeed = \val ->
|
|
||||||
Effect.always (Ok val)
|
|
||||||
|
|
||||||
fail : err -> Task * err
|
|
||||||
fail = \val ->
|
|
||||||
Effect.always (Err val)
|
|
||||||
|
|
||||||
after : Task a err, (a -> Task b err) -> Task b err
|
|
||||||
after = \effect, transform ->
|
|
||||||
Effect.after
|
|
||||||
effect
|
|
||||||
\result ->
|
|
||||||
when result is
|
|
||||||
Ok a -> transform a
|
|
||||||
Err err -> Task.fail err
|
|
||||||
|
|
||||||
attempt : Task a b, (Result a b -> Task c d) -> Task c d
|
|
||||||
attempt = \task, transform ->
|
|
||||||
Effect.after
|
|
||||||
task
|
|
||||||
\result ->
|
|
||||||
when result is
|
|
||||||
Ok ok -> transform (Ok ok)
|
|
||||||
Err err -> transform (Err err)
|
|
||||||
|
|
||||||
map : Task a err, (a -> b) -> Task b err
|
|
||||||
map = \effect, transform ->
|
|
||||||
Effect.map
|
|
||||||
effect
|
|
||||||
\result ->
|
|
||||||
when result is
|
|
||||||
Ok a -> Ok (transform a)
|
|
||||||
Err err -> Err err
|
|
||||||
|
|
||||||
putLine : Str -> Task {} *
|
|
||||||
putLine = \line -> Effect.map (Effect.putLine line) (\_ -> Ok {})
|
|
||||||
|
|
||||||
putInt : I64 -> Task {} *
|
|
||||||
putInt = \line -> Effect.map (Effect.putInt line) (\_ -> Ok {})
|
|
||||||
|
|
||||||
getInt : Task I64 [GetIntError]
|
|
||||||
getInt =
|
|
||||||
Effect.after
|
|
||||||
Effect.getInt
|
|
||||||
\{ isError, value } ->
|
|
||||||
if
|
|
||||||
isError
|
|
||||||
then
|
|
||||||
# TODO
|
|
||||||
# when errorCode is
|
|
||||||
# # A -> Task.fail InvalidCharacter
|
|
||||||
# # B -> Task.fail IOError
|
|
||||||
# _ ->
|
|
||||||
Task.fail GetIntError
|
|
||||||
else
|
|
||||||
Task.succeed value
|
|
|
@ -2,7 +2,7 @@ platform "benchmarks"
|
||||||
requires {} { main : Task {} [] }
|
requires {} { main : Task {} [] }
|
||||||
exposes []
|
exposes []
|
||||||
packages {}
|
packages {}
|
||||||
imports [Task.{ Task }]
|
imports []
|
||||||
provides [mainForHost]
|
provides [mainForHost]
|
||||||
|
|
||||||
mainForHost : Task {} []
|
mainForHost : Task {} []
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
app "quicksortapp"
|
app [main] { pf: platform "platform/main.roc" }
|
||||||
packages { pf: "platform/main.roc" }
|
|
||||||
imports [pf.Task, Quicksort]
|
import pf.PlatformTasks
|
||||||
provides [main] to pf
|
import Quicksort
|
||||||
|
|
||||||
main : Task.Task {} []
|
main : Task.Task {} []
|
||||||
main =
|
main =
|
||||||
inputResult <- Task.attempt Task.getInt
|
{ value, isError } = PlatformTasks.getInt!
|
||||||
|
inputResult =
|
||||||
|
if isError then
|
||||||
|
Err GetIntError
|
||||||
|
else
|
||||||
|
Ok value
|
||||||
|
|
||||||
when inputResult is
|
when inputResult is
|
||||||
Ok n ->
|
Ok n ->
|
||||||
|
@ -19,10 +24,10 @@ main =
|
||||||
|
|
||||||
sort unsortedList
|
sort unsortedList
|
||||||
|> Quicksort.show
|
|> Quicksort.show
|
||||||
|> Task.putLine
|
|> PlatformTasks.putLine
|
||||||
|
|
||||||
Err GetIntError ->
|
Err GetIntError ->
|
||||||
Task.putLine "Error: Failed to get Integer from stdin."
|
PlatformTasks.putLine "Error: Failed to get Integer from stdin."
|
||||||
|
|
||||||
sort : List I64 -> List I64
|
sort : List I64 -> List I64
|
||||||
sort = \list ->
|
sort = \list ->
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
app "rbtree-ck"
|
app [main] { pf: platform "platform/main.roc" }
|
||||||
packages { pf: "platform/main.roc" }
|
|
||||||
imports [pf.Task]
|
import pf.PlatformTasks
|
||||||
provides [main] to pf
|
|
||||||
|
|
||||||
Color : [Red, Black]
|
Color : [Red, Black]
|
||||||
|
|
||||||
|
@ -38,9 +37,14 @@ fold = \f, tree, b ->
|
||||||
Leaf -> b
|
Leaf -> b
|
||||||
Node _ l k v r -> fold f r (f k v (fold f l b))
|
Node _ l k v r -> fold f r (f k v (fold f l b))
|
||||||
|
|
||||||
main : Task.Task {} []
|
main : Task {} []
|
||||||
main =
|
main =
|
||||||
inputResult <- Task.attempt Task.getInt
|
{ value, isError } = PlatformTasks.getInt!
|
||||||
|
inputResult =
|
||||||
|
if isError then
|
||||||
|
Err GetIntError
|
||||||
|
else
|
||||||
|
Ok value
|
||||||
|
|
||||||
when inputResult is
|
when inputResult is
|
||||||
Ok n ->
|
Ok n ->
|
||||||
|
@ -54,13 +58,13 @@ main =
|
||||||
|
|
||||||
val
|
val
|
||||||
|> Num.toStr
|
|> Num.toStr
|
||||||
|> Task.putLine
|
|> PlatformTasks.putLine
|
||||||
|
|
||||||
Nil ->
|
Nil ->
|
||||||
Task.putLine "fail"
|
PlatformTasks.putLine "fail"
|
||||||
|
|
||||||
Err GetIntError ->
|
Err GetIntError ->
|
||||||
Task.putLine "Error: Failed to get Integer from stdin."
|
PlatformTasks.putLine "Error: Failed to get Integer from stdin."
|
||||||
|
|
||||||
insert : Tree (Num k) v, Num k, v -> Tree (Num k) v
|
insert : Tree (Num k) v, Num k, v -> Tree (Num k) v
|
||||||
insert = \t, k, v -> if isRed t then setBlack (ins t k v) else ins t k v
|
insert = \t, k, v -> if isRed t then setBlack (ins t k v) else ins t k v
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
app "rbtree-del"
|
app [main] { pf: platform "platform/main.roc" }
|
||||||
packages { pf: "platform/main.roc" }
|
|
||||||
imports [pf.Task]
|
import pf.PlatformTasks
|
||||||
provides [main] to pf
|
|
||||||
|
|
||||||
Color : [Red, Black]
|
Color : [Red, Black]
|
||||||
|
|
||||||
|
@ -11,9 +10,14 @@ Map : Tree I64 Bool
|
||||||
|
|
||||||
ConsList a : [Nil, Cons a (ConsList a)]
|
ConsList a : [Nil, Cons a (ConsList a)]
|
||||||
|
|
||||||
main : Task.Task {} []
|
main : Task {} []
|
||||||
main =
|
main =
|
||||||
inputResult <- Task.attempt Task.getInt
|
{ value, isError } = PlatformTasks.getInt!
|
||||||
|
inputResult =
|
||||||
|
if isError then
|
||||||
|
Err GetIntError
|
||||||
|
else
|
||||||
|
Ok value
|
||||||
|
|
||||||
when inputResult is
|
when inputResult is
|
||||||
Ok n ->
|
Ok n ->
|
||||||
|
@ -22,10 +26,10 @@ main =
|
||||||
|
|
||||||
val
|
val
|
||||||
|> Num.toStr
|
|> Num.toStr
|
||||||
|> Task.putLine
|
|> PlatformTasks.putLine
|
||||||
|
|
||||||
Err GetIntError ->
|
Err GetIntError ->
|
||||||
Task.putLine "Error: Failed to get Integer from stdin."
|
PlatformTasks.putLine "Error: Failed to get Integer from stdin."
|
||||||
|
|
||||||
boom : Str -> a
|
boom : Str -> a
|
||||||
boom = \_ -> boom ""
|
boom = \_ -> boom ""
|
||||||
|
@ -248,4 +252,4 @@ del = \t, k ->
|
||||||
rebalanceLeft cx lx ky vy ry
|
rebalanceLeft cx lx ky vy ry
|
||||||
|
|
||||||
Delmin (Del ry Bool.false) ky vy ->
|
Delmin (Del ry Bool.false) ky vy ->
|
||||||
Del (Node cx lx ky vy ry) Bool.false
|
Del (Node cx lx ky vy ry) Bool.false
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
app "rbtree-insert"
|
app [main] { pf: platform "platform/main.roc" }
|
||||||
packages { pf: "platform/main.roc" }
|
|
||||||
imports [pf.Task]
|
|
||||||
provides [main] to pf
|
|
||||||
|
|
||||||
main : Task.Task {} []
|
import pf.PlatformTasks
|
||||||
|
|
||||||
|
main : Task {} []
|
||||||
main =
|
main =
|
||||||
tree : RedBlackTree I64 {}
|
tree : RedBlackTree I64 {}
|
||||||
tree = insert 0 {} Empty
|
tree = insert 0 {} Empty
|
||||||
|
|
||||||
tree
|
tree
|
||||||
|> show
|
|> show
|
||||||
|> Task.putLine
|
|> PlatformTasks.putLine
|
||||||
|
|
||||||
show : RedBlackTree I64 {} -> Str
|
show : RedBlackTree I64 {} -> Str
|
||||||
show = \tree -> showRBTree tree Num.toStr (\{} -> "{}")
|
show = \tree -> showRBTree tree Num.toStr (\{} -> "{}")
|
||||||
|
|
|
@ -1,20 +1,12 @@
|
||||||
app "test-astar"
|
app [main] { pf: platform "platform/main.roc" }
|
||||||
packages { pf: "platform/main.roc" }
|
|
||||||
imports [pf.Task, AStar]
|
|
||||||
provides [main] to pf
|
|
||||||
|
|
||||||
main : Task.Task {} []
|
import pf.PlatformTasks
|
||||||
|
import AStar
|
||||||
|
|
||||||
|
#main : Task {} *
|
||||||
main =
|
main =
|
||||||
Task.putLine (showBool test1)
|
PlatformTasks.putLine! (showBool test1)
|
||||||
|
|
||||||
# Task.after Task.getInt \n ->
|
|
||||||
# when n is
|
|
||||||
# 1 ->
|
|
||||||
# Task.putLine (showBool test1)
|
|
||||||
#
|
|
||||||
# _ ->
|
|
||||||
# ns = Num.toStr n
|
|
||||||
# Task.putLine "No test $(ns)"
|
|
||||||
showBool : Bool -> Str
|
showBool : Bool -> Str
|
||||||
showBool = \b ->
|
showBool = \b ->
|
||||||
if
|
if
|
||||||
|
|
|
@ -1,18 +1,17 @@
|
||||||
app "test-base64"
|
app [main] { pf: platform "platform/main.roc" }
|
||||||
packages { pf: "platform/main.roc" }
|
|
||||||
imports [pf.Task, Base64]
|
|
||||||
provides [main] to pf
|
|
||||||
|
|
||||||
IO a : Task.Task a []
|
import Base64
|
||||||
|
import pf.PlatformTasks
|
||||||
|
|
||||||
|
IO a : Task a []
|
||||||
|
|
||||||
main : IO {}
|
main : IO {}
|
||||||
main =
|
main =
|
||||||
when Base64.fromBytes (Str.toUtf8 "Hello World") is
|
when Base64.fromBytes (Str.toUtf8 "Hello World") is
|
||||||
Err _ -> Task.putLine "sadness"
|
Err _ -> PlatformTasks.putLine "sadness"
|
||||||
Ok encoded ->
|
Ok encoded ->
|
||||||
Task.after
|
PlatformTasks.putLine! (Str.concat "encoded: " encoded)
|
||||||
(Task.putLine (Str.concat "encoded: " encoded))
|
|
||||||
\_ ->
|
when Base64.toStr encoded is
|
||||||
when Base64.toStr encoded is
|
Ok decoded -> PlatformTasks.putLine (Str.concat "decoded: " decoded)
|
||||||
Ok decoded -> Task.putLine (Str.concat "decoded: " decoded)
|
Err _ -> PlatformTasks.putLine "sadness"
|
||||||
Err _ -> Task.putLine "sadness"
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.12.0/Lb8EgiejTUzbggO2HVVuPJFkwvvsfW6LojkLR20kTVE.tar.br" }
|
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.15.0/SlwdbJ-3GR7uBWQo6zlmYWNYOxnvo8r6YABXD-45UOw.tar.br" }
|
||||||
|
|
||||||
import pf.Stdout
|
import pf.Stdout
|
||||||
import pf.Task exposing [Task]
|
|
||||||
|
|
||||||
main =
|
main =
|
||||||
multipleIn =
|
multipleIn =
|
||||||
|
|
|
@ -1,19 +1,18 @@
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.12.0/Lb8EgiejTUzbggO2HVVuPJFkwvvsfW6LojkLR20kTVE.tar.br" }
|
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.15.0/SlwdbJ-3GR7uBWQo6zlmYWNYOxnvo8r6YABXD-45UOw.tar.br" }
|
||||||
|
|
||||||
import pf.Stdin
|
import pf.Stdin
|
||||||
import pf.Stdout
|
import pf.Stdout
|
||||||
import pf.Task exposing [await, loop]
|
|
||||||
|
|
||||||
main =
|
main =
|
||||||
_ <- await (Stdout.line "\nLet's count down from 3 together - all you have to do is press <ENTER>.")
|
Stdout.line! "\nLet's count down from 3 together - all you have to do is press <ENTER>."
|
||||||
_ <- await Stdin.line
|
_ = Stdin.line!
|
||||||
loop 3 tick
|
Task.loop 3 tick
|
||||||
|
|
||||||
tick = \n ->
|
tick = \n ->
|
||||||
if n == 0 then
|
if n == 0 then
|
||||||
_ <- await (Stdout.line "🎉 SURPRISE! Happy Birthday! 🎂")
|
Stdout.line! "🎉 SURPRISE! Happy Birthday! 🎂"
|
||||||
Task.ok (Done {})
|
Task.ok (Done {})
|
||||||
else
|
else
|
||||||
_ <- await (n |> Num.toStr |> \s -> "$(s)..." |> Stdout.line)
|
Stdout.line! (n |> Num.toStr |> \s -> "$(s)...")
|
||||||
_ <- await Stdin.line
|
_ = Stdin.line!
|
||||||
Task.ok (Step (n - 1))
|
Task.ok (Step (n - 1))
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.12.0/Lb8EgiejTUzbggO2HVVuPJFkwvvsfW6LojkLR20kTVE.tar.br" }
|
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.15.0/SlwdbJ-3GR7uBWQo6zlmYWNYOxnvo8r6YABXD-45UOw.tar.br" }
|
||||||
|
|
||||||
import pf.Stdin
|
import pf.Stdin
|
||||||
import pf.Stdout
|
import pf.Stdout
|
||||||
import pf.Task exposing [Task]
|
|
||||||
|
|
||||||
main =
|
main =
|
||||||
_ <- Task.await (Stdout.line "🗣 Shout into this cave and hear the echo! 👂👂👂")
|
Stdout.line! "🗣 Shout into this cave and hear the echo! 👂👂👂"
|
||||||
|
|
||||||
Task.loop {} tick
|
Task.loop {} tick
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.12.0/Lb8EgiejTUzbggO2HVVuPJFkwvvsfW6LojkLR20kTVE.tar.br" }
|
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.15.0/SlwdbJ-3GR7uBWQo6zlmYWNYOxnvo8r6YABXD-45UOw.tar.br" }
|
||||||
|
|
||||||
import pf.Stdout
|
import pf.Stdout
|
||||||
import pf.Stderr
|
import pf.Stderr
|
||||||
import pf.Env
|
import pf.Env
|
||||||
import pf.Task exposing [Task]
|
|
||||||
|
|
||||||
main =
|
main =
|
||||||
task =
|
task =
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.12.0/Lb8EgiejTUzbggO2HVVuPJFkwvvsfW6LojkLR20kTVE.tar.br" }
|
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.15.0/SlwdbJ-3GR7uBWQo6zlmYWNYOxnvo8r6YABXD-45UOw.tar.br" }
|
||||||
|
|
||||||
import pf.Stdout
|
import pf.Stdout
|
||||||
import pf.Task exposing [Task]
|
|
||||||
import pf.File
|
import pf.File
|
||||||
import pf.Path
|
import pf.Path
|
||||||
import pf.Env
|
import pf.Env
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.12.0/Lb8EgiejTUzbggO2HVVuPJFkwvvsfW6LojkLR20kTVE.tar.br" }
|
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.15.0/SlwdbJ-3GR7uBWQo6zlmYWNYOxnvo8r6YABXD-45UOw.tar.br" }
|
||||||
|
|
||||||
import pf.Stdin
|
import pf.Stdin
|
||||||
import pf.Stdout
|
import pf.Stdout
|
||||||
import pf.Task exposing [await, Task]
|
|
||||||
|
|
||||||
main =
|
main =
|
||||||
Stdout.line! "What's your first name?"
|
Stdout.line! "What's your first name?"
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.12.0/Lb8EgiejTUzbggO2HVVuPJFkwvvsfW6LojkLR20kTVE.tar.br" }
|
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.15.0/SlwdbJ-3GR7uBWQo6zlmYWNYOxnvo8r6YABXD-45UOw.tar.br" }
|
||||||
|
|
||||||
import pf.Http
|
import pf.Http
|
||||||
import pf.Task exposing [Task]
|
|
||||||
import pf.Stdout
|
import pf.Stdout
|
||||||
|
|
||||||
main =
|
main =
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.12.0/Lb8EgiejTUzbggO2HVVuPJFkwvvsfW6LojkLR20kTVE.tar.br" }
|
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.15.0/SlwdbJ-3GR7uBWQo6zlmYWNYOxnvo8r6YABXD-45UOw.tar.br" }
|
||||||
|
|
||||||
import pf.Stdout
|
import pf.Stdout
|
||||||
import "test-file.txt" as testFile
|
import "test-file.txt" as testFile
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.12.0/Lb8EgiejTUzbggO2HVVuPJFkwvvsfW6LojkLR20kTVE.tar.br" }
|
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.15.0/SlwdbJ-3GR7uBWQo6zlmYWNYOxnvo8r6YABXD-45UOw.tar.br" }
|
||||||
|
|
||||||
import pf.Stdout
|
import pf.Stdout
|
||||||
import "test-file.txt" as testFile : _ # the _ is optional
|
import "test-file.txt" as testFile : _ # the _ is optional
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.12.0/Lb8EgiejTUzbggO2HVVuPJFkwvvsfW6LojkLR20kTVE.tar.br" }
|
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.15.0/SlwdbJ-3GR7uBWQo6zlmYWNYOxnvo8r6YABXD-45UOw.tar.br" }
|
||||||
|
|
||||||
import pf.Stdout
|
import pf.Stdout
|
||||||
import "ingested-file.roc" as ownCode : Str
|
import "ingested-file.roc" as ownCode : Str
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
app [main] {
|
app [main] {
|
||||||
pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.12.0/Lb8EgiejTUzbggO2HVVuPJFkwvvsfW6LojkLR20kTVE.tar.br",
|
pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.15.0/SlwdbJ-3GR7uBWQo6zlmYWNYOxnvo8r6YABXD-45UOw.tar.br",
|
||||||
}
|
}
|
||||||
|
|
||||||
import pf.Stdout
|
import pf.Stdout
|
||||||
import pf.Task exposing [Task]
|
|
||||||
|
|
||||||
main =
|
main =
|
||||||
file = strParam { name: "file" }
|
file = strParam { name: "file" }
|
||||||
|
@ -12,7 +11,7 @@ main =
|
||||||
file,
|
file,
|
||||||
count: numParam { name: "count" },
|
count: numParam { name: "count" },
|
||||||
doubled: numParam { name: "doubled" }
|
doubled: numParam { name: "doubled" }
|
||||||
|> cliMap \d -> d * 2,
|
|> cliMap \d -> d * 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
args = ["parse-args", "file.txt", "5", "7"]
|
args = ["parse-args", "file.txt", "5", "7"]
|
||||||
|
@ -55,23 +54,23 @@ numParam = \{ name } ->
|
||||||
{ params: [param], parser }
|
{ params: [param], parser }
|
||||||
|
|
||||||
cliMap : ArgParser a, (a -> b) -> ArgParser b
|
cliMap : ArgParser a, (a -> b) -> ArgParser b
|
||||||
cliMap = \{ params, parser }, mapper -> {
|
cliMap = \{ params, parser }, mapper ->
|
||||||
params,
|
mappedParser = \args ->
|
||||||
parser: \args ->
|
(data, afterData) = parser? args
|
||||||
(data, afterData) <- parser args
|
|
||||||
|> Result.try
|
|
||||||
|
|
||||||
Ok (mapper data, afterData),
|
Ok (mapper data, afterData)
|
||||||
}
|
|
||||||
|
{
|
||||||
|
params,
|
||||||
|
parser: mappedParser,
|
||||||
|
}
|
||||||
|
|
||||||
cliBuild : ArgParser a, ArgParser b, (a, b -> c) -> ArgParser c
|
cliBuild : ArgParser a, ArgParser b, (a, b -> c) -> ArgParser c
|
||||||
cliBuild = \firstWeaver, secondWeaver, combine ->
|
cliBuild = \firstWeaver, secondWeaver, combine ->
|
||||||
allParams = List.concat firstWeaver.params secondWeaver.params
|
allParams = List.concat firstWeaver.params secondWeaver.params
|
||||||
combinedParser = \args ->
|
combinedParser = \args ->
|
||||||
(firstValue, afterFirst) <- firstWeaver.parser args
|
(firstValue, afterFirst) = firstWeaver.parser? args
|
||||||
|> Result.try
|
(secondValue, afterSecond) = secondWeaver.parser? afterFirst
|
||||||
(secondValue, afterSecond) <- secondWeaver.parser afterFirst
|
|
||||||
|> Result.try
|
|
||||||
|
|
||||||
Ok (combine firstValue secondValue, afterSecond)
|
Ok (combine firstValue secondValue, afterSecond)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
app [main] {
|
app [main] {
|
||||||
cli: platform "https://github.com/roc-lang/basic-cli/releases/download/0.12.0/Lb8EgiejTUzbggO2HVVuPJFkwvvsfW6LojkLR20kTVE.tar.br",
|
cli: platform "https://github.com/roc-lang/basic-cli/releases/download/0.15.0/SlwdbJ-3GR7uBWQo6zlmYWNYOxnvo8r6YABXD-45UOw.tar.br",
|
||||||
parser: "https://github.com/lukewilliamboswell/roc-parser/releases/download/0.5.2/9VrPjwfQQ1QeSL3CfmWr2Pr9DESdDIXy97pwpuq84Ck.tar.br",
|
parser: "https://github.com/lukewilliamboswell/roc-parser/releases/download/0.5.2/9VrPjwfQQ1QeSL3CfmWr2Pr9DESdDIXy97pwpuq84Ck.tar.br",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,18 +26,17 @@ Letter : [A, B, C, Other]
|
||||||
|
|
||||||
letterParser : Parser (List U8) Letter
|
letterParser : Parser (List U8) Letter
|
||||||
letterParser =
|
letterParser =
|
||||||
input <- buildPrimitiveParser
|
buildPrimitiveParser \input ->
|
||||||
|
valResult =
|
||||||
|
when input is
|
||||||
|
[] -> Err (ParsingFailure "Nothing to parse")
|
||||||
|
['A', ..] -> Ok A
|
||||||
|
['B', ..] -> Ok B
|
||||||
|
['C', ..] -> Ok C
|
||||||
|
_ -> Ok Other
|
||||||
|
|
||||||
valResult =
|
valResult
|
||||||
when input is
|
|> Result.map \val -> { val, input: List.dropFirst input 1 }
|
||||||
[] -> Err (ParsingFailure "Nothing to parse")
|
|
||||||
['A', ..] -> Ok A
|
|
||||||
['B', ..] -> Ok B
|
|
||||||
['C', ..] -> Ok C
|
|
||||||
_ -> Ok Other
|
|
||||||
|
|
||||||
valResult
|
|
||||||
|> Result.map \val -> { val, input: List.dropFirst input 1 }
|
|
||||||
|
|
||||||
expect
|
expect
|
||||||
input = "B"
|
input = "B"
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
app [main] {
|
app [main] {
|
||||||
pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.12.0/Lb8EgiejTUzbggO2HVVuPJFkwvvsfW6LojkLR20kTVE.tar.br",
|
pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.15.0/SlwdbJ-3GR7uBWQo6zlmYWNYOxnvo8r6YABXD-45UOw.tar.br",
|
||||||
parser: "https://github.com/lukewilliamboswell/roc-parser/releases/download/0.5.2/9VrPjwfQQ1QeSL3CfmWr2Pr9DESdDIXy97pwpuq84Ck.tar.br",
|
parser: "https://github.com/lukewilliamboswell/roc-parser/releases/download/0.5.2/9VrPjwfQQ1QeSL3CfmWr2Pr9DESdDIXy97pwpuq84Ck.tar.br",
|
||||||
}
|
}
|
||||||
|
|
||||||
import pf.Stdout
|
import pf.Stdout
|
||||||
import pf.Stderr
|
import pf.Stderr
|
||||||
import pf.Task exposing [Task]
|
|
||||||
import parser.Core exposing [map, keep]
|
import parser.Core exposing [map, keep]
|
||||||
import parser.String exposing [strFromUtf8]
|
import parser.String exposing [strFromUtf8]
|
||||||
import parser.CSV
|
import parser.CSV
|
||||||
|
|
|
@ -10,8 +10,8 @@ extern crate roc_module;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod cli_run {
|
mod cli_run {
|
||||||
use cli_utils::helpers::{
|
use cli_utils::helpers::{
|
||||||
extract_valgrind_errors, file_path_from_root, fixture_file, fixtures_dir, has_error,
|
cli_testing_dir, extract_valgrind_errors, file_path_from_root, fixture_file, fixtures_dir,
|
||||||
known_bad_file, run_cmd, run_roc, run_with_valgrind, Out, ValgrindError,
|
has_error, known_bad_file, run_cmd, run_roc, run_with_valgrind, Out, ValgrindError,
|
||||||
ValgrindErrorXWhat,
|
ValgrindErrorXWhat,
|
||||||
};
|
};
|
||||||
use const_format::concatcp;
|
use const_format::concatcp;
|
||||||
|
@ -23,6 +23,7 @@ mod cli_run {
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::process::ExitStatus;
|
||||||
|
|
||||||
#[cfg(all(unix, not(target_os = "macos")))]
|
#[cfg(all(unix, not(target_os = "macos")))]
|
||||||
const ALLOW_VALGRIND: bool = true;
|
const ALLOW_VALGRIND: bool = true;
|
||||||
|
@ -85,11 +86,11 @@ mod cli_run {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_compile_error(file: &Path, flags: &[&str], expected: &str) {
|
fn check_compile_error(file: &Path, flags: &[&str], expected: &str) {
|
||||||
let compile_out = run_roc(
|
check_compile_error_with(CMD_CHECK, file, flags, expected);
|
||||||
[CMD_CHECK, file.to_str().unwrap()].iter().chain(flags),
|
}
|
||||||
&[],
|
|
||||||
&[],
|
fn check_compile_error_with(cmd: &str, file: &Path, flags: &[&str], expected: &str) {
|
||||||
);
|
let compile_out = run_roc([cmd, file.to_str().unwrap()].iter().chain(flags), &[], &[]);
|
||||||
let err = compile_out.stdout.trim();
|
let err = compile_out.stdout.trim();
|
||||||
let err = strip_colors(err);
|
let err = strip_colors(err);
|
||||||
|
|
||||||
|
@ -106,6 +107,11 @@ mod cli_run {
|
||||||
assert_multiline_str_eq!(err.as_str(), expected);
|
assert_multiline_str_eq!(err.as_str(), expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn assert_valid_roc_check_status(status: ExitStatus) {
|
||||||
|
// 0 means no errors or warnings, 2 means just warnings
|
||||||
|
assert!(status.code().is_some_and(|code| code == 0 || code == 2))
|
||||||
|
}
|
||||||
|
|
||||||
fn check_format_check_as_expected(file: &Path, expects_success_exit_code: bool) {
|
fn check_format_check_as_expected(file: &Path, expects_success_exit_code: bool) {
|
||||||
let out = run_roc([CMD_FORMAT, file.to_str().unwrap(), CHECK_FLAG], &[], &[]);
|
let out = run_roc([CMD_FORMAT, file.to_str().unwrap(), CHECK_FLAG], &[], &[]);
|
||||||
|
|
||||||
|
@ -722,6 +728,200 @@ mod cli_run {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg_attr(windows, ignore)]
|
||||||
|
fn module_params() {
|
||||||
|
test_roc_app(
|
||||||
|
"crates/cli/tests/module_params",
|
||||||
|
"app.roc",
|
||||||
|
&[],
|
||||||
|
&[],
|
||||||
|
&[],
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
App1.baseUrl: https://api.example.com/one
|
||||||
|
App2.baseUrl: http://api.example.com/two
|
||||||
|
App3.baseUrl: https://api.example.com/three
|
||||||
|
App1.getUser 1: https://api.example.com/one/users/1
|
||||||
|
App2.getUser 2: http://api.example.com/two/users/2
|
||||||
|
App3.getUser 3: https://api.example.com/three/users/3
|
||||||
|
App1.getPost 1: https://api.example.com/one/posts/1
|
||||||
|
App2.getPost 2: http://api.example.com/two/posts/2
|
||||||
|
App3.getPost 3: https://api.example.com/three/posts/3
|
||||||
|
App1.getPosts [1, 2]: ["https://api.example.com/one/posts/1", "https://api.example.com/one/posts/2"]
|
||||||
|
App2.getPosts [3, 4]: ["http://api.example.com/two/posts/3", "http://api.example.com/two/posts/4"]
|
||||||
|
App2.getPosts [5, 6]: ["http://api.example.com/two/posts/5", "http://api.example.com/two/posts/6"]
|
||||||
|
App1.getPostComments 1: https://api.example.com/one/posts/1/comments
|
||||||
|
App2.getPostComments 2: http://api.example.com/two/posts/2/comments
|
||||||
|
App2.getPostComments 3: http://api.example.com/two/posts/3/comments
|
||||||
|
App1.getCompanies [1, 2]: ["https://api.example.com/one/companies/1", "https://api.example.com/one/companies/2"]
|
||||||
|
App2.getCompanies [3, 4]: ["http://api.example.com/two/companies/3", "http://api.example.com/two/companies/4"]
|
||||||
|
App2.getCompanies [5, 6]: ["http://api.example.com/two/companies/5", "http://api.example.com/two/companies/6"]
|
||||||
|
App1.getPostAliased 1: https://api.example.com/one/posts/1
|
||||||
|
App2.getPostAliased 2: http://api.example.com/two/posts/2
|
||||||
|
App3.getPostAliased 3: https://api.example.com/three/posts/3
|
||||||
|
App1.baseUrlAliased: https://api.example.com/one
|
||||||
|
App2.baseUrlAliased: http://api.example.com/two
|
||||||
|
App3.baseUrlAliased: https://api.example.com/three
|
||||||
|
App1.getUserSafe 1: https://api.example.com/one/users/1
|
||||||
|
Prod.getUserSafe 2: http://api.example.com/prod_1/users/2?safe=true
|
||||||
|
usersApp1: ["https://api.example.com/one/users/1", "https://api.example.com/one/users/2", "https://api.example.com/one/users/3"]
|
||||||
|
getUserApp3Nested 3: https://api.example.com/three/users/3
|
||||||
|
usersApp3Passed: ["https://api.example.com/three/users/1", "https://api.example.com/three/users/2", "https://api.example.com/three/users/3"]
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
UseValgrind::No,
|
||||||
|
TestCliCommands::Run,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg_attr(windows, ignore)]
|
||||||
|
fn module_params_arity_mismatch() {
|
||||||
|
check_compile_error_with(
|
||||||
|
CMD_DEV,
|
||||||
|
&cli_testing_dir("/module_params/arity_mismatch.roc"),
|
||||||
|
&[],
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
── TOO MANY ARGS in tests/module_params/arity_mismatch.roc ─────────────────────
|
||||||
|
|
||||||
|
The getUser function expects 1 argument, but it got 2 instead:
|
||||||
|
|
||||||
|
12│ $(Api.getUser 1 2)
|
||||||
|
^^^^^^^^^^^
|
||||||
|
|
||||||
|
Are there any missing commas? Or missing parentheses?
|
||||||
|
|
||||||
|
|
||||||
|
── TOO MANY ARGS in tests/module_params/arity_mismatch.roc ─────────────────────
|
||||||
|
|
||||||
|
This value is not a function, but it was given 1 argument:
|
||||||
|
|
||||||
|
13│ $(Api.baseUrl 1)
|
||||||
|
^^^^^^^^^^^
|
||||||
|
|
||||||
|
Are there any missing commas? Or missing parentheses?
|
||||||
|
|
||||||
|
|
||||||
|
── TOO FEW ARGS in tests/module_params/arity_mismatch.roc ──────────────────────
|
||||||
|
|
||||||
|
The getPostComment function expects 2 arguments, but it got only 1:
|
||||||
|
|
||||||
|
16│ $(Api.getPostComment 1)
|
||||||
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Roc does not allow functions to be partially applied. Use a closure to
|
||||||
|
make partial application explicit.
|
||||||
|
|
||||||
|
────────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
3 errors and 0 warnings found in <ignored for test> ms."#
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg_attr(windows, ignore)]
|
||||||
|
fn module_params_unexpected_fn() {
|
||||||
|
check_compile_error_with(
|
||||||
|
CMD_DEV,
|
||||||
|
&cli_testing_dir("/module_params/unexpected_fn.roc"),
|
||||||
|
&[],
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
── TYPE MISMATCH in tests/module_params/unexpected_fn.roc ──────────────────────
|
||||||
|
|
||||||
|
This argument to this string interpolation has an unexpected type:
|
||||||
|
|
||||||
|
11│ $(Api.getPost)
|
||||||
|
^^^^^^^^^^^
|
||||||
|
|
||||||
|
The argument is an anonymous function of type:
|
||||||
|
|
||||||
|
U32 -> Str
|
||||||
|
|
||||||
|
But this string interpolation needs its argument to be:
|
||||||
|
|
||||||
|
Str
|
||||||
|
|
||||||
|
────────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
1 error and 0 warnings found in <ignored for test> ms."#
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg_attr(windows, ignore)]
|
||||||
|
fn module_params_bad_ann() {
|
||||||
|
check_compile_error_with(
|
||||||
|
CMD_DEV,
|
||||||
|
&cli_testing_dir("/module_params/bad_ann.roc"),
|
||||||
|
&[],
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
── TYPE MISMATCH in tests/module_params/BadAnn.roc ─────────────────────────────
|
||||||
|
|
||||||
|
Something is off with the body of the fnAnnotatedAsValue definition:
|
||||||
|
|
||||||
|
3│ fnAnnotatedAsValue : Str
|
||||||
|
4│> fnAnnotatedAsValue = /postId, commentId ->
|
||||||
|
5│> "/posts/$(postId)/comments/$(Num.toStr commentId)"
|
||||||
|
|
||||||
|
The body is an anonymous function of type:
|
||||||
|
|
||||||
|
Str, Num * -> Str
|
||||||
|
|
||||||
|
But the type annotation on fnAnnotatedAsValue says it should be:
|
||||||
|
|
||||||
|
Str
|
||||||
|
|
||||||
|
|
||||||
|
── TYPE MISMATCH in tests/module_params/BadAnn.roc ─────────────────────────────
|
||||||
|
|
||||||
|
Something is off with the body of the missingArg definition:
|
||||||
|
|
||||||
|
7│ missingArg : Str -> Str
|
||||||
|
8│> missingArg = /postId, _ ->
|
||||||
|
9│> "/posts/$(postId)/comments"
|
||||||
|
|
||||||
|
The body is an anonymous function of type:
|
||||||
|
|
||||||
|
(Str, ? -> Str)
|
||||||
|
|
||||||
|
But the type annotation on missingArg says it should be:
|
||||||
|
|
||||||
|
(Str -> Str)
|
||||||
|
|
||||||
|
Tip: It looks like it takes too many arguments. I'm seeing 1 extra.
|
||||||
|
|
||||||
|
────────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
2 errors and 1 warning found in <ignored for test> ms."#
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg_attr(windows, ignore)]
|
||||||
|
fn module_params_pass_task() {
|
||||||
|
test_roc_app(
|
||||||
|
"crates/cli/tests/module_params",
|
||||||
|
"pass_task.roc",
|
||||||
|
&[],
|
||||||
|
&[],
|
||||||
|
&[],
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
Hi, Agus!
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
UseValgrind::No,
|
||||||
|
TestCliCommands::Run,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg_attr(windows, ignore)]
|
#[cfg_attr(windows, ignore)]
|
||||||
fn transitive_expects() {
|
fn transitive_expects() {
|
||||||
|
@ -803,7 +1003,7 @@ mod cli_run {
|
||||||
fn check_virtual_dom_server() {
|
fn check_virtual_dom_server() {
|
||||||
let path = file_path_from_root("examples/virtual-dom-wip", "example-server.roc");
|
let path = file_path_from_root("examples/virtual-dom-wip", "example-server.roc");
|
||||||
let out = run_roc([CMD_CHECK, path.to_str().unwrap()], &[], &[]);
|
let out = run_roc([CMD_CHECK, path.to_str().unwrap()], &[], &[]);
|
||||||
assert!(out.status.success());
|
assert_valid_roc_check_status(out.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: write a new test once mono bugs are resolved in investigation
|
// TODO: write a new test once mono bugs are resolved in investigation
|
||||||
|
@ -812,7 +1012,7 @@ mod cli_run {
|
||||||
fn check_virtual_dom_client() {
|
fn check_virtual_dom_client() {
|
||||||
let path = file_path_from_root("examples/virtual-dom-wip", "example-client.roc");
|
let path = file_path_from_root("examples/virtual-dom-wip", "example-client.roc");
|
||||||
let out = run_roc([CMD_CHECK, path.to_str().unwrap()], &[], &[]);
|
let out = run_roc([CMD_CHECK, path.to_str().unwrap()], &[], &[]);
|
||||||
assert!(out.status.success());
|
assert_valid_roc_check_status(out.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -821,7 +1021,7 @@ mod cli_run {
|
||||||
fn cli_countdown_check() {
|
fn cli_countdown_check() {
|
||||||
let path = file_path_from_root("crates/cli/tests/cli", "countdown.roc");
|
let path = file_path_from_root("crates/cli/tests/cli", "countdown.roc");
|
||||||
let out = run_roc([CMD_CHECK, path.to_str().unwrap()], &[], &[]);
|
let out = run_roc([CMD_CHECK, path.to_str().unwrap()], &[], &[]);
|
||||||
assert!(out.status.success());
|
assert_valid_roc_check_status(out.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -830,7 +1030,7 @@ mod cli_run {
|
||||||
fn cli_echo_check() {
|
fn cli_echo_check() {
|
||||||
let path = file_path_from_root("crates/cli/tests/cli", "echo.roc");
|
let path = file_path_from_root("crates/cli/tests/cli", "echo.roc");
|
||||||
let out = run_roc([CMD_CHECK, path.to_str().unwrap()], &[], &[]);
|
let out = run_roc([CMD_CHECK, path.to_str().unwrap()], &[], &[]);
|
||||||
assert!(out.status.success());
|
assert_valid_roc_check_status(out.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -839,7 +1039,7 @@ mod cli_run {
|
||||||
fn cli_file_check() {
|
fn cli_file_check() {
|
||||||
let path = file_path_from_root("crates/cli/tests/cli", "fileBROKEN.roc");
|
let path = file_path_from_root("crates/cli/tests/cli", "fileBROKEN.roc");
|
||||||
let out = run_roc([CMD_CHECK, path.to_str().unwrap()], &[], &[]);
|
let out = run_roc([CMD_CHECK, path.to_str().unwrap()], &[], &[]);
|
||||||
assert!(out.status.success());
|
assert_valid_roc_check_status(out.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -848,7 +1048,8 @@ mod cli_run {
|
||||||
fn cli_form_check() {
|
fn cli_form_check() {
|
||||||
let path = file_path_from_root("crates/cli/tests/cli", "form.roc");
|
let path = file_path_from_root("crates/cli/tests/cli", "form.roc");
|
||||||
let out = run_roc([CMD_CHECK, path.to_str().unwrap()], &[], &[]);
|
let out = run_roc([CMD_CHECK, path.to_str().unwrap()], &[], &[]);
|
||||||
assert!(out.status.success());
|
dbg!(out.stdout, out.stderr);
|
||||||
|
assert_valid_roc_check_status(out.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -857,7 +1058,7 @@ mod cli_run {
|
||||||
fn cli_http_get_check() {
|
fn cli_http_get_check() {
|
||||||
let path = file_path_from_root("crates/cli/tests/cli", "http-get.roc");
|
let path = file_path_from_root("crates/cli/tests/cli", "http-get.roc");
|
||||||
let out = run_roc([CMD_CHECK, path.to_str().unwrap()], &[], &[]);
|
let out = run_roc([CMD_CHECK, path.to_str().unwrap()], &[], &[]);
|
||||||
assert!(out.status.success());
|
assert_valid_roc_check_status(out.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -891,8 +1092,8 @@ mod cli_run {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[ignore = "likely broken because of alias analysis: https://github.com/roc-lang/roc/issues/6544"]
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg_attr(any(target_os = "windows", target_os = "linux"), ignore = "Segfault")]
|
|
||||||
fn false_interpreter() {
|
fn false_interpreter() {
|
||||||
test_roc_app(
|
test_roc_app(
|
||||||
"examples/cli/false-interpreter",
|
"examples/cli/false-interpreter",
|
||||||
|
@ -1482,9 +1683,9 @@ mod cli_run {
|
||||||
|
|
||||||
Something is off with the body of the main definition:
|
Something is off with the body of the main definition:
|
||||||
|
|
||||||
6│ main : Str -> Task {} []
|
3│ main : Str -> Task {} []
|
||||||
7│ main = /_ ->
|
4│ main = /_ ->
|
||||||
8│ "this is a string, not a Task {} [] function like the platform expects."
|
5│ "this is a string, not a Task {} [] function like the platform expects."
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
The body is a string of type:
|
The body is a string of type:
|
||||||
|
@ -1493,7 +1694,7 @@ mod cli_run {
|
||||||
|
|
||||||
But the type annotation on main says it should be:
|
But the type annotation on main says it should be:
|
||||||
|
|
||||||
Effect.Effect (Result {} [])
|
Task {} []
|
||||||
|
|
||||||
Tip: Add type annotations to functions or values to help you figure
|
Tip: Add type annotations to functions or values to help you figure
|
||||||
this out.
|
this out.
|
||||||
|
@ -1572,30 +1773,6 @@ mod cli_run {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn unknown_generates_with() {
|
|
||||||
check_compile_error(
|
|
||||||
&known_bad_file("UnknownGeneratesWith.roc"),
|
|
||||||
&[],
|
|
||||||
indoc!(
|
|
||||||
r#"
|
|
||||||
── UNKNOWN GENERATES FUNCTION in tests/known_bad/UnknownGeneratesWith.roc ──────
|
|
||||||
|
|
||||||
I don't know how to generate the foobar function.
|
|
||||||
|
|
||||||
4│ generates Effect with [after, map, always, foobar]
|
|
||||||
^^^^^^
|
|
||||||
|
|
||||||
Only specific functions like `after` and `map` can be generated.Learn
|
|
||||||
more about hosted modules at TODO.
|
|
||||||
|
|
||||||
────────────────────────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
1 error and 0 warnings found in <ignored for test> ms."#
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn format_check_good() {
|
fn format_check_good() {
|
||||||
check_format_check_as_expected(&fixture_file("format", "Formatted.roc"), true);
|
check_format_check_as_expected(&fixture_file("format", "Formatted.roc"), true);
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
app "type-error"
|
app [main] { pf: platform "../../../../examples/cli/false-interpreter/platform/main.roc" }
|
||||||
packages { pf: "../../../../examples/cli/false-interpreter/platform/main.roc" }
|
|
||||||
imports [pf.Task.{ Task }]
|
|
||||||
provides [main] to pf
|
|
||||||
|
|
||||||
main : Str -> Task {} []
|
main : Str -> Task {} []
|
||||||
main = \_ ->
|
main = \_ ->
|
||||||
"this is a string, not a Task {} [] function like the platform expects."
|
"this is a string, not a Task {} [] function like the platform expects."
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
hosted UnknownGeneratesWith
|
|
||||||
exposes [Effect, after, map, always]
|
|
||||||
imports []
|
|
||||||
generates Effect with [after, map, always, foobar]
|
|
69
crates/cli/tests/module_params/Api.roc
Normal file
69
crates/cli/tests/module_params/Api.roc
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
module { appId, protocol } -> [
|
||||||
|
baseUrl,
|
||||||
|
getUser,
|
||||||
|
getPost,
|
||||||
|
getPosts,
|
||||||
|
getPostComments,
|
||||||
|
getCompanies,
|
||||||
|
baseUrlAliased,
|
||||||
|
getPostAliased,
|
||||||
|
getUserSafe,
|
||||||
|
getPostComment,
|
||||||
|
]
|
||||||
|
|
||||||
|
## value def referencing params
|
||||||
|
baseUrl : Str
|
||||||
|
baseUrl =
|
||||||
|
protocol "api.example.com/$(appId)"
|
||||||
|
|
||||||
|
## function def referencing params
|
||||||
|
getUser : U32 -> Str
|
||||||
|
getUser = \userId ->
|
||||||
|
# purposefully not using baseUrl to test top-level fn referencing param
|
||||||
|
protocol "api.example.com/$(appId)/users/$(Num.toStr userId)"
|
||||||
|
|
||||||
|
## function def referencing top-level value
|
||||||
|
getPost : U32 -> Str
|
||||||
|
getPost = \postId ->
|
||||||
|
"$(baseUrl)/posts/$(Num.toStr postId)"
|
||||||
|
|
||||||
|
## function def passing top-level function
|
||||||
|
getPosts : List U32 -> List Str
|
||||||
|
getPosts = \ids ->
|
||||||
|
List.map ids getPost
|
||||||
|
|
||||||
|
## function def calling top-level function
|
||||||
|
getPostComments : U32 -> Str
|
||||||
|
getPostComments = \postId ->
|
||||||
|
"$(getPost postId)/comments"
|
||||||
|
|
||||||
|
## function def passing nested function
|
||||||
|
getCompanies : List U32 -> List Str
|
||||||
|
getCompanies = \ids ->
|
||||||
|
getCompany = \id ->
|
||||||
|
protocol "api.example.com/$(appId)/companies/$(Num.toStr id)"
|
||||||
|
|
||||||
|
List.map ids getCompany
|
||||||
|
|
||||||
|
## aliasing top-level value
|
||||||
|
baseUrlAliased : Str
|
||||||
|
baseUrlAliased =
|
||||||
|
baseUrl
|
||||||
|
|
||||||
|
## aliasing top-level fn
|
||||||
|
getPostAliased : U32 -> Str
|
||||||
|
getPostAliased =
|
||||||
|
getPost
|
||||||
|
|
||||||
|
## top-level value returning functions
|
||||||
|
getUserSafe : U32 -> Str
|
||||||
|
getUserSafe =
|
||||||
|
if Str.startsWith appId "prod_" then
|
||||||
|
\id -> "$(getUser id)?safe=true"
|
||||||
|
else
|
||||||
|
getUser
|
||||||
|
|
||||||
|
## two-argument function
|
||||||
|
getPostComment : U32, U32 -> Str
|
||||||
|
getPostComment = \postId, commentId ->
|
||||||
|
"$(getPost postId)/comments/$(Num.toStr commentId)"
|
9
crates/cli/tests/module_params/BadAnn.roc
Normal file
9
crates/cli/tests/module_params/BadAnn.roc
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
module { appId } -> [fnAnnotatedAsValue, missingArg]
|
||||||
|
|
||||||
|
fnAnnotatedAsValue : Str
|
||||||
|
fnAnnotatedAsValue = \postId, commentId ->
|
||||||
|
"/posts/$(postId)/comments/$(Num.toStr commentId)"
|
||||||
|
|
||||||
|
missingArg : Str -> Str
|
||||||
|
missingArg = \postId, _ ->
|
||||||
|
"/posts/$(postId)/comments"
|
7
crates/cli/tests/module_params/Menu.roc
Normal file
7
crates/cli/tests/module_params/Menu.roc
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
module { echo } -> [menu]
|
||||||
|
|
||||||
|
menu = \name ->
|
||||||
|
indirect name
|
||||||
|
|
||||||
|
indirect = \name ->
|
||||||
|
echo "Hi, $(name)!"
|
59
crates/cli/tests/module_params/app.roc
Normal file
59
crates/cli/tests/module_params/app.roc
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
app [main] {
|
||||||
|
pf: platform "../fixtures/multi-dep-str/platform/main.roc",
|
||||||
|
}
|
||||||
|
|
||||||
|
import Api { appId: "one", protocol: https } as App1
|
||||||
|
import Api { appId: "two", protocol: http } as App2
|
||||||
|
import Api { appId: "prod_1", protocol: http } as Prod
|
||||||
|
|
||||||
|
https = \url -> "https://$(url)"
|
||||||
|
http = \url -> "http://$(url)"
|
||||||
|
|
||||||
|
usersApp1 =
|
||||||
|
# pass top-level fn in a module with params
|
||||||
|
List.map [1, 2, 3] App1.getUser
|
||||||
|
|
||||||
|
main =
|
||||||
|
app3Id = "three"
|
||||||
|
|
||||||
|
import Api { appId: app3Id, protocol: https } as App3
|
||||||
|
|
||||||
|
getUserApp3Nested = \userId ->
|
||||||
|
# use captured params def
|
||||||
|
App3.getUser userId
|
||||||
|
|
||||||
|
usersApp3Passed =
|
||||||
|
# pass top-level fn in a nested def
|
||||||
|
List.map [1, 2, 3] App3.getUser
|
||||||
|
|
||||||
|
"""
|
||||||
|
App1.baseUrl: $(App1.baseUrl)
|
||||||
|
App2.baseUrl: $(App2.baseUrl)
|
||||||
|
App3.baseUrl: $(App3.baseUrl)
|
||||||
|
App1.getUser 1: $(App1.getUser 1)
|
||||||
|
App2.getUser 2: $(App2.getUser 2)
|
||||||
|
App3.getUser 3: $(App3.getUser 3)
|
||||||
|
App1.getPost 1: $(App1.getPost 1)
|
||||||
|
App2.getPost 2: $(App2.getPost 2)
|
||||||
|
App3.getPost 3: $(App3.getPost 3)
|
||||||
|
App1.getPosts [1, 2]: $(Inspect.toStr (App1.getPosts [1, 2]))
|
||||||
|
App2.getPosts [3, 4]: $(Inspect.toStr (App2.getPosts [3, 4]))
|
||||||
|
App2.getPosts [5, 6]: $(Inspect.toStr (App2.getPosts [5, 6]))
|
||||||
|
App1.getPostComments 1: $(App1.getPostComments 1)
|
||||||
|
App2.getPostComments 2: $(App2.getPostComments 2)
|
||||||
|
App2.getPostComments 3: $(App2.getPostComments 3)
|
||||||
|
App1.getCompanies [1, 2]: $(Inspect.toStr (App1.getCompanies [1, 2]))
|
||||||
|
App2.getCompanies [3, 4]: $(Inspect.toStr (App2.getCompanies [3, 4]))
|
||||||
|
App2.getCompanies [5, 6]: $(Inspect.toStr (App2.getCompanies [5, 6]))
|
||||||
|
App1.getPostAliased 1: $(App1.getPostAliased 1)
|
||||||
|
App2.getPostAliased 2: $(App2.getPostAliased 2)
|
||||||
|
App3.getPostAliased 3: $(App3.getPostAliased 3)
|
||||||
|
App1.baseUrlAliased: $(App1.baseUrlAliased)
|
||||||
|
App2.baseUrlAliased: $(App2.baseUrlAliased)
|
||||||
|
App3.baseUrlAliased: $(App3.baseUrlAliased)
|
||||||
|
App1.getUserSafe 1: $(App1.getUserSafe 1)
|
||||||
|
Prod.getUserSafe 2: $(Prod.getUserSafe 2)
|
||||||
|
usersApp1: $(Inspect.toStr usersApp1)
|
||||||
|
getUserApp3Nested 3: $(getUserApp3Nested 3)
|
||||||
|
usersApp3Passed: $(Inspect.toStr usersApp3Passed)
|
||||||
|
"""
|
17
crates/cli/tests/module_params/arity_mismatch.roc
Normal file
17
crates/cli/tests/module_params/arity_mismatch.roc
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
app [main] {
|
||||||
|
pf: platform "../fixtures/multi-dep-str/platform/main.roc",
|
||||||
|
}
|
||||||
|
|
||||||
|
import Api { appId: "one", protocol: https }
|
||||||
|
|
||||||
|
https = \url -> "https://$(url)"
|
||||||
|
|
||||||
|
main =
|
||||||
|
"""
|
||||||
|
# too many args
|
||||||
|
$(Api.getUser 1 2)
|
||||||
|
$(Api.baseUrl 1)
|
||||||
|
|
||||||
|
# too few args
|
||||||
|
$(Api.getPostComment 1)
|
||||||
|
"""
|
8
crates/cli/tests/module_params/bad_ann.roc
Normal file
8
crates/cli/tests/module_params/bad_ann.roc
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
app [main] {
|
||||||
|
pf: platform "../fixtures/multi-dep-str/platform/main.roc",
|
||||||
|
}
|
||||||
|
|
||||||
|
import BadAnn { appId: "one" }
|
||||||
|
|
||||||
|
main =
|
||||||
|
""
|
7
crates/cli/tests/module_params/pass_task.roc
Normal file
7
crates/cli/tests/module_params/pass_task.roc
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.15.0/SlwdbJ-3GR7uBWQo6zlmYWNYOxnvo8r6YABXD-45UOw.tar.br" }
|
||||||
|
|
||||||
|
import pf.Stdout
|
||||||
|
import Menu { echo: Stdout.line }
|
||||||
|
|
||||||
|
main =
|
||||||
|
Menu.menu "Agus"
|
12
crates/cli/tests/module_params/unexpected_fn.roc
Normal file
12
crates/cli/tests/module_params/unexpected_fn.roc
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
app [main] {
|
||||||
|
pf: platform "../fixtures/multi-dep-str/platform/main.roc",
|
||||||
|
}
|
||||||
|
|
||||||
|
import Api { appId: "one", protocol: https }
|
||||||
|
|
||||||
|
https = \url -> "https://$(url)"
|
||||||
|
|
||||||
|
main =
|
||||||
|
"""
|
||||||
|
$(Api.getPost)
|
||||||
|
"""
|
|
@ -1129,7 +1129,7 @@ fn link_macos(
|
||||||
Architecture::Aarch64 => {
|
Architecture::Aarch64 => {
|
||||||
ld_child.wait()?;
|
ld_child.wait()?;
|
||||||
|
|
||||||
let mut codesign_cmd = Command::new("codesign");
|
let mut codesign_cmd = Command::new("/usr/bin/codesign");
|
||||||
codesign_cmd.args(["-s", "-", output_path.to_str().unwrap()]);
|
codesign_cmd.args(["-s", "-", output_path.to_str().unwrap()]);
|
||||||
debug_print_command(&codesign_cmd);
|
debug_print_command(&codesign_cmd);
|
||||||
let codesign_child = codesign_cmd.spawn()?;
|
let codesign_child = codesign_cmd.spawn()?;
|
||||||
|
|
|
@ -129,8 +129,8 @@ 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
|
toInspectorDict : Dict k v -> Inspector f where k implements Inspect & Hash & Eq, v implements Inspect, f implements InspectFormatter
|
||||||
toInspectorDict = \dict ->
|
toInspectorDict = \dict ->
|
||||||
fmt <- Inspect.custom
|
Inspect.custom \fmt ->
|
||||||
Inspect.apply (Inspect.dict dict walk Inspect.toInspector Inspect.toInspector) fmt
|
Inspect.apply (Inspect.dict dict walk Inspect.toInspector Inspect.toInspector) fmt
|
||||||
|
|
||||||
## Return an empty dictionary.
|
## Return an empty dictionary.
|
||||||
## ```roc
|
## ```roc
|
||||||
|
@ -894,9 +894,9 @@ calcNumBuckets = \shifts ->
|
||||||
maxBucketCount
|
maxBucketCount
|
||||||
|
|
||||||
fillBucketsFromData = \buckets0, data, shifts ->
|
fillBucketsFromData = \buckets0, data, shifts ->
|
||||||
buckets1, (key, _), dataIndex <- List.walkWithIndex data buckets0
|
List.walkWithIndex data buckets0 \buckets1, (key, _), dataIndex ->
|
||||||
(bucketIndex, distAndFingerprint) = nextWhileLess buckets1 key shifts
|
(bucketIndex, distAndFingerprint) = nextWhileLess buckets1 key shifts
|
||||||
placeAndShiftUp buckets1 { distAndFingerprint, dataIndex: Num.toU32 dataIndex } bucketIndex
|
placeAndShiftUp buckets1 { distAndFingerprint, dataIndex: Num.toU32 dataIndex } bucketIndex
|
||||||
|
|
||||||
nextWhileLess : List Bucket, k, U8 -> (U64, U32) where k implements Hash & Eq
|
nextWhileLess : List Bucket, k, U8 -> (U64, U32) where k implements Hash & Eq
|
||||||
nextWhileLess = \buckets, key, shifts ->
|
nextWhileLess = \buckets, key, shifts ->
|
||||||
|
@ -1213,15 +1213,15 @@ expect
|
||||||
]
|
]
|
||||||
|
|
||||||
dict =
|
dict =
|
||||||
acc, k <- List.walk badKeys (Dict.empty {})
|
List.walk badKeys (Dict.empty {}) \acc, k ->
|
||||||
Dict.update acc k \val ->
|
Dict.update acc k \val ->
|
||||||
when val is
|
when val is
|
||||||
Present p -> Present (p |> Num.addWrap 1)
|
Present p -> Present (p |> Num.addWrap 1)
|
||||||
Missing -> Present 0
|
Missing -> Present 0
|
||||||
|
|
||||||
allInsertedCorrectly =
|
allInsertedCorrectly =
|
||||||
acc, k <- List.walk badKeys Bool.true
|
List.walk badKeys Bool.true \acc, k ->
|
||||||
acc && Dict.contains dict k
|
acc && Dict.contains dict k
|
||||||
|
|
||||||
allInsertedCorrectly
|
allInsertedCorrectly
|
||||||
|
|
||||||
|
|
|
@ -138,203 +138,203 @@ dbgInit = \{} -> @DbgFormatter { data: "" }
|
||||||
|
|
||||||
dbgList : list, ElemWalker (DbgFormatter, Bool) list elem, (elem -> Inspector DbgFormatter) -> Inspector DbgFormatter
|
dbgList : list, ElemWalker (DbgFormatter, Bool) list elem, (elem -> Inspector DbgFormatter) -> Inspector DbgFormatter
|
||||||
dbgList = \content, walkFn, toDbgInspector ->
|
dbgList = \content, walkFn, toDbgInspector ->
|
||||||
f0 <- custom
|
custom \f0 ->
|
||||||
dbgWrite f0 "["
|
dbgWrite f0 "["
|
||||||
|> \f1 ->
|
|> \f1 ->
|
||||||
(f2, prependSep), elem <- walkFn content (f1, Bool.false)
|
walkFn content (f1, Bool.false) \(f2, prependSep), elem ->
|
||||||
f3 =
|
f3 =
|
||||||
if prependSep then
|
if prependSep then
|
||||||
dbgWrite f2 ", "
|
dbgWrite f2 ", "
|
||||||
else
|
else
|
||||||
f2
|
f2
|
||||||
|
|
||||||
elem
|
elem
|
||||||
|> toDbgInspector
|
|> toDbgInspector
|
||||||
|> apply f3
|
|> apply f3
|
||||||
|> \f4 -> (f4, Bool.true)
|
|> \f4 -> (f4, Bool.true)
|
||||||
|> .0
|
|> .0
|
||||||
|> dbgWrite "]"
|
|> dbgWrite "]"
|
||||||
|
|
||||||
dbgSet : set, ElemWalker (DbgFormatter, Bool) set elem, (elem -> Inspector DbgFormatter) -> Inspector DbgFormatter
|
dbgSet : set, ElemWalker (DbgFormatter, Bool) set elem, (elem -> Inspector DbgFormatter) -> Inspector DbgFormatter
|
||||||
dbgSet = \content, walkFn, toDbgInspector ->
|
dbgSet = \content, walkFn, toDbgInspector ->
|
||||||
f0 <- custom
|
custom \f0 ->
|
||||||
dbgWrite f0 "{"
|
dbgWrite f0 "{"
|
||||||
|> \f1 ->
|
|> \f1 ->
|
||||||
(f2, prependSep), elem <- walkFn content (f1, Bool.false)
|
walkFn content (f1, Bool.false) \(f2, prependSep), elem ->
|
||||||
f3 =
|
f3 =
|
||||||
if prependSep then
|
if prependSep then
|
||||||
dbgWrite f2 ", "
|
dbgWrite f2 ", "
|
||||||
else
|
else
|
||||||
f2
|
f2
|
||||||
|
|
||||||
elem
|
elem
|
||||||
|> toDbgInspector
|
|> toDbgInspector
|
||||||
|> apply f3
|
|> apply f3
|
||||||
|> \f4 -> (f4, Bool.true)
|
|> \f4 -> (f4, Bool.true)
|
||||||
|> .0
|
|> .0
|
||||||
|> dbgWrite "}"
|
|> dbgWrite "}"
|
||||||
|
|
||||||
dbgDict : dict, KeyValWalker (DbgFormatter, Bool) dict key value, (key -> Inspector DbgFormatter), (value -> Inspector DbgFormatter) -> Inspector DbgFormatter
|
dbgDict : dict, KeyValWalker (DbgFormatter, Bool) dict key value, (key -> Inspector DbgFormatter), (value -> Inspector DbgFormatter) -> Inspector DbgFormatter
|
||||||
dbgDict = \d, walkFn, keyToInspector, valueToInspector ->
|
dbgDict = \d, walkFn, keyToInspector, valueToInspector ->
|
||||||
f0 <- custom
|
custom \f0 ->
|
||||||
dbgWrite f0 "{"
|
dbgWrite f0 "{"
|
||||||
|> \f1 ->
|
|> \f1 ->
|
||||||
(f2, prependSep), key, value <- walkFn d (f1, Bool.false)
|
walkFn d (f1, Bool.false) \(f2, prependSep), key, value ->
|
||||||
f3 =
|
f3 =
|
||||||
if prependSep then
|
if prependSep then
|
||||||
dbgWrite f2 ", "
|
dbgWrite f2 ", "
|
||||||
else
|
else
|
||||||
f2
|
f2
|
||||||
|
|
||||||
apply (keyToInspector key) f3
|
apply (keyToInspector key) f3
|
||||||
|> dbgWrite ": "
|
|> dbgWrite ": "
|
||||||
|> \x -> apply (valueToInspector value) x
|
|> \x -> apply (valueToInspector value) x
|
||||||
|> \f4 -> (f4, Bool.true)
|
|> \f4 -> (f4, Bool.true)
|
||||||
|> .0
|
|> .0
|
||||||
|> dbgWrite "}"
|
|> dbgWrite "}"
|
||||||
|
|
||||||
dbgTag : Str, List (Inspector DbgFormatter) -> Inspector DbgFormatter
|
dbgTag : Str, List (Inspector DbgFormatter) -> Inspector DbgFormatter
|
||||||
dbgTag = \name, fields ->
|
dbgTag = \name, fields ->
|
||||||
if List.isEmpty fields then
|
if List.isEmpty fields then
|
||||||
f0 <- custom
|
custom \f0 ->
|
||||||
dbgWrite f0 name
|
dbgWrite f0 name
|
||||||
else
|
else
|
||||||
f0 <- custom
|
custom \f0 ->
|
||||||
dbgWrite f0 "("
|
dbgWrite f0 "("
|
||||||
|> dbgWrite name
|
|> dbgWrite name
|
||||||
|> \f1 ->
|
|> \f1 ->
|
||||||
f2, inspector <- List.walk fields f1
|
List.walk fields f1 \f2, inspector ->
|
||||||
dbgWrite f2 " "
|
dbgWrite f2 " "
|
||||||
|> \x -> apply inspector x
|
|> \x -> apply inspector x
|
||||||
|> dbgWrite ")"
|
|> dbgWrite ")"
|
||||||
|
|
||||||
dbgTuple : List (Inspector DbgFormatter) -> Inspector DbgFormatter
|
dbgTuple : List (Inspector DbgFormatter) -> Inspector DbgFormatter
|
||||||
dbgTuple = \fields ->
|
dbgTuple = \fields ->
|
||||||
f0 <- custom
|
custom \f0 ->
|
||||||
dbgWrite f0 "("
|
dbgWrite f0 "("
|
||||||
|> \f1 ->
|
|> \f1 ->
|
||||||
(f2, prependSep), inspector <- List.walk fields (f1, Bool.false)
|
List.walk fields (f1, Bool.false) \(f2, prependSep), inspector ->
|
||||||
f3 =
|
f3 =
|
||||||
if prependSep then
|
if prependSep then
|
||||||
dbgWrite f2 ", "
|
dbgWrite f2 ", "
|
||||||
else
|
else
|
||||||
f2
|
f2
|
||||||
|
|
||||||
apply inspector f3
|
apply inspector f3
|
||||||
|> \f4 -> (f4, Bool.true)
|
|> \f4 -> (f4, Bool.true)
|
||||||
|> .0
|
|> .0
|
||||||
|> dbgWrite ")"
|
|> dbgWrite ")"
|
||||||
|
|
||||||
dbgRecord : List { key : Str, value : Inspector DbgFormatter } -> Inspector DbgFormatter
|
dbgRecord : List { key : Str, value : Inspector DbgFormatter } -> Inspector DbgFormatter
|
||||||
dbgRecord = \fields ->
|
dbgRecord = \fields ->
|
||||||
f0 <- custom
|
custom \f0 ->
|
||||||
dbgWrite f0 "{"
|
dbgWrite f0 "{"
|
||||||
|> \f1 ->
|
|> \f1 ->
|
||||||
(f2, prependSep), { key, value } <- List.walk fields (f1, Bool.false)
|
List.walk fields (f1, Bool.false) \(f2, prependSep), { key, value } ->
|
||||||
f3 =
|
f3 =
|
||||||
if prependSep then
|
if prependSep then
|
||||||
dbgWrite f2 ", "
|
dbgWrite f2 ", "
|
||||||
else
|
else
|
||||||
f2
|
f2
|
||||||
|
|
||||||
dbgWrite f3 key
|
dbgWrite f3 key
|
||||||
|> dbgWrite ": "
|
|> dbgWrite ": "
|
||||||
|> \x -> apply value x
|
|> \x -> apply value x
|
||||||
|> \f4 -> (f4, Bool.true)
|
|> \f4 -> (f4, Bool.true)
|
||||||
|> .0
|
|> .0
|
||||||
|> dbgWrite "}"
|
|> dbgWrite "}"
|
||||||
|
|
||||||
dbgBool : Bool -> Inspector DbgFormatter
|
dbgBool : Bool -> Inspector DbgFormatter
|
||||||
dbgBool = \b ->
|
dbgBool = \b ->
|
||||||
if b then
|
if b then
|
||||||
f0 <- custom
|
custom \f0 ->
|
||||||
dbgWrite f0 "Bool.true"
|
dbgWrite f0 "Bool.true"
|
||||||
else
|
else
|
||||||
f0 <- custom
|
custom \f0 ->
|
||||||
dbgWrite f0 "Bool.false"
|
dbgWrite f0 "Bool.false"
|
||||||
|
|
||||||
dbgStr : Str -> Inspector DbgFormatter
|
dbgStr : Str -> Inspector DbgFormatter
|
||||||
dbgStr = \s ->
|
dbgStr = \s ->
|
||||||
f0 <- custom
|
custom \f0 ->
|
||||||
f0
|
f0
|
||||||
|> dbgWrite "\""
|
|> dbgWrite "\""
|
||||||
|> dbgWrite s # TODO: Should we be escaping strings for dbg/logging?
|
|> dbgWrite s # TODO: Should we be escaping strings for dbg/logging?
|
||||||
|> dbgWrite "\""
|
|> dbgWrite "\""
|
||||||
|
|
||||||
dbgOpaque : * -> Inspector DbgFormatter
|
dbgOpaque : * -> Inspector DbgFormatter
|
||||||
dbgOpaque = \_ ->
|
dbgOpaque = \_ ->
|
||||||
f0 <- custom
|
custom \f0 ->
|
||||||
dbgWrite f0 "<opaque>"
|
dbgWrite f0 "<opaque>"
|
||||||
|
|
||||||
dbgFunction : * -> Inspector DbgFormatter
|
dbgFunction : * -> Inspector DbgFormatter
|
||||||
dbgFunction = \_ ->
|
dbgFunction = \_ ->
|
||||||
f0 <- custom
|
custom \f0 ->
|
||||||
dbgWrite f0 "<function>"
|
dbgWrite f0 "<function>"
|
||||||
|
|
||||||
dbgU8 : U8 -> Inspector DbgFormatter
|
dbgU8 : U8 -> Inspector DbgFormatter
|
||||||
dbgU8 = \num ->
|
dbgU8 = \num ->
|
||||||
f0 <- custom
|
custom \f0 ->
|
||||||
dbgWrite f0 (num |> Num.toStr)
|
dbgWrite f0 (num |> Num.toStr)
|
||||||
|
|
||||||
dbgI8 : I8 -> Inspector DbgFormatter
|
dbgI8 : I8 -> Inspector DbgFormatter
|
||||||
dbgI8 = \num ->
|
dbgI8 = \num ->
|
||||||
f0 <- custom
|
custom \f0 ->
|
||||||
dbgWrite f0 (num |> Num.toStr)
|
dbgWrite f0 (num |> Num.toStr)
|
||||||
|
|
||||||
dbgU16 : U16 -> Inspector DbgFormatter
|
dbgU16 : U16 -> Inspector DbgFormatter
|
||||||
dbgU16 = \num ->
|
dbgU16 = \num ->
|
||||||
f0 <- custom
|
custom \f0 ->
|
||||||
dbgWrite f0 (num |> Num.toStr)
|
dbgWrite f0 (num |> Num.toStr)
|
||||||
|
|
||||||
dbgI16 : I16 -> Inspector DbgFormatter
|
dbgI16 : I16 -> Inspector DbgFormatter
|
||||||
dbgI16 = \num ->
|
dbgI16 = \num ->
|
||||||
f0 <- custom
|
custom \f0 ->
|
||||||
dbgWrite f0 (num |> Num.toStr)
|
dbgWrite f0 (num |> Num.toStr)
|
||||||
|
|
||||||
dbgU32 : U32 -> Inspector DbgFormatter
|
dbgU32 : U32 -> Inspector DbgFormatter
|
||||||
dbgU32 = \num ->
|
dbgU32 = \num ->
|
||||||
f0 <- custom
|
custom \f0 ->
|
||||||
dbgWrite f0 (num |> Num.toStr)
|
dbgWrite f0 (num |> Num.toStr)
|
||||||
|
|
||||||
dbgI32 : I32 -> Inspector DbgFormatter
|
dbgI32 : I32 -> Inspector DbgFormatter
|
||||||
dbgI32 = \num ->
|
dbgI32 = \num ->
|
||||||
f0 <- custom
|
custom \f0 ->
|
||||||
dbgWrite f0 (num |> Num.toStr)
|
dbgWrite f0 (num |> Num.toStr)
|
||||||
|
|
||||||
dbgU64 : U64 -> Inspector DbgFormatter
|
dbgU64 : U64 -> Inspector DbgFormatter
|
||||||
dbgU64 = \num ->
|
dbgU64 = \num ->
|
||||||
f0 <- custom
|
custom \f0 ->
|
||||||
dbgWrite f0 (num |> Num.toStr)
|
dbgWrite f0 (num |> Num.toStr)
|
||||||
|
|
||||||
dbgI64 : I64 -> Inspector DbgFormatter
|
dbgI64 : I64 -> Inspector DbgFormatter
|
||||||
dbgI64 = \num ->
|
dbgI64 = \num ->
|
||||||
f0 <- custom
|
custom \f0 ->
|
||||||
dbgWrite f0 (num |> Num.toStr)
|
dbgWrite f0 (num |> Num.toStr)
|
||||||
|
|
||||||
dbgU128 : U128 -> Inspector DbgFormatter
|
dbgU128 : U128 -> Inspector DbgFormatter
|
||||||
dbgU128 = \num ->
|
dbgU128 = \num ->
|
||||||
f0 <- custom
|
custom \f0 ->
|
||||||
dbgWrite f0 (num |> Num.toStr)
|
dbgWrite f0 (num |> Num.toStr)
|
||||||
|
|
||||||
dbgI128 : I128 -> Inspector DbgFormatter
|
dbgI128 : I128 -> Inspector DbgFormatter
|
||||||
dbgI128 = \num ->
|
dbgI128 = \num ->
|
||||||
f0 <- custom
|
custom \f0 ->
|
||||||
dbgWrite f0 (num |> Num.toStr)
|
dbgWrite f0 (num |> Num.toStr)
|
||||||
|
|
||||||
dbgF32 : F32 -> Inspector DbgFormatter
|
dbgF32 : F32 -> Inspector DbgFormatter
|
||||||
dbgF32 = \num ->
|
dbgF32 = \num ->
|
||||||
f0 <- custom
|
custom \f0 ->
|
||||||
dbgWrite f0 (num |> Num.toStr)
|
dbgWrite f0 (num |> Num.toStr)
|
||||||
|
|
||||||
dbgF64 : F64 -> Inspector DbgFormatter
|
dbgF64 : F64 -> Inspector DbgFormatter
|
||||||
dbgF64 = \num ->
|
dbgF64 = \num ->
|
||||||
f0 <- custom
|
custom \f0 ->
|
||||||
dbgWrite f0 (num |> Num.toStr)
|
dbgWrite f0 (num |> Num.toStr)
|
||||||
|
|
||||||
dbgDec : Dec -> Inspector DbgFormatter
|
dbgDec : Dec -> Inspector DbgFormatter
|
||||||
dbgDec = \num ->
|
dbgDec = \num ->
|
||||||
f0 <- custom
|
custom \f0 ->
|
||||||
dbgWrite f0 (num |> Num.toStr)
|
dbgWrite f0 (num |> Num.toStr)
|
||||||
|
|
||||||
dbgWrite : DbgFormatter, Str -> DbgFormatter
|
dbgWrite : DbgFormatter, Str -> DbgFormatter
|
||||||
dbgWrite = \@DbgFormatter { data }, added ->
|
dbgWrite = \@DbgFormatter { data }, added ->
|
||||||
|
|
|
@ -62,8 +62,8 @@ hashSet = \hasher, @Set inner -> Hash.hash hasher inner
|
||||||
|
|
||||||
toInspectorSet : Set k -> Inspector f where k implements Inspect & Hash & Eq, f implements InspectFormatter
|
toInspectorSet : Set k -> Inspector f where k implements Inspect & Hash & Eq, f implements InspectFormatter
|
||||||
toInspectorSet = \set ->
|
toInspectorSet = \set ->
|
||||||
fmt <- Inspect.custom
|
Inspect.custom \fmt ->
|
||||||
Inspect.apply (Inspect.set set walk Inspect.toInspector) fmt
|
Inspect.apply (Inspect.set set walk Inspect.toInspector) fmt
|
||||||
|
|
||||||
## Creates a new empty `Set`.
|
## Creates a new empty `Set`.
|
||||||
## ```roc
|
## ```roc
|
||||||
|
|
265
crates/compiler/builtins/roc/Task.roc
Normal file
265
crates/compiler/builtins/roc/Task.roc
Normal file
|
@ -0,0 +1,265 @@
|
||||||
|
module [
|
||||||
|
Task,
|
||||||
|
ok,
|
||||||
|
err,
|
||||||
|
await,
|
||||||
|
map,
|
||||||
|
mapErr,
|
||||||
|
onErr,
|
||||||
|
attempt,
|
||||||
|
forever,
|
||||||
|
loop,
|
||||||
|
fromResult,
|
||||||
|
batch,
|
||||||
|
sequence,
|
||||||
|
forEach,
|
||||||
|
result,
|
||||||
|
]
|
||||||
|
|
||||||
|
import List
|
||||||
|
import Result exposing [Result]
|
||||||
|
|
||||||
|
## A Task represents an effect; an interaction with state outside your Roc
|
||||||
|
## program, such as the terminal's standard output, or a file.
|
||||||
|
Task ok err := {} -> Result ok err
|
||||||
|
|
||||||
|
## Run a task repeatedly, until it fails with `err`. Note that this task does not return a success value.
|
||||||
|
forever : Task a err -> Task * err
|
||||||
|
forever = \@Task task ->
|
||||||
|
looper = \{} ->
|
||||||
|
when task {} is
|
||||||
|
Err e -> Err e
|
||||||
|
Ok _ -> looper {}
|
||||||
|
|
||||||
|
@Task \{} -> looper {}
|
||||||
|
|
||||||
|
## Run a task repeatedly, until it fails with `err` or completes with `done`.
|
||||||
|
##
|
||||||
|
## ```
|
||||||
|
## sum =
|
||||||
|
## Task.loop! 0 \total ->
|
||||||
|
## numResult =
|
||||||
|
## Stdin.line
|
||||||
|
## |> Task.result!
|
||||||
|
## |> Result.try Str.toU64
|
||||||
|
##
|
||||||
|
## when numResult is
|
||||||
|
## Ok num -> Task.ok (Step (total + num))
|
||||||
|
## Err (StdinErr EndOfFile) -> Task.ok (Done total)
|
||||||
|
## Err InvalidNumStr -> Task.err NonNumberGiven
|
||||||
|
## ```
|
||||||
|
loop : state, (state -> Task [Step state, Done done] err) -> Task done err
|
||||||
|
loop = \state, step ->
|
||||||
|
looper = \current ->
|
||||||
|
(@Task next) = step current
|
||||||
|
when next {} is
|
||||||
|
Err e -> Err e
|
||||||
|
Ok (Done newResult) -> Ok newResult
|
||||||
|
Ok (Step newState) -> looper (newState)
|
||||||
|
|
||||||
|
@Task \{} -> looper state
|
||||||
|
|
||||||
|
## Create a task that always succeeds with the value provided.
|
||||||
|
##
|
||||||
|
## ```
|
||||||
|
## # Always succeeds with "Louis"
|
||||||
|
## getName : Task.Task Str *
|
||||||
|
## getName = Task.ok "Louis"
|
||||||
|
## ```
|
||||||
|
##
|
||||||
|
ok : a -> Task a *
|
||||||
|
ok = \a -> @Task \{} -> Ok a
|
||||||
|
|
||||||
|
## Create a task that always fails with the error provided.
|
||||||
|
##
|
||||||
|
## ```
|
||||||
|
## # Always fails with the tag `CustomError Str`
|
||||||
|
## customError : Str -> Task.Task {} [CustomError Str]
|
||||||
|
## customError = \err -> Task.err (CustomError err)
|
||||||
|
## ```
|
||||||
|
##
|
||||||
|
err : a -> Task * a
|
||||||
|
err = \a -> @Task \{} -> Err a
|
||||||
|
|
||||||
|
## Transform a given Task with a function that handles the success or error case
|
||||||
|
## and returns another task based on that. This is useful for chaining tasks
|
||||||
|
## together or performing error handling and recovery.
|
||||||
|
##
|
||||||
|
## Consider the following task:
|
||||||
|
##
|
||||||
|
## `canFail : Task {} [Failure, AnotherFail, YetAnotherFail]`
|
||||||
|
##
|
||||||
|
## We can use [attempt] to handle the failure cases using the following:
|
||||||
|
##
|
||||||
|
## ```
|
||||||
|
## Task.attempt canFail \result ->
|
||||||
|
## when result is
|
||||||
|
## Ok Success -> Stdout.line "Success!"
|
||||||
|
## Err Failure -> Stdout.line "Oops, failed!"
|
||||||
|
## Err AnotherFail -> Stdout.line "Ooooops, another failure!"
|
||||||
|
## Err YetAnotherFail -> Stdout.line "Really big oooooops, yet again!"
|
||||||
|
## ```
|
||||||
|
##
|
||||||
|
## Here we know that the `canFail` task may fail, and so we use
|
||||||
|
## `Task.attempt` to convert the task to a `Result` and then use pattern
|
||||||
|
## matching to handle the success and possible failure cases.
|
||||||
|
attempt : Task a b, (Result a b -> Task c d) -> Task c d
|
||||||
|
attempt = \@Task task, transform ->
|
||||||
|
@Task \{} ->
|
||||||
|
(@Task transformed) = transform (task {})
|
||||||
|
|
||||||
|
transformed {}
|
||||||
|
|
||||||
|
## Take the success value from a given [Task] and use that to generate a new [Task].
|
||||||
|
##
|
||||||
|
## We can [await] Task results with callbacks:
|
||||||
|
##
|
||||||
|
## ```
|
||||||
|
## Task.await (Stdin.line "What's your name?") \name ->
|
||||||
|
## Stdout.line "Your name is: $(name)"
|
||||||
|
## ```
|
||||||
|
##
|
||||||
|
## Or we can more succinctly use the `!` bang operator, which desugars to [await]:
|
||||||
|
##
|
||||||
|
## ```
|
||||||
|
## name = Stdin.line! "What's your name?"
|
||||||
|
## Stdout.line "Your name is: $(name)"
|
||||||
|
## ```
|
||||||
|
await : Task a b, (a -> Task c b) -> Task c b
|
||||||
|
await = \@Task task, transform ->
|
||||||
|
@Task \{} ->
|
||||||
|
when task {} is
|
||||||
|
Ok a ->
|
||||||
|
(@Task transformed) = transform a
|
||||||
|
transformed {}
|
||||||
|
|
||||||
|
Err b ->
|
||||||
|
Err b
|
||||||
|
|
||||||
|
## Take the error value from a given [Task] and use that to generate a new [Task].
|
||||||
|
##
|
||||||
|
## ```
|
||||||
|
## # Prints "Something went wrong!" to standard error if `canFail` fails.
|
||||||
|
## canFail
|
||||||
|
## |> Task.onErr \_ -> Stderr.line "Something went wrong!"
|
||||||
|
## ```
|
||||||
|
onErr : Task a b, (b -> Task a c) -> Task a c
|
||||||
|
onErr = \@Task task, transform ->
|
||||||
|
@Task \{} ->
|
||||||
|
when task {} is
|
||||||
|
Ok a ->
|
||||||
|
Ok a
|
||||||
|
|
||||||
|
Err b ->
|
||||||
|
(@Task transformed) = transform b
|
||||||
|
transformed {}
|
||||||
|
|
||||||
|
## Transform the success value of a given [Task] with a given function.
|
||||||
|
##
|
||||||
|
## ```
|
||||||
|
## # Succeeds with a value of "Bonjour Louis!"
|
||||||
|
## Task.ok "Louis"
|
||||||
|
## |> Task.map (\name -> "Bonjour $(name)!")
|
||||||
|
## ```
|
||||||
|
map : Task a c, (a -> b) -> Task b c
|
||||||
|
map = \@Task task, transform ->
|
||||||
|
@Task \{} ->
|
||||||
|
when task {} is
|
||||||
|
Ok a -> Ok (transform a)
|
||||||
|
Err b -> Err b
|
||||||
|
|
||||||
|
## Transform the error value of a given [Task] with a given function.
|
||||||
|
##
|
||||||
|
## ```
|
||||||
|
## # Ignore the fail value, and map it to the tag `CustomError`
|
||||||
|
## canFail
|
||||||
|
## |> Task.mapErr \_ -> CustomError
|
||||||
|
## ```
|
||||||
|
mapErr : Task c a, (a -> b) -> Task c b
|
||||||
|
mapErr = \@Task task, transform ->
|
||||||
|
@Task \{} ->
|
||||||
|
when task {} is
|
||||||
|
Ok a -> Ok a
|
||||||
|
Err b -> Err (transform b)
|
||||||
|
|
||||||
|
## Use a Result among other Tasks by converting it into a [Task].
|
||||||
|
fromResult : Result a b -> Task a b
|
||||||
|
fromResult = \res ->
|
||||||
|
@Task \{} -> res
|
||||||
|
|
||||||
|
## Apply a task to another task applicatively. This can be used with
|
||||||
|
## [ok] to build a [Task] that returns a record.
|
||||||
|
##
|
||||||
|
## The following example returns a Record with two fields, `apples` and
|
||||||
|
## `oranges`, each of which is a `List Str`. If it fails it returns the tag
|
||||||
|
## `NoFruitAvailable`.
|
||||||
|
##
|
||||||
|
## ```
|
||||||
|
## getFruitBasket : Task { apples : List Str, oranges : List Str } [NoFruitAvailable]
|
||||||
|
## getFruitBasket = Task.ok {
|
||||||
|
## apples: <- getFruit Apples |> Task.batch,
|
||||||
|
## oranges: <- getFruit Oranges |> Task.batch,
|
||||||
|
## }
|
||||||
|
## ```
|
||||||
|
batch : Task a c -> (Task (a -> b) c -> Task b c)
|
||||||
|
batch = \current ->
|
||||||
|
\next ->
|
||||||
|
await next \f ->
|
||||||
|
map current f
|
||||||
|
|
||||||
|
## Apply each task in a list sequentially, and return a list of the resulting values.
|
||||||
|
## Each task will be awaited before beginning the next task.
|
||||||
|
##
|
||||||
|
## ```
|
||||||
|
## fetchAuthorTasks : List (Task Author [DbError])
|
||||||
|
##
|
||||||
|
## getAuthors : Task (List Author) [DbError]
|
||||||
|
## getAuthors = Task.sequence fetchAuthorTasks
|
||||||
|
## ```
|
||||||
|
##
|
||||||
|
sequence : List (Task ok err) -> Task (List ok) err
|
||||||
|
sequence = \taskList ->
|
||||||
|
Task.loop (taskList, List.withCapacity (List.len taskList)) \(tasks, values) ->
|
||||||
|
when tasks is
|
||||||
|
[task, .. as rest] ->
|
||||||
|
value = task!
|
||||||
|
Task.ok (Step (rest, List.append values value))
|
||||||
|
|
||||||
|
[] ->
|
||||||
|
Task.ok (Done values)
|
||||||
|
|
||||||
|
## Apply a task repeatedly for each item in a list
|
||||||
|
##
|
||||||
|
## ```
|
||||||
|
## authors : List Author
|
||||||
|
## saveAuthor : Author -> Task {} [DbError]
|
||||||
|
##
|
||||||
|
## saveAuthors : Task (List Author) [DbError]
|
||||||
|
## saveAuthors = Task.forEach authors saveAuthor
|
||||||
|
## ```
|
||||||
|
##
|
||||||
|
forEach : List a, (a -> Task {} b) -> Task {} b
|
||||||
|
forEach = \items, fn ->
|
||||||
|
List.walk items (ok {}) \state, item ->
|
||||||
|
state |> await \_ -> fn item
|
||||||
|
|
||||||
|
## Transform a task that can either succeed with `ok`, or fail with `err`, into
|
||||||
|
## a task that succeeds with `Result ok err`.
|
||||||
|
##
|
||||||
|
## This is useful when chaining tasks using the `!` suffix. For example:
|
||||||
|
##
|
||||||
|
## ```
|
||||||
|
## # Path.roc
|
||||||
|
## checkFile : Str -> Task [Good, Bad] [IOError]
|
||||||
|
##
|
||||||
|
## # main.roc
|
||||||
|
## when checkFile "/usr/local/bin/roc" |> Task.result! is
|
||||||
|
## Ok Good -> "..."
|
||||||
|
## Ok Bad -> "..."
|
||||||
|
## Err IOError -> "..."
|
||||||
|
## ```
|
||||||
|
##
|
||||||
|
result : Task ok err -> Task (Result ok err) *
|
||||||
|
result = \@Task task ->
|
||||||
|
@Task \{} ->
|
||||||
|
Ok (task {})
|
|
@ -11,4 +11,5 @@ package [
|
||||||
Hash,
|
Hash,
|
||||||
Box,
|
Box,
|
||||||
Inspect,
|
Inspect,
|
||||||
|
Task,
|
||||||
] {}
|
] {}
|
||||||
|
|
|
@ -16,6 +16,7 @@ pub fn module_source(module_id: ModuleId) -> &'static str {
|
||||||
ModuleId::DECODE => DECODE,
|
ModuleId::DECODE => DECODE,
|
||||||
ModuleId::HASH => HASH,
|
ModuleId::HASH => HASH,
|
||||||
ModuleId::INSPECT => INSPECT,
|
ModuleId::INSPECT => INSPECT,
|
||||||
|
ModuleId::TASK => TASK,
|
||||||
_ => internal_error!(
|
_ => internal_error!(
|
||||||
"ModuleId {:?} is not part of the standard library",
|
"ModuleId {:?} is not part of the standard library",
|
||||||
module_id
|
module_id
|
||||||
|
@ -35,3 +36,4 @@ const ENCODE: &str = include_str!("../roc/Encode.roc");
|
||||||
const DECODE: &str = include_str!("../roc/Decode.roc");
|
const DECODE: &str = include_str!("../roc/Decode.roc");
|
||||||
const HASH: &str = include_str!("../roc/Hash.roc");
|
const HASH: &str = include_str!("../roc/Hash.roc");
|
||||||
const INSPECT: &str = include_str!("../roc/Inspect.roc");
|
const INSPECT: &str = include_str!("../roc/Inspect.roc");
|
||||||
|
const TASK: &str = include_str!("../roc/Task.roc");
|
||||||
|
|
|
@ -290,12 +290,14 @@ fn deep_copy_expr_help<C: CopyEnv>(env: &mut C, copied: &mut Vec<Variable>, expr
|
||||||
Var(sym, var) => Var(*sym, sub!(*var)),
|
Var(sym, var) => Var(*sym, sub!(*var)),
|
||||||
ParamsVar {
|
ParamsVar {
|
||||||
symbol,
|
symbol,
|
||||||
params,
|
|
||||||
var,
|
var,
|
||||||
|
params_symbol,
|
||||||
|
params_var,
|
||||||
} => ParamsVar {
|
} => ParamsVar {
|
||||||
symbol: *symbol,
|
symbol: *symbol,
|
||||||
params: *params,
|
|
||||||
var: sub!(*var),
|
var: sub!(*var),
|
||||||
|
params_symbol: *params_symbol,
|
||||||
|
params_var: sub!(*params_var),
|
||||||
},
|
},
|
||||||
ImportParams(module_id, region, opt_provided) => ImportParams(
|
ImportParams(module_id, region, opt_provided) => ImportParams(
|
||||||
*module_id,
|
*module_id,
|
||||||
|
|
|
@ -3,12 +3,14 @@
|
||||||
use crate::def::Def;
|
use crate::def::Def;
|
||||||
use crate::expr::Expr::{self, *};
|
use crate::expr::Expr::{self, *};
|
||||||
use crate::expr::{
|
use crate::expr::{
|
||||||
ClosureData, DeclarationTag, Declarations, FunctionDef, OpaqueWrapFunctionData, WhenBranch,
|
ClosureData, DeclarationTag, Declarations, FunctionDef, OpaqueWrapFunctionData,
|
||||||
|
StructAccessorData, WhenBranch,
|
||||||
};
|
};
|
||||||
use crate::pattern::{Pattern, RecordDestruct, TupleDestruct};
|
use crate::pattern::{Pattern, RecordDestruct, TupleDestruct};
|
||||||
|
|
||||||
use roc_module::symbol::{Interns, ModuleId, Symbol};
|
use roc_module::symbol::{Interns, ModuleId, Symbol};
|
||||||
|
|
||||||
|
use roc_types::types::IndexOrField;
|
||||||
use ven_pretty::{text, Arena, DocAllocator, DocBuilder};
|
use ven_pretty::{text, Arena, DocAllocator, DocBuilder};
|
||||||
|
|
||||||
pub struct Ctx<'a> {
|
pub struct Ctx<'a> {
|
||||||
|
@ -381,7 +383,10 @@ fn expr<'a>(c: &Ctx, p: EPrec, f: &'a Arena<'a>, e: &'a Expr) -> DocBuilder<'a,
|
||||||
OpaqueWrapFunction(OpaqueWrapFunctionData { opaque_name, .. }) => {
|
OpaqueWrapFunction(OpaqueWrapFunctionData { opaque_name, .. }) => {
|
||||||
text!(f, "@{}", opaque_name.as_str(c.interns))
|
text!(f, "@{}", opaque_name.as_str(c.interns))
|
||||||
}
|
}
|
||||||
RecordAccessor(_) => todo!(),
|
RecordAccessor(StructAccessorData { field, .. }) => match field {
|
||||||
|
IndexOrField::Index(index) => text!(f, ".{}", index),
|
||||||
|
IndexOrField::Field(name) => text!(f, ".{}", name),
|
||||||
|
},
|
||||||
RecordUpdate {
|
RecordUpdate {
|
||||||
symbol, updates, ..
|
symbol, updates, ..
|
||||||
} => f
|
} => f
|
||||||
|
|
|
@ -22,6 +22,7 @@ use crate::pattern::{canonicalize_def_header_pattern, BindingsFromPattern, Patte
|
||||||
use crate::procedure::QualifiedReference;
|
use crate::procedure::QualifiedReference;
|
||||||
use crate::procedure::References;
|
use crate::procedure::References;
|
||||||
use crate::scope::create_alias;
|
use crate::scope::create_alias;
|
||||||
|
use crate::scope::SymbolLookup;
|
||||||
use crate::scope::{PendingAbilitiesInScope, Scope};
|
use crate::scope::{PendingAbilitiesInScope, Scope};
|
||||||
use roc_collections::ReferenceMatrix;
|
use roc_collections::ReferenceMatrix;
|
||||||
use roc_collections::VecMap;
|
use roc_collections::VecMap;
|
||||||
|
@ -111,6 +112,23 @@ impl Annotation {
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn convert_to_fn(&mut self, argument_count: usize, var_store: &mut VarStore) {
|
||||||
|
let mut arg_types = Vec::with_capacity(argument_count);
|
||||||
|
|
||||||
|
for _ in 0..argument_count {
|
||||||
|
let var = var_store.fresh();
|
||||||
|
self.introduced_variables.insert_inferred(Loc::at_zero(var));
|
||||||
|
|
||||||
|
arg_types.push(Type::Variable(var));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.signature = Type::Function(
|
||||||
|
arg_types,
|
||||||
|
Box::new(Type::Variable(var_store.fresh())),
|
||||||
|
Box::new(self.signature.clone()),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -165,6 +183,7 @@ enum PendingValueDef<'a> {
|
||||||
/// Module params from an import
|
/// Module params from an import
|
||||||
ImportParams {
|
ImportParams {
|
||||||
symbol: Symbol,
|
symbol: Symbol,
|
||||||
|
variable: Variable,
|
||||||
loc_pattern: Loc<Pattern>,
|
loc_pattern: Loc<Pattern>,
|
||||||
module_id: ModuleId,
|
module_id: ModuleId,
|
||||||
opt_provided: Option<ast::Collection<'a, Loc<AssignedField<'a, ast::Expr<'a>>>>>,
|
opt_provided: Option<ast::Collection<'a, Loc<AssignedField<'a, ast::Expr<'a>>>>>,
|
||||||
|
@ -186,6 +205,7 @@ impl PendingValueDef<'_> {
|
||||||
PendingValueDef::ImportParams {
|
PendingValueDef::ImportParams {
|
||||||
loc_pattern,
|
loc_pattern,
|
||||||
symbol: _,
|
symbol: _,
|
||||||
|
variable: _,
|
||||||
module_id: _,
|
module_id: _,
|
||||||
opt_provided: _,
|
opt_provided: _,
|
||||||
} => loc_pattern,
|
} => loc_pattern,
|
||||||
|
@ -1153,6 +1173,7 @@ fn canonicalize_value_defs<'a>(
|
||||||
|
|
||||||
pending_value_defs.push(PendingValueDef::ImportParams {
|
pending_value_defs.push(PendingValueDef::ImportParams {
|
||||||
symbol: params.symbol,
|
symbol: params.symbol,
|
||||||
|
variable: params.variable,
|
||||||
loc_pattern: params.loc_pattern,
|
loc_pattern: params.loc_pattern,
|
||||||
opt_provided: params.opt_provided,
|
opt_provided: params.opt_provided,
|
||||||
module_id,
|
module_id,
|
||||||
|
@ -2400,15 +2421,17 @@ fn canonicalize_pending_value_def<'a>(
|
||||||
}
|
}
|
||||||
ImportParams {
|
ImportParams {
|
||||||
symbol,
|
symbol,
|
||||||
|
variable,
|
||||||
loc_pattern,
|
loc_pattern,
|
||||||
module_id,
|
module_id,
|
||||||
opt_provided,
|
opt_provided,
|
||||||
} => {
|
} => {
|
||||||
// Insert a reference to the record so that we don't report it as unused
|
// Insert a reference to the record so that we don't report it as unused
|
||||||
// If the whole module is unused, we'll report that separately
|
// If the whole module is unused, we'll report that separately
|
||||||
output
|
output.references.insert_value_lookup(
|
||||||
.references
|
SymbolLookup::no_params(symbol),
|
||||||
.insert_value_lookup(symbol, QualifiedReference::Unqualified);
|
QualifiedReference::Unqualified,
|
||||||
|
);
|
||||||
|
|
||||||
let (opt_var_record, references) = match opt_provided {
|
let (opt_var_record, references) = match opt_provided {
|
||||||
Some(params) => {
|
Some(params) => {
|
||||||
|
@ -2418,7 +2441,7 @@ fn canonicalize_pending_value_def<'a>(
|
||||||
let references = can_output.references.clone();
|
let references = can_output.references.clone();
|
||||||
output.union(can_output);
|
output.union(can_output);
|
||||||
|
|
||||||
(Some((var_store.fresh(), Box::new(record))), references)
|
(Some((variable, Box::new(record))), references)
|
||||||
}
|
}
|
||||||
None => (None, References::new()),
|
None => (None, References::new()),
|
||||||
};
|
};
|
||||||
|
@ -2725,12 +2748,11 @@ pub fn report_unused_imports(
|
||||||
for (symbol, region) in &import.exposed_symbols {
|
for (symbol, region) in &import.exposed_symbols {
|
||||||
if !references.has_unqualified_type_or_value_lookup(*symbol)
|
if !references.has_unqualified_type_or_value_lookup(*symbol)
|
||||||
&& !scope.abilities_store.is_specialization_name(*symbol)
|
&& !scope.abilities_store.is_specialization_name(*symbol)
|
||||||
&& !import.is_task(env)
|
|
||||||
{
|
{
|
||||||
env.problem(Problem::UnusedImport(*symbol, *region));
|
env.problem(Problem::UnusedImport(*symbol, *region));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if !import.is_task(env) {
|
} else {
|
||||||
env.problem(Problem::UnusedModuleImport(import.module_id, import.region));
|
env.problem(Problem::UnusedModuleImport(import.module_id, import.region));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3003,6 +3025,7 @@ struct PendingModuleImport<'a> {
|
||||||
|
|
||||||
struct PendingModuleImportParams<'a> {
|
struct PendingModuleImportParams<'a> {
|
||||||
symbol: Symbol,
|
symbol: Symbol,
|
||||||
|
variable: Variable,
|
||||||
loc_pattern: Loc<Pattern>,
|
loc_pattern: Loc<Pattern>,
|
||||||
opt_provided: Option<ast::Collection<'a, Loc<AssignedField<'a, ast::Expr<'a>>>>>,
|
opt_provided: Option<ast::Collection<'a, Loc<AssignedField<'a, ast::Expr<'a>>>>>,
|
||||||
}
|
}
|
||||||
|
@ -3013,16 +3036,6 @@ pub struct IntroducedImport {
|
||||||
exposed_symbols: Vec<(Symbol, Region)>,
|
exposed_symbols: Vec<(Symbol, Region)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntroducedImport {
|
|
||||||
pub fn is_task(&self, env: &Env<'_>) -> bool {
|
|
||||||
// Temporarily needed for `!` convenience. Can be removed when Task becomes a builtin.
|
|
||||||
match env.qualified_module_ids.get_name(self.module_id) {
|
|
||||||
Some(name) => name.as_inner().as_str() == "Task",
|
|
||||||
None => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn to_pending_value_def<'a>(
|
fn to_pending_value_def<'a>(
|
||||||
env: &mut Env<'a>,
|
env: &mut Env<'a>,
|
||||||
|
@ -3160,15 +3173,17 @@ fn to_pending_value_def<'a>(
|
||||||
// We do this even if params weren't provided so that solve can report if they are missing
|
// We do this even if params weren't provided so that solve can report if they are missing
|
||||||
let params_sym = scope.gen_unique_symbol();
|
let params_sym = scope.gen_unique_symbol();
|
||||||
let params_region = module_import.params.map(|p| p.params.region).unwrap_or(region);
|
let params_region = module_import.params.map(|p| p.params.region).unwrap_or(region);
|
||||||
|
let params_var = var_store.fresh();
|
||||||
let params =
|
let params =
|
||||||
PendingModuleImportParams {
|
PendingModuleImportParams {
|
||||||
symbol: params_sym,
|
symbol: params_sym,
|
||||||
|
variable: params_var,
|
||||||
loc_pattern: Loc::at(params_region, Pattern::Identifier(params_sym)),
|
loc_pattern: Loc::at(params_region, Pattern::Identifier(params_sym)),
|
||||||
opt_provided: module_import.params.map(|p| p.params.value),
|
opt_provided: module_import.params.map(|p| p.params.value),
|
||||||
};
|
};
|
||||||
let provided_params_sym = if module_import.params.is_some() {
|
let provided_params = if module_import.params.is_some() {
|
||||||
// Only add params to scope if they are provided
|
// Only add params to scope if they are provided
|
||||||
Some(params_sym)
|
Some((params_var, params_sym))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -3176,7 +3191,7 @@ fn to_pending_value_def<'a>(
|
||||||
if let Err(existing_import) =
|
if let Err(existing_import) =
|
||||||
scope
|
scope
|
||||||
.modules
|
.modules
|
||||||
.insert(name_with_alias.clone(), module_id, provided_params_sym, region)
|
.insert(name_with_alias.clone(), module_id, provided_params, region)
|
||||||
{
|
{
|
||||||
env.problems.push(Problem::ImportNameConflict {
|
env.problems.push(Problem::ImportNameConflict {
|
||||||
name: name_with_alias,
|
name: name_with_alias,
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -8,6 +8,7 @@ use roc_module::ident::{Ident, ModuleName};
|
||||||
use roc_module::symbol::{IdentIdsByModule, ModuleId, PQModuleName, PackageModuleIds, Symbol};
|
use roc_module::symbol::{IdentIdsByModule, ModuleId, PQModuleName, PackageModuleIds, Symbol};
|
||||||
use roc_problem::can::{Problem, RuntimeError};
|
use roc_problem::can::{Problem, RuntimeError};
|
||||||
use roc_region::all::{Loc, Region};
|
use roc_region::all::{Loc, Region};
|
||||||
|
use roc_types::subs::Variable;
|
||||||
|
|
||||||
/// The canonicalization environment for a particular module.
|
/// The canonicalization environment for a particular module.
|
||||||
pub struct Env<'a> {
|
pub struct Env<'a> {
|
||||||
|
@ -38,6 +39,8 @@ pub struct Env<'a> {
|
||||||
|
|
||||||
pub top_level_symbols: VecSet<Symbol>,
|
pub top_level_symbols: VecSet<Symbol>,
|
||||||
|
|
||||||
|
pub home_params_record: Option<(Symbol, Variable)>,
|
||||||
|
|
||||||
pub arena: &'a Bump,
|
pub arena: &'a Bump,
|
||||||
|
|
||||||
pub opt_shorthand: Option<&'a str>,
|
pub opt_shorthand: Option<&'a str>,
|
||||||
|
@ -64,6 +67,7 @@ impl<'a> Env<'a> {
|
||||||
qualified_type_lookups: VecSet::default(),
|
qualified_type_lookups: VecSet::default(),
|
||||||
tailcallable_symbol: None,
|
tailcallable_symbol: None,
|
||||||
top_level_symbols: VecSet::default(),
|
top_level_symbols: VecSet::default(),
|
||||||
|
home_params_record: None,
|
||||||
opt_shorthand,
|
opt_shorthand,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ use roc_error_macros::internal_error;
|
||||||
use roc_module::called_via::CalledVia;
|
use roc_module::called_via::CalledVia;
|
||||||
use roc_module::ident::{ForeignSymbol, Lowercase, TagName};
|
use roc_module::ident::{ForeignSymbol, Lowercase, TagName};
|
||||||
use roc_module::low_level::LowLevel;
|
use roc_module::low_level::LowLevel;
|
||||||
use roc_module::symbol::{ModuleId, Symbol};
|
use roc_module::symbol::{IdentId, ModuleId, Symbol};
|
||||||
use roc_parse::ast::{self, Defs, PrecedenceConflict, StrLiteral};
|
use roc_parse::ast::{self, Defs, PrecedenceConflict, StrLiteral};
|
||||||
use roc_parse::ident::Accessor;
|
use roc_parse::ident::Accessor;
|
||||||
use roc_parse::pattern::PatternType::*;
|
use roc_parse::pattern::PatternType::*;
|
||||||
|
@ -111,8 +111,9 @@ pub enum Expr {
|
||||||
/// Like Var, but from a module with params
|
/// Like Var, but from a module with params
|
||||||
ParamsVar {
|
ParamsVar {
|
||||||
symbol: Symbol,
|
symbol: Symbol,
|
||||||
params: Symbol,
|
|
||||||
var: Variable,
|
var: Variable,
|
||||||
|
params_symbol: Symbol,
|
||||||
|
params_var: Variable,
|
||||||
},
|
},
|
||||||
AbilityMember(
|
AbilityMember(
|
||||||
/// Actual member name
|
/// Actual member name
|
||||||
|
@ -320,8 +321,9 @@ impl Expr {
|
||||||
&Self::Var(sym, _) => Category::Lookup(sym),
|
&Self::Var(sym, _) => Category::Lookup(sym),
|
||||||
&Self::ParamsVar {
|
&Self::ParamsVar {
|
||||||
symbol,
|
symbol,
|
||||||
params: _,
|
|
||||||
var: _,
|
var: _,
|
||||||
|
params_symbol: _,
|
||||||
|
params_var: _,
|
||||||
} => Category::Lookup(symbol),
|
} => Category::Lookup(symbol),
|
||||||
&Self::AbilityMember(sym, _, _) => Category::Lookup(sym),
|
&Self::AbilityMember(sym, _, _) => Category::Lookup(sym),
|
||||||
Self::When { .. } => Category::When,
|
Self::When { .. } => Category::When,
|
||||||
|
@ -648,9 +650,7 @@ pub fn canonicalize_expr<'a>(
|
||||||
|
|
||||||
(answer, Output::default())
|
(answer, Output::default())
|
||||||
}
|
}
|
||||||
ast::Expr::Record(fields) => {
|
ast::Expr::Record(fields) => canonicalize_record(env, var_store, scope, region, *fields),
|
||||||
canonicalize_record(env, var_store, scope, region, *fields)
|
|
||||||
}
|
|
||||||
ast::Expr::RecordUpdate {
|
ast::Expr::RecordUpdate {
|
||||||
fields,
|
fields,
|
||||||
update: loc_update,
|
update: loc_update,
|
||||||
|
@ -1022,6 +1022,9 @@ pub fn canonicalize_expr<'a>(
|
||||||
ast::Expr::Backpassing(_, _, _) => {
|
ast::Expr::Backpassing(_, _, _) => {
|
||||||
internal_error!("Backpassing should have been desugared by now")
|
internal_error!("Backpassing should have been desugared by now")
|
||||||
}
|
}
|
||||||
|
ast::Expr::RecordUpdater(_) => {
|
||||||
|
internal_error!("Record updater should have been desugared by now")
|
||||||
|
}
|
||||||
ast::Expr::Closure(loc_arg_patterns, loc_body_expr) => {
|
ast::Expr::Closure(loc_arg_patterns, loc_body_expr) => {
|
||||||
let (closure_data, output) =
|
let (closure_data, output) =
|
||||||
canonicalize_closure(env, var_store, scope, loc_arg_patterns, loc_body_expr, None);
|
canonicalize_closure(env, var_store, scope, loc_arg_patterns, loc_body_expr, None);
|
||||||
|
@ -1119,7 +1122,9 @@ pub fn canonicalize_expr<'a>(
|
||||||
output,
|
output,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ast::Expr::TaskAwaitBang(..) => internal_error!("a Expr::TaskAwaitBang expression was not completely removed in desugar_value_def_suffixed"),
|
ast::Expr::TrySuffix { .. } => internal_error!(
|
||||||
|
"a Expr::TrySuffix expression was not completely removed in desugar_value_def_suffixed"
|
||||||
|
),
|
||||||
ast::Expr::Tag(tag) => {
|
ast::Expr::Tag(tag) => {
|
||||||
let variant_var = var_store.fresh();
|
let variant_var = var_store.fresh();
|
||||||
let ext_var = var_store.fresh();
|
let ext_var = var_store.fresh();
|
||||||
|
@ -1204,7 +1209,7 @@ pub fn canonicalize_expr<'a>(
|
||||||
output,
|
output,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ast::Expr::Dbg(_, _) => {
|
ast::Expr::Dbg | ast::Expr::DbgStmt(_, _) => {
|
||||||
internal_error!("Dbg should have been desugared by now")
|
internal_error!("Dbg should have been desugared by now")
|
||||||
}
|
}
|
||||||
ast::Expr::LowLevelDbg((source_location, source), message, continuation) => {
|
ast::Expr::LowLevelDbg((source_location, source), message, continuation) => {
|
||||||
|
@ -1371,7 +1376,10 @@ pub fn canonicalize_expr<'a>(
|
||||||
use roc_problem::can::RuntimeError::*;
|
use roc_problem::can::RuntimeError::*;
|
||||||
|
|
||||||
let sub_region = Region::span_across(&loc_name.region, &loc_value.region);
|
let sub_region = Region::span_across(&loc_name.region, &loc_value.region);
|
||||||
let problem = OptionalFieldInRecordBuilder {record: region, field: sub_region };
|
let problem = OptionalFieldInRecordBuilder {
|
||||||
|
record: region,
|
||||||
|
field: sub_region,
|
||||||
|
};
|
||||||
env.problem(Problem::RuntimeError(problem.clone()));
|
env.problem(Problem::RuntimeError(problem.clone()));
|
||||||
|
|
||||||
(RuntimeError(problem), Output::default())
|
(RuntimeError(problem), Output::default())
|
||||||
|
@ -1548,6 +1556,8 @@ fn canonicalize_closure_body<'a>(
|
||||||
&loc_body_expr.value,
|
&loc_body_expr.value,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let mut references_top_level = false;
|
||||||
|
|
||||||
let mut captured_symbols: Vec<_> = new_output
|
let mut captured_symbols: Vec<_> = new_output
|
||||||
.references
|
.references
|
||||||
.value_lookups()
|
.value_lookups()
|
||||||
|
@ -1558,7 +1568,11 @@ fn canonicalize_closure_body<'a>(
|
||||||
.filter(|s| !new_output.references.bound_symbols().any(|x| x == s))
|
.filter(|s| !new_output.references.bound_symbols().any(|x| x == s))
|
||||||
.filter(|s| bound_by_argument_patterns.iter().all(|(k, _)| s != k))
|
.filter(|s| bound_by_argument_patterns.iter().all(|(k, _)| s != k))
|
||||||
// filter out top-level symbols those will be globally available, and don't need to be captured
|
// filter out top-level symbols those will be globally available, and don't need to be captured
|
||||||
.filter(|s| !env.top_level_symbols.contains(s))
|
.filter(|s| {
|
||||||
|
let is_top_level = env.top_level_symbols.contains(s);
|
||||||
|
references_top_level = references_top_level || is_top_level;
|
||||||
|
!is_top_level
|
||||||
|
})
|
||||||
// filter out imported symbols those will be globally available, and don't need to be captured
|
// filter out imported symbols those will be globally available, and don't need to be captured
|
||||||
.filter(|s| s.module_id() == env.home)
|
.filter(|s| s.module_id() == env.home)
|
||||||
// filter out functions that don't close over anything
|
// filter out functions that don't close over anything
|
||||||
|
@ -1567,6 +1581,15 @@ fn canonicalize_closure_body<'a>(
|
||||||
.map(|s| (s, var_store.fresh()))
|
.map(|s| (s, var_store.fresh()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
if references_top_level {
|
||||||
|
if let Some(params_record) = env.home_params_record {
|
||||||
|
// If this module has params and the closure references top-level symbols,
|
||||||
|
// we need to capture the whole record so we can pass it.
|
||||||
|
// The lower_params pass will take care of removing the captures for top-level fns.
|
||||||
|
captured_symbols.push(params_record);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
output.union(new_output);
|
output.union(new_output);
|
||||||
|
|
||||||
// Now that we've collected all the references, check to see if any of the args we defined
|
// Now that we've collected all the references, check to see if any of the args we defined
|
||||||
|
@ -1912,7 +1935,7 @@ fn canonicalize_var_lookup(
|
||||||
Ok(lookup) => {
|
Ok(lookup) => {
|
||||||
output
|
output
|
||||||
.references
|
.references
|
||||||
.insert_value_lookup(lookup.symbol, QualifiedReference::Unqualified);
|
.insert_value_lookup(lookup, QualifiedReference::Unqualified);
|
||||||
|
|
||||||
if scope.abilities_store.is_ability_member_name(lookup.symbol) {
|
if scope.abilities_store.is_ability_member_name(lookup.symbol) {
|
||||||
AbilityMember(
|
AbilityMember(
|
||||||
|
@ -1921,7 +1944,7 @@ fn canonicalize_var_lookup(
|
||||||
var_store.fresh(),
|
var_store.fresh(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
lookup_to_expr(lookup, var_store.fresh())
|
lookup_to_expr(var_store, lookup)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(problem) => {
|
Err(problem) => {
|
||||||
|
@ -1937,7 +1960,7 @@ fn canonicalize_var_lookup(
|
||||||
Ok(lookup) => {
|
Ok(lookup) => {
|
||||||
output
|
output
|
||||||
.references
|
.references
|
||||||
.insert_value_lookup(lookup.symbol, QualifiedReference::Qualified);
|
.insert_value_lookup(lookup, QualifiedReference::Qualified);
|
||||||
|
|
||||||
if scope.abilities_store.is_ability_member_name(lookup.symbol) {
|
if scope.abilities_store.is_ability_member_name(lookup.symbol) {
|
||||||
AbilityMember(
|
AbilityMember(
|
||||||
|
@ -1946,7 +1969,7 @@ fn canonicalize_var_lookup(
|
||||||
var_store.fresh(),
|
var_store.fresh(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
lookup_to_expr(lookup, var_store.fresh())
|
lookup_to_expr(var_store, lookup)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(problem) => {
|
Err(problem) => {
|
||||||
|
@ -1965,20 +1988,21 @@ fn canonicalize_var_lookup(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_to_expr(
|
fn lookup_to_expr(
|
||||||
|
var_store: &mut VarStore,
|
||||||
SymbolLookup {
|
SymbolLookup {
|
||||||
symbol,
|
symbol,
|
||||||
module_params: params,
|
module_params,
|
||||||
}: SymbolLookup,
|
}: SymbolLookup,
|
||||||
var: Variable,
|
|
||||||
) -> Expr {
|
) -> Expr {
|
||||||
if let Some(params) = params {
|
if let Some((params_var, params_symbol)) = module_params {
|
||||||
Expr::ParamsVar {
|
Expr::ParamsVar {
|
||||||
symbol,
|
symbol,
|
||||||
params,
|
var: var_store.fresh(),
|
||||||
var,
|
params_symbol,
|
||||||
|
params_var,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Expr::Var(symbol, var)
|
Expr::Var(symbol, var_store.fresh())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2462,22 +2486,30 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
|
||||||
| ast::Expr::Num(_)
|
| ast::Expr::Num(_)
|
||||||
| ast::Expr::NonBase10Int { .. }
|
| ast::Expr::NonBase10Int { .. }
|
||||||
| ast::Expr::AccessorFunction(_)
|
| ast::Expr::AccessorFunction(_)
|
||||||
|
| ast::Expr::RecordUpdater(_)
|
||||||
| ast::Expr::Crash
|
| ast::Expr::Crash
|
||||||
|
| ast::Expr::Dbg
|
||||||
| ast::Expr::Underscore(_)
|
| ast::Expr::Underscore(_)
|
||||||
| ast::Expr::MalformedIdent(_, _)
|
| ast::Expr::MalformedIdent(_, _)
|
||||||
| ast::Expr::Tag(_)
|
| ast::Expr::Tag(_)
|
||||||
| ast::Expr::OpaqueRef(_)
|
| ast::Expr::OpaqueRef(_)
|
||||||
| ast::Expr::MalformedClosure => true,
|
| ast::Expr::MalformedClosure => true,
|
||||||
// Newlines are disallowed inside interpolation, and these all require newlines
|
// Newlines are disallowed inside interpolation, and these all require newlines
|
||||||
ast::Expr::Dbg(_, _)
|
ast::Expr::DbgStmt(_, _)
|
||||||
| ast::Expr::LowLevelDbg(_, _, _)
|
| ast::Expr::LowLevelDbg(_, _, _)
|
||||||
| ast::Expr::Defs(_, _)
|
|
||||||
| ast::Expr::Expect(_, _)
|
| ast::Expr::Expect(_, _)
|
||||||
| ast::Expr::When(_, _)
|
| ast::Expr::When(_, _)
|
||||||
| ast::Expr::Backpassing(_, _, _)
|
| ast::Expr::Backpassing(_, _, _)
|
||||||
| ast::Expr::SpaceBefore(_, _)
|
| ast::Expr::SpaceBefore(_, _)
|
||||||
| ast::Expr::Str(StrLiteral::Block(_))
|
| ast::Expr::Str(StrLiteral::Block(_))
|
||||||
| ast::Expr::SpaceAfter(_, _) => false,
|
| ast::Expr::SpaceAfter(_, _) => false,
|
||||||
|
// Desugared dbg expression
|
||||||
|
ast::Expr::Defs(_, loc_ret) => match loc_ret.value {
|
||||||
|
ast::Expr::LowLevelDbg(_, _, continuation) => {
|
||||||
|
is_valid_interpolation(&continuation.value)
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
// These can contain subexpressions, so we need to recursively check those
|
// These can contain subexpressions, so we need to recursively check those
|
||||||
ast::Expr::Str(StrLiteral::Line(segments)) => {
|
ast::Expr::Str(StrLiteral::Line(segments)) => {
|
||||||
segments.iter().all(|segment| match segment {
|
segments.iter().all(|segment| match segment {
|
||||||
|
@ -2515,7 +2547,7 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
|
||||||
ast::Expr::TupleAccess(sub_expr, _)
|
ast::Expr::TupleAccess(sub_expr, _)
|
||||||
| ast::Expr::ParensAround(sub_expr)
|
| ast::Expr::ParensAround(sub_expr)
|
||||||
| ast::Expr::RecordAccess(sub_expr, _)
|
| ast::Expr::RecordAccess(sub_expr, _)
|
||||||
| ast::Expr::TaskAwaitBang(sub_expr) => is_valid_interpolation(sub_expr),
|
| ast::Expr::TrySuffix { expr: sub_expr, .. } => is_valid_interpolation(sub_expr),
|
||||||
ast::Expr::Apply(loc_expr, args, _called_via) => {
|
ast::Expr::Apply(loc_expr, args, _called_via) => {
|
||||||
is_valid_interpolation(&loc_expr.value)
|
is_valid_interpolation(&loc_expr.value)
|
||||||
&& args
|
&& args
|
||||||
|
@ -2767,6 +2799,9 @@ pub struct Declarations {
|
||||||
// used for ability member specializatons.
|
// used for ability member specializatons.
|
||||||
pub specializes: VecMap<usize, Symbol>,
|
pub specializes: VecMap<usize, Symbol>,
|
||||||
|
|
||||||
|
// used while lowering params.
|
||||||
|
arity_by_name: VecMap<IdentId, usize>,
|
||||||
|
|
||||||
pub host_exposed_annotations: VecMap<usize, (Variable, crate::def::Annotation)>,
|
pub host_exposed_annotations: VecMap<usize, (Variable, crate::def::Annotation)>,
|
||||||
|
|
||||||
pub function_bodies: Vec<Loc<FunctionDef>>,
|
pub function_bodies: Vec<Loc<FunctionDef>>,
|
||||||
|
@ -2795,6 +2830,7 @@ impl Declarations {
|
||||||
expressions: Vec::with_capacity(capacity),
|
expressions: Vec::with_capacity(capacity),
|
||||||
specializes: VecMap::default(), // number of specializations is probably low
|
specializes: VecMap::default(), // number of specializations is probably low
|
||||||
destructs: Vec::new(), // number of destructs is probably low
|
destructs: Vec::new(), // number of destructs is probably low
|
||||||
|
arity_by_name: VecMap::with_capacity(capacity),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2833,6 +2869,9 @@ impl Declarations {
|
||||||
arguments: loc_closure_data.value.arguments,
|
arguments: loc_closure_data.value.arguments,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.arity_by_name
|
||||||
|
.insert(symbol.value.ident_id(), function_def.arguments.len());
|
||||||
|
|
||||||
let loc_function_def = Loc::at(loc_closure_data.region, function_def);
|
let loc_function_def = Loc::at(loc_closure_data.region, function_def);
|
||||||
|
|
||||||
let function_def_index = Index::push_new(&mut self.function_bodies, loc_function_def);
|
let function_def_index = Index::push_new(&mut self.function_bodies, loc_function_def);
|
||||||
|
@ -2881,6 +2920,9 @@ impl Declarations {
|
||||||
arguments: loc_closure_data.value.arguments,
|
arguments: loc_closure_data.value.arguments,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.arity_by_name
|
||||||
|
.insert(symbol.value.ident_id(), function_def.arguments.len());
|
||||||
|
|
||||||
let loc_function_def = Loc::at(loc_closure_data.region, function_def);
|
let loc_function_def = Loc::at(loc_closure_data.region, function_def);
|
||||||
|
|
||||||
let function_def_index = Index::push_new(&mut self.function_bodies, loc_function_def);
|
let function_def_index = Index::push_new(&mut self.function_bodies, loc_function_def);
|
||||||
|
@ -2957,6 +2999,8 @@ impl Declarations {
|
||||||
.insert(self.declarations.len(), annotation);
|
.insert(self.declarations.len(), annotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.arity_by_name.insert(symbol.value.ident_id(), 0);
|
||||||
|
|
||||||
self.declarations.push(DeclarationTag::Value);
|
self.declarations.push(DeclarationTag::Value);
|
||||||
self.variables.push(expr_var);
|
self.variables.push(expr_var);
|
||||||
self.symbols.push(symbol);
|
self.symbols.push(symbol);
|
||||||
|
@ -3073,6 +3117,60 @@ impl Declarations {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convert a value def to a function def with the given arguments
|
||||||
|
/// Currently used in lower_params
|
||||||
|
pub fn convert_value_to_function(
|
||||||
|
&mut self,
|
||||||
|
index: usize,
|
||||||
|
new_arguments: Vec<(Variable, AnnotatedMark, Loc<Pattern>)>,
|
||||||
|
var_store: &mut VarStore,
|
||||||
|
) {
|
||||||
|
match self.declarations[index] {
|
||||||
|
DeclarationTag::Value => {
|
||||||
|
let new_args_len = new_arguments.len();
|
||||||
|
|
||||||
|
let loc_body = self.expressions[index].clone();
|
||||||
|
let region = loc_body.region;
|
||||||
|
|
||||||
|
let closure_data = ClosureData {
|
||||||
|
function_type: var_store.fresh(),
|
||||||
|
closure_type: var_store.fresh(),
|
||||||
|
return_type: var_store.fresh(),
|
||||||
|
name: self.symbols[index].value,
|
||||||
|
captured_symbols: vec![],
|
||||||
|
recursive: Recursive::NotRecursive,
|
||||||
|
arguments: new_arguments,
|
||||||
|
loc_body: Box::new(loc_body),
|
||||||
|
};
|
||||||
|
|
||||||
|
let loc_closure_data = Loc::at(region, closure_data);
|
||||||
|
|
||||||
|
let function_def = FunctionDef {
|
||||||
|
closure_type: loc_closure_data.value.closure_type,
|
||||||
|
return_type: loc_closure_data.value.return_type,
|
||||||
|
captured_symbols: loc_closure_data.value.captured_symbols,
|
||||||
|
arguments: loc_closure_data.value.arguments,
|
||||||
|
};
|
||||||
|
|
||||||
|
let loc_function_def = Loc::at(region, function_def);
|
||||||
|
|
||||||
|
let function_def_index =
|
||||||
|
Index::push_new(&mut self.function_bodies, loc_function_def);
|
||||||
|
|
||||||
|
if let Some(annotation) = &mut self.annotations[index] {
|
||||||
|
annotation.convert_to_fn(new_args_len, var_store);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some((_var, annotation)) = self.host_exposed_annotations.get_mut(&index) {
|
||||||
|
annotation.convert_to_fn(new_args_len, var_store);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.declarations[index] = DeclarationTag::Function(function_def_index);
|
||||||
|
}
|
||||||
|
_ => internal_error!("Expected value declaration"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.declarations.len()
|
self.declarations.len()
|
||||||
}
|
}
|
||||||
|
@ -3142,6 +3240,11 @@ impl Declarations {
|
||||||
|
|
||||||
collector
|
collector
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn take_arity_by_name(&mut self) -> VecMap<IdentId, usize> {
|
||||||
|
// `arity_by_name` is only needed for lowering module params
|
||||||
|
std::mem::take(&mut self.arity_by_name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
roc_error_macros::assert_sizeof_default!(DeclarationTag, 8);
|
roc_error_macros::assert_sizeof_default!(DeclarationTag, 8);
|
||||||
|
@ -3198,8 +3301,9 @@ pub(crate) fn get_lookup_symbols(expr: &Expr) -> Vec<ExpectLookup> {
|
||||||
Expr::Var(symbol, var)
|
Expr::Var(symbol, var)
|
||||||
| Expr::ParamsVar {
|
| Expr::ParamsVar {
|
||||||
symbol,
|
symbol,
|
||||||
params: _,
|
|
||||||
var,
|
var,
|
||||||
|
params_symbol: _,
|
||||||
|
params_var: _,
|
||||||
}
|
}
|
||||||
| Expr::RecordUpdate {
|
| Expr::RecordUpdate {
|
||||||
symbol,
|
symbol,
|
||||||
|
|
|
@ -14,7 +14,6 @@ pub mod copy;
|
||||||
pub mod def;
|
pub mod def;
|
||||||
mod derive;
|
mod derive;
|
||||||
pub mod desugar;
|
pub mod desugar;
|
||||||
pub mod effect_module;
|
|
||||||
pub mod env;
|
pub mod env;
|
||||||
pub mod exhaustive;
|
pub mod exhaustive;
|
||||||
pub mod expected;
|
pub mod expected;
|
||||||
|
@ -26,6 +25,7 @@ pub mod procedure;
|
||||||
pub mod scope;
|
pub mod scope;
|
||||||
pub mod string;
|
pub mod string;
|
||||||
pub mod suffixed;
|
pub mod suffixed;
|
||||||
|
pub mod task_module;
|
||||||
pub mod traverse;
|
pub mod traverse;
|
||||||
|
|
||||||
pub use derive::DERIVED_REGION;
|
pub use derive::DERIVED_REGION;
|
||||||
|
|
|
@ -3,13 +3,12 @@ use std::path::Path;
|
||||||
use crate::abilities::{AbilitiesStore, ImplKey, PendingAbilitiesStore, ResolvedImpl};
|
use crate::abilities::{AbilitiesStore, ImplKey, PendingAbilitiesStore, ResolvedImpl};
|
||||||
use crate::annotation::{canonicalize_annotation, AnnotationFor};
|
use crate::annotation::{canonicalize_annotation, AnnotationFor};
|
||||||
use crate::def::{canonicalize_defs, report_unused_imports, Def};
|
use crate::def::{canonicalize_defs, report_unused_imports, Def};
|
||||||
use crate::effect_module::HostedGeneratedFunctions;
|
|
||||||
use crate::env::Env;
|
use crate::env::Env;
|
||||||
use crate::expr::{
|
use crate::expr::{
|
||||||
AnnotatedMark, ClosureData, DbgLookup, Declarations, ExpectLookup, Expr, Output, PendingDerives,
|
ClosureData, DbgLookup, Declarations, ExpectLookup, Expr, Output, PendingDerives,
|
||||||
};
|
};
|
||||||
use crate::pattern::{
|
use crate::pattern::{
|
||||||
canonicalize_record_destructure, BindingsFromPattern, Pattern, PermitShadows,
|
canonicalize_record_destructs, BindingsFromPattern, Pattern, PermitShadows, RecordDestruct,
|
||||||
};
|
};
|
||||||
use crate::procedure::References;
|
use crate::procedure::References;
|
||||||
use crate::scope::Scope;
|
use crate::scope::Scope;
|
||||||
|
@ -18,14 +17,14 @@ use roc_collections::{MutMap, SendMap, VecMap, VecSet};
|
||||||
use roc_error_macros::internal_error;
|
use roc_error_macros::internal_error;
|
||||||
use roc_module::ident::Ident;
|
use roc_module::ident::Ident;
|
||||||
use roc_module::ident::Lowercase;
|
use roc_module::ident::Lowercase;
|
||||||
use roc_module::symbol::{IdentIds, IdentIdsByModule, ModuleId, PackageModuleIds, Symbol};
|
use roc_module::symbol::{IdentId, IdentIds, IdentIdsByModule, ModuleId, PackageModuleIds, Symbol};
|
||||||
use roc_parse::ast::{Defs, TypeAnnotation};
|
use roc_parse::ast::{Defs, TypeAnnotation};
|
||||||
use roc_parse::header::{HeaderType, ModuleParams};
|
use roc_parse::header::HeaderType;
|
||||||
use roc_parse::pattern::PatternType;
|
use roc_parse::pattern::PatternType;
|
||||||
use roc_problem::can::{Problem, RuntimeError};
|
use roc_problem::can::{Problem, RuntimeError};
|
||||||
use roc_region::all::{Loc, Region};
|
use roc_region::all::{Loc, Region};
|
||||||
use roc_types::subs::{ExposedTypesStorageSubs, Subs, VarStore, Variable};
|
use roc_types::subs::{ExposedTypesStorageSubs, Subs, VarStore, Variable};
|
||||||
use roc_types::types::{AbilitySet, Alias, AliasKind, AliasVar, Type};
|
use roc_types::types::{AbilitySet, Alias, Type};
|
||||||
|
|
||||||
/// The types of all exposed values/functions of a collection of modules
|
/// The types of all exposed values/functions of a collection of modules
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
|
@ -138,7 +137,33 @@ pub struct Module {
|
||||||
pub abilities_store: PendingAbilitiesStore,
|
pub abilities_store: PendingAbilitiesStore,
|
||||||
pub loc_expects: VecMap<Region, Vec<ExpectLookup>>,
|
pub loc_expects: VecMap<Region, Vec<ExpectLookup>>,
|
||||||
pub loc_dbgs: VecMap<Symbol, DbgLookup>,
|
pub loc_dbgs: VecMap<Symbol, DbgLookup>,
|
||||||
pub params_pattern: Option<(Variable, AnnotatedMark, Loc<Pattern>)>,
|
pub module_params: Option<ModuleParams>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ModuleParams {
|
||||||
|
pub region: Region,
|
||||||
|
pub whole_symbol: Symbol,
|
||||||
|
pub whole_var: Variable,
|
||||||
|
pub record_var: Variable,
|
||||||
|
pub record_ext_var: Variable,
|
||||||
|
pub destructs: Vec<Loc<RecordDestruct>>,
|
||||||
|
// used while lowering passed functions
|
||||||
|
pub arity_by_name: VecMap<IdentId, usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ModuleParams {
|
||||||
|
pub fn pattern(&self) -> Loc<Pattern> {
|
||||||
|
let record_pattern = Pattern::RecordDestructure {
|
||||||
|
whole_var: self.record_var,
|
||||||
|
ext_var: self.record_ext_var,
|
||||||
|
destructs: self.destructs.clone(),
|
||||||
|
};
|
||||||
|
let loc_record_pattern = Loc::at(self.region, record_pattern);
|
||||||
|
|
||||||
|
let as_pattern = Pattern::As(Box::new(loc_record_pattern), self.whole_symbol);
|
||||||
|
Loc::at(self.region, as_pattern)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
@ -152,7 +177,7 @@ pub struct RigidVariables {
|
||||||
pub struct ModuleOutput {
|
pub struct ModuleOutput {
|
||||||
pub aliases: MutMap<Symbol, Alias>,
|
pub aliases: MutMap<Symbol, Alias>,
|
||||||
pub rigid_variables: RigidVariables,
|
pub rigid_variables: RigidVariables,
|
||||||
pub params_pattern: Option<(Variable, AnnotatedMark, Loc<Pattern>)>,
|
pub module_params: Option<ModuleParams>,
|
||||||
pub declarations: Declarations,
|
pub declarations: Declarations,
|
||||||
pub exposed_imports: MutMap<Symbol, Region>,
|
pub exposed_imports: MutMap<Symbol, Region>,
|
||||||
pub exposed_symbols: VecSet<Symbol>,
|
pub exposed_symbols: VecSet<Symbol>,
|
||||||
|
@ -165,99 +190,6 @@ pub struct ModuleOutput {
|
||||||
pub loc_dbgs: VecMap<Symbol, DbgLookup>,
|
pub loc_dbgs: VecMap<Symbol, DbgLookup>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_generate_with<'a>(
|
|
||||||
generate_with: &'a [Loc<roc_parse::header::ExposedName<'a>>],
|
|
||||||
) -> (HostedGeneratedFunctions, Vec<Loc<Ident>>) {
|
|
||||||
let mut functions = HostedGeneratedFunctions::default();
|
|
||||||
let mut unknown = Vec::new();
|
|
||||||
|
|
||||||
for generated in generate_with {
|
|
||||||
match generated.value.as_str() {
|
|
||||||
"after" => functions.after = true,
|
|
||||||
"map" => functions.map = true,
|
|
||||||
"always" => functions.always = true,
|
|
||||||
"loop" => functions.loop_ = true,
|
|
||||||
"forever" => functions.forever = true,
|
|
||||||
other => {
|
|
||||||
// we don't know how to generate this function
|
|
||||||
let ident = Ident::from(other);
|
|
||||||
unknown.push(Loc::at(generated.region, ident));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(functions, unknown)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum GeneratedInfo {
|
|
||||||
Hosted {
|
|
||||||
effect_symbol: Symbol,
|
|
||||||
generated_functions: HostedGeneratedFunctions,
|
|
||||||
},
|
|
||||||
Builtin,
|
|
||||||
NotSpecial,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GeneratedInfo {
|
|
||||||
fn from_header_type(
|
|
||||||
env: &mut Env,
|
|
||||||
scope: &mut Scope,
|
|
||||||
var_store: &mut VarStore,
|
|
||||||
header_type: &HeaderType,
|
|
||||||
) -> Self {
|
|
||||||
match header_type {
|
|
||||||
HeaderType::Hosted {
|
|
||||||
generates,
|
|
||||||
generates_with,
|
|
||||||
name: _,
|
|
||||||
exposes: _,
|
|
||||||
} => {
|
|
||||||
let name: &str = generates.into();
|
|
||||||
let (generated_functions, unknown_generated) =
|
|
||||||
validate_generate_with(generates_with);
|
|
||||||
|
|
||||||
for unknown in unknown_generated {
|
|
||||||
env.problem(Problem::UnknownGeneratesWith(unknown));
|
|
||||||
}
|
|
||||||
|
|
||||||
let effect_symbol = scope.introduce(name.into(), Region::zero()).unwrap();
|
|
||||||
|
|
||||||
{
|
|
||||||
let a_var = var_store.fresh();
|
|
||||||
|
|
||||||
let actual =
|
|
||||||
crate::effect_module::build_effect_actual(Type::Variable(a_var), var_store);
|
|
||||||
|
|
||||||
scope.add_alias(
|
|
||||||
effect_symbol,
|
|
||||||
Region::zero(),
|
|
||||||
vec![Loc::at_zero(AliasVar::unbound("a".into(), a_var))],
|
|
||||||
vec![],
|
|
||||||
actual,
|
|
||||||
AliasKind::Opaque,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
GeneratedInfo::Hosted {
|
|
||||||
effect_symbol,
|
|
||||||
generated_functions,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
HeaderType::Builtin {
|
|
||||||
generates_with,
|
|
||||||
name: _,
|
|
||||||
exposes: _,
|
|
||||||
opt_params: _,
|
|
||||||
} => {
|
|
||||||
debug_assert!(generates_with.is_empty());
|
|
||||||
GeneratedInfo::Builtin
|
|
||||||
}
|
|
||||||
_ => GeneratedInfo::NotSpecial,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn has_no_implementation(expr: &Expr) -> bool {
|
fn has_no_implementation(expr: &Expr) -> bool {
|
||||||
match expr {
|
match expr {
|
||||||
Expr::RuntimeError(RuntimeError::NoImplementationNamed { .. }) => true,
|
Expr::RuntimeError(RuntimeError::NoImplementationNamed { .. }) => true,
|
||||||
|
@ -326,9 +258,6 @@ pub fn canonicalize_module_defs<'a>(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let generated_info =
|
|
||||||
GeneratedInfo::from_header_type(&mut env, &mut scope, var_store, header_type);
|
|
||||||
|
|
||||||
// Desugar operators (convert them to Apply calls, taking into account
|
// Desugar operators (convert them to Apply calls, taking into account
|
||||||
// operator precedence and associativity rules), before doing other canonicalization.
|
// operator precedence and associativity rules), before doing other canonicalization.
|
||||||
//
|
//
|
||||||
|
@ -337,11 +266,20 @@ pub fn canonicalize_module_defs<'a>(
|
||||||
// operators, and then again on *their* nested operators, ultimately applying the
|
// operators, and then again on *their* nested operators, ultimately applying the
|
||||||
// rules multiple times unnecessarily.
|
// rules multiple times unnecessarily.
|
||||||
|
|
||||||
crate::desugar::desugar_defs_node_values(arena, loc_defs, src, &mut None, module_path, true);
|
crate::desugar::desugar_defs_node_values(
|
||||||
|
arena,
|
||||||
|
var_store,
|
||||||
|
loc_defs,
|
||||||
|
src,
|
||||||
|
&mut None,
|
||||||
|
module_path,
|
||||||
|
true,
|
||||||
|
&mut env.problems,
|
||||||
|
);
|
||||||
|
|
||||||
let mut rigid_variables = RigidVariables::default();
|
let mut rigid_variables = RigidVariables::default();
|
||||||
|
|
||||||
// Iniital scope values are treated like defs that appear before any others.
|
// Initial scope values are treated like defs that appear before any others.
|
||||||
// They include builtin types that are automatically imported, and for a platform
|
// They include builtin types that are automatically imported, and for a platform
|
||||||
// package, the required values from the app.
|
// package, the required values from the app.
|
||||||
//
|
//
|
||||||
|
@ -390,13 +328,13 @@ pub fn canonicalize_module_defs<'a>(
|
||||||
|
|
||||||
let mut output = Output::default();
|
let mut output = Output::default();
|
||||||
|
|
||||||
let params_pattern = header_type.get_params().as_ref().map(
|
let module_params = header_type.get_params().as_ref().map(
|
||||||
|ModuleParams {
|
|roc_parse::header::ModuleParams {
|
||||||
pattern,
|
pattern,
|
||||||
before_arrow: _,
|
before_arrow: _,
|
||||||
after_arrow: _,
|
after_arrow: _,
|
||||||
}| {
|
}| {
|
||||||
let can_pattern = canonicalize_record_destructure(
|
let (destructs, _) = canonicalize_record_destructs(
|
||||||
&mut env,
|
&mut env,
|
||||||
var_store,
|
var_store,
|
||||||
&mut scope,
|
&mut scope,
|
||||||
|
@ -407,17 +345,22 @@ pub fn canonicalize_module_defs<'a>(
|
||||||
PermitShadows(false),
|
PermitShadows(false),
|
||||||
);
|
);
|
||||||
|
|
||||||
let loc_pattern = Loc::at(pattern.region, can_pattern);
|
let whole_symbol = scope.gen_unique_symbol();
|
||||||
|
env.top_level_symbols.insert(whole_symbol);
|
||||||
|
|
||||||
for (symbol, _) in BindingsFromPattern::new(&loc_pattern) {
|
let whole_var = var_store.fresh();
|
||||||
env.top_level_symbols.insert(symbol);
|
|
||||||
|
env.home_params_record = Some((whole_symbol, whole_var));
|
||||||
|
|
||||||
|
ModuleParams {
|
||||||
|
region: pattern.region,
|
||||||
|
whole_var,
|
||||||
|
whole_symbol,
|
||||||
|
record_var: var_store.fresh(),
|
||||||
|
record_ext_var: var_store.fresh(),
|
||||||
|
destructs,
|
||||||
|
arity_by_name: Default::default(),
|
||||||
}
|
}
|
||||||
|
|
||||||
(
|
|
||||||
var_store.fresh(),
|
|
||||||
AnnotatedMark::new(var_store),
|
|
||||||
loc_pattern,
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -495,6 +438,11 @@ pub fn canonicalize_module_defs<'a>(
|
||||||
&exposed_symbols,
|
&exposed_symbols,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let module_params = module_params.map(|params| ModuleParams {
|
||||||
|
arity_by_name: declarations.take_arity_by_name(),
|
||||||
|
..params
|
||||||
|
});
|
||||||
|
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
output.pending_derives.is_empty(),
|
output.pending_derives.is_empty(),
|
||||||
"I thought pending derives are only found during def introduction"
|
"I thought pending derives are only found during def introduction"
|
||||||
|
@ -534,24 +482,6 @@ pub fn canonicalize_module_defs<'a>(
|
||||||
|
|
||||||
report_unused_imports(imports_introduced, &output.references, &mut env, &mut scope);
|
report_unused_imports(imports_introduced, &output.references, &mut env, &mut scope);
|
||||||
|
|
||||||
if let GeneratedInfo::Hosted {
|
|
||||||
effect_symbol,
|
|
||||||
generated_functions,
|
|
||||||
} = generated_info
|
|
||||||
{
|
|
||||||
let mut exposed_symbols = VecSet::default();
|
|
||||||
|
|
||||||
// NOTE this currently builds all functions, not just the ones that the user requested
|
|
||||||
crate::effect_module::build_effect_builtins(
|
|
||||||
&mut scope,
|
|
||||||
effect_symbol,
|
|
||||||
var_store,
|
|
||||||
&mut exposed_symbols,
|
|
||||||
&mut declarations,
|
|
||||||
generated_functions,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
for index in 0..declarations.len() {
|
for index in 0..declarations.len() {
|
||||||
use crate::expr::DeclarationTag::*;
|
use crate::expr::DeclarationTag::*;
|
||||||
|
|
||||||
|
@ -572,8 +502,8 @@ pub fn canonicalize_module_defs<'a>(
|
||||||
// and which are meant to be normal definitions without a body. So for now
|
// and which are meant to be normal definitions without a body. So for now
|
||||||
// we just assume they are hosted functions (meant to be provided by the platform)
|
// we just assume they are hosted functions (meant to be provided by the platform)
|
||||||
if has_no_implementation(&declarations.expressions[index].value) {
|
if has_no_implementation(&declarations.expressions[index].value) {
|
||||||
match generated_info {
|
match header_type {
|
||||||
GeneratedInfo::Builtin => {
|
HeaderType::Builtin { .. } => {
|
||||||
match crate::builtins::builtin_defs_map(*symbol, var_store) {
|
match crate::builtins::builtin_defs_map(*symbol, var_store) {
|
||||||
None => {
|
None => {
|
||||||
internal_error!("A builtin module contains a signature without implementation for {:?}", symbol)
|
internal_error!("A builtin module contains a signature without implementation for {:?}", symbol)
|
||||||
|
@ -583,7 +513,7 @@ pub fn canonicalize_module_defs<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GeneratedInfo::Hosted { effect_symbol, .. } => {
|
HeaderType::Hosted { .. } => {
|
||||||
let ident_id = symbol.ident_id();
|
let ident_id = symbol.ident_id();
|
||||||
let ident = scope
|
let ident = scope
|
||||||
.locals
|
.locals
|
||||||
|
@ -601,13 +531,8 @@ pub fn canonicalize_module_defs<'a>(
|
||||||
aliases: Default::default(),
|
aliases: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let hosted_def = crate::effect_module::build_host_exposed_def(
|
let hosted_def = crate::task_module::build_host_exposed_def(
|
||||||
&mut scope,
|
&mut scope, *symbol, &ident, var_store, annotation,
|
||||||
*symbol,
|
|
||||||
&ident,
|
|
||||||
effect_symbol,
|
|
||||||
var_store,
|
|
||||||
annotation,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
declarations.update_builtin_def(index, hosted_def);
|
declarations.update_builtin_def(index, hosted_def);
|
||||||
|
@ -630,8 +555,8 @@ pub fn canonicalize_module_defs<'a>(
|
||||||
// and which are meant to be normal definitions without a body. So for now
|
// and which are meant to be normal definitions without a body. So for now
|
||||||
// we just assume they are hosted functions (meant to be provided by the platform)
|
// we just assume they are hosted functions (meant to be provided by the platform)
|
||||||
if has_no_implementation(&declarations.expressions[index].value) {
|
if has_no_implementation(&declarations.expressions[index].value) {
|
||||||
match generated_info {
|
match header_type {
|
||||||
GeneratedInfo::Builtin => {
|
HeaderType::Builtin { .. } => {
|
||||||
match crate::builtins::builtin_defs_map(*symbol, var_store) {
|
match crate::builtins::builtin_defs_map(*symbol, var_store) {
|
||||||
None => {
|
None => {
|
||||||
internal_error!("A builtin module contains a signature without implementation for {:?}", symbol)
|
internal_error!("A builtin module contains a signature without implementation for {:?}", symbol)
|
||||||
|
@ -641,7 +566,7 @@ pub fn canonicalize_module_defs<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GeneratedInfo::Hosted { effect_symbol, .. } => {
|
HeaderType::Hosted { .. } => {
|
||||||
let ident_id = symbol.ident_id();
|
let ident_id = symbol.ident_id();
|
||||||
let ident = scope
|
let ident = scope
|
||||||
.locals
|
.locals
|
||||||
|
@ -659,13 +584,8 @@ pub fn canonicalize_module_defs<'a>(
|
||||||
aliases: Default::default(),
|
aliases: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let hosted_def = crate::effect_module::build_host_exposed_def(
|
let hosted_def = crate::task_module::build_host_exposed_def(
|
||||||
&mut scope,
|
&mut scope, *symbol, &ident, var_store, annotation,
|
||||||
*symbol,
|
|
||||||
&ident,
|
|
||||||
effect_symbol,
|
|
||||||
var_store,
|
|
||||||
annotation,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
declarations.update_builtin_def(index, hosted_def);
|
declarations.update_builtin_def(index, hosted_def);
|
||||||
|
@ -691,18 +611,6 @@ pub fn canonicalize_module_defs<'a>(
|
||||||
|
|
||||||
let mut aliases = MutMap::default();
|
let mut aliases = MutMap::default();
|
||||||
|
|
||||||
if let GeneratedInfo::Hosted { effect_symbol, .. } = generated_info {
|
|
||||||
// Remove this from exposed_symbols,
|
|
||||||
// so that at the end of the process,
|
|
||||||
// we can see if there were any
|
|
||||||
// exposed symbols which did not have
|
|
||||||
// corresponding defs.
|
|
||||||
exposed_but_not_defined.remove(&effect_symbol);
|
|
||||||
|
|
||||||
let hosted_alias = scope.lookup_alias(effect_symbol).unwrap().clone();
|
|
||||||
aliases.insert(effect_symbol, hosted_alias);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (symbol, alias) in output.aliases {
|
for (symbol, alias) in output.aliases {
|
||||||
// Remove this from exposed_symbols,
|
// Remove this from exposed_symbols,
|
||||||
// so that at the end of the process,
|
// so that at the end of the process,
|
||||||
|
@ -851,7 +759,7 @@ pub fn canonicalize_module_defs<'a>(
|
||||||
scope,
|
scope,
|
||||||
aliases,
|
aliases,
|
||||||
rigid_variables,
|
rigid_variables,
|
||||||
params_pattern,
|
module_params,
|
||||||
declarations,
|
declarations,
|
||||||
referenced_values,
|
referenced_values,
|
||||||
exposed_imports: can_exposed_imports,
|
exposed_imports: can_exposed_imports,
|
||||||
|
|
|
@ -623,16 +623,29 @@ pub fn canonicalize_pattern<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RecordDestructure(patterns) => canonicalize_record_destructure(
|
RecordDestructure(patterns) => {
|
||||||
env,
|
let ext_var = var_store.fresh();
|
||||||
var_store,
|
let whole_var = var_store.fresh();
|
||||||
scope,
|
|
||||||
output,
|
let (destructs, opt_erroneous) = canonicalize_record_destructs(
|
||||||
pattern_type,
|
env,
|
||||||
patterns,
|
var_store,
|
||||||
region,
|
scope,
|
||||||
permit_shadows,
|
output,
|
||||||
),
|
pattern_type,
|
||||||
|
patterns,
|
||||||
|
region,
|
||||||
|
permit_shadows,
|
||||||
|
);
|
||||||
|
|
||||||
|
// If we encountered an erroneous pattern (e.g. one with shadowing),
|
||||||
|
// use the resulting RuntimeError. Otherwise, return a successful record destructure.
|
||||||
|
opt_erroneous.unwrap_or(Pattern::RecordDestructure {
|
||||||
|
whole_var,
|
||||||
|
ext_var,
|
||||||
|
destructs,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
RequiredField(_name, _loc_pattern) => {
|
RequiredField(_name, _loc_pattern) => {
|
||||||
unreachable!("should have been handled in RecordDestructure");
|
unreachable!("should have been handled in RecordDestructure");
|
||||||
|
@ -779,7 +792,7 @@ pub fn canonicalize_pattern<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn canonicalize_record_destructure<'a>(
|
pub fn canonicalize_record_destructs<'a>(
|
||||||
env: &mut Env<'a>,
|
env: &mut Env<'a>,
|
||||||
var_store: &mut VarStore,
|
var_store: &mut VarStore,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
|
@ -788,11 +801,9 @@ pub fn canonicalize_record_destructure<'a>(
|
||||||
patterns: &ast::Collection<Loc<ast::Pattern<'a>>>,
|
patterns: &ast::Collection<Loc<ast::Pattern<'a>>>,
|
||||||
region: Region,
|
region: Region,
|
||||||
permit_shadows: PermitShadows,
|
permit_shadows: PermitShadows,
|
||||||
) -> Pattern {
|
) -> (Vec<Loc<RecordDestruct>>, Option<Pattern>) {
|
||||||
use ast::Pattern::*;
|
use ast::Pattern::*;
|
||||||
|
|
||||||
let ext_var = var_store.fresh();
|
|
||||||
let whole_var = var_store.fresh();
|
|
||||||
let mut destructs = Vec::with_capacity(patterns.len());
|
let mut destructs = Vec::with_capacity(patterns.len());
|
||||||
let mut opt_erroneous = None;
|
let mut opt_erroneous = None;
|
||||||
|
|
||||||
|
@ -907,13 +918,7 @@ pub fn canonicalize_record_destructure<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we encountered an erroneous pattern (e.g. one with shadowing),
|
(destructs, opt_erroneous)
|
||||||
// use the resulting RuntimeError. Otherwise, return a successful record destructure.
|
|
||||||
opt_erroneous.unwrap_or(Pattern::RecordDestructure {
|
|
||||||
whole_var,
|
|
||||||
ext_var,
|
|
||||||
destructs,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// When we detect an unsupported pattern type (e.g. 5 = 1 + 2 is unsupported because you can't
|
/// When we detect an unsupported pattern type (e.g. 5 = 1 + 2 is unsupported because you can't
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::expr::Expr;
|
|
||||||
use crate::pattern::Pattern;
|
use crate::pattern::Pattern;
|
||||||
|
use crate::{expr::Expr, scope::SymbolLookup};
|
||||||
use roc_module::symbol::{ModuleId, Symbol};
|
use roc_module::symbol::{ModuleId, Symbol};
|
||||||
use roc_region::all::{Loc, Region};
|
use roc_region::all::{Loc, Region};
|
||||||
use roc_types::subs::Variable;
|
use roc_types::subs::Variable;
|
||||||
|
@ -125,8 +125,18 @@ impl References {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_value_lookup(&mut self, symbol: Symbol, qualified: QualifiedReference) {
|
pub fn insert_value_lookup(&mut self, lookup: SymbolLookup, qualified: QualifiedReference) {
|
||||||
self.insert(symbol, qualified.flags(ReferencesBitflags::VALUE_LOOKUP));
|
self.insert(
|
||||||
|
lookup.symbol,
|
||||||
|
qualified.flags(ReferencesBitflags::VALUE_LOOKUP),
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some((_, params_symbol)) = lookup.module_params {
|
||||||
|
self.insert(
|
||||||
|
params_symbol,
|
||||||
|
qualified.flags(ReferencesBitflags::VALUE_LOOKUP),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_type_lookup(&mut self, symbol: Symbol, qualified: QualifiedReference) {
|
pub fn insert_type_lookup(&mut self, symbol: Symbol, qualified: QualifiedReference) {
|
||||||
|
|
|
@ -669,7 +669,7 @@ pub struct ScopeModules {
|
||||||
/// Why is this module in scope?
|
/// Why is this module in scope?
|
||||||
sources: Vec<ScopeModuleSource>,
|
sources: Vec<ScopeModuleSource>,
|
||||||
/// The params of a module if any
|
/// The params of a module if any
|
||||||
params: Vec<Option<Symbol>>,
|
params: Vec<Option<(Variable, Symbol)>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ScopeModules {
|
impl ScopeModules {
|
||||||
|
@ -731,7 +731,7 @@ impl ScopeModules {
|
||||||
&mut self,
|
&mut self,
|
||||||
module_name: ModuleName,
|
module_name: ModuleName,
|
||||||
module_id: ModuleId,
|
module_id: ModuleId,
|
||||||
params_symbol: Option<Symbol>,
|
params: Option<(Variable, Symbol)>,
|
||||||
region: Region,
|
region: Region,
|
||||||
) -> Result<(), ScopeModuleSource> {
|
) -> Result<(), ScopeModuleSource> {
|
||||||
if let Some(index) = self.names.iter().position(|name| name == &module_name) {
|
if let Some(index) = self.names.iter().position(|name| name == &module_name) {
|
||||||
|
@ -745,7 +745,7 @@ impl ScopeModules {
|
||||||
self.ids.push(module_id);
|
self.ids.push(module_id);
|
||||||
self.names.push(module_name);
|
self.names.push(module_name);
|
||||||
self.sources.push(ScopeModuleSource::Import(region));
|
self.sources.push(ScopeModuleSource::Import(region));
|
||||||
self.params.push(params_symbol);
|
self.params.push(params);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -768,14 +768,14 @@ impl ScopeModules {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct SymbolLookup {
|
pub struct SymbolLookup {
|
||||||
pub symbol: Symbol,
|
pub symbol: Symbol,
|
||||||
pub module_params: Option<Symbol>,
|
pub module_params: Option<(Variable, Symbol)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SymbolLookup {
|
impl SymbolLookup {
|
||||||
pub fn new(symbol: Symbol, params: Option<Symbol>) -> Self {
|
pub fn new(symbol: Symbol, params: Option<(Variable, Symbol)>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
symbol,
|
symbol,
|
||||||
module_params: params,
|
module_params: params,
|
||||||
|
@ -789,7 +789,7 @@ impl SymbolLookup {
|
||||||
|
|
||||||
pub struct ModuleLookup {
|
pub struct ModuleLookup {
|
||||||
pub id: ModuleId,
|
pub id: ModuleId,
|
||||||
pub params: Option<Symbol>,
|
pub params: Option<(Variable, Symbol)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModuleLookup {
|
impl ModuleLookup {
|
||||||
|
|
|
@ -6,7 +6,7 @@ use roc_error_macros::internal_error;
|
||||||
use roc_module::called_via::CalledVia;
|
use roc_module::called_via::CalledVia;
|
||||||
use roc_module::ident::ModuleName;
|
use roc_module::ident::ModuleName;
|
||||||
use roc_parse::ast::Expr::{self, *};
|
use roc_parse::ast::Expr::{self, *};
|
||||||
use roc_parse::ast::{is_expr_suffixed, Pattern, TypeAnnotation, ValueDef, WhenBranch};
|
use roc_parse::ast::{is_expr_suffixed, Pattern, TryTarget, TypeAnnotation, ValueDef, WhenBranch};
|
||||||
use roc_region::all::{Loc, Region};
|
use roc_region::all::{Loc, Region};
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
||||||
|
@ -34,14 +34,17 @@ pub enum EUnwrapped<'a> {
|
||||||
/// e.g. x = first! (second! 42)
|
/// e.g. x = first! (second! 42)
|
||||||
/// The first unwrap will produce
|
/// The first unwrap will produce
|
||||||
/// `UnwrappedDefExpr<first (second! 42)>`
|
/// `UnwrappedDefExpr<first (second! 42)>`
|
||||||
UnwrappedDefExpr(&'a Loc<Expr<'a>>),
|
UnwrappedDefExpr {
|
||||||
|
loc_expr: &'a Loc<Expr<'a>>,
|
||||||
|
target: TryTarget,
|
||||||
|
},
|
||||||
|
|
||||||
/// Suffixed sub expression
|
/// Suffixed sub expression
|
||||||
/// e.g. x = first! (second! 42)
|
/// e.g. x = first! (second! 42)
|
||||||
/// In this example, the second unwrap (after unwrapping the top level `first!`) will produce
|
/// In this example, the second unwrap (after unwrapping the top level `first!`) will produce
|
||||||
/// `UnwrappedSubExpr<{ sub_arg: second 42, sub_pat: #!0_arg, sub_new: #!0_arg }>`
|
/// `UnwrappedSubExpr<{ sub_arg: second 42, sub_pat: #!0_arg, sub_new: #!0_arg }>`
|
||||||
UnwrappedSubExpr {
|
UnwrappedSubExpr {
|
||||||
/// the unwrapped expression argument for Task.await
|
/// the unwrapped expression argument for `try` functions
|
||||||
sub_arg: &'a Loc<Expr<'a>>,
|
sub_arg: &'a Loc<Expr<'a>>,
|
||||||
|
|
||||||
/// the pattern for the closure
|
/// the pattern for the closure
|
||||||
|
@ -49,6 +52,9 @@ pub enum EUnwrapped<'a> {
|
||||||
|
|
||||||
/// the expression to replace the unwrapped
|
/// the expression to replace the unwrapped
|
||||||
sub_new: &'a Loc<Expr<'a>>,
|
sub_new: &'a Loc<Expr<'a>>,
|
||||||
|
|
||||||
|
/// The type of the target for the suffix, e.g. a Task or Result
|
||||||
|
target: TryTarget,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Malformed use of the suffix
|
/// Malformed use of the suffix
|
||||||
|
@ -59,12 +65,16 @@ fn init_unwrapped_err<'a>(
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
unwrapped_expr: &'a Loc<Expr<'a>>,
|
unwrapped_expr: &'a Loc<Expr<'a>>,
|
||||||
maybe_def_pat: Option<&'a Loc<Pattern<'a>>>,
|
maybe_def_pat: Option<&'a Loc<Pattern<'a>>>,
|
||||||
|
target: TryTarget,
|
||||||
) -> Result<&'a Loc<Expr<'a>>, EUnwrapped<'a>> {
|
) -> Result<&'a Loc<Expr<'a>>, EUnwrapped<'a>> {
|
||||||
match maybe_def_pat {
|
match maybe_def_pat {
|
||||||
Some(..) => {
|
Some(..) => {
|
||||||
// we have a def pattern, so no need to generate a new pattern
|
// we have a def pattern, so no need to generate a new pattern
|
||||||
// as this should only be created in the first call from a def
|
// as this should only be created in the first call from a def
|
||||||
Err(EUnwrapped::UnwrappedDefExpr(unwrapped_expr))
|
Err(EUnwrapped::UnwrappedDefExpr {
|
||||||
|
loc_expr: unwrapped_expr,
|
||||||
|
target,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// Provide an intermediate answer expression and pattern when unwrapping a
|
// Provide an intermediate answer expression and pattern when unwrapping a
|
||||||
|
@ -87,13 +97,14 @@ fn init_unwrapped_err<'a>(
|
||||||
sub_arg: unwrapped_expr,
|
sub_arg: unwrapped_expr,
|
||||||
sub_pat,
|
sub_pat,
|
||||||
sub_new,
|
sub_new,
|
||||||
|
target,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Descend through the AST and unwrap each suffixed expression
|
/// Descend through the AST and unwrap each suffixed expression
|
||||||
/// when an expression is unwrapped, we apply a `Task.await` and
|
/// when an expression is unwrapped, we apply the appropriate try function and
|
||||||
/// then descend through the AST again until there are no more suffixed
|
/// then descend through the AST again until there are no more suffixed
|
||||||
/// expressions, or we hit an error
|
/// expressions, or we hit an error
|
||||||
pub fn unwrap_suffixed_expression<'a>(
|
pub fn unwrap_suffixed_expression<'a>(
|
||||||
|
@ -103,10 +114,13 @@ pub fn unwrap_suffixed_expression<'a>(
|
||||||
) -> Result<&'a Loc<Expr<'a>>, EUnwrapped<'a>> {
|
) -> Result<&'a Loc<Expr<'a>>, EUnwrapped<'a>> {
|
||||||
let unwrapped_expression = {
|
let unwrapped_expression = {
|
||||||
match loc_expr.value {
|
match loc_expr.value {
|
||||||
Expr::TaskAwaitBang(sub_expr) => {
|
Expr::TrySuffix {
|
||||||
|
expr: sub_expr,
|
||||||
|
target,
|
||||||
|
} => {
|
||||||
let unwrapped_sub_expr = arena.alloc(Loc::at(loc_expr.region, *sub_expr));
|
let unwrapped_sub_expr = arena.alloc(Loc::at(loc_expr.region, *sub_expr));
|
||||||
|
|
||||||
init_unwrapped_err(arena, unwrapped_sub_expr, maybe_def_pat)
|
init_unwrapped_err(arena, unwrapped_sub_expr, maybe_def_pat, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr::Defs(..) => unwrap_suffixed_expression_defs_help(arena, loc_expr, maybe_def_pat),
|
Expr::Defs(..) => unwrap_suffixed_expression_defs_help(arena, loc_expr, maybe_def_pat),
|
||||||
|
@ -154,15 +168,22 @@ pub fn unwrap_suffixed_expression<'a>(
|
||||||
.alloc(Loc::at(loc_expr.region, Expect(condition, unwrapped_expr)));
|
.alloc(Loc::at(loc_expr.region, Expect(condition, unwrapped_expr)));
|
||||||
return Ok(new_expect);
|
return Ok(new_expect);
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedDefExpr(unwrapped_expr)) => {
|
Err(EUnwrapped::UnwrappedDefExpr {
|
||||||
|
loc_expr: unwrapped_expr,
|
||||||
|
target,
|
||||||
|
}) => {
|
||||||
let new_expect = arena
|
let new_expect = arena
|
||||||
.alloc(Loc::at(loc_expr.region, Expect(condition, unwrapped_expr)));
|
.alloc(Loc::at(loc_expr.region, Expect(condition, unwrapped_expr)));
|
||||||
Err(EUnwrapped::UnwrappedDefExpr(new_expect))
|
Err(EUnwrapped::UnwrappedDefExpr {
|
||||||
|
loc_expr: new_expect,
|
||||||
|
target,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedSubExpr {
|
Err(EUnwrapped::UnwrappedSubExpr {
|
||||||
sub_arg: unwrapped_expr,
|
sub_arg: unwrapped_expr,
|
||||||
sub_pat,
|
sub_pat,
|
||||||
sub_new,
|
sub_new,
|
||||||
|
target,
|
||||||
}) => {
|
}) => {
|
||||||
let new_expect = arena
|
let new_expect = arena
|
||||||
.alloc(Loc::at(loc_expr.region, Expect(condition, unwrapped_expr)));
|
.alloc(Loc::at(loc_expr.region, Expect(condition, unwrapped_expr)));
|
||||||
|
@ -170,6 +191,7 @@ pub fn unwrap_suffixed_expression<'a>(
|
||||||
sub_arg: new_expect,
|
sub_arg: new_expect,
|
||||||
sub_pat,
|
sub_pat,
|
||||||
sub_new,
|
sub_new,
|
||||||
|
target,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::Malformed) => Err(EUnwrapped::Malformed),
|
Err(EUnwrapped::Malformed) => Err(EUnwrapped::Malformed),
|
||||||
|
@ -208,13 +230,14 @@ pub fn unwrap_suffixed_expression_parens_help<'a>(
|
||||||
));
|
));
|
||||||
Ok(new_parens)
|
Ok(new_parens)
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedDefExpr(..)) => {
|
Err(EUnwrapped::UnwrappedDefExpr { .. }) => {
|
||||||
internal_error!("unreachable, child expressions from ParensAround should generate UnwrappedSubExpr instead");
|
internal_error!("unreachable, child expressions from ParensAround should generate UnwrappedSubExpr instead");
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedSubExpr {
|
Err(EUnwrapped::UnwrappedSubExpr {
|
||||||
sub_arg,
|
sub_arg,
|
||||||
sub_pat,
|
sub_pat,
|
||||||
sub_new,
|
sub_new,
|
||||||
|
target,
|
||||||
}) => {
|
}) => {
|
||||||
let new_parens = arena.alloc(Loc::at(
|
let new_parens = arena.alloc(Loc::at(
|
||||||
loc_expr.region,
|
loc_expr.region,
|
||||||
|
@ -224,6 +247,7 @@ pub fn unwrap_suffixed_expression_parens_help<'a>(
|
||||||
sub_arg,
|
sub_arg,
|
||||||
sub_pat,
|
sub_pat,
|
||||||
sub_new: new_parens,
|
sub_new: new_parens,
|
||||||
|
target,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Err(err) => Err(err),
|
Err(err) => Err(err),
|
||||||
|
@ -247,13 +271,13 @@ pub fn unwrap_suffixed_expression_closure_help<'a>(
|
||||||
let new_closure = arena.alloc(Loc::at(loc_expr.region, Expr::Closure(closure_args, unwrapped_expr)));
|
let new_closure = arena.alloc(Loc::at(loc_expr.region, Expr::Closure(closure_args, unwrapped_expr)));
|
||||||
Ok(new_closure)
|
Ok(new_closure)
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new }) => {
|
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new, target }) => {
|
||||||
let new_closure_loc_ret = apply_task_await(arena, loc_expr.region, sub_arg, sub_pat, sub_new, None);
|
let new_closure_loc_ret = apply_try_function(arena, loc_expr.region, sub_arg, sub_pat, sub_new, None, target);
|
||||||
let new_closure = arena.alloc(Loc::at(loc_expr.region, Expr::Closure(closure_args, new_closure_loc_ret)));
|
let new_closure = arena.alloc(Loc::at(loc_expr.region, Expr::Closure(closure_args, new_closure_loc_ret)));
|
||||||
Ok(new_closure)
|
Ok(new_closure)
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
debug_assert!(false,"the closure Defs was malformd, got {:#?}", err);
|
debug_assert!(false,"the closure Defs was malformed, got {:#?}", err);
|
||||||
Err(EUnwrapped::Malformed)
|
Err(EUnwrapped::Malformed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -278,22 +302,22 @@ pub fn unwrap_suffixed_expression_apply_help<'a>(
|
||||||
Ok(new_arg) => {
|
Ok(new_arg) => {
|
||||||
*arg = new_arg;
|
*arg = new_arg;
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedDefExpr(..)) => {
|
Err(EUnwrapped::UnwrappedDefExpr { .. }) => {
|
||||||
internal_error!("unreachable, unwrapped arg cannot be def expression as `None` was passed as pattern");
|
internal_error!("unreachable, unwrapped arg cannot be def expression as `None` was passed as pattern");
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new: new_arg }) => {
|
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new: new_arg, target }) => {
|
||||||
|
|
||||||
*arg = new_arg;
|
*arg = new_arg;
|
||||||
|
|
||||||
let new_apply = arena.alloc(Loc::at(loc_expr.region, Apply(function, local_args, called_via)));
|
let new_apply = arena.alloc(Loc::at(loc_expr.region, Apply(function, local_args, called_via)));
|
||||||
return Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new: new_apply});
|
return Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new: new_apply, target });
|
||||||
}
|
}
|
||||||
Err(err) => return Err(err),
|
Err(err) => return Err(err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// special case for when our Apply function is a suffixed Var (but not multiple suffixed)
|
// special case for when our Apply function is a suffixed Var (but not multiple suffixed)
|
||||||
if let Expr::TaskAwaitBang(sub_expr) = function.value {
|
if let Expr::TrySuffix { expr: sub_expr, target } = function.value {
|
||||||
let unwrapped_function = arena.alloc(Loc::at(
|
let unwrapped_function = arena.alloc(Loc::at(
|
||||||
loc_expr.region,
|
loc_expr.region,
|
||||||
*sub_expr,
|
*sub_expr,
|
||||||
|
@ -301,7 +325,7 @@ pub fn unwrap_suffixed_expression_apply_help<'a>(
|
||||||
|
|
||||||
let new_apply = arena.alloc(Loc::at(loc_expr.region, Expr::Apply(unwrapped_function, local_args, called_via)));
|
let new_apply = arena.alloc(Loc::at(loc_expr.region, Expr::Apply(unwrapped_function, local_args, called_via)));
|
||||||
|
|
||||||
return init_unwrapped_err(arena, new_apply, maybe_def_pat);
|
return init_unwrapped_err(arena, new_apply, maybe_def_pat, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
// function is another expression
|
// function is another expression
|
||||||
|
@ -310,15 +334,14 @@ pub fn unwrap_suffixed_expression_apply_help<'a>(
|
||||||
let new_apply = arena.alloc(Loc::at(loc_expr.region, Expr::Apply(new_function, local_args, called_via)));
|
let new_apply = arena.alloc(Loc::at(loc_expr.region, Expr::Apply(new_function, local_args, called_via)));
|
||||||
Ok(new_apply)
|
Ok(new_apply)
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedDefExpr(unwrapped_function)) => {
|
Err(EUnwrapped::UnwrappedDefExpr { loc_expr: unwrapped_function, target }) => {
|
||||||
let new_apply = arena.alloc(Loc::at(loc_expr.region, Expr::Apply(unwrapped_function, local_args, called_via)));
|
let new_apply = arena.alloc(Loc::at(loc_expr.region, Expr::Apply(unwrapped_function, local_args, called_via)));
|
||||||
Err(EUnwrapped::UnwrappedDefExpr(new_apply))
|
Err(EUnwrapped::UnwrappedDefExpr { loc_expr: new_apply, target })
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg: unwrapped_function, sub_pat, sub_new }) => {
|
Err(EUnwrapped::UnwrappedSubExpr { sub_arg: unwrapped_function, sub_pat, sub_new, target }) => {
|
||||||
|
|
||||||
let new_apply = arena.alloc(Loc::at(loc_expr.region, Expr::Apply(sub_new, local_args, called_via)));
|
let new_apply = arena.alloc(Loc::at(loc_expr.region, Expr::Apply(sub_new, local_args, called_via)));
|
||||||
|
|
||||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg: unwrapped_function, sub_pat, sub_new:new_apply})
|
Err(EUnwrapped::UnwrappedSubExpr { sub_arg: unwrapped_function, sub_pat, sub_new:new_apply, target })
|
||||||
}
|
}
|
||||||
Err(err) => Err(err)
|
Err(err) => Err(err)
|
||||||
}
|
}
|
||||||
|
@ -361,21 +384,23 @@ pub fn unwrap_suffixed_expression_if_then_else_help<'a>(
|
||||||
|
|
||||||
return unwrap_suffixed_expression(arena, new_if, maybe_def_pat);
|
return unwrap_suffixed_expression(arena, new_if, maybe_def_pat);
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedDefExpr(..)) => {
|
Err(EUnwrapped::UnwrappedDefExpr { .. }) => {
|
||||||
internal_error!("unexpected, unwrapped if-then-else Def expr should have intermediate answer as `None` was passed as pattern");
|
internal_error!("unexpected, unwrapped if-then-else Def expr should have intermediate answer as `None` was passed as pattern");
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedSubExpr {
|
Err(EUnwrapped::UnwrappedSubExpr {
|
||||||
sub_arg,
|
sub_arg,
|
||||||
sub_pat,
|
sub_pat,
|
||||||
sub_new,
|
sub_new,
|
||||||
|
target,
|
||||||
}) => {
|
}) => {
|
||||||
let unwrapped_expression = apply_task_await(
|
let unwrapped_expression = apply_try_function(
|
||||||
arena,
|
arena,
|
||||||
sub_arg.region,
|
sub_arg.region,
|
||||||
sub_arg,
|
sub_arg,
|
||||||
sub_pat,
|
sub_pat,
|
||||||
sub_new,
|
sub_new,
|
||||||
None,
|
None,
|
||||||
|
target,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut new_if_thens = Vec::new_in(arena);
|
let mut new_if_thens = Vec::new_in(arena);
|
||||||
|
@ -422,13 +447,14 @@ pub fn unwrap_suffixed_expression_if_then_else_help<'a>(
|
||||||
|
|
||||||
return unwrap_suffixed_expression(arena, new_if, maybe_def_pat);
|
return unwrap_suffixed_expression(arena, new_if, maybe_def_pat);
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedDefExpr(..)) => {
|
Err(EUnwrapped::UnwrappedDefExpr { .. }) => {
|
||||||
internal_error!("unexpected, unwrapped if-then-else Def expr should have intermediate answer as `None` was passed as pattern");
|
internal_error!("unexpected, unwrapped if-then-else Def expr should have intermediate answer as `None` was passed as pattern");
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedSubExpr {
|
Err(EUnwrapped::UnwrappedSubExpr {
|
||||||
sub_arg,
|
sub_arg,
|
||||||
sub_pat,
|
sub_pat,
|
||||||
sub_new,
|
sub_new,
|
||||||
|
target,
|
||||||
}) => {
|
}) => {
|
||||||
if before.is_empty() {
|
if before.is_empty() {
|
||||||
let mut new_if_thens = Vec::new_in(arena);
|
let mut new_if_thens = Vec::new_in(arena);
|
||||||
|
@ -445,13 +471,14 @@ pub fn unwrap_suffixed_expression_if_then_else_help<'a>(
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|
||||||
let unwrapped_if_then = apply_task_await(
|
let unwrapped_if_then = apply_try_function(
|
||||||
arena,
|
arena,
|
||||||
sub_arg.region,
|
sub_arg.region,
|
||||||
sub_arg,
|
sub_arg,
|
||||||
sub_pat,
|
sub_pat,
|
||||||
new_if,
|
new_if,
|
||||||
None,
|
None,
|
||||||
|
target,
|
||||||
);
|
);
|
||||||
|
|
||||||
return unwrap_suffixed_expression(
|
return unwrap_suffixed_expression(
|
||||||
|
@ -473,13 +500,14 @@ pub fn unwrap_suffixed_expression_if_then_else_help<'a>(
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|
||||||
let after_if_then = apply_task_await(
|
let after_if_then = apply_try_function(
|
||||||
arena,
|
arena,
|
||||||
sub_arg.region,
|
sub_arg.region,
|
||||||
sub_arg,
|
sub_arg,
|
||||||
sub_pat,
|
sub_pat,
|
||||||
after_if,
|
after_if,
|
||||||
None,
|
None,
|
||||||
|
target,
|
||||||
);
|
);
|
||||||
|
|
||||||
let before_if_then = arena.alloc(Loc::at(
|
let before_if_then = arena.alloc(Loc::at(
|
||||||
|
@ -507,16 +535,24 @@ pub fn unwrap_suffixed_expression_if_then_else_help<'a>(
|
||||||
Expr::If(if_thens, unwrapped_final_else),
|
Expr::If(if_thens, unwrapped_final_else),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedDefExpr(..)) => {
|
Err(EUnwrapped::UnwrappedDefExpr { .. }) => {
|
||||||
internal_error!("unexpected, unwrapped if-then-else Def expr should have intermediate answer as `None` was passed as pattern");
|
internal_error!("unexpected, unwrapped if-then-else Def expr should have intermediate answer as `None` was passed as pattern");
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedSubExpr {
|
Err(EUnwrapped::UnwrappedSubExpr {
|
||||||
sub_arg,
|
sub_arg,
|
||||||
sub_pat,
|
sub_pat,
|
||||||
sub_new,
|
sub_new,
|
||||||
|
target,
|
||||||
}) => {
|
}) => {
|
||||||
let unwrapped_final_else =
|
let unwrapped_final_else = apply_try_function(
|
||||||
apply_task_await(arena, sub_arg.region, sub_arg, sub_pat, sub_new, None);
|
arena,
|
||||||
|
sub_arg.region,
|
||||||
|
sub_arg,
|
||||||
|
sub_pat,
|
||||||
|
sub_new,
|
||||||
|
None,
|
||||||
|
target,
|
||||||
|
);
|
||||||
|
|
||||||
let new_if = arena.alloc(Loc::at(
|
let new_if = arena.alloc(Loc::at(
|
||||||
loc_expr.region,
|
loc_expr.region,
|
||||||
|
@ -551,7 +587,7 @@ pub fn unwrap_suffixed_expression_when_help<'a>(
|
||||||
if is_expr_suffixed(&branch_loc_expr.value) {
|
if is_expr_suffixed(&branch_loc_expr.value) {
|
||||||
let unwrapped_branch_value = match unwrap_suffixed_expression(arena, branch_loc_expr, None) {
|
let unwrapped_branch_value = match unwrap_suffixed_expression(arena, branch_loc_expr, None) {
|
||||||
Ok(unwrapped_branch_value) => unwrapped_branch_value,
|
Ok(unwrapped_branch_value) => unwrapped_branch_value,
|
||||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new }) => apply_task_await(arena, branch_loc_expr.region, sub_arg, sub_pat, sub_new, None),
|
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new, target }) => apply_try_function(arena, branch_loc_expr.region, sub_arg, sub_pat, sub_new, None, target),
|
||||||
Err(..) => return Err(EUnwrapped::Malformed),
|
Err(..) => return Err(EUnwrapped::Malformed),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -578,12 +614,12 @@ pub fn unwrap_suffixed_expression_when_help<'a>(
|
||||||
let new_when = arena.alloc(Loc::at(loc_expr.region, Expr::When(unwrapped_condition, branches)));
|
let new_when = arena.alloc(Loc::at(loc_expr.region, Expr::When(unwrapped_condition, branches)));
|
||||||
Ok(new_when)
|
Ok(new_when)
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new }) => {
|
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new, target }) => {
|
||||||
let new_when = arena.alloc(Loc::at(loc_expr.region, Expr::When(sub_new, branches)));
|
let new_when = arena.alloc(Loc::at(loc_expr.region, Expr::When(sub_new, branches)));
|
||||||
let applied_task_await = apply_task_await(arena,loc_expr.region,sub_arg,sub_pat,new_when, None);
|
let applied_task_await = apply_try_function(arena,loc_expr.region,sub_arg,sub_pat,new_when, None, target);
|
||||||
Ok(applied_task_await)
|
Ok(applied_task_await)
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedDefExpr(..))
|
Err(EUnwrapped::UnwrappedDefExpr { .. })
|
||||||
| Err(EUnwrapped::Malformed) => Err(EUnwrapped::Malformed)
|
| Err(EUnwrapped::Malformed) => Err(EUnwrapped::Malformed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -631,7 +667,7 @@ pub fn unwrap_suffixed_expression_defs_help<'a>(
|
||||||
current_value_def.replace_expr(unwrapped_def);
|
current_value_def.replace_expr(unwrapped_def);
|
||||||
local_defs.replace_with_value_def(tag_index, current_value_def, def_expr.region);
|
local_defs.replace_with_value_def(tag_index, current_value_def, def_expr.region);
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedDefExpr(unwrapped_expr)) => {
|
Err(EUnwrapped::UnwrappedDefExpr { loc_expr: unwrapped_expr, target }) => {
|
||||||
let split_defs = local_defs.split_defs_around(tag_index);
|
let split_defs = local_defs.split_defs_around(tag_index);
|
||||||
let before_empty = split_defs.before.is_empty();
|
let before_empty = split_defs.before.is_empty();
|
||||||
let after_empty = split_defs.after.is_empty();
|
let after_empty = split_defs.after.is_empty();
|
||||||
|
@ -640,48 +676,60 @@ pub fn unwrap_suffixed_expression_defs_help<'a>(
|
||||||
// We pass None as a def pattern here because it's desugaring of the ret expression
|
// We pass None as a def pattern here because it's desugaring of the ret expression
|
||||||
let next_expr = match unwrap_suffixed_expression(arena,loc_ret, None) {
|
let next_expr = match unwrap_suffixed_expression(arena,loc_ret, None) {
|
||||||
Ok(next_expr) => next_expr,
|
Ok(next_expr) => next_expr,
|
||||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new }) => {
|
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new, target }) => {
|
||||||
// We need to apply Task.ok here as the defs final expression was unwrapped
|
// We need to apply Task.ok here as the defs final expression was unwrapped
|
||||||
apply_task_await(arena,def_expr.region,sub_arg,sub_pat,sub_new, None)
|
apply_try_function(arena,def_expr.region,sub_arg,sub_pat,sub_new, None, target)
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedDefExpr(..)) | Err(EUnwrapped::Malformed) => {
|
Err(EUnwrapped::UnwrappedDefExpr { .. }) | Err(EUnwrapped::Malformed) => {
|
||||||
// TODO handle case when we have maybe_def_pat so can return an unwrapped up
|
// TODO handle case when we have maybe_def_pat so can return an unwrapped up
|
||||||
return Err(EUnwrapped::Malformed);
|
return Err(EUnwrapped::Malformed);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
return unwrap_suffixed_expression(arena, apply_task_await(arena,def_expr.region,unwrapped_expr,def_pattern,next_expr, ann_type), maybe_def_pat);
|
return unwrap_suffixed_expression(
|
||||||
|
arena,
|
||||||
|
apply_try_function(
|
||||||
|
arena,
|
||||||
|
def_expr.region,
|
||||||
|
unwrapped_expr,
|
||||||
|
def_pattern,
|
||||||
|
next_expr,
|
||||||
|
ann_type,
|
||||||
|
target,
|
||||||
|
),
|
||||||
|
maybe_def_pat
|
||||||
|
);
|
||||||
} else if before_empty {
|
} else if before_empty {
|
||||||
// NIL before, SOME after -> FIRST DEF
|
// NIL before, SOME after -> FIRST DEF
|
||||||
let new_defs = arena.alloc(Loc::at(def_expr.region, Defs(arena.alloc(split_defs.after), loc_ret)));
|
let new_defs = arena.alloc(Loc::at(def_expr.region, Defs(arena.alloc(split_defs.after), loc_ret)));
|
||||||
|
|
||||||
let next_expr = match unwrap_suffixed_expression(arena,new_defs,maybe_def_pat){
|
let next_expr = match unwrap_suffixed_expression(arena,new_defs,maybe_def_pat){
|
||||||
Ok(next_expr) => next_expr,
|
Ok(next_expr) => next_expr,
|
||||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new }) => {
|
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new, target }) => {
|
||||||
apply_task_await(arena, def_expr.region, sub_arg, sub_pat, sub_new, None)
|
apply_try_function(arena, def_expr.region, sub_arg, sub_pat, sub_new, None, target)
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedDefExpr(..)) | Err(EUnwrapped::Malformed) => {
|
Err(EUnwrapped::UnwrappedDefExpr { .. }) | Err(EUnwrapped::Malformed) => {
|
||||||
// TODO handle case when we have maybe_def_pat so can return an unwrapped up
|
// TODO handle case when we have maybe_def_pat so can return an unwrapped up
|
||||||
return Err(EUnwrapped::Malformed);
|
return Err(EUnwrapped::Malformed);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return unwrap_suffixed_expression(arena, apply_task_await(arena,def_expr.region,unwrapped_expr,def_pattern,next_expr,ann_type), maybe_def_pat);
|
return unwrap_suffixed_expression(arena, apply_try_function(arena,def_expr.region,unwrapped_expr,def_pattern,next_expr, ann_type, target), maybe_def_pat);
|
||||||
} else if after_empty {
|
} else if after_empty {
|
||||||
// SOME before, NIL after -> LAST DEF
|
// SOME before, NIL after -> LAST DEF
|
||||||
// We pass None as a def pattern here because it's desugaring of the ret expression
|
// We pass None as a def pattern here because it's desugaring of the ret expression
|
||||||
match unwrap_suffixed_expression(arena,loc_ret,None){
|
match unwrap_suffixed_expression(arena,loc_ret,None){
|
||||||
Ok(new_loc_ret) => {
|
Ok(new_loc_ret) => {
|
||||||
let applied_task_await = apply_task_await(arena, loc_expr.region, unwrapped_expr, def_pattern, new_loc_ret, ann_type);
|
let applied_task_await = apply_try_function(arena, loc_expr.region, unwrapped_expr, def_pattern, new_loc_ret, ann_type, target);
|
||||||
let new_defs = arena.alloc(Loc::at(loc_expr.region,Defs(arena.alloc(split_defs.before), applied_task_await)));
|
let new_defs = arena.alloc(Loc::at(loc_expr.region,Defs(arena.alloc(split_defs.before), applied_task_await)));
|
||||||
return unwrap_suffixed_expression(arena, new_defs, maybe_def_pat);
|
return unwrap_suffixed_expression(arena, new_defs, maybe_def_pat);
|
||||||
},
|
},
|
||||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new }) => {
|
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new, target }) => {
|
||||||
let new_loc_ret = apply_task_await(arena,def_expr.region,sub_arg,sub_pat,sub_new, None);
|
let new_loc_ret = apply_try_function(arena,def_expr.region,sub_arg,sub_pat,sub_new, None, target);
|
||||||
let applied_task_await = apply_task_await(arena, loc_expr.region, unwrapped_expr, def_pattern, new_loc_ret, ann_type);
|
let applied_task_await = apply_try_function(arena, loc_expr.region, unwrapped_expr, def_pattern, new_loc_ret, ann_type, target);
|
||||||
let new_defs = arena.alloc(Loc::at(loc_expr.region,Defs(arena.alloc(split_defs.before), applied_task_await)));
|
let new_defs = arena.alloc(Loc::at(loc_expr.region,Defs(arena.alloc(split_defs.before), applied_task_await)));
|
||||||
return unwrap_suffixed_expression(arena, new_defs, maybe_def_pat);
|
return unwrap_suffixed_expression(arena, new_defs, maybe_def_pat);
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedDefExpr(..)) => {
|
Err(EUnwrapped::UnwrappedDefExpr { .. }) => {
|
||||||
// TODO confirm this is correct with test case
|
// TODO confirm this is correct with test case
|
||||||
return Err(EUnwrapped::Malformed);
|
return Err(EUnwrapped::Malformed);
|
||||||
}
|
}
|
||||||
|
@ -695,28 +743,28 @@ pub fn unwrap_suffixed_expression_defs_help<'a>(
|
||||||
|
|
||||||
match unwrap_suffixed_expression(arena,after_defs,maybe_def_pat){
|
match unwrap_suffixed_expression(arena,after_defs,maybe_def_pat){
|
||||||
Ok(new_loc_ret) => {
|
Ok(new_loc_ret) => {
|
||||||
let applied_await = apply_task_await(arena, loc_expr.region, unwrapped_expr, def_pattern, new_loc_ret, ann_type);
|
let applied_await = apply_try_function(arena, loc_expr.region, unwrapped_expr, def_pattern, new_loc_ret, ann_type, target);
|
||||||
let new_defs = arena.alloc(Loc::at(loc_expr.region,Defs(arena.alloc(split_defs.before), applied_await)));
|
let new_defs = arena.alloc(Loc::at(loc_expr.region,Defs(arena.alloc(split_defs.before), applied_await)));
|
||||||
return unwrap_suffixed_expression(arena, new_defs, maybe_def_pat);
|
return unwrap_suffixed_expression(arena, new_defs, maybe_def_pat);
|
||||||
},
|
},
|
||||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new }) => {
|
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new, target }) => {
|
||||||
let new_loc_ret = apply_task_await(arena, def_expr.region, sub_arg, sub_pat, sub_new, None);
|
let new_loc_ret = apply_try_function(arena, def_expr.region, sub_arg, sub_pat, sub_new, None, target);
|
||||||
let applied_await = apply_task_await(arena, loc_expr.region, unwrapped_expr, def_pattern, new_loc_ret, ann_type);
|
let applied_await = apply_try_function(arena, loc_expr.region, unwrapped_expr, def_pattern, new_loc_ret, ann_type, target);
|
||||||
let new_defs = arena.alloc(Loc::at(loc_expr.region,Defs(arena.alloc(split_defs.before), applied_await)));
|
let new_defs = arena.alloc(Loc::at(loc_expr.region,Defs(arena.alloc(split_defs.before), applied_await)));
|
||||||
return unwrap_suffixed_expression(arena, new_defs, maybe_def_pat);
|
return unwrap_suffixed_expression(arena, new_defs, maybe_def_pat);
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedDefExpr(..)) | Err(EUnwrapped::Malformed) => {
|
Err(EUnwrapped::UnwrappedDefExpr { .. }) | Err(EUnwrapped::Malformed) => {
|
||||||
// TODO handle case when we have maybe_def_pat so can return an unwrapped up
|
// TODO handle case when we have maybe_def_pat so can return an unwrapped up
|
||||||
return Err(EUnwrapped::Malformed);
|
return Err(EUnwrapped::Malformed);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new }) => {
|
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new, target }) => {
|
||||||
let new_body_def = ValueDef::Body(def_pattern, sub_new);
|
let new_body_def = ValueDef::Body(def_pattern, sub_new);
|
||||||
local_defs.replace_with_value_def(tag_index,new_body_def, sub_new.region);
|
local_defs.replace_with_value_def(tag_index,new_body_def, sub_new.region);
|
||||||
let new_defs_expr = arena.alloc(Loc::at(def_expr.region,Defs(arena.alloc(local_defs), loc_ret)));
|
let new_defs_expr = arena.alloc(Loc::at(def_expr.region,Defs(arena.alloc(local_defs), loc_ret)));
|
||||||
let replaced_def = apply_task_await(arena,def_expr.region,sub_arg,sub_pat,new_defs_expr, ann_type);
|
let replaced_def = apply_try_function(arena,def_expr.region,sub_arg,sub_pat,new_defs_expr, ann_type, target);
|
||||||
return unwrap_suffixed_expression(arena,replaced_def,maybe_def_pat);
|
return unwrap_suffixed_expression(arena,replaced_def,maybe_def_pat);
|
||||||
}
|
}
|
||||||
Err(err) => return Err(err)
|
Err(err) => return Err(err)
|
||||||
|
@ -730,12 +778,12 @@ pub fn unwrap_suffixed_expression_defs_help<'a>(
|
||||||
Ok(new_loc_ret) => {
|
Ok(new_loc_ret) => {
|
||||||
Ok(arena.alloc(Loc::at(loc_expr.region,Defs(arena.alloc(local_defs), new_loc_ret))))
|
Ok(arena.alloc(Loc::at(loc_expr.region,Defs(arena.alloc(local_defs), new_loc_ret))))
|
||||||
},
|
},
|
||||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new }) => {
|
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new, target }) => {
|
||||||
let new_loc_ret = apply_task_await(arena, loc_expr.region,sub_arg,sub_pat,sub_new, None);
|
let new_loc_ret = apply_try_function(arena, loc_expr.region,sub_arg,sub_pat,sub_new, None, target);
|
||||||
let new_defs = arena.alloc(Loc::at(loc_expr.region,Defs(arena.alloc(local_defs), new_loc_ret)));
|
let new_defs = arena.alloc(Loc::at(loc_expr.region,Defs(arena.alloc(local_defs), new_loc_ret)));
|
||||||
unwrap_suffixed_expression(arena, new_defs, None)
|
unwrap_suffixed_expression(arena, new_defs, None)
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedDefExpr(..)) => {
|
Err(EUnwrapped::UnwrappedDefExpr { .. }) => {
|
||||||
// TODO confirm this is correct with test case
|
// TODO confirm this is correct with test case
|
||||||
Err(EUnwrapped::Malformed)
|
Err(EUnwrapped::Malformed)
|
||||||
}
|
}
|
||||||
|
@ -769,6 +817,7 @@ fn unwrap_low_level_dbg<'a>(
|
||||||
sub_arg,
|
sub_arg,
|
||||||
sub_pat,
|
sub_pat,
|
||||||
sub_new,
|
sub_new,
|
||||||
|
target,
|
||||||
}) => {
|
}) => {
|
||||||
let new_dbg = arena.alloc(Loc::at(
|
let new_dbg = arena.alloc(Loc::at(
|
||||||
loc_expr.region,
|
loc_expr.region,
|
||||||
|
@ -777,18 +826,19 @@ fn unwrap_low_level_dbg<'a>(
|
||||||
|
|
||||||
unwrap_suffixed_expression(
|
unwrap_suffixed_expression(
|
||||||
arena,
|
arena,
|
||||||
apply_task_await(
|
apply_try_function(
|
||||||
arena,
|
arena,
|
||||||
new_dbg.region,
|
new_dbg.region,
|
||||||
sub_arg,
|
sub_arg,
|
||||||
sub_pat,
|
sub_pat,
|
||||||
new_dbg,
|
new_dbg,
|
||||||
None,
|
None,
|
||||||
|
target,
|
||||||
),
|
),
|
||||||
maybe_def_pat,
|
maybe_def_pat,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedDefExpr(..)) => {
|
Err(EUnwrapped::UnwrappedDefExpr { .. }) => {
|
||||||
internal_error!(
|
internal_error!(
|
||||||
"unreachable, arg of LowLevelDbg should generate UnwrappedSubExpr instead"
|
"unreachable, arg of LowLevelDbg should generate UnwrappedSubExpr instead"
|
||||||
);
|
);
|
||||||
|
@ -805,17 +855,24 @@ fn unwrap_low_level_dbg<'a>(
|
||||||
));
|
));
|
||||||
Ok(&*new_dbg)
|
Ok(&*new_dbg)
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedDefExpr(unwrapped_expr)) => {
|
Err(EUnwrapped::UnwrappedDefExpr {
|
||||||
|
loc_expr: unwrapped_expr,
|
||||||
|
target,
|
||||||
|
}) => {
|
||||||
let new_dbg = arena.alloc(Loc::at(
|
let new_dbg = arena.alloc(Loc::at(
|
||||||
loc_expr.region,
|
loc_expr.region,
|
||||||
LowLevelDbg(dbg_src, arg, unwrapped_expr),
|
LowLevelDbg(dbg_src, arg, unwrapped_expr),
|
||||||
));
|
));
|
||||||
Err(EUnwrapped::UnwrappedDefExpr(new_dbg))
|
Err(EUnwrapped::UnwrappedDefExpr {
|
||||||
|
loc_expr: new_dbg,
|
||||||
|
target,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::UnwrappedSubExpr {
|
Err(EUnwrapped::UnwrappedSubExpr {
|
||||||
sub_arg: unwrapped_expr,
|
sub_arg: unwrapped_expr,
|
||||||
sub_pat,
|
sub_pat,
|
||||||
sub_new,
|
sub_new,
|
||||||
|
target,
|
||||||
}) => {
|
}) => {
|
||||||
let new_dbg = arena.alloc(Loc::at(
|
let new_dbg = arena.alloc(Loc::at(
|
||||||
loc_expr.region,
|
loc_expr.region,
|
||||||
|
@ -825,6 +882,7 @@ fn unwrap_low_level_dbg<'a>(
|
||||||
sub_arg: new_dbg,
|
sub_arg: new_dbg,
|
||||||
sub_pat,
|
sub_pat,
|
||||||
sub_new,
|
sub_new,
|
||||||
|
target,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Err(EUnwrapped::Malformed) => Err(EUnwrapped::Malformed),
|
Err(EUnwrapped::Malformed) => Err(EUnwrapped::Malformed),
|
||||||
|
@ -836,25 +894,26 @@ fn unwrap_low_level_dbg<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper for `Task.await loc_expr \loc_pat -> loc_cont`
|
/// Helper for try_function loc_expr \loc_pat -> loc_cont`
|
||||||
pub fn apply_task_await<'a>(
|
pub fn apply_try_function<'a>(
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
region: Region,
|
region: Region,
|
||||||
loc_expr: &'a Loc<Expr<'a>>,
|
loc_expr: &'a Loc<Expr<'a>>,
|
||||||
loc_pat: &'a Loc<Pattern<'a>>,
|
loc_pat: &'a Loc<Pattern<'a>>,
|
||||||
loc_cont: &'a Loc<Expr<'a>>,
|
loc_cont: &'a Loc<Expr<'a>>,
|
||||||
maybe_loc_ann: Option<(&'a Loc<Pattern>, &'a Loc<TypeAnnotation<'a>>)>,
|
maybe_loc_ann: Option<(&'a Loc<Pattern>, &'a Loc<TypeAnnotation<'a>>)>,
|
||||||
|
target: TryTarget,
|
||||||
) -> &'a Loc<Expr<'a>> {
|
) -> &'a Loc<Expr<'a>> {
|
||||||
let task_await_first_arg = match maybe_loc_ann {
|
let try_function_first_arg = match maybe_loc_ann {
|
||||||
Some((loc_ann_pat, loc_type)) => {
|
Some((loc_ann_pat, loc_type)) => {
|
||||||
// loc_ann_pat : loc_type
|
// loc_ann_pat : loc_type
|
||||||
// loc_pat = loc_expr!
|
// loc_pat = loc_expr!
|
||||||
// loc_cont
|
// loc_cont
|
||||||
|
|
||||||
// desugar to
|
// desugar to
|
||||||
// Task.await
|
// try_function
|
||||||
// (
|
// (
|
||||||
// #!0_expr : Task loc_type _
|
// #!0_expr : Target loc_type _
|
||||||
// #!0_expr = loc_expr
|
// #!0_expr = loc_expr
|
||||||
// #!0_expr
|
// #!0_expr
|
||||||
// )
|
// )
|
||||||
|
@ -875,8 +934,12 @@ pub fn apply_task_await<'a>(
|
||||||
let new_ident = arena.alloc(new_ident);
|
let new_ident = arena.alloc(new_ident);
|
||||||
|
|
||||||
// #!0_expr (pattern)
|
// #!0_expr (pattern)
|
||||||
// #!0_expr : Task loc_type _
|
// #!0_expr : Target loc_type _
|
||||||
// #!0_expr = loc_expr
|
// #!0_expr = loc_expr
|
||||||
|
let target_type_name = match target {
|
||||||
|
TryTarget::Task => "Task",
|
||||||
|
TryTarget::Result => "Result",
|
||||||
|
};
|
||||||
let value_def = ValueDef::AnnotatedBody {
|
let value_def = ValueDef::AnnotatedBody {
|
||||||
ann_pattern: arena.alloc(Loc::at(
|
ann_pattern: arena.alloc(Loc::at(
|
||||||
loc_ann_pat.region,
|
loc_ann_pat.region,
|
||||||
|
@ -893,7 +956,7 @@ pub fn apply_task_await<'a>(
|
||||||
loc_type.region,
|
loc_type.region,
|
||||||
TypeAnnotation::Apply(
|
TypeAnnotation::Apply(
|
||||||
arena.alloc(""),
|
arena.alloc(""),
|
||||||
arena.alloc("Task"),
|
arena.alloc(target_type_name),
|
||||||
arena.alloc([
|
arena.alloc([
|
||||||
*loc_type,
|
*loc_type,
|
||||||
Loc::at(loc_type.region, TypeAnnotation::Inferred),
|
Loc::at(loc_type.region, TypeAnnotation::Inferred),
|
||||||
|
@ -918,7 +981,7 @@ pub fn apply_task_await<'a>(
|
||||||
));
|
));
|
||||||
|
|
||||||
// (
|
// (
|
||||||
// #!0_expr : Task loc_type _
|
// #!0_expr : Target loc_type _
|
||||||
// #!0_expr = loc_expr
|
// #!0_expr = loc_expr
|
||||||
// #!0_expr
|
// #!0_expr
|
||||||
// )
|
// )
|
||||||
|
@ -935,7 +998,7 @@ pub fn apply_task_await<'a>(
|
||||||
// loc_cont
|
// loc_cont
|
||||||
|
|
||||||
// desugar to
|
// desugar to
|
||||||
// Task.await loc_expr \loc_pat -> loc_cont
|
// try_function loc_expr \loc_pat -> loc_cont
|
||||||
loc_expr
|
loc_expr
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -945,25 +1008,29 @@ pub fn apply_task_await<'a>(
|
||||||
// \x -> x!
|
// \x -> x!
|
||||||
// \x -> x
|
// \x -> x
|
||||||
if is_matching_intermediate_answer(loc_pat, loc_cont) {
|
if is_matching_intermediate_answer(loc_pat, loc_cont) {
|
||||||
return task_await_first_arg;
|
return try_function_first_arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
// \loc_pat -> loc_cont
|
// \loc_pat -> loc_cont
|
||||||
let closure = arena.alloc(Loc::at(region, Closure(arena.alloc([*loc_pat]), loc_cont)));
|
let closure = arena.alloc(Loc::at(region, Closure(arena.alloc([*loc_pat]), loc_cont)));
|
||||||
|
|
||||||
// Task.await task_first_arg closure
|
// try_function first_arg closure
|
||||||
|
let (try_function_module, try_function_ident, called_via) = match target {
|
||||||
|
TryTarget::Task => (ModuleName::TASK, "await", CalledVia::BangSuffix),
|
||||||
|
TryTarget::Result => (ModuleName::RESULT, "try", CalledVia::QuestionSuffix),
|
||||||
|
};
|
||||||
arena.alloc(Loc::at(
|
arena.alloc(Loc::at(
|
||||||
region,
|
region,
|
||||||
Apply(
|
Apply(
|
||||||
arena.alloc(Loc {
|
arena.alloc(Loc {
|
||||||
region,
|
region,
|
||||||
value: Var {
|
value: Var {
|
||||||
module_name: ModuleName::TASK,
|
module_name: try_function_module,
|
||||||
ident: "await",
|
ident: try_function_ident,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
arena.alloc([task_await_first_arg, closure]),
|
arena.alloc([try_function_first_arg, closure]),
|
||||||
CalledVia::BangSuffix,
|
called_via,
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
207
crates/compiler/can/src/task_module.rs
Normal file
207
crates/compiler/can/src/task_module.rs
Normal file
|
@ -0,0 +1,207 @@
|
||||||
|
use crate::def::Def;
|
||||||
|
use crate::expr::{AnnotatedMark, ClosureData, Expr, Recursive};
|
||||||
|
use crate::pattern::Pattern;
|
||||||
|
use crate::scope::Scope;
|
||||||
|
use roc_collections::SendMap;
|
||||||
|
use roc_module::symbol::Symbol;
|
||||||
|
use roc_region::all::{Loc, Region};
|
||||||
|
use roc_types::subs::{VarStore, Variable};
|
||||||
|
use roc_types::types::{LambdaSet, OptAbleVar, Type};
|
||||||
|
|
||||||
|
pub fn build_host_exposed_def(
|
||||||
|
scope: &mut Scope,
|
||||||
|
symbol: Symbol,
|
||||||
|
ident: &str,
|
||||||
|
var_store: &mut VarStore,
|
||||||
|
annotation: crate::annotation::Annotation,
|
||||||
|
) -> Def {
|
||||||
|
let expr_var = var_store.fresh();
|
||||||
|
let pattern = Pattern::Identifier(symbol);
|
||||||
|
let mut pattern_vars = SendMap::default();
|
||||||
|
pattern_vars.insert(symbol, expr_var);
|
||||||
|
|
||||||
|
let mut arguments: Vec<(Variable, AnnotatedMark, Loc<Pattern>)> = Vec::new();
|
||||||
|
let mut linked_symbol_arguments: Vec<(Variable, Expr)> = Vec::new();
|
||||||
|
let mut captured_symbols: Vec<(Symbol, Variable)> = Vec::new();
|
||||||
|
|
||||||
|
let crate::annotation::Annotation {
|
||||||
|
introduced_variables,
|
||||||
|
typ,
|
||||||
|
aliases,
|
||||||
|
..
|
||||||
|
} = annotation;
|
||||||
|
|
||||||
|
let def_body = {
|
||||||
|
match typ.shallow_structural_dealias() {
|
||||||
|
Type::Function(args, _, _) => {
|
||||||
|
for i in 0..args.len() {
|
||||||
|
let name = format!("closure_arg_{ident}_{i}");
|
||||||
|
|
||||||
|
let arg_symbol = {
|
||||||
|
let ident = name.clone().into();
|
||||||
|
scope.introduce(ident, Region::zero()).unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
let arg_var = var_store.fresh();
|
||||||
|
|
||||||
|
arguments.push((
|
||||||
|
arg_var,
|
||||||
|
AnnotatedMark::new(var_store),
|
||||||
|
Loc::at_zero(Pattern::Identifier(arg_symbol)),
|
||||||
|
));
|
||||||
|
|
||||||
|
captured_symbols.push((arg_symbol, arg_var));
|
||||||
|
linked_symbol_arguments.push((arg_var, Expr::Var(arg_symbol, arg_var)));
|
||||||
|
}
|
||||||
|
|
||||||
|
let foreign_symbol_name = format!("roc_fx_{ident}");
|
||||||
|
let low_level_call = Expr::ForeignCall {
|
||||||
|
foreign_symbol: foreign_symbol_name.into(),
|
||||||
|
args: linked_symbol_arguments,
|
||||||
|
ret_var: var_store.fresh(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let task_closure_symbol = {
|
||||||
|
let name = format!("task_closure_{ident}");
|
||||||
|
|
||||||
|
let ident = name.into();
|
||||||
|
scope.introduce(ident, Region::zero()).unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
let task_closure = Expr::Closure(ClosureData {
|
||||||
|
function_type: var_store.fresh(),
|
||||||
|
closure_type: var_store.fresh(),
|
||||||
|
return_type: var_store.fresh(),
|
||||||
|
name: task_closure_symbol,
|
||||||
|
captured_symbols,
|
||||||
|
recursive: Recursive::NotRecursive,
|
||||||
|
arguments: vec![(
|
||||||
|
var_store.fresh(),
|
||||||
|
AnnotatedMark::new(var_store),
|
||||||
|
Loc::at_zero(empty_record_pattern(var_store)),
|
||||||
|
)],
|
||||||
|
loc_body: Box::new(Loc::at_zero(low_level_call)),
|
||||||
|
});
|
||||||
|
|
||||||
|
let (specialized_def_type, type_arguments, lambda_set_variables) =
|
||||||
|
build_fresh_opaque_variables(var_store);
|
||||||
|
let body = Expr::OpaqueRef {
|
||||||
|
opaque_var: var_store.fresh(),
|
||||||
|
name: Symbol::TASK_TASK,
|
||||||
|
argument: Box::new((var_store.fresh(), Loc::at_zero(task_closure))),
|
||||||
|
specialized_def_type,
|
||||||
|
type_arguments,
|
||||||
|
lambda_set_variables,
|
||||||
|
};
|
||||||
|
|
||||||
|
Expr::Closure(ClosureData {
|
||||||
|
function_type: var_store.fresh(),
|
||||||
|
closure_type: var_store.fresh(),
|
||||||
|
return_type: var_store.fresh(),
|
||||||
|
name: symbol,
|
||||||
|
captured_symbols: std::vec::Vec::new(),
|
||||||
|
recursive: Recursive::NotRecursive,
|
||||||
|
arguments,
|
||||||
|
loc_body: Box::new(Loc::at_zero(body)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// not a function
|
||||||
|
|
||||||
|
let foreign_symbol_name = format!("roc_fx_{ident}");
|
||||||
|
let low_level_call = Expr::ForeignCall {
|
||||||
|
foreign_symbol: foreign_symbol_name.into(),
|
||||||
|
args: linked_symbol_arguments,
|
||||||
|
ret_var: var_store.fresh(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let task_closure_symbol = {
|
||||||
|
let name = format!("task_closure_{ident}");
|
||||||
|
|
||||||
|
let ident = name.into();
|
||||||
|
scope.introduce(ident, Region::zero()).unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
let task_closure = Expr::Closure(ClosureData {
|
||||||
|
function_type: var_store.fresh(),
|
||||||
|
closure_type: var_store.fresh(),
|
||||||
|
return_type: var_store.fresh(),
|
||||||
|
name: task_closure_symbol,
|
||||||
|
captured_symbols,
|
||||||
|
recursive: Recursive::NotRecursive,
|
||||||
|
arguments: vec![(
|
||||||
|
var_store.fresh(),
|
||||||
|
AnnotatedMark::new(var_store),
|
||||||
|
Loc::at_zero(empty_record_pattern(var_store)),
|
||||||
|
)],
|
||||||
|
loc_body: Box::new(Loc::at_zero(low_level_call)),
|
||||||
|
});
|
||||||
|
|
||||||
|
let (specialized_def_type, type_arguments, lambda_set_variables) =
|
||||||
|
build_fresh_opaque_variables(var_store);
|
||||||
|
Expr::OpaqueRef {
|
||||||
|
opaque_var: var_store.fresh(),
|
||||||
|
name: Symbol::TASK_TASK,
|
||||||
|
argument: Box::new((var_store.fresh(), Loc::at_zero(task_closure))),
|
||||||
|
specialized_def_type,
|
||||||
|
type_arguments,
|
||||||
|
lambda_set_variables,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let def_annotation = crate::def::Annotation {
|
||||||
|
signature: typ,
|
||||||
|
introduced_variables,
|
||||||
|
aliases,
|
||||||
|
region: Region::zero(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Def {
|
||||||
|
loc_pattern: Loc::at_zero(pattern),
|
||||||
|
loc_expr: Loc::at_zero(def_body),
|
||||||
|
expr_var,
|
||||||
|
pattern_vars,
|
||||||
|
annotation: Some(def_annotation),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_fresh_opaque_variables(
|
||||||
|
var_store: &mut VarStore,
|
||||||
|
) -> (Box<Type>, Vec<OptAbleVar>, Vec<LambdaSet>) {
|
||||||
|
let closure_var = var_store.fresh();
|
||||||
|
|
||||||
|
let ok_var = var_store.fresh();
|
||||||
|
let err_var = var_store.fresh();
|
||||||
|
let result_var = var_store.fresh();
|
||||||
|
|
||||||
|
let actual = Type::Function(
|
||||||
|
vec![Type::EmptyRec],
|
||||||
|
Box::new(Type::Variable(closure_var)),
|
||||||
|
Box::new(Type::Variable(result_var)),
|
||||||
|
);
|
||||||
|
|
||||||
|
let type_arguments = vec![
|
||||||
|
OptAbleVar {
|
||||||
|
var: ok_var,
|
||||||
|
opt_abilities: None,
|
||||||
|
},
|
||||||
|
OptAbleVar {
|
||||||
|
var: err_var,
|
||||||
|
opt_abilities: None,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
let lambda_set_variables = vec![roc_types::types::LambdaSet(Type::Variable(closure_var))];
|
||||||
|
|
||||||
|
(Box::new(actual), type_arguments, lambda_set_variables)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn empty_record_pattern(var_store: &mut VarStore) -> Pattern {
|
||||||
|
Pattern::RecordDestructure {
|
||||||
|
whole_var: var_store.fresh(),
|
||||||
|
ext_var: var_store.fresh(),
|
||||||
|
destructs: vec![],
|
||||||
|
}
|
||||||
|
}
|
|
@ -55,10 +55,12 @@ pub fn can_expr_with(arena: &Bump, home: ModuleId, expr_str: &str) -> CanExprOut
|
||||||
// rules multiple times unnecessarily.
|
// rules multiple times unnecessarily.
|
||||||
let loc_expr = desugar::desugar_expr(
|
let loc_expr = desugar::desugar_expr(
|
||||||
arena,
|
arena,
|
||||||
|
&mut var_store,
|
||||||
&loc_expr,
|
&loc_expr,
|
||||||
expr_str,
|
expr_str,
|
||||||
&mut None,
|
&mut None,
|
||||||
arena.alloc("TestPath"),
|
arena.alloc("TestPath"),
|
||||||
|
&mut Default::default(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut scope = Scope::new(
|
let mut scope = Scope::new(
|
||||||
|
|
|
@ -0,0 +1,145 @@
|
||||||
|
---
|
||||||
|
source: crates/compiler/can/tests/test_suffixed.rs
|
||||||
|
assertion_line: 449
|
||||||
|
expression: snapshot
|
||||||
|
---
|
||||||
|
Defs {
|
||||||
|
tags: [
|
||||||
|
Index(2147483648),
|
||||||
|
],
|
||||||
|
regions: [
|
||||||
|
@0-26,
|
||||||
|
],
|
||||||
|
space_before: [
|
||||||
|
Slice(start = 0, length = 0),
|
||||||
|
],
|
||||||
|
space_after: [
|
||||||
|
Slice(start = 0, length = 1),
|
||||||
|
],
|
||||||
|
spaces: [
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
type_defs: [],
|
||||||
|
value_defs: [
|
||||||
|
Body(
|
||||||
|
@0-4 Identifier {
|
||||||
|
ident: "main",
|
||||||
|
},
|
||||||
|
@11-26 Defs(
|
||||||
|
Defs {
|
||||||
|
tags: [
|
||||||
|
Index(2147483648),
|
||||||
|
],
|
||||||
|
regions: [
|
||||||
|
@15-26,
|
||||||
|
],
|
||||||
|
space_before: [
|
||||||
|
Slice(start = 0, length = 0),
|
||||||
|
],
|
||||||
|
space_after: [
|
||||||
|
Slice(start = 0, length = 0),
|
||||||
|
],
|
||||||
|
spaces: [],
|
||||||
|
type_defs: [],
|
||||||
|
value_defs: [
|
||||||
|
Body(
|
||||||
|
@15-26 Identifier {
|
||||||
|
ident: "64",
|
||||||
|
},
|
||||||
|
@15-26 ParensAround(
|
||||||
|
Defs(
|
||||||
|
Defs {
|
||||||
|
tags: [
|
||||||
|
Index(2147483648),
|
||||||
|
],
|
||||||
|
regions: [
|
||||||
|
@20-25,
|
||||||
|
],
|
||||||
|
space_before: [
|
||||||
|
Slice(start = 0, length = 0),
|
||||||
|
],
|
||||||
|
space_after: [
|
||||||
|
Slice(start = 0, length = 0),
|
||||||
|
],
|
||||||
|
spaces: [],
|
||||||
|
type_defs: [],
|
||||||
|
value_defs: [
|
||||||
|
Body(
|
||||||
|
@20-25 Identifier {
|
||||||
|
ident: "63",
|
||||||
|
},
|
||||||
|
@20-25 Apply(
|
||||||
|
@22-23 Var {
|
||||||
|
module_name: "Num",
|
||||||
|
ident: "add",
|
||||||
|
},
|
||||||
|
[
|
||||||
|
@20-21 Num(
|
||||||
|
"1",
|
||||||
|
),
|
||||||
|
@24-25 Num(
|
||||||
|
"1",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
BinOp(
|
||||||
|
Plus,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
@15-26 LowLevelDbg(
|
||||||
|
(
|
||||||
|
"test.roc:3",
|
||||||
|
" ",
|
||||||
|
),
|
||||||
|
@20-25 Apply(
|
||||||
|
@20-25 Var {
|
||||||
|
module_name: "Inspect",
|
||||||
|
ident: "toStr",
|
||||||
|
},
|
||||||
|
[
|
||||||
|
@20-25 Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "63",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
Space,
|
||||||
|
),
|
||||||
|
@20-25 Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "63",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
@11-26 LowLevelDbg(
|
||||||
|
(
|
||||||
|
"test.roc:2",
|
||||||
|
"in =\n ",
|
||||||
|
),
|
||||||
|
@15-26 Apply(
|
||||||
|
@15-26 Var {
|
||||||
|
module_name: "Inspect",
|
||||||
|
ident: "toStr",
|
||||||
|
},
|
||||||
|
[
|
||||||
|
@15-26 Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "64",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
Space,
|
||||||
|
),
|
||||||
|
@15-26 Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "64",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
---
|
||||||
|
source: crates/compiler/can/tests/test_suffixed.rs
|
||||||
|
assertion_line: 459
|
||||||
|
expression: snapshot
|
||||||
|
---
|
||||||
|
Defs {
|
||||||
|
tags: [
|
||||||
|
Index(2147483648),
|
||||||
|
],
|
||||||
|
regions: [
|
||||||
|
@0-19,
|
||||||
|
],
|
||||||
|
space_before: [
|
||||||
|
Slice(start = 0, length = 0),
|
||||||
|
],
|
||||||
|
space_after: [
|
||||||
|
Slice(start = 0, length = 1),
|
||||||
|
],
|
||||||
|
spaces: [
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
type_defs: [],
|
||||||
|
value_defs: [
|
||||||
|
Body(
|
||||||
|
@0-4 Identifier {
|
||||||
|
ident: "main",
|
||||||
|
},
|
||||||
|
@11-19 Defs(
|
||||||
|
Defs {
|
||||||
|
tags: [
|
||||||
|
Index(2147483648),
|
||||||
|
],
|
||||||
|
regions: [
|
||||||
|
@11-12,
|
||||||
|
],
|
||||||
|
space_before: [
|
||||||
|
Slice(start = 0, length = 0),
|
||||||
|
],
|
||||||
|
space_after: [
|
||||||
|
Slice(start = 0, length = 0),
|
||||||
|
],
|
||||||
|
spaces: [],
|
||||||
|
type_defs: [],
|
||||||
|
value_defs: [
|
||||||
|
Body(
|
||||||
|
@11-12 Identifier {
|
||||||
|
ident: "63",
|
||||||
|
},
|
||||||
|
@11-12 Num(
|
||||||
|
"1",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
@11-19 LowLevelDbg(
|
||||||
|
(
|
||||||
|
"test.roc:2",
|
||||||
|
" ",
|
||||||
|
),
|
||||||
|
@11-12 Apply(
|
||||||
|
@11-12 Var {
|
||||||
|
module_name: "Inspect",
|
||||||
|
ident: "toStr",
|
||||||
|
},
|
||||||
|
[
|
||||||
|
@11-12 Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "63",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
Space,
|
||||||
|
),
|
||||||
|
@11-12 Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "63",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
}
|
|
@ -7,12 +7,23 @@ mod suffixed_tests {
|
||||||
use insta::assert_snapshot;
|
use insta::assert_snapshot;
|
||||||
use roc_can::desugar::desugar_defs_node_values;
|
use roc_can::desugar::desugar_defs_node_values;
|
||||||
use roc_parse::test_helpers::parse_defs_with;
|
use roc_parse::test_helpers::parse_defs_with;
|
||||||
|
use roc_types::subs::VarStore;
|
||||||
|
|
||||||
macro_rules! run_test {
|
macro_rules! run_test {
|
||||||
($src:expr) => {{
|
($src:expr) => {{
|
||||||
let arena = &Bump::new();
|
let arena = &Bump::new();
|
||||||
|
let mut var_store = VarStore::default();
|
||||||
let mut defs = parse_defs_with(arena, indoc!($src)).unwrap();
|
let mut defs = parse_defs_with(arena, indoc!($src)).unwrap();
|
||||||
desugar_defs_node_values(arena, &mut defs, $src, &mut None, "test.roc", true);
|
desugar_defs_node_values(
|
||||||
|
arena,
|
||||||
|
&mut var_store,
|
||||||
|
&mut defs,
|
||||||
|
$src,
|
||||||
|
&mut None,
|
||||||
|
"test.roc",
|
||||||
|
true,
|
||||||
|
&mut Default::default(),
|
||||||
|
);
|
||||||
|
|
||||||
let snapshot = format!("{:#?}", &defs);
|
let snapshot = format!("{:#?}", &defs);
|
||||||
println!("{}", snapshot);
|
println!("{}", snapshot);
|
||||||
|
@ -433,6 +444,16 @@ mod suffixed_tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn dbg_expr() {
|
||||||
|
run_test!(
|
||||||
|
r#"
|
||||||
|
main =
|
||||||
|
dbg (dbg 1 + 1)
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn apply_argument_single() {
|
fn apply_argument_single() {
|
||||||
run_test!(
|
run_test!(
|
||||||
|
|
231
crates/compiler/checkmate/www/package-lock.json
generated
231
crates/compiler/checkmate/www/package-lock.json
generated
|
@ -3424,21 +3424,15 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@jridgewell/trace-mapping": {
|
"node_modules/@jridgewell/trace-mapping": {
|
||||||
"version": "0.3.18",
|
"version": "0.3.25",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
|
||||||
"integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==",
|
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/resolve-uri": "3.1.0",
|
"@jridgewell/resolve-uri": "^3.1.0",
|
||||||
"@jridgewell/sourcemap-codec": "1.4.14"
|
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": {
|
|
||||||
"version": "1.4.14",
|
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
|
|
||||||
"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/@jsdevtools/ono": {
|
"node_modules/@jsdevtools/ono": {
|
||||||
"version": "7.1.3",
|
"version": "7.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz",
|
||||||
|
@ -4351,20 +4345,10 @@
|
||||||
"@types/json-schema": "*"
|
"@types/json-schema": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/eslint-scope": {
|
|
||||||
"version": "3.7.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz",
|
|
||||||
"integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@types/eslint": "*",
|
|
||||||
"@types/estree": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@types/estree": {
|
"node_modules/@types/estree": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
|
||||||
"integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==",
|
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@types/express": {
|
"node_modules/@types/express": {
|
||||||
|
@ -4932,9 +4916,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@webassemblyjs/ast": {
|
"node_modules/@webassemblyjs/ast": {
|
||||||
"version": "1.11.6",
|
"version": "1.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz",
|
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz",
|
||||||
"integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==",
|
"integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@webassemblyjs/helper-numbers": "1.11.6",
|
"@webassemblyjs/helper-numbers": "1.11.6",
|
||||||
|
@ -4954,9 +4938,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@webassemblyjs/helper-buffer": {
|
"node_modules/@webassemblyjs/helper-buffer": {
|
||||||
"version": "1.11.6",
|
"version": "1.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz",
|
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz",
|
||||||
"integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==",
|
"integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@webassemblyjs/helper-numbers": {
|
"node_modules/@webassemblyjs/helper-numbers": {
|
||||||
|
@ -4977,15 +4961,15 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@webassemblyjs/helper-wasm-section": {
|
"node_modules/@webassemblyjs/helper-wasm-section": {
|
||||||
"version": "1.11.6",
|
"version": "1.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz",
|
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz",
|
||||||
"integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==",
|
"integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@webassemblyjs/ast": "1.11.6",
|
"@webassemblyjs/ast": "1.12.1",
|
||||||
"@webassemblyjs/helper-buffer": "1.11.6",
|
"@webassemblyjs/helper-buffer": "1.12.1",
|
||||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
|
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
|
||||||
"@webassemblyjs/wasm-gen": "1.11.6"
|
"@webassemblyjs/wasm-gen": "1.12.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@webassemblyjs/ieee754": {
|
"node_modules/@webassemblyjs/ieee754": {
|
||||||
|
@ -5013,28 +4997,28 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@webassemblyjs/wasm-edit": {
|
"node_modules/@webassemblyjs/wasm-edit": {
|
||||||
"version": "1.11.6",
|
"version": "1.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz",
|
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz",
|
||||||
"integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==",
|
"integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@webassemblyjs/ast": "1.11.6",
|
"@webassemblyjs/ast": "1.12.1",
|
||||||
"@webassemblyjs/helper-buffer": "1.11.6",
|
"@webassemblyjs/helper-buffer": "1.12.1",
|
||||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
|
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
|
||||||
"@webassemblyjs/helper-wasm-section": "1.11.6",
|
"@webassemblyjs/helper-wasm-section": "1.12.1",
|
||||||
"@webassemblyjs/wasm-gen": "1.11.6",
|
"@webassemblyjs/wasm-gen": "1.12.1",
|
||||||
"@webassemblyjs/wasm-opt": "1.11.6",
|
"@webassemblyjs/wasm-opt": "1.12.1",
|
||||||
"@webassemblyjs/wasm-parser": "1.11.6",
|
"@webassemblyjs/wasm-parser": "1.12.1",
|
||||||
"@webassemblyjs/wast-printer": "1.11.6"
|
"@webassemblyjs/wast-printer": "1.12.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@webassemblyjs/wasm-gen": {
|
"node_modules/@webassemblyjs/wasm-gen": {
|
||||||
"version": "1.11.6",
|
"version": "1.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz",
|
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz",
|
||||||
"integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==",
|
"integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@webassemblyjs/ast": "1.11.6",
|
"@webassemblyjs/ast": "1.12.1",
|
||||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
|
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
|
||||||
"@webassemblyjs/ieee754": "1.11.6",
|
"@webassemblyjs/ieee754": "1.11.6",
|
||||||
"@webassemblyjs/leb128": "1.11.6",
|
"@webassemblyjs/leb128": "1.11.6",
|
||||||
|
@ -5042,24 +5026,24 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@webassemblyjs/wasm-opt": {
|
"node_modules/@webassemblyjs/wasm-opt": {
|
||||||
"version": "1.11.6",
|
"version": "1.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz",
|
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz",
|
||||||
"integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==",
|
"integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@webassemblyjs/ast": "1.11.6",
|
"@webassemblyjs/ast": "1.12.1",
|
||||||
"@webassemblyjs/helper-buffer": "1.11.6",
|
"@webassemblyjs/helper-buffer": "1.12.1",
|
||||||
"@webassemblyjs/wasm-gen": "1.11.6",
|
"@webassemblyjs/wasm-gen": "1.12.1",
|
||||||
"@webassemblyjs/wasm-parser": "1.11.6"
|
"@webassemblyjs/wasm-parser": "1.12.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@webassemblyjs/wasm-parser": {
|
"node_modules/@webassemblyjs/wasm-parser": {
|
||||||
"version": "1.11.6",
|
"version": "1.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz",
|
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz",
|
||||||
"integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==",
|
"integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@webassemblyjs/ast": "1.11.6",
|
"@webassemblyjs/ast": "1.12.1",
|
||||||
"@webassemblyjs/helper-api-error": "1.11.6",
|
"@webassemblyjs/helper-api-error": "1.11.6",
|
||||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
|
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
|
||||||
"@webassemblyjs/ieee754": "1.11.6",
|
"@webassemblyjs/ieee754": "1.11.6",
|
||||||
|
@ -5068,12 +5052,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@webassemblyjs/wast-printer": {
|
"node_modules/@webassemblyjs/wast-printer": {
|
||||||
"version": "1.11.6",
|
"version": "1.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz",
|
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz",
|
||||||
"integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==",
|
"integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@webassemblyjs/ast": "1.11.6",
|
"@webassemblyjs/ast": "1.12.1",
|
||||||
"@xtuc/long": "4.2.2"
|
"@xtuc/long": "4.2.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -5142,10 +5126,10 @@
|
||||||
"node": ">=0.4.0"
|
"node": ">=0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/acorn-import-assertions": {
|
"node_modules/acorn-import-attributes": {
|
||||||
"version": "1.9.0",
|
"version": "1.9.5",
|
||||||
"resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz",
|
||||||
"integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==",
|
"integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"acorn": "^8"
|
"acorn": "^8"
|
||||||
|
@ -6039,9 +6023,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/browserslist": {
|
"node_modules/browserslist": {
|
||||||
"version": "4.21.9",
|
"version": "4.23.3",
|
||||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz",
|
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz",
|
||||||
"integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==",
|
"integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -6058,10 +6042,10 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"caniuse-lite": "^1.0.30001503",
|
"caniuse-lite": "^1.0.30001646",
|
||||||
"electron-to-chromium": "^1.4.431",
|
"electron-to-chromium": "^1.5.4",
|
||||||
"node-releases": "^2.0.12",
|
"node-releases": "^2.0.18",
|
||||||
"update-browserslist-db": "^1.0.11"
|
"update-browserslist-db": "^1.1.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"browserslist": "cli.js"
|
"browserslist": "cli.js"
|
||||||
|
@ -6178,9 +6162,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/caniuse-lite": {
|
"node_modules/caniuse-lite": {
|
||||||
"version": "1.0.30001516",
|
"version": "1.0.30001655",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001516.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001655.tgz",
|
||||||
"integrity": "sha512-Wmec9pCBY8CWbmI4HsjBeQLqDTqV91nFVR83DnZpYyRnPI1wePDsTg0bGLPC5VU/3OIZV1fmxEea1b+tFKe86g==",
|
"integrity": "sha512-jRGVy3iSGO5Uutn2owlb5gR6qsGngTw9ZTb4ali9f3glshcNmJ2noam4Mo9zia5P9Dk3jNNydy7vQjuE5dQmfg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -7575,9 +7559,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/electron-to-chromium": {
|
"node_modules/electron-to-chromium": {
|
||||||
"version": "1.4.461",
|
"version": "1.5.13",
|
||||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.461.tgz",
|
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz",
|
||||||
"integrity": "sha512-1JkvV2sgEGTDXjdsaQCeSwYYuhLRphRpc+g6EHTFELJXEiznLt3/0pZ9JuAOQ5p2rI3YxKTbivtvajirIfhrEQ==",
|
"integrity": "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/elkjs": {
|
"node_modules/elkjs": {
|
||||||
|
@ -7622,9 +7606,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/enhanced-resolve": {
|
"node_modules/enhanced-resolve": {
|
||||||
"version": "5.15.0",
|
"version": "5.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz",
|
||||||
"integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==",
|
"integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"graceful-fs": "^4.2.4",
|
"graceful-fs": "^4.2.4",
|
||||||
|
@ -7815,9 +7799,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/escalade": {
|
"node_modules/escalade": {
|
||||||
"version": "3.1.1",
|
"version": "3.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
|
||||||
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
|
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
|
@ -13471,9 +13455,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/node-releases": {
|
"node_modules/node-releases": {
|
||||||
"version": "2.0.13",
|
"version": "2.0.18",
|
||||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
|
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz",
|
||||||
"integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==",
|
"integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/normalize-path": {
|
"node_modules/normalize-path": {
|
||||||
|
@ -13926,9 +13910,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/picocolors": {
|
"node_modules/picocolors": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
|
||||||
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
|
"integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/picomatch": {
|
"node_modules/picomatch": {
|
||||||
|
@ -17473,9 +17457,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/terser": {
|
"node_modules/terser": {
|
||||||
"version": "5.19.0",
|
"version": "5.31.6",
|
||||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/terser/-/terser-5.31.6.tgz",
|
||||||
"integrity": "sha512-JpcpGOQLOXm2jsomozdMDpd5f8ZHh1rR48OFgWUH3QsyZcfPgv2qDCYbcDEAYNd4OZRj2bWYKpwdll/udZCk/Q==",
|
"integrity": "sha512-PQ4DAriWzKj+qgehQ7LK5bQqCFNMmlhjR2PFFLuqGCpuCAauxemVBWwWOxo3UIwWQx8+Pr61Df++r76wDmkQBg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/source-map": "^0.3.3",
|
"@jridgewell/source-map": "^0.3.3",
|
||||||
|
@ -17491,16 +17475,16 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/terser-webpack-plugin": {
|
"node_modules/terser-webpack-plugin": {
|
||||||
"version": "5.3.9",
|
"version": "5.3.10",
|
||||||
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz",
|
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz",
|
||||||
"integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==",
|
"integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/trace-mapping": "^0.3.17",
|
"@jridgewell/trace-mapping": "^0.3.20",
|
||||||
"jest-worker": "^27.4.5",
|
"jest-worker": "^27.4.5",
|
||||||
"schema-utils": "^3.1.1",
|
"schema-utils": "^3.1.1",
|
||||||
"serialize-javascript": "^6.0.1",
|
"serialize-javascript": "^6.0.1",
|
||||||
"terser": "^5.16.8"
|
"terser": "^5.26.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 10.13.0"
|
"node": ">= 10.13.0"
|
||||||
|
@ -17984,9 +17968,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/update-browserslist-db": {
|
"node_modules/update-browserslist-db": {
|
||||||
"version": "1.0.11",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz",
|
||||||
"integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==",
|
"integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -18003,8 +17987,8 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"escalade": "^3.1.1",
|
"escalade": "^3.1.2",
|
||||||
"picocolors": "^1.0.0"
|
"picocolors": "^1.0.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"update-browserslist-db": "cli.js"
|
"update-browserslist-db": "cli.js"
|
||||||
|
@ -18140,9 +18124,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/watchpack": {
|
"node_modules/watchpack": {
|
||||||
"version": "2.4.0",
|
"version": "2.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz",
|
||||||
"integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==",
|
"integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"glob-to-regexp": "^0.4.1",
|
"glob-to-regexp": "^0.4.1",
|
||||||
|
@ -18171,34 +18155,33 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/webpack": {
|
"node_modules/webpack": {
|
||||||
"version": "5.88.1",
|
"version": "5.94.0",
|
||||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.1.tgz",
|
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz",
|
||||||
"integrity": "sha512-FROX3TxQnC/ox4N+3xQoWZzvGXSuscxR32rbzjpXgEzWudJFEJBpdlkkob2ylrv5yzzufD1zph1OoFsLtm6stQ==",
|
"integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/eslint-scope": "^3.7.3",
|
"@types/estree": "^1.0.5",
|
||||||
"@types/estree": "^1.0.0",
|
"@webassemblyjs/ast": "^1.12.1",
|
||||||
"@webassemblyjs/ast": "^1.11.5",
|
"@webassemblyjs/wasm-edit": "^1.12.1",
|
||||||
"@webassemblyjs/wasm-edit": "^1.11.5",
|
"@webassemblyjs/wasm-parser": "^1.12.1",
|
||||||
"@webassemblyjs/wasm-parser": "^1.11.5",
|
|
||||||
"acorn": "^8.7.1",
|
"acorn": "^8.7.1",
|
||||||
"acorn-import-assertions": "^1.9.0",
|
"acorn-import-attributes": "^1.9.5",
|
||||||
"browserslist": "^4.14.5",
|
"browserslist": "^4.21.10",
|
||||||
"chrome-trace-event": "^1.0.2",
|
"chrome-trace-event": "^1.0.2",
|
||||||
"enhanced-resolve": "^5.15.0",
|
"enhanced-resolve": "^5.17.1",
|
||||||
"es-module-lexer": "^1.2.1",
|
"es-module-lexer": "^1.2.1",
|
||||||
"eslint-scope": "5.1.1",
|
"eslint-scope": "5.1.1",
|
||||||
"events": "^3.2.0",
|
"events": "^3.2.0",
|
||||||
"glob-to-regexp": "^0.4.1",
|
"glob-to-regexp": "^0.4.1",
|
||||||
"graceful-fs": "^4.2.9",
|
"graceful-fs": "^4.2.11",
|
||||||
"json-parse-even-better-errors": "^2.3.1",
|
"json-parse-even-better-errors": "^2.3.1",
|
||||||
"loader-runner": "^4.2.0",
|
"loader-runner": "^4.2.0",
|
||||||
"mime-types": "^2.1.27",
|
"mime-types": "^2.1.27",
|
||||||
"neo-async": "^2.6.2",
|
"neo-async": "^2.6.2",
|
||||||
"schema-utils": "^3.2.0",
|
"schema-utils": "^3.2.0",
|
||||||
"tapable": "^2.1.1",
|
"tapable": "^2.1.1",
|
||||||
"terser-webpack-plugin": "^5.3.7",
|
"terser-webpack-plugin": "^5.3.10",
|
||||||
"watchpack": "^2.4.0",
|
"watchpack": "^2.4.1",
|
||||||
"webpack-sources": "^3.2.3"
|
"webpack-sources": "^3.2.3"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
|
@ -17,6 +17,10 @@ impl<T> VecSet<T> {
|
||||||
pub fn into_vec(self) -> Vec<T> {
|
pub fn into_vec(self) -> Vec<T> {
|
||||||
self.elements
|
self.elements
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reserve(&mut self, additional: usize) {
|
||||||
|
self.elements.reserve(additional)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: PartialEq> VecSet<T> {
|
impl<T: PartialEq> VecSet<T> {
|
||||||
|
|
|
@ -569,8 +569,8 @@ pub fn constrain_expr(
|
||||||
Var(symbol, variable)
|
Var(symbol, variable)
|
||||||
| ParamsVar {
|
| ParamsVar {
|
||||||
symbol,
|
symbol,
|
||||||
params: _,
|
|
||||||
var: variable,
|
var: variable,
|
||||||
|
..
|
||||||
} => {
|
} => {
|
||||||
// Save the expectation in the variable, then lookup the symbol's type in the environment
|
// Save the expectation in the variable, then lookup the symbol's type in the environment
|
||||||
let expected_type = *constraints[expected].get_type_ref();
|
let expected_type = *constraints[expected].get_type_ref();
|
||||||
|
|
|
@ -3,13 +3,12 @@ use crate::pattern::{constrain_pattern, PatternState};
|
||||||
use roc_can::abilities::{PendingAbilitiesStore, PendingMemberType};
|
use roc_can::abilities::{PendingAbilitiesStore, PendingMemberType};
|
||||||
use roc_can::constraint::{Constraint, Constraints, Generalizable};
|
use roc_can::constraint::{Constraint, Constraints, Generalizable};
|
||||||
use roc_can::expected::{Expected, PExpected};
|
use roc_can::expected::{Expected, PExpected};
|
||||||
use roc_can::expr::{AnnotatedMark, Declarations};
|
use roc_can::expr::Declarations;
|
||||||
|
use roc_can::module::ModuleParams;
|
||||||
use roc_can::pattern::Pattern;
|
use roc_can::pattern::Pattern;
|
||||||
use roc_collections::MutMap;
|
use roc_collections::MutMap;
|
||||||
use roc_error_macros::internal_error;
|
|
||||||
use roc_module::symbol::{ModuleId, Symbol};
|
use roc_module::symbol::{ModuleId, Symbol};
|
||||||
use roc_region::all::{Loc, Region};
|
use roc_region::all::{Loc, Region};
|
||||||
use roc_types::subs::Variable;
|
|
||||||
use roc_types::types::{AnnotationSource, Category, Type, Types};
|
use roc_types::types::{AnnotationSource, Category, Type, Types};
|
||||||
|
|
||||||
pub fn constrain_module(
|
pub fn constrain_module(
|
||||||
|
@ -18,12 +17,12 @@ pub fn constrain_module(
|
||||||
symbols_from_requires: Vec<(Loc<Symbol>, Loc<Type>)>,
|
symbols_from_requires: Vec<(Loc<Symbol>, Loc<Type>)>,
|
||||||
abilities_store: &PendingAbilitiesStore,
|
abilities_store: &PendingAbilitiesStore,
|
||||||
declarations: &Declarations,
|
declarations: &Declarations,
|
||||||
params_pattern: &Option<(Variable, AnnotatedMark, Loc<Pattern>)>,
|
opt_module_params: &Option<ModuleParams>,
|
||||||
home: ModuleId,
|
home: ModuleId,
|
||||||
) -> Constraint {
|
) -> Constraint {
|
||||||
let constraint = crate::expr::constrain_decls(types, constraints, home, declarations);
|
let constraint = crate::expr::constrain_decls(types, constraints, home, declarations);
|
||||||
|
|
||||||
let constraint = match params_pattern {
|
let constraint = match opt_module_params {
|
||||||
Some(params_pattern) => {
|
Some(params_pattern) => {
|
||||||
constrain_params(types, constraints, home, constraint, params_pattern)
|
constrain_params(types, constraints, home, constraint, params_pattern)
|
||||||
}
|
}
|
||||||
|
@ -51,7 +50,7 @@ fn constrain_params(
|
||||||
constraints: &mut Constraints,
|
constraints: &mut Constraints,
|
||||||
home: ModuleId,
|
home: ModuleId,
|
||||||
constraint: Constraint,
|
constraint: Constraint,
|
||||||
(pattern_var, _, loc_pattern): &(Variable, AnnotatedMark, Loc<Pattern>),
|
module_params: &ModuleParams,
|
||||||
) -> Constraint {
|
) -> Constraint {
|
||||||
let mut env = Env {
|
let mut env = Env {
|
||||||
home,
|
home,
|
||||||
|
@ -59,23 +58,13 @@ fn constrain_params(
|
||||||
resolutions_to_make: vec![],
|
resolutions_to_make: vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
let index = constraints.push_variable(*pattern_var);
|
let index = constraints.push_variable(module_params.whole_var);
|
||||||
let expected_params = constraints.push_pat_expected_type(PExpected::NoExpectation(index));
|
let expected_params = constraints.push_pat_expected_type(PExpected::NoExpectation(index));
|
||||||
|
|
||||||
let mut state = PatternState::default();
|
let mut state = PatternState::default();
|
||||||
|
|
||||||
let closed_con = match loc_pattern.value {
|
let empty_rec = constraints.push_type(types, Types::EMPTY_RECORD);
|
||||||
Pattern::RecordDestructure {
|
let closed_con = constraints.store(empty_rec, module_params.record_ext_var, file!(), line!());
|
||||||
whole_var: _,
|
|
||||||
ext_var,
|
|
||||||
destructs: _,
|
|
||||||
} => {
|
|
||||||
// Disallow record extension for module params
|
|
||||||
let empty_rec = constraints.push_type(types, Types::EMPTY_RECORD);
|
|
||||||
constraints.store(empty_rec, ext_var, file!(), line!())
|
|
||||||
}
|
|
||||||
_ => internal_error!("Only record destructures are allowed in module params. This should've been caught earlier."),
|
|
||||||
};
|
|
||||||
|
|
||||||
state.constraints.push(closed_con);
|
state.constraints.push(closed_con);
|
||||||
|
|
||||||
|
@ -83,8 +72,8 @@ fn constrain_params(
|
||||||
types,
|
types,
|
||||||
constraints,
|
constraints,
|
||||||
&mut env,
|
&mut env,
|
||||||
&loc_pattern.value,
|
&module_params.pattern().value,
|
||||||
loc_pattern.region,
|
module_params.region,
|
||||||
expected_params,
|
expected_params,
|
||||||
&mut state,
|
&mut state,
|
||||||
);
|
);
|
||||||
|
@ -100,7 +89,7 @@ fn constrain_params(
|
||||||
Generalizable(true),
|
Generalizable(true),
|
||||||
);
|
);
|
||||||
|
|
||||||
constraints.exists([*pattern_var], cons)
|
constraints.exists([module_params.whole_var], cons)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn constrain_symbols_from_requires(
|
fn constrain_symbols_from_requires(
|
||||||
|
|
|
@ -38,6 +38,7 @@ pub enum Parens {
|
||||||
InFunctionType,
|
InFunctionType,
|
||||||
InApply,
|
InApply,
|
||||||
InOperator,
|
InOperator,
|
||||||
|
InAsPattern,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// In an AST node, do we show newlines around it
|
/// In an AST node, do we show newlines around it
|
||||||
|
|
|
@ -10,7 +10,7 @@ use crate::Buf;
|
||||||
use roc_module::called_via::{self, BinOp};
|
use roc_module::called_via::{self, BinOp};
|
||||||
use roc_parse::ast::{
|
use roc_parse::ast::{
|
||||||
is_expr_suffixed, AssignedField, Base, Collection, CommentOrNewline, Expr, ExtractSpaces,
|
is_expr_suffixed, AssignedField, Base, Collection, CommentOrNewline, Expr, ExtractSpaces,
|
||||||
OldRecordBuilderField, Pattern, WhenBranch,
|
OldRecordBuilderField, Pattern, TryTarget, WhenBranch,
|
||||||
};
|
};
|
||||||
use roc_parse::ast::{StrLiteral, StrSegment};
|
use roc_parse::ast::{StrLiteral, StrSegment};
|
||||||
use roc_parse::ident::Accessor;
|
use roc_parse::ident::Accessor;
|
||||||
|
@ -39,15 +39,17 @@ impl<'a> Formattable for Expr<'a> {
|
||||||
| NonBase10Int { .. }
|
| NonBase10Int { .. }
|
||||||
| SingleQuote(_)
|
| SingleQuote(_)
|
||||||
| AccessorFunction(_)
|
| AccessorFunction(_)
|
||||||
|
| RecordUpdater(_)
|
||||||
| Var { .. }
|
| Var { .. }
|
||||||
| Underscore { .. }
|
| Underscore { .. }
|
||||||
| MalformedIdent(_, _)
|
| MalformedIdent(_, _)
|
||||||
| MalformedClosure
|
| MalformedClosure
|
||||||
| Tag(_)
|
| Tag(_)
|
||||||
| OpaqueRef(_)
|
| OpaqueRef(_)
|
||||||
| Crash => false,
|
| Crash
|
||||||
|
| Dbg => false,
|
||||||
|
|
||||||
RecordAccess(inner, _) | TupleAccess(inner, _) | TaskAwaitBang(inner) => {
|
RecordAccess(inner, _) | TupleAccess(inner, _) | TrySuffix { expr: inner, .. } => {
|
||||||
inner.is_multiline()
|
inner.is_multiline()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +66,7 @@ impl<'a> Formattable for Expr<'a> {
|
||||||
Expect(condition, continuation) => {
|
Expect(condition, continuation) => {
|
||||||
condition.is_multiline() || continuation.is_multiline()
|
condition.is_multiline() || continuation.is_multiline()
|
||||||
}
|
}
|
||||||
Dbg(condition, _) => condition.is_multiline(),
|
DbgStmt(condition, _) => condition.is_multiline(),
|
||||||
LowLevelDbg(_, _, _) => unreachable!(
|
LowLevelDbg(_, _, _) => unreachable!(
|
||||||
"LowLevelDbg should only exist after desugaring, not during formatting"
|
"LowLevelDbg should only exist after desugaring, not during formatting"
|
||||||
),
|
),
|
||||||
|
@ -452,8 +454,12 @@ impl<'a> Formattable for Expr<'a> {
|
||||||
Expect(condition, continuation) => {
|
Expect(condition, continuation) => {
|
||||||
fmt_expect(buf, condition, continuation, self.is_multiline(), indent);
|
fmt_expect(buf, condition, continuation, self.is_multiline(), indent);
|
||||||
}
|
}
|
||||||
Dbg(condition, continuation) => {
|
Dbg => {
|
||||||
fmt_dbg(buf, condition, continuation, self.is_multiline(), indent);
|
buf.indent(indent);
|
||||||
|
buf.push_str("dbg");
|
||||||
|
}
|
||||||
|
DbgStmt(condition, continuation) => {
|
||||||
|
fmt_dbg_stmt(buf, condition, continuation, self.is_multiline(), indent);
|
||||||
}
|
}
|
||||||
LowLevelDbg(_, _, _) => unreachable!(
|
LowLevelDbg(_, _, _) => unreachable!(
|
||||||
"LowLevelDbg should only exist after desugaring, not during formatting"
|
"LowLevelDbg should only exist after desugaring, not during formatting"
|
||||||
|
@ -510,6 +516,11 @@ impl<'a> Formattable for Expr<'a> {
|
||||||
Accessor::TupleIndex(key) => buf.push_str(key),
|
Accessor::TupleIndex(key) => buf.push_str(key),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
RecordUpdater(key) => {
|
||||||
|
buf.indent(indent);
|
||||||
|
buf.push('&');
|
||||||
|
buf.push_str(key);
|
||||||
|
}
|
||||||
RecordAccess(expr, key) => {
|
RecordAccess(expr, key) => {
|
||||||
expr.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
|
expr.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
|
||||||
buf.push('.');
|
buf.push('.');
|
||||||
|
@ -520,9 +531,12 @@ impl<'a> Formattable for Expr<'a> {
|
||||||
buf.push('.');
|
buf.push('.');
|
||||||
buf.push_str(key);
|
buf.push_str(key);
|
||||||
}
|
}
|
||||||
TaskAwaitBang(expr) => {
|
TrySuffix { expr, target } => {
|
||||||
expr.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
|
expr.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
|
||||||
buf.push('!');
|
match target {
|
||||||
|
TryTarget::Task => buf.push('!'),
|
||||||
|
TryTarget::Result => buf.push('?'),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
MalformedIdent(str, _) => {
|
MalformedIdent(str, _) => {
|
||||||
buf.indent(indent);
|
buf.indent(indent);
|
||||||
|
@ -615,6 +629,22 @@ fn starts_with_newline(expr: &Expr) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fmt_str_body(body: &str, buf: &mut Buf) {
|
||||||
|
for c in body.chars() {
|
||||||
|
match c {
|
||||||
|
// Format blank characters as unicode escapes
|
||||||
|
'\u{200a}' => buf.push_str("\\u(200a)"),
|
||||||
|
'\u{200b}' => buf.push_str("\\u(200b)"),
|
||||||
|
'\u{200c}' => buf.push_str("\\u(200c)"),
|
||||||
|
'\u{feff}' => buf.push_str("\\u(feff)"),
|
||||||
|
// Don't change anything else in the string
|
||||||
|
' ' => buf.push_str_allow_spaces(" "),
|
||||||
|
'\n' => buf.push_str_allow_spaces("\n"),
|
||||||
|
_ => buf.push(c),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn format_str_segment(seg: &StrSegment, buf: &mut Buf, indent: u16) {
|
fn format_str_segment(seg: &StrSegment, buf: &mut Buf, indent: u16) {
|
||||||
use StrSegment::*;
|
use StrSegment::*;
|
||||||
|
|
||||||
|
@ -624,10 +654,10 @@ fn format_str_segment(seg: &StrSegment, buf: &mut Buf, indent: u16) {
|
||||||
// a line break in the input string
|
// a line break in the input string
|
||||||
match string.strip_suffix('\n') {
|
match string.strip_suffix('\n') {
|
||||||
Some(string_without_newline) => {
|
Some(string_without_newline) => {
|
||||||
buf.push_str_allow_spaces(string_without_newline);
|
fmt_str_body(string_without_newline, buf);
|
||||||
buf.newline();
|
buf.newline();
|
||||||
}
|
}
|
||||||
None => buf.push_str_allow_spaces(string),
|
None => fmt_str_body(string, buf),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Unicode(loc_str) => {
|
Unicode(loc_str) => {
|
||||||
|
@ -687,7 +717,7 @@ pub fn fmt_str_literal(buf: &mut Buf, literal: StrLiteral, indent: u16) {
|
||||||
buf.push_newline_literal();
|
buf.push_newline_literal();
|
||||||
for line in string.split('\n') {
|
for line in string.split('\n') {
|
||||||
buf.indent(indent);
|
buf.indent(indent);
|
||||||
buf.push_str_allow_spaces(line);
|
fmt_str_body(line, buf);
|
||||||
buf.push_newline_literal();
|
buf.push_newline_literal();
|
||||||
}
|
}
|
||||||
buf.indent(indent);
|
buf.indent(indent);
|
||||||
|
@ -695,7 +725,7 @@ pub fn fmt_str_literal(buf: &mut Buf, literal: StrLiteral, indent: u16) {
|
||||||
} else {
|
} else {
|
||||||
buf.indent(indent);
|
buf.indent(indent);
|
||||||
buf.push('"');
|
buf.push('"');
|
||||||
buf.push_str_allow_spaces(string);
|
fmt_str_body(string, buf);
|
||||||
buf.push('"');
|
buf.push('"');
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -993,7 +1023,7 @@ fn fmt_when<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fmt_dbg<'a>(
|
fn fmt_dbg_stmt<'a>(
|
||||||
buf: &mut Buf,
|
buf: &mut Buf,
|
||||||
condition: &'a Loc<Expr<'a>>,
|
condition: &'a Loc<Expr<'a>>,
|
||||||
continuation: &'a Loc<Expr<'a>>,
|
continuation: &'a Loc<Expr<'a>>,
|
||||||
|
@ -1215,7 +1245,7 @@ fn fmt_closure<'a>(
|
||||||
let mut it = loc_patterns.iter().peekable();
|
let mut it = loc_patterns.iter().peekable();
|
||||||
|
|
||||||
while let Some(loc_pattern) = it.next() {
|
while let Some(loc_pattern) = it.next() {
|
||||||
loc_pattern.format(buf, indent);
|
loc_pattern.format_with_options(buf, Parens::InAsPattern, Newlines::No, indent);
|
||||||
|
|
||||||
if it.peek().is_some() {
|
if it.peek().is_some() {
|
||||||
buf.indent(indent);
|
buf.indent(indent);
|
||||||
|
|
|
@ -7,11 +7,10 @@ use crate::spaces::{fmt_comments_only, fmt_default_spaces, fmt_spaces, NewlineAt
|
||||||
use crate::Buf;
|
use crate::Buf;
|
||||||
use roc_parse::ast::{Collection, CommentOrNewline, Header, Spaced, Spaces, SpacesBefore};
|
use roc_parse::ast::{Collection, CommentOrNewline, Header, Spaced, Spaces, SpacesBefore};
|
||||||
use roc_parse::header::{
|
use roc_parse::header::{
|
||||||
AppHeader, ExposedName, ExposesKeyword, GeneratesKeyword, HostedHeader, ImportsEntry,
|
AppHeader, ExposedName, ExposesKeyword, HostedHeader, ImportsEntry, ImportsKeyword, Keyword,
|
||||||
ImportsKeyword, Keyword, KeywordItem, ModuleHeader, ModuleName, PackageEntry, PackageHeader,
|
KeywordItem, ModuleHeader, ModuleName, PackageEntry, PackageHeader, PackageKeyword,
|
||||||
PackageKeyword, PackageName, PackagesKeyword, PlatformHeader, PlatformKeyword,
|
PackageName, PackagesKeyword, PlatformHeader, PlatformKeyword, PlatformRequires,
|
||||||
PlatformRequires, ProvidesKeyword, ProvidesTo, RequiresKeyword, To, ToKeyword, TypedIdent,
|
ProvidesKeyword, ProvidesTo, RequiresKeyword, To, ToKeyword, TypedIdent,
|
||||||
WithKeyword,
|
|
||||||
};
|
};
|
||||||
use roc_parse::ident::UppercaseIdent;
|
use roc_parse::ident::UppercaseIdent;
|
||||||
use roc_region::all::Loc;
|
use roc_region::all::Loc;
|
||||||
|
@ -63,8 +62,6 @@ macro_rules! keywords {
|
||||||
keywords! {
|
keywords! {
|
||||||
ExposesKeyword,
|
ExposesKeyword,
|
||||||
ImportsKeyword,
|
ImportsKeyword,
|
||||||
WithKeyword,
|
|
||||||
GeneratesKeyword,
|
|
||||||
PackageKeyword,
|
PackageKeyword,
|
||||||
PackagesKeyword,
|
PackagesKeyword,
|
||||||
RequiresKeyword,
|
RequiresKeyword,
|
||||||
|
@ -206,9 +203,6 @@ pub fn fmt_hosted_header<'a>(buf: &mut Buf, header: &'a HostedHeader<'a>) {
|
||||||
fmt_exposes(buf, header.exposes.item, indent);
|
fmt_exposes(buf, header.exposes.item, indent);
|
||||||
header.imports.keyword.format(buf, indent);
|
header.imports.keyword.format(buf, indent);
|
||||||
fmt_imports(buf, header.imports.item, indent);
|
fmt_imports(buf, header.imports.item, indent);
|
||||||
header.generates.format(buf, indent);
|
|
||||||
header.generates_with.keyword.format(buf, indent);
|
|
||||||
fmt_exposes(buf, header.generates_with.item, indent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmt_app_header<'a>(buf: &mut Buf, header: &'a AppHeader<'a>) {
|
pub fn fmt_app_header<'a>(buf: &mut Buf, header: &'a AppHeader<'a>) {
|
||||||
|
|
|
@ -244,9 +244,19 @@ impl<'a> Formattable for Pattern<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
As(pattern, pattern_as) => {
|
As(pattern, pattern_as) => {
|
||||||
|
let needs_parens = parens == Parens::InAsPattern;
|
||||||
|
|
||||||
|
if needs_parens {
|
||||||
|
buf.push('(');
|
||||||
|
}
|
||||||
|
|
||||||
fmt_pattern(buf, &pattern.value, indent, parens);
|
fmt_pattern(buf, &pattern.value, indent, parens);
|
||||||
|
|
||||||
pattern_as.format(buf, indent + INDENT);
|
pattern_as.format(buf, indent + INDENT);
|
||||||
|
|
||||||
|
if needs_parens {
|
||||||
|
buf.push(')');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Space
|
// Space
|
||||||
|
|
|
@ -244,7 +244,7 @@ fn alignment_type(context: &Context, alignment: u32) -> BasicTypeEnum {
|
||||||
2 => context.i16_type().into(),
|
2 => context.i16_type().into(),
|
||||||
4 => context.i32_type().into(),
|
4 => context.i32_type().into(),
|
||||||
8 => context.i64_type().into(),
|
8 => context.i64_type().into(),
|
||||||
16 => context.i128_type().into(),
|
16 => context.f128_type().into(),
|
||||||
_ => unimplemented!("weird alignment: {alignment}"),
|
_ => unimplemented!("weird alignment: {alignment}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -385,7 +385,8 @@ impl<'ctx> RocUnion<'ctx> {
|
||||||
let mut width = self.data_width;
|
let mut width = self.data_width;
|
||||||
|
|
||||||
// add padding between data and the tag id
|
// add padding between data and the tag id
|
||||||
width = round_up_to_alignment(width, tag_id_width);
|
let tag_id_alignment = tag_id_width.max(1);
|
||||||
|
width = round_up_to_alignment(width, tag_id_alignment);
|
||||||
|
|
||||||
// add tag id
|
// add tag id
|
||||||
width += tag_id_width;
|
width += tag_id_width;
|
||||||
|
|
|
@ -25,6 +25,7 @@ const MODULES: &[(ModuleId, &str)] = &[
|
||||||
(ModuleId::DECODE, "Decode.roc"),
|
(ModuleId::DECODE, "Decode.roc"),
|
||||||
(ModuleId::HASH, "Hash.roc"),
|
(ModuleId::HASH, "Hash.roc"),
|
||||||
(ModuleId::INSPECT, "Inspect.roc"),
|
(ModuleId::INSPECT, "Inspect.roc"),
|
||||||
|
(ModuleId::TASK, "Task.roc"),
|
||||||
];
|
];
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -256,6 +256,7 @@ fn read_cached_types() -> MutMap<ModuleId, TypeState> {
|
||||||
let mod_decode = include_bytes_align_as!(u128, concat!(env!("OUT_DIR"), "/Decode.dat"));
|
let mod_decode = include_bytes_align_as!(u128, concat!(env!("OUT_DIR"), "/Decode.dat"));
|
||||||
let mod_hash = include_bytes_align_as!(u128, concat!(env!("OUT_DIR"), "/Hash.dat"));
|
let mod_hash = include_bytes_align_as!(u128, concat!(env!("OUT_DIR"), "/Hash.dat"));
|
||||||
let mod_inspect = include_bytes_align_as!(u128, concat!(env!("OUT_DIR"), "/Inspect.dat"));
|
let mod_inspect = include_bytes_align_as!(u128, concat!(env!("OUT_DIR"), "/Inspect.dat"));
|
||||||
|
let mod_task = include_bytes_align_as!(u128, concat!(env!("OUT_DIR"), "/Task.dat"));
|
||||||
|
|
||||||
let mut output = MutMap::default();
|
let mut output = MutMap::default();
|
||||||
|
|
||||||
|
@ -279,6 +280,8 @@ fn read_cached_types() -> MutMap<ModuleId, TypeState> {
|
||||||
|
|
||||||
output.insert(ModuleId::HASH, deserialize_help(mod_hash));
|
output.insert(ModuleId::HASH, deserialize_help(mod_hash));
|
||||||
output.insert(ModuleId::INSPECT, deserialize_help(mod_inspect));
|
output.insert(ModuleId::INSPECT, deserialize_help(mod_inspect));
|
||||||
|
|
||||||
|
output.insert(ModuleId::TASK, deserialize_help(mod_task));
|
||||||
}
|
}
|
||||||
|
|
||||||
output
|
output
|
||||||
|
|
|
@ -51,7 +51,7 @@ pub fn infer_expr(
|
||||||
exposed_by_module: &Default::default(),
|
exposed_by_module: &Default::default(),
|
||||||
derived_module,
|
derived_module,
|
||||||
function_kind: FunctionKind::LambdaSet,
|
function_kind: FunctionKind::LambdaSet,
|
||||||
params_pattern: None,
|
module_params: None,
|
||||||
module_params_vars: Default::default(),
|
module_params_vars: Default::default(),
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
checkmate: None,
|
checkmate: None,
|
||||||
|
@ -170,10 +170,12 @@ pub fn can_expr_with<'a>(
|
||||||
// rules multiple times unnecessarily.
|
// rules multiple times unnecessarily.
|
||||||
let loc_expr = desugar::desugar_expr(
|
let loc_expr = desugar::desugar_expr(
|
||||||
arena,
|
arena,
|
||||||
|
&mut var_store,
|
||||||
&loc_expr,
|
&loc_expr,
|
||||||
expr_str,
|
expr_str,
|
||||||
&mut None,
|
&mut None,
|
||||||
arena.alloc("TestPath"),
|
arena.alloc("TestPath"),
|
||||||
|
&mut Default::default(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut scope = Scope::new(
|
let mut scope = Scope::new(
|
||||||
|
|
|
@ -3793,9 +3793,9 @@ mod test_reporting {
|
||||||
of these?
|
of these?
|
||||||
|
|
||||||
Set
|
Set
|
||||||
|
Task
|
||||||
List
|
List
|
||||||
Dict
|
Dict
|
||||||
Hash
|
|
||||||
|
|
||||||
── SYNTAX PROBLEM in /code/proj/Main.roc ───────────────────────────────────────
|
── SYNTAX PROBLEM in /code/proj/Main.roc ───────────────────────────────────────
|
||||||
|
|
||||||
|
@ -3804,7 +3804,7 @@ mod test_reporting {
|
||||||
10│ y = { Test.example & age: 3 }
|
10│ y = { Test.example & age: 3 }
|
||||||
^^^^^^^^^^^^
|
^^^^^^^^^^^^
|
||||||
|
|
||||||
Only variables can be updated with record update syntax.
|
Only variables can be updated with record update syntax.
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -4816,7 +4816,7 @@ mod test_reporting {
|
||||||
expression_indentation_end,
|
expression_indentation_end,
|
||||||
indoc!(
|
indoc!(
|
||||||
r"
|
r"
|
||||||
f <- Foo.foo
|
f = Foo.foo
|
||||||
"
|
"
|
||||||
),
|
),
|
||||||
@r#"
|
@r#"
|
||||||
|
@ -4827,8 +4827,8 @@ mod test_reporting {
|
||||||
1│ app "test" provides [main] to "./platform"
|
1│ app "test" provides [main] to "./platform"
|
||||||
2│
|
2│
|
||||||
3│ main =
|
3│ main =
|
||||||
4│ f <- Foo.foo
|
4│ f = Foo.foo
|
||||||
^
|
^
|
||||||
|
|
||||||
Looks like the indentation ends prematurely here. Did you mean to have
|
Looks like the indentation ends prematurely here. Did you mean to have
|
||||||
another expression after this line?
|
another expression after this line?
|
||||||
|
@ -5760,28 +5760,6 @@ mod test_reporting {
|
||||||
"#
|
"#
|
||||||
);
|
);
|
||||||
|
|
||||||
test_report!(
|
|
||||||
dbg_without_final_expression,
|
|
||||||
indoc!(
|
|
||||||
r"
|
|
||||||
dbg 42
|
|
||||||
"
|
|
||||||
),
|
|
||||||
@r#"
|
|
||||||
── INDENT ENDS AFTER EXPRESSION in tmp/dbg_without_final_expression/Test.roc ───
|
|
||||||
|
|
||||||
I am partway through parsing a dbg statement, but I got stuck here:
|
|
||||||
|
|
||||||
4│ dbg 42
|
|
||||||
^
|
|
||||||
|
|
||||||
I was expecting a final expression, like so
|
|
||||||
|
|
||||||
dbg 42
|
|
||||||
"done"
|
|
||||||
"#
|
|
||||||
);
|
|
||||||
|
|
||||||
test_report!(
|
test_report!(
|
||||||
expect_without_final_expression,
|
expect_without_final_expression,
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -6318,16 +6296,17 @@ All branches in an `if` must have the same type!
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: this test seems out of date (what is the `effects` clause?) and as such should be removed
|
||||||
#[test]
|
#[test]
|
||||||
fn platform_requires_rigids() {
|
fn platform_requires_rigids() {
|
||||||
report_header_problem_as(
|
report_header_problem_as(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
platform "folkertdev/foo"
|
platform "folkertdev/foo"
|
||||||
requires { main : Effect {} }
|
requires { main : Task {} [] }
|
||||||
exposes []
|
exposes []
|
||||||
packages {}
|
packages {}
|
||||||
imports [Task]
|
imports []
|
||||||
provides [mainForHost]
|
provides [mainForHost]
|
||||||
effects fx.Effect
|
effects fx.Effect
|
||||||
{
|
{
|
||||||
|
@ -6344,13 +6323,13 @@ All branches in an `if` must have the same type!
|
||||||
I am partway through parsing a header, but I got stuck here:
|
I am partway through parsing a header, but I got stuck here:
|
||||||
|
|
||||||
1│ platform "folkertdev/foo"
|
1│ platform "folkertdev/foo"
|
||||||
2│ requires { main : Effect {} }
|
2│ requires { main : Task {} [] }
|
||||||
^
|
^
|
||||||
|
|
||||||
I am expecting a list of type names like `{}` or `{ Model }` next. A full
|
I am expecting a list of type names like `{}` or `{ Model }` next. A full
|
||||||
`requires` definition looks like
|
`requires` definition looks like
|
||||||
|
|
||||||
requires { Model, Msg } {main : Effect {}}
|
requires { Model, Msg } {main : Task {} []}
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -6617,34 +6596,6 @@ All branches in an `if` must have the same type!
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
|
|
||||||
test_report!(
|
|
||||||
backpassing_type_error,
|
|
||||||
indoc!(
|
|
||||||
r#"
|
|
||||||
x <- List.map ["a", "b"]
|
|
||||||
|
|
||||||
x + 1
|
|
||||||
"#
|
|
||||||
),
|
|
||||||
@r#"
|
|
||||||
── TYPE MISMATCH in /code/proj/Main.roc ────────────────────────────────────────
|
|
||||||
|
|
||||||
This 2nd argument to `map` has an unexpected type:
|
|
||||||
|
|
||||||
4│> x <- List.map ["a", "b"]
|
|
||||||
5│>
|
|
||||||
6│> x + 1
|
|
||||||
|
|
||||||
The argument is an anonymous function of type:
|
|
||||||
|
|
||||||
Num * -> Num *
|
|
||||||
|
|
||||||
But `map` needs its 2nd argument to be:
|
|
||||||
|
|
||||||
Str -> Num *
|
|
||||||
"#
|
|
||||||
);
|
|
||||||
|
|
||||||
test_report!(
|
test_report!(
|
||||||
expect_expr_type_error,
|
expect_expr_type_error,
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -8144,7 +8095,7 @@ All branches in an `if` must have the same type!
|
||||||
unimported_modules_reported,
|
unimported_modules_reported,
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
alt : Task.Task {} []
|
alt : Unimported.CustomType
|
||||||
alt = "whatever man you don't even know my type"
|
alt = "whatever man you don't even know my type"
|
||||||
alt
|
alt
|
||||||
"#
|
"#
|
||||||
|
@ -8152,18 +8103,18 @@ All branches in an `if` must have the same type!
|
||||||
@r"
|
@r"
|
||||||
── MODULE NOT IMPORTED in /code/proj/Main.roc ──────────────────────────────────
|
── MODULE NOT IMPORTED in /code/proj/Main.roc ──────────────────────────────────
|
||||||
|
|
||||||
The `Task` module is not imported:
|
The `Unimported` module is not imported:
|
||||||
|
|
||||||
4│ alt : Task.Task {} []
|
4│ alt : Unimported.CustomType
|
||||||
^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Is there an import missing? Perhaps there is a typo. Did you mean one
|
Is there an import missing? Perhaps there is a typo. Did you mean one
|
||||||
of these?
|
of these?
|
||||||
|
|
||||||
Hash
|
Encode
|
||||||
|
Inspect
|
||||||
|
Dict
|
||||||
List
|
List
|
||||||
Num
|
|
||||||
Box
|
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -10198,9 +10149,9 @@ All branches in an `if` must have the same type!
|
||||||
|
|
||||||
withOpen : (Handle -> Result {} *) -> Result {} *
|
withOpen : (Handle -> Result {} *) -> Result {} *
|
||||||
withOpen = \callback ->
|
withOpen = \callback ->
|
||||||
handle <- await (open {})
|
await (open {}) \handle ->
|
||||||
{} <- await (callback handle)
|
await (callback handle) \_ ->
|
||||||
close handle
|
close handle
|
||||||
|
|
||||||
withOpen
|
withOpen
|
||||||
"
|
"
|
||||||
|
@ -10212,9 +10163,9 @@ All branches in an `if` must have the same type!
|
||||||
|
|
||||||
10│ withOpen : (Handle -> Result {} *) -> Result {} *
|
10│ withOpen : (Handle -> Result {} *) -> Result {} *
|
||||||
11│ withOpen = \callback ->
|
11│ withOpen = \callback ->
|
||||||
12│> handle <- await (open {})
|
12│> await (open {}) \handle ->
|
||||||
13│> {} <- await (callback handle)
|
13│> await (callback handle) \_ ->
|
||||||
14│> close handle
|
14│> close handle
|
||||||
|
|
||||||
The type annotation on `withOpen` says this `await` call should have the
|
The type annotation on `withOpen` says this `await` call should have the
|
||||||
type:
|
type:
|
||||||
|
@ -10227,6 +10178,7 @@ All branches in an `if` must have the same type!
|
||||||
Tip: Any connection between types must use a named type variable, not
|
Tip: Any connection between types must use a named type variable, not
|
||||||
a `*`! Maybe the annotation on `withOpen` should have a named type
|
a `*`! Maybe the annotation on `withOpen` should have a named type
|
||||||
variable in place of the `*`?
|
variable in place of the `*`?
|
||||||
|
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -10830,7 +10782,7 @@ All branches in an `if` must have the same type!
|
||||||
7│ a: <- "a",
|
7│ a: <- "a",
|
||||||
^^^
|
^^^
|
||||||
|
|
||||||
Tip: Remove `<-` to assign the field directly.
|
Tip: Remove <- to assign the field directly.
|
||||||
"#
|
"#
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -10962,7 +10914,7 @@ All branches in an `if` must have the same type!
|
||||||
6│ { xyz <-
|
6│ { xyz <-
|
||||||
^^^
|
^^^
|
||||||
|
|
||||||
Note: Record builders need a mapper function before the `<-` to combine
|
Note: Record builders need a mapper function before the <- to combine
|
||||||
fields together with.
|
fields together with.
|
||||||
"#
|
"#
|
||||||
);
|
);
|
||||||
|
@ -11844,6 +11796,32 @@ All branches in an `if` must have the same type!
|
||||||
@r"
|
@r"
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
test_report!(
|
||||||
|
deprecated_backpassing,
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
foo = \bar ->
|
||||||
|
baz <- Result.try bar
|
||||||
|
|
||||||
|
Ok (baz * 3)
|
||||||
|
|
||||||
|
foo (Ok 123)
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
@r###"
|
||||||
|
── BACKPASSING DEPRECATED in /code/proj/Main.roc ───────────────────────────────
|
||||||
|
|
||||||
|
Backpassing (<-) like this will soon be deprecated:
|
||||||
|
|
||||||
|
5│ baz <- Result.try bar
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
You should use a ! for awaiting tasks or a ? for trying results, and
|
||||||
|
functions everywhere else.
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
|
||||||
test_report!(
|
test_report!(
|
||||||
unknown_shorthand_no_deps,
|
unknown_shorthand_no_deps,
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -13881,7 +13859,7 @@ All branches in an `if` must have the same type!
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
@r#"
|
@r#"
|
||||||
── DEFINITIONs ONLY USED IN RECURSION in /code/proj/Main.roc ───────────────────
|
── DEFINITIONS ONLY USED IN RECURSION in /code/proj/Main.roc ───────────────────
|
||||||
|
|
||||||
These 2 definitions are only used in mutual recursion with themselves:
|
These 2 definitions are only used in mutual recursion with themselves:
|
||||||
|
|
||||||
|
@ -13890,6 +13868,7 @@ All branches in an `if` must have the same type!
|
||||||
|
|
||||||
If you don't intend to use or export any of them, they should all be
|
If you don't intend to use or export any of them, they should all be
|
||||||
removed!
|
removed!
|
||||||
|
|
||||||
"#
|
"#
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -13953,7 +13932,7 @@ All branches in an `if` must have the same type!
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
@r#"
|
@r#"
|
||||||
── DEFINITIONs ONLY USED IN RECURSION in /code/proj/Main.roc ───────────────────
|
── DEFINITIONS ONLY USED IN RECURSION in /code/proj/Main.roc ───────────────────
|
||||||
|
|
||||||
These 2 definitions are only used in mutual recursion with themselves:
|
These 2 definitions are only used in mutual recursion with themselves:
|
||||||
|
|
||||||
|
@ -13962,6 +13941,7 @@ All branches in an `if` must have the same type!
|
||||||
|
|
||||||
If you don't intend to use or export any of them, they should all be
|
If you don't intend to use or export any of them, they should all be
|
||||||
removed!
|
removed!
|
||||||
|
|
||||||
"#
|
"#
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -14515,6 +14495,76 @@ All branches in an `if` must have the same type!
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
test_report!(
|
||||||
|
dbg_unapplied,
|
||||||
|
indoc!(
|
||||||
|
r"
|
||||||
|
1 + dbg + 2
|
||||||
|
"
|
||||||
|
),
|
||||||
|
@r"
|
||||||
|
── UNAPPLIED DBG in /code/proj/Main.roc ────────────────────────────────────────
|
||||||
|
|
||||||
|
This `dbg` doesn't have a value given to it:
|
||||||
|
|
||||||
|
4│ 1 + dbg + 2
|
||||||
|
^^^
|
||||||
|
|
||||||
|
`dbg` must be passed a value to print at the exact place it's used. `dbg`
|
||||||
|
can't be used as a value that's passed around, like functions can be -
|
||||||
|
it must be applied immediately!
|
||||||
|
|
||||||
|
── TYPE MISMATCH in /code/proj/Main.roc ────────────────────────────────────────
|
||||||
|
|
||||||
|
This 2nd argument to + has an unexpected type:
|
||||||
|
|
||||||
|
4│ 1 + dbg + 2
|
||||||
|
^^^
|
||||||
|
|
||||||
|
This `63` value is a:
|
||||||
|
|
||||||
|
{}
|
||||||
|
|
||||||
|
But + needs its 2nd argument to be:
|
||||||
|
|
||||||
|
Num *
|
||||||
|
"
|
||||||
|
);
|
||||||
|
|
||||||
|
test_report!(
|
||||||
|
dbg_overapplied,
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
1 + dbg "" "" + 2
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
@r#"
|
||||||
|
── OVERAPPLIED DBG in /code/proj/Main.roc ──────────────────────────────────────
|
||||||
|
|
||||||
|
This `dbg` has too many values given to it:
|
||||||
|
|
||||||
|
4│ 1 + dbg "" "" + 2
|
||||||
|
^^^^^
|
||||||
|
|
||||||
|
`dbg` must be given exactly one value to print.
|
||||||
|
|
||||||
|
── TYPE MISMATCH in /code/proj/Main.roc ────────────────────────────────────────
|
||||||
|
|
||||||
|
This 2nd argument to + has an unexpected type:
|
||||||
|
|
||||||
|
4│ 1 + dbg "" "" + 2
|
||||||
|
^^^^^^^^^
|
||||||
|
|
||||||
|
This `63` value is a:
|
||||||
|
|
||||||
|
{}
|
||||||
|
|
||||||
|
But + needs its 2nd argument to be:
|
||||||
|
|
||||||
|
Num *
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
|
||||||
// TODO: add the following tests after built-in Tasks are added
|
// TODO: add the following tests after built-in Tasks are added
|
||||||
// https://github.com/roc-lang/roc/pull/6836
|
// https://github.com/roc-lang/roc/pull/6836
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ roc_tracing = { path = "../../tracing" }
|
||||||
roc_types = { path = "../types" }
|
roc_types = { path = "../types" }
|
||||||
roc_unify = { path = "../unify" }
|
roc_unify = { path = "../unify" }
|
||||||
roc_worker = { path = "../worker" }
|
roc_worker = { path = "../worker" }
|
||||||
|
roc_lower_params = { path = "../lower_params" }
|
||||||
|
|
||||||
ven_pretty = { path = "../../vendor/pretty" }
|
ven_pretty = { path = "../../vendor/pretty" }
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ use roc_can::constraint::{Constraint as ConstraintSoa, Constraints, TypeOrVar};
|
||||||
use roc_can::expr::{DbgLookup, Declarations, ExpectLookup, PendingDerives};
|
use roc_can::expr::{DbgLookup, Declarations, ExpectLookup, PendingDerives};
|
||||||
use roc_can::module::{
|
use roc_can::module::{
|
||||||
canonicalize_module_defs, ExposedByModule, ExposedForModule, ExposedModuleTypes, Module,
|
canonicalize_module_defs, ExposedByModule, ExposedForModule, ExposedModuleTypes, Module,
|
||||||
ResolvedImplementations, TypeState,
|
ModuleParams, ResolvedImplementations, TypeState,
|
||||||
};
|
};
|
||||||
use roc_collections::{default_hasher, BumpMap, MutMap, MutSet, VecMap, VecSet};
|
use roc_collections::{default_hasher, BumpMap, MutMap, MutSet, VecMap, VecSet};
|
||||||
use roc_constrain::module::constrain_module;
|
use roc_constrain::module::constrain_module;
|
||||||
|
@ -251,6 +251,7 @@ fn start_phase<'a>(
|
||||||
|
|
||||||
let mut aliases = MutMap::default();
|
let mut aliases = MutMap::default();
|
||||||
let mut abilities_store = PendingAbilitiesStore::default();
|
let mut abilities_store = PendingAbilitiesStore::default();
|
||||||
|
let mut imported_module_params = VecMap::default();
|
||||||
|
|
||||||
for imported in parsed.available_modules.keys() {
|
for imported in parsed.available_modules.keys() {
|
||||||
match state.module_cache.aliases.get(imported) {
|
match state.module_cache.aliases.get(imported) {
|
||||||
|
@ -293,6 +294,10 @@ fn start_phase<'a>(
|
||||||
.union(import_store.closure_from_imported(exposed_symbols));
|
.union(import_store.closure_from_imported(exposed_symbols));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(params) = state.module_cache.module_params.get(imported) {
|
||||||
|
imported_module_params.insert(*imported, params.clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let skip_constraint_gen = {
|
let skip_constraint_gen = {
|
||||||
|
@ -310,6 +315,8 @@ fn start_phase<'a>(
|
||||||
abilities_store,
|
abilities_store,
|
||||||
skip_constraint_gen,
|
skip_constraint_gen,
|
||||||
exposed_module_ids: state.exposed_modules,
|
exposed_module_ids: state.exposed_modules,
|
||||||
|
exec_mode: state.exec_mode,
|
||||||
|
imported_module_params,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,6 +363,7 @@ fn start_phase<'a>(
|
||||||
declarations,
|
declarations,
|
||||||
state.cached_types.clone(),
|
state.cached_types.clone(),
|
||||||
derived_module,
|
derived_module,
|
||||||
|
state.exec_mode,
|
||||||
//
|
//
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
checkmate,
|
checkmate,
|
||||||
|
@ -889,6 +897,8 @@ enum BuildTask<'a> {
|
||||||
abilities_store: PendingAbilitiesStore,
|
abilities_store: PendingAbilitiesStore,
|
||||||
exposed_module_ids: &'a [ModuleId],
|
exposed_module_ids: &'a [ModuleId],
|
||||||
skip_constraint_gen: bool,
|
skip_constraint_gen: bool,
|
||||||
|
exec_mode: ExecutionMode,
|
||||||
|
imported_module_params: VecMap<ModuleId, ModuleParams>,
|
||||||
},
|
},
|
||||||
Solve {
|
Solve {
|
||||||
module: Module,
|
module: Module,
|
||||||
|
@ -905,6 +915,7 @@ enum BuildTask<'a> {
|
||||||
dep_idents: IdentIdsByModule,
|
dep_idents: IdentIdsByModule,
|
||||||
cached_subs: CachedTypeState,
|
cached_subs: CachedTypeState,
|
||||||
derived_module: SharedDerivedModule,
|
derived_module: SharedDerivedModule,
|
||||||
|
exec_mode: ExecutionMode,
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
checkmate: Option<roc_checkmate::Collector>,
|
checkmate: Option<roc_checkmate::Collector>,
|
||||||
|
@ -2318,6 +2329,7 @@ fn update<'a>(
|
||||||
extend_module_with_builtin_import(parsed, ModuleId::DECODE);
|
extend_module_with_builtin_import(parsed, ModuleId::DECODE);
|
||||||
extend_module_with_builtin_import(parsed, ModuleId::HASH);
|
extend_module_with_builtin_import(parsed, ModuleId::HASH);
|
||||||
extend_module_with_builtin_import(parsed, ModuleId::INSPECT);
|
extend_module_with_builtin_import(parsed, ModuleId::INSPECT);
|
||||||
|
extend_module_with_builtin_import(parsed, ModuleId::TASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
state
|
state
|
||||||
|
@ -2395,11 +2407,11 @@ fn update<'a>(
|
||||||
.pending_abilities
|
.pending_abilities
|
||||||
.insert(module_id, constrained_module.module.abilities_store.clone());
|
.insert(module_id, constrained_module.module.abilities_store.clone());
|
||||||
|
|
||||||
if let Some(params_pattern) = constrained_module.module.params_pattern.clone() {
|
if let Some(module_params) = constrained_module.module.module_params.clone() {
|
||||||
state
|
state
|
||||||
.module_cache
|
.module_cache
|
||||||
.param_patterns
|
.module_params
|
||||||
.insert(module_id, params_pattern);
|
.insert(module_id, module_params);
|
||||||
}
|
}
|
||||||
|
|
||||||
state
|
state
|
||||||
|
@ -3557,7 +3569,6 @@ fn load_builtin_module_help<'a>(
|
||||||
header_type: HeaderType::Builtin {
|
header_type: HeaderType::Builtin {
|
||||||
name: header::ModuleName::new(name_stem),
|
name: header::ModuleName::new(name_stem),
|
||||||
exposes: unspace(arena, header.exposes.items),
|
exposes: unspace(arena, header.exposes.items),
|
||||||
generates_with: &[],
|
|
||||||
opt_params: header.params,
|
opt_params: header.params,
|
||||||
},
|
},
|
||||||
module_comments: comments,
|
module_comments: comments,
|
||||||
|
@ -3640,6 +3651,7 @@ fn load_module<'a>(
|
||||||
"Decode", ModuleId::DECODE
|
"Decode", ModuleId::DECODE
|
||||||
"Hash", ModuleId::HASH
|
"Hash", ModuleId::HASH
|
||||||
"Inspect", ModuleId::INSPECT
|
"Inspect", ModuleId::INSPECT
|
||||||
|
"Task", ModuleId::TASK
|
||||||
}
|
}
|
||||||
|
|
||||||
let (filename, opt_shorthand) = module_name_to_path(src_dir, &module_name, arc_shorthands);
|
let (filename, opt_shorthand) = module_name_to_path(src_dir, &module_name, arc_shorthands);
|
||||||
|
@ -3875,8 +3887,6 @@ fn parse_header<'a>(
|
||||||
header_type: HeaderType::Hosted {
|
header_type: HeaderType::Hosted {
|
||||||
name: header.name.value,
|
name: header.name.value,
|
||||||
exposes: unspace(arena, header.exposes.item.items),
|
exposes: unspace(arena, header.exposes.item.items),
|
||||||
generates: header.generates.item,
|
|
||||||
generates_with: unspace(arena, header.generates_with.item.items),
|
|
||||||
},
|
},
|
||||||
module_comments: comments,
|
module_comments: comments,
|
||||||
header_imports: Some(header.imports),
|
header_imports: Some(header.imports),
|
||||||
|
@ -4311,6 +4321,7 @@ impl<'a> BuildTask<'a> {
|
||||||
declarations: Declarations,
|
declarations: Declarations,
|
||||||
cached_subs: CachedTypeState,
|
cached_subs: CachedTypeState,
|
||||||
derived_module: SharedDerivedModule,
|
derived_module: SharedDerivedModule,
|
||||||
|
exec_mode: ExecutionMode,
|
||||||
|
|
||||||
#[cfg(debug_assertions)] checkmate: Option<roc_checkmate::Collector>,
|
#[cfg(debug_assertions)] checkmate: Option<roc_checkmate::Collector>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -4334,6 +4345,7 @@ impl<'a> BuildTask<'a> {
|
||||||
module_timing,
|
module_timing,
|
||||||
cached_subs,
|
cached_subs,
|
||||||
derived_module,
|
derived_module,
|
||||||
|
exec_mode,
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
checkmate,
|
checkmate,
|
||||||
|
@ -4618,6 +4630,7 @@ struct SolveResult {
|
||||||
exposed_vars_by_symbol: Vec<(Symbol, Variable)>,
|
exposed_vars_by_symbol: Vec<(Symbol, Variable)>,
|
||||||
problems: Vec<TypeError>,
|
problems: Vec<TypeError>,
|
||||||
abilities_store: AbilitiesStore,
|
abilities_store: AbilitiesStore,
|
||||||
|
imported_modules_with_params: Vec<ModuleId>,
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
checkmate: Option<roc_checkmate::Collector>,
|
checkmate: Option<roc_checkmate::Collector>,
|
||||||
|
@ -4642,7 +4655,7 @@ fn run_solve_solve(
|
||||||
aliases,
|
aliases,
|
||||||
rigid_variables,
|
rigid_variables,
|
||||||
abilities_store: pending_abilities,
|
abilities_store: pending_abilities,
|
||||||
params_pattern,
|
module_params,
|
||||||
..
|
..
|
||||||
} = module;
|
} = module;
|
||||||
|
|
||||||
|
@ -4663,6 +4676,11 @@ fn run_solve_solve(
|
||||||
&mut imported_flex_vars,
|
&mut imported_flex_vars,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let imported_modules_with_params = imported_param_vars
|
||||||
|
.keys()
|
||||||
|
.copied()
|
||||||
|
.collect::<Vec<ModuleId>>();
|
||||||
|
|
||||||
let actual_constraint = constraints.let_import_constraint(
|
let actual_constraint = constraints.let_import_constraint(
|
||||||
imported_rigid_vars,
|
imported_rigid_vars,
|
||||||
imported_flex_vars,
|
imported_flex_vars,
|
||||||
|
@ -4690,7 +4708,7 @@ fn run_solve_solve(
|
||||||
derived_module,
|
derived_module,
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
checkmate,
|
checkmate,
|
||||||
params_pattern: params_pattern.map(|(_, _, pattern)| pattern.value),
|
module_params,
|
||||||
module_params_vars: imported_param_vars,
|
module_params_vars: imported_param_vars,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4745,6 +4763,7 @@ fn run_solve_solve(
|
||||||
exposed_vars_by_symbol,
|
exposed_vars_by_symbol,
|
||||||
problems: errors,
|
problems: errors,
|
||||||
abilities_store: resolved_abilities_store,
|
abilities_store: resolved_abilities_store,
|
||||||
|
imported_modules_with_params,
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
checkmate,
|
checkmate,
|
||||||
|
@ -4766,6 +4785,7 @@ fn run_solve<'a>(
|
||||||
dep_idents: IdentIdsByModule,
|
dep_idents: IdentIdsByModule,
|
||||||
cached_types: CachedTypeState,
|
cached_types: CachedTypeState,
|
||||||
derived_module: SharedDerivedModule,
|
derived_module: SharedDerivedModule,
|
||||||
|
exec_mode: ExecutionMode,
|
||||||
|
|
||||||
#[cfg(debug_assertions)] checkmate: Option<roc_checkmate::Collector>,
|
#[cfg(debug_assertions)] checkmate: Option<roc_checkmate::Collector>,
|
||||||
) -> Msg<'a> {
|
) -> Msg<'a> {
|
||||||
|
@ -4776,10 +4796,8 @@ fn run_solve<'a>(
|
||||||
// TODO remove when we write builtins in roc
|
// TODO remove when we write builtins in roc
|
||||||
let aliases = module.aliases.clone();
|
let aliases = module.aliases.clone();
|
||||||
|
|
||||||
let opt_params_var = module
|
let opt_params_var = module.module_params.as_ref().map(|params| params.whole_var);
|
||||||
.params_pattern
|
let home_has_params = opt_params_var.is_some();
|
||||||
.as_ref()
|
|
||||||
.map(|(params_var, _, _)| *params_var);
|
|
||||||
|
|
||||||
let mut module = module;
|
let mut module = module;
|
||||||
let loc_expects = std::mem::take(&mut module.loc_expects);
|
let loc_expects = std::mem::take(&mut module.loc_expects);
|
||||||
|
@ -4814,6 +4832,7 @@ fn run_solve<'a>(
|
||||||
exposed_vars_by_symbol,
|
exposed_vars_by_symbol,
|
||||||
problems: vec![],
|
problems: vec![],
|
||||||
abilities_store: abilities,
|
abilities_store: abilities,
|
||||||
|
imported_modules_with_params: vec![],
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
checkmate: None,
|
checkmate: None,
|
||||||
|
@ -4841,8 +4860,9 @@ fn run_solve<'a>(
|
||||||
solved: mut solved_subs,
|
solved: mut solved_subs,
|
||||||
solved_implementations,
|
solved_implementations,
|
||||||
exposed_vars_by_symbol,
|
exposed_vars_by_symbol,
|
||||||
problems,
|
mut problems,
|
||||||
abilities_store,
|
abilities_store,
|
||||||
|
imported_modules_with_params,
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
checkmate,
|
checkmate,
|
||||||
|
@ -4857,6 +4877,20 @@ fn run_solve<'a>(
|
||||||
&abilities_store,
|
&abilities_store,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
match exec_mode {
|
||||||
|
ExecutionMode::Check => {
|
||||||
|
// Params are not lowered in check mode
|
||||||
|
}
|
||||||
|
ExecutionMode::Executable | ExecutionMode::ExecutableIfCheck | ExecutionMode::Test => {
|
||||||
|
roc_lower_params::type_error::remove_module_param_arguments(
|
||||||
|
&mut problems,
|
||||||
|
home_has_params,
|
||||||
|
&decls.symbols,
|
||||||
|
imported_modules_with_params,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let solved_module = SolvedModule {
|
let solved_module = SolvedModule {
|
||||||
exposed_vars_by_symbol,
|
exposed_vars_by_symbol,
|
||||||
problems,
|
problems,
|
||||||
|
@ -5006,6 +5040,8 @@ fn canonicalize_and_constrain<'a>(
|
||||||
parsed: ParsedModule<'a>,
|
parsed: ParsedModule<'a>,
|
||||||
skip_constraint_gen: bool,
|
skip_constraint_gen: bool,
|
||||||
exposed_module_ids: &[ModuleId],
|
exposed_module_ids: &[ModuleId],
|
||||||
|
exec_mode: ExecutionMode,
|
||||||
|
imported_module_params: VecMap<ModuleId, ModuleParams>,
|
||||||
) -> CanAndCon {
|
) -> CanAndCon {
|
||||||
let canonicalize_start = Instant::now();
|
let canonicalize_start = Instant::now();
|
||||||
|
|
||||||
|
@ -5032,7 +5068,7 @@ fn canonicalize_and_constrain<'a>(
|
||||||
|
|
||||||
let mut var_store = VarStore::default();
|
let mut var_store = VarStore::default();
|
||||||
|
|
||||||
let module_output = canonicalize_module_defs(
|
let mut module_output = canonicalize_module_defs(
|
||||||
arena,
|
arena,
|
||||||
parsed_defs,
|
parsed_defs,
|
||||||
&header_type,
|
&header_type,
|
||||||
|
@ -5091,6 +5127,26 @@ fn canonicalize_and_constrain<'a>(
|
||||||
// _before has an underscore because it's unused in --release builds
|
// _before has an underscore because it's unused in --release builds
|
||||||
let _before = roc_types::types::get_type_clone_count();
|
let _before = roc_types::types::get_type_clone_count();
|
||||||
|
|
||||||
|
match exec_mode {
|
||||||
|
ExecutionMode::Check => {
|
||||||
|
// No need to lower params for `roc check` and lang server
|
||||||
|
// If we did, we'd have to update the language server to exclude the extra arguments
|
||||||
|
}
|
||||||
|
ExecutionMode::Executable | ExecutionMode::ExecutableIfCheck | ExecutionMode::Test => {
|
||||||
|
// We need to lower params only if the current module has any or imports at least one with params
|
||||||
|
if module_output.module_params.is_some() || !imported_module_params.is_empty() {
|
||||||
|
roc_lower_params::lower::lower(
|
||||||
|
module_id,
|
||||||
|
&module_output.module_params,
|
||||||
|
imported_module_params,
|
||||||
|
&mut module_output.declarations,
|
||||||
|
&mut module_output.scope.locals.ident_ids,
|
||||||
|
&mut var_store,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut constraints = Constraints::new();
|
let mut constraints = Constraints::new();
|
||||||
|
|
||||||
let constraint = if skip_constraint_gen {
|
let constraint = if skip_constraint_gen {
|
||||||
|
@ -5102,7 +5158,7 @@ fn canonicalize_and_constrain<'a>(
|
||||||
module_output.symbols_from_requires,
|
module_output.symbols_from_requires,
|
||||||
&module_output.scope.abilities_store,
|
&module_output.scope.abilities_store,
|
||||||
&module_output.declarations,
|
&module_output.declarations,
|
||||||
&module_output.params_pattern,
|
&module_output.module_params,
|
||||||
module_id,
|
module_id,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
@ -5140,6 +5196,7 @@ fn canonicalize_and_constrain<'a>(
|
||||||
| ModuleId::SET
|
| ModuleId::SET
|
||||||
| ModuleId::HASH
|
| ModuleId::HASH
|
||||||
| ModuleId::INSPECT
|
| ModuleId::INSPECT
|
||||||
|
| ModuleId::TASK
|
||||||
);
|
);
|
||||||
|
|
||||||
if !name.is_builtin() || should_include_builtin {
|
if !name.is_builtin() || should_include_builtin {
|
||||||
|
@ -5159,7 +5216,7 @@ fn canonicalize_and_constrain<'a>(
|
||||||
abilities_store: module_output.scope.abilities_store,
|
abilities_store: module_output.scope.abilities_store,
|
||||||
loc_expects: module_output.loc_expects,
|
loc_expects: module_output.loc_expects,
|
||||||
loc_dbgs: module_output.loc_dbgs,
|
loc_dbgs: module_output.loc_dbgs,
|
||||||
params_pattern: module_output.params_pattern,
|
module_params: module_output.module_params,
|
||||||
};
|
};
|
||||||
|
|
||||||
let constrained_module = ConstrainedModule {
|
let constrained_module = ConstrainedModule {
|
||||||
|
@ -6209,6 +6266,8 @@ fn run_task<'a>(
|
||||||
abilities_store,
|
abilities_store,
|
||||||
skip_constraint_gen,
|
skip_constraint_gen,
|
||||||
exposed_module_ids,
|
exposed_module_ids,
|
||||||
|
exec_mode,
|
||||||
|
imported_module_params,
|
||||||
} => {
|
} => {
|
||||||
let can_and_con = canonicalize_and_constrain(
|
let can_and_con = canonicalize_and_constrain(
|
||||||
arena,
|
arena,
|
||||||
|
@ -6220,6 +6279,8 @@ fn run_task<'a>(
|
||||||
parsed,
|
parsed,
|
||||||
skip_constraint_gen,
|
skip_constraint_gen,
|
||||||
exposed_module_ids,
|
exposed_module_ids,
|
||||||
|
exec_mode,
|
||||||
|
imported_module_params,
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(Msg::CanonicalizedAndConstrained(can_and_con))
|
Ok(Msg::CanonicalizedAndConstrained(can_and_con))
|
||||||
|
@ -6239,6 +6300,7 @@ fn run_task<'a>(
|
||||||
dep_idents,
|
dep_idents,
|
||||||
cached_subs,
|
cached_subs,
|
||||||
derived_module,
|
derived_module,
|
||||||
|
exec_mode,
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
checkmate,
|
checkmate,
|
||||||
|
@ -6257,6 +6319,7 @@ fn run_task<'a>(
|
||||||
dep_idents,
|
dep_idents,
|
||||||
cached_subs,
|
cached_subs,
|
||||||
derived_module,
|
derived_module,
|
||||||
|
exec_mode,
|
||||||
//
|
//
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
checkmate,
|
checkmate,
|
||||||
|
|
|
@ -25,4 +25,5 @@ pub const BUILTIN_MODULES: &[(ModuleId, &str)] = &[
|
||||||
(ModuleId::DECODE, "Decode"),
|
(ModuleId::DECODE, "Decode"),
|
||||||
(ModuleId::HASH, "Hash"),
|
(ModuleId::HASH, "Hash"),
|
||||||
(ModuleId::INSPECT, "Inspect"),
|
(ModuleId::INSPECT, "Inspect"),
|
||||||
|
(ModuleId::TASK, "Task"),
|
||||||
];
|
];
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue