mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
Merge remote-tracking branch 'origin/trunk' into remove-old-expect-logic
This commit is contained in:
commit
f05274faef
1139 changed files with 23491 additions and 21403 deletions
|
@ -2,7 +2,7 @@ on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 9 * * *'
|
- cron: '0 9 * * *'
|
||||||
|
|
||||||
name: Nightly Release Apple Silicon
|
name: Nightly Release macOS Apple Silicon
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test-and-build:
|
test-and-build:
|
52
.github/workflows/nightly_macos_x86_64.yml
vendored
Normal file
52
.github/workflows/nightly_macos_x86_64.yml
vendored
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 9 * * 1' # 9=9am utc+0, 1=monday
|
||||||
|
|
||||||
|
name: Nightly Release macOS x86_64
|
||||||
|
|
||||||
|
env:
|
||||||
|
ZIG_VERSION: 0.9.1
|
||||||
|
LLVM_SYS_130_PREFIX: /usr/local/opt/llvm
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test-and-build:
|
||||||
|
name: Rust tests, build and package nightly release
|
||||||
|
runs-on: [macos-12]
|
||||||
|
timeout-minutes: 90
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install zig
|
||||||
|
run: |
|
||||||
|
curl -L -o zig.tar.xz https://ziglang.org/download/${ZIG_VERSION}/zig-macos-x86_64-${ZIG_VERSION}.tar.xz && tar -xf zig.tar.xz
|
||||||
|
echo "${GITHUB_WORKSPACE}/zig-macos-x86_64-${ZIG_VERSION}" >> $GITHUB_PATH
|
||||||
|
- name: zig version
|
||||||
|
run: zig version
|
||||||
|
- name: Install LLVM
|
||||||
|
run: brew install llvm@13
|
||||||
|
- name: execute rust tests
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: test
|
||||||
|
args: --locked # no --release yet until #3166 is fixed
|
||||||
|
- name: write version to file
|
||||||
|
run: ./ci/write_version.sh
|
||||||
|
- name: build release
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: build
|
||||||
|
args: --release --locked
|
||||||
|
- name: package release
|
||||||
|
run: ./ci/package_release.sh roc_darwin_x86_64.tar.gz
|
||||||
|
- name: Create pre-release with test_archive.tar.gz
|
||||||
|
uses: Anton-4/deploy-nightly@1609d8dfe211b078674801113ab7a2ec2938b2a9
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # automatically provided by github actions
|
||||||
|
with:
|
||||||
|
upload_url: https://uploads.github.com/repos/rtfeldman/roc/releases/51880579/assets{?name,label}
|
||||||
|
release_id: 51880579
|
||||||
|
asset_path: ./roc_darwin_x86_64.tar.gz
|
||||||
|
asset_name: roc_nightly-macos_x86_64-$$.tar.gz # $$ inserts 6 char commit hash and date (YYYY-MM-DD)
|
||||||
|
asset_content_type: application/gzip
|
||||||
|
max_releases: 3
|
||||||
|
|
21
.github/workflows/stale.yml
vendored
Normal file
21
.github/workflows/stale.yml
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
name: 'Close stale PRs'
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '30 1 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
stale:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
pull-requests: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/stale@v5
|
||||||
|
with:
|
||||||
|
delete-branch: true
|
||||||
|
exempt-pr-labels: 'blocked'
|
||||||
|
days-before-issue-close: -1
|
||||||
|
days-before-pr-stale: 30
|
||||||
|
days-before-pr-close: 30
|
||||||
|
stale-pr-message: 'Thank you for your contribution! Sometimes PRs end up staying open for a long time without activity, which can make the list of open PRs get long and time-consuming to review. To keep things manageable for reviewers, this bot automatically closes PRs that haven’t had activity in 60 days. This PR hasn’t had activity in 30 days, so it will be automatically closed if there is no more activity in the next 30 days. Keep in mind that PRs marked `Closed` are not deleted, so no matter what, the PR will still be right here in the repo. You can always access it and reopen it anytime you like!'
|
||||||
|
stale-pr-label: 'inactive for 30 days'
|
||||||
|
close-pr-label: 'auto-closed'
|
1
AUTHORS
1
AUTHORS
|
@ -84,3 +84,4 @@ Drake Bennion <drake.bennion@gmail.com>
|
||||||
Hashi364 <49736221+Kiyoshi364@users.noreply.github.com>
|
Hashi364 <49736221+Kiyoshi364@users.noreply.github.com>
|
||||||
Jared Forsyth <jared@jaredforsyth.com>
|
Jared Forsyth <jared@jaredforsyth.com>
|
||||||
Patrick Kilgore <git@pck.email>
|
Patrick Kilgore <git@pck.email>
|
||||||
|
Marten/Qqwy <w-m@wmcode.nl>
|
||||||
|
|
1239
Cargo.lock
generated
1239
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
108
Cargo.toml
108
Cargo.toml
|
@ -1,56 +1,56 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
"compiler/ident",
|
"crates/compiler/ident",
|
||||||
"compiler/region",
|
"crates/compiler/region",
|
||||||
"compiler/collections",
|
"crates/compiler/collections",
|
||||||
"compiler/exhaustive",
|
"crates/compiler/exhaustive",
|
||||||
"compiler/module",
|
"crates/compiler/module",
|
||||||
"compiler/parse",
|
"crates/compiler/parse",
|
||||||
"compiler/can",
|
"crates/compiler/can",
|
||||||
"compiler/problem",
|
"crates/compiler/problem",
|
||||||
"compiler/types",
|
"crates/compiler/types",
|
||||||
"compiler/builtins",
|
"crates/compiler/builtins",
|
||||||
"compiler/constrain",
|
"crates/compiler/constrain",
|
||||||
"compiler/unify",
|
"crates/compiler/unify",
|
||||||
"compiler/solve",
|
"crates/compiler/solve",
|
||||||
"compiler/late_solve",
|
"crates/compiler/late_solve",
|
||||||
"compiler/fmt",
|
"crates/compiler/fmt",
|
||||||
"compiler/derive_key",
|
"crates/compiler/derive_key",
|
||||||
"compiler/mono",
|
"crates/compiler/mono",
|
||||||
"compiler/alias_analysis",
|
"crates/compiler/alias_analysis",
|
||||||
"compiler/test_mono",
|
"crates/compiler/test_mono",
|
||||||
"compiler/test_derive",
|
"crates/compiler/test_derive",
|
||||||
"compiler/load",
|
"crates/compiler/load",
|
||||||
"compiler/load_internal",
|
"crates/compiler/load_internal",
|
||||||
"compiler/gen_llvm",
|
"crates/compiler/gen_llvm",
|
||||||
"compiler/gen_dev",
|
"crates/compiler/gen_dev",
|
||||||
"compiler/gen_wasm",
|
"crates/compiler/gen_wasm",
|
||||||
"compiler/build",
|
"crates/compiler/build",
|
||||||
"compiler/arena_pool",
|
"crates/compiler/arena_pool",
|
||||||
"compiler/test_gen",
|
"crates/compiler/test_gen",
|
||||||
"compiler/roc_target",
|
"crates/compiler/roc_target",
|
||||||
"compiler/debug_flags",
|
"crates/compiler/debug_flags",
|
||||||
"vendor/inkwell",
|
"crates/vendor/inkwell",
|
||||||
"vendor/pathfinding",
|
"crates/vendor/pathfinding",
|
||||||
"vendor/pretty",
|
"crates/vendor/pretty",
|
||||||
"bindgen",
|
"crates/bindgen",
|
||||||
"editor",
|
"crates/editor",
|
||||||
"ast",
|
"crates/ast",
|
||||||
"cli",
|
"crates/cli",
|
||||||
"code_markup",
|
"crates/code_markup",
|
||||||
"highlight",
|
"crates/highlight",
|
||||||
"error_macros",
|
"crates/error_macros",
|
||||||
"reporting",
|
"crates/reporting",
|
||||||
"repl_cli",
|
"crates/repl_cli",
|
||||||
"repl_eval",
|
"crates/repl_eval",
|
||||||
"repl_test",
|
"crates/repl_test",
|
||||||
"repl_wasm",
|
"crates/repl_wasm",
|
||||||
"test_utils",
|
"crates/test_utils",
|
||||||
"utils",
|
"crates/utils",
|
||||||
"docs",
|
"crates/docs",
|
||||||
"docs_cli",
|
"crates/docs_cli",
|
||||||
"linker",
|
"crates/linker",
|
||||||
"wasi-libc-sys",
|
"crates/wasi-libc-sys",
|
||||||
]
|
]
|
||||||
exclude = [
|
exclude = [
|
||||||
# Examples sometimes have Rust hosts in their platforms. The compiler should ignore those.
|
# Examples sometimes have Rust hosts in their platforms. The compiler should ignore those.
|
||||||
|
@ -58,10 +58,10 @@ exclude = [
|
||||||
"ci/bench-runner",
|
"ci/bench-runner",
|
||||||
# Ignore building these normally. They are only imported by tests.
|
# Ignore building these normally. They are only imported by tests.
|
||||||
# The tests will still correctly build them.
|
# The tests will still correctly build them.
|
||||||
"cli_utils",
|
"crates/cli_utils",
|
||||||
"compiler/test_mono_macros",
|
"crates/compiler/test_mono_macros",
|
||||||
# `cargo build` would cause roc_std to be built with default features which errors on windows
|
# `cargo build` would cause roc_std to be built with default features which errors on windows
|
||||||
"roc_std",
|
"crates/roc_std",
|
||||||
]
|
]
|
||||||
# Needed to be able to run `cargo run -p roc_cli --no-default-features` -
|
# Needed to be able to run `cargo run -p roc_cli --no-default-features` -
|
||||||
# see www/build.sh for more.
|
# see www/build.sh for more.
|
||||||
|
|
19
Earthfile
19
Earthfile
|
@ -53,15 +53,19 @@ install-zig-llvm-valgrind-clippy-rustfmt:
|
||||||
|
|
||||||
copy-dirs:
|
copy-dirs:
|
||||||
FROM +install-zig-llvm-valgrind-clippy-rustfmt
|
FROM +install-zig-llvm-valgrind-clippy-rustfmt
|
||||||
COPY --dir bindgen cli cli_utils compiler docs docs_cli editor ast code_markup error_macros highlight utils test_utils reporting repl_cli repl_eval repl_test repl_wasm repl_www roc_std vendor examples linker Cargo.toml Cargo.lock version.txt www wasi-libc-sys ./
|
COPY --dir crates repl_www examples Cargo.toml Cargo.lock version.txt www ./
|
||||||
|
|
||||||
test-zig:
|
test-zig:
|
||||||
FROM +install-zig-llvm-valgrind-clippy-rustfmt
|
FROM +install-zig-llvm-valgrind-clippy-rustfmt
|
||||||
COPY --dir compiler/builtins/bitcode ./
|
COPY --dir crates/compiler/builtins/bitcode ./
|
||||||
RUN cd bitcode && ./run-tests.sh && ./run-wasm-tests.sh
|
RUN cd bitcode && ./run-tests.sh && ./run-wasm-tests.sh
|
||||||
|
|
||||||
build-rust-test:
|
build-rust-test:
|
||||||
FROM +copy-dirs
|
FROM +copy-dirs
|
||||||
|
RUN echo "deb http://deb.debian.org/debian testing main contrib non-free" >> /etc/apt/sources.list # to get gcc 10.3
|
||||||
|
RUN apt -y update
|
||||||
|
RUN apt -y install gcc-10 g++-10 && rm /usr/bin/gcc && ln -s /usr/bin/gcc-10 /usr/bin/gcc # gcc-9 maybe causes segfault
|
||||||
|
RUN gcc --version
|
||||||
RUN --mount=type=cache,target=$SCCACHE_DIR \
|
RUN --mount=type=cache,target=$SCCACHE_DIR \
|
||||||
cargo test --locked --release --features with_sound --workspace --no-run && sccache --show-stats
|
cargo test --locked --release --features with_sound --workspace --no-run && sccache --show-stats
|
||||||
|
|
||||||
|
@ -80,7 +84,7 @@ check-rustfmt:
|
||||||
|
|
||||||
check-typos:
|
check-typos:
|
||||||
RUN cargo install typos-cli --version 1.0.11 # version set to prevent confusion if the version is updated automatically
|
RUN cargo install typos-cli --version 1.0.11 # version set to prevent confusion if the version is updated automatically
|
||||||
COPY --dir .github ci cli cli_utils compiler docs editor examples ast code_markup highlight utils linker nightly_benches packages roc_std www *.md LEGAL_DETAILS shell.nix version.txt ./
|
COPY --dir .github ci crates examples nightly_benches www *.md LEGAL_DETAILS flake.nix version.txt ./
|
||||||
RUN typos
|
RUN typos
|
||||||
|
|
||||||
test-rust:
|
test-rust:
|
||||||
|
@ -91,6 +95,7 @@ test-rust:
|
||||||
ENV ROC_NUM_WORKERS=1
|
ENV ROC_NUM_WORKERS=1
|
||||||
# run one of the benchmarks to make sure the host is compiled
|
# run one of the benchmarks to make sure the host is compiled
|
||||||
# not pre-compiling the host can cause race conditions
|
# not pre-compiling the host can cause race conditions
|
||||||
|
RUN gcc --version
|
||||||
RUN echo "4" | cargo run --release examples/benchmarks/NQueens.roc
|
RUN echo "4" | cargo run --release examples/benchmarks/NQueens.roc
|
||||||
RUN --mount=type=cache,target=$SCCACHE_DIR \
|
RUN --mount=type=cache,target=$SCCACHE_DIR \
|
||||||
cargo test --locked --release --features with_sound --workspace && sccache --show-stats
|
cargo test --locked --release --features with_sound --workspace && sccache --show-stats
|
||||||
|
@ -102,7 +107,7 @@ test-rust:
|
||||||
cargo test --locked --release --package test_gen --no-default-features --features gen-wasm -- --test-threads=1 && sccache --show-stats
|
cargo test --locked --release --package test_gen --no-default-features --features gen-wasm -- --test-threads=1 && sccache --show-stats
|
||||||
# repl_test: build the compiler for wasm target, then run the tests on native target
|
# repl_test: build the compiler for wasm target, then run the tests on native target
|
||||||
RUN --mount=type=cache,target=$SCCACHE_DIR \
|
RUN --mount=type=cache,target=$SCCACHE_DIR \
|
||||||
repl_test/test_wasm.sh && sccache --show-stats
|
crates/repl_test/test_wasm.sh && sccache --show-stats
|
||||||
# run i386 (32-bit linux) cli tests
|
# run i386 (32-bit linux) cli tests
|
||||||
# NOTE: disabled until zig 0.9
|
# NOTE: disabled until zig 0.9
|
||||||
# RUN echo "4" | cargo run --locked --release --features="target-x86" -- --target=x86_32 examples/benchmarks/NQueens.roc
|
# RUN echo "4" | cargo run --locked --release --features="target-x86" -- --target=x86_32 examples/benchmarks/NQueens.roc
|
||||||
|
@ -147,13 +152,13 @@ prep-bench-folder:
|
||||||
ENV RUSTFLAGS="-C link-arg=-fuse-ld=lld -C target-cpu=native"
|
ENV RUSTFLAGS="-C link-arg=-fuse-ld=lld -C target-cpu=native"
|
||||||
ARG BENCH_SUFFIX=branch
|
ARG BENCH_SUFFIX=branch
|
||||||
RUN cargo criterion -V
|
RUN cargo criterion -V
|
||||||
RUN --mount=type=cache,target=$SCCACHE_DIR cd cli && cargo criterion --no-run
|
RUN --mount=type=cache,target=$SCCACHE_DIR cd crates/cli && cargo criterion --no-run
|
||||||
RUN mkdir -p bench-folder/compiler/builtins/bitcode/src
|
RUN mkdir -p bench-folder/crates/compiler/builtins/bitcode/src
|
||||||
RUN mkdir -p bench-folder/target/release/deps
|
RUN mkdir -p bench-folder/target/release/deps
|
||||||
RUN mkdir -p bench-folder/examples/benchmarks
|
RUN mkdir -p bench-folder/examples/benchmarks
|
||||||
RUN cp examples/benchmarks/*.roc bench-folder/examples/benchmarks/
|
RUN cp examples/benchmarks/*.roc bench-folder/examples/benchmarks/
|
||||||
RUN cp -r examples/benchmarks/platform bench-folder/examples/benchmarks/
|
RUN cp -r examples/benchmarks/platform bench-folder/examples/benchmarks/
|
||||||
RUN cp compiler/builtins/bitcode/src/str.zig bench-folder/compiler/builtins/bitcode/src
|
RUN cp crates/compiler/builtins/bitcode/src/str.zig bench-folder/crates/compiler/builtins/bitcode/src
|
||||||
RUN cp target/release/roc bench-folder/target/release
|
RUN cp target/release/roc bench-folder/target/release
|
||||||
# copy the most recent time bench to bench-folder
|
# copy the most recent time bench to bench-folder
|
||||||
RUN cp target/release/deps/`ls -t target/release/deps/ | grep time_bench | head -n 1` bench-folder/target/release/deps/time_bench
|
RUN cp target/release/deps/`ls -t target/release/deps/ | grep time_bench | head -n 1` bench-folder/target/release/deps/time_bench
|
||||||
|
|
|
@ -17,6 +17,7 @@ Many programs can however be compiled correctly. Check out [examples](examples)
|
||||||
|
|
||||||
- [Linux x86](getting_started/linux_x86.md)
|
- [Linux x86](getting_started/linux_x86.md)
|
||||||
- [MacOS Apple Silicon](getting_started/macos_apple_silicon.md)
|
- [MacOS Apple Silicon](getting_started/macos_apple_silicon.md)
|
||||||
|
- [MacOS x86](getting_started/macos_x86.md)
|
||||||
- [Windows](getting_started/windows.md)
|
- [Windows](getting_started/windows.md)
|
||||||
- [Other](getting_started/other.md)
|
- [Other](getting_started/other.md)
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
cp target/release/roc ./roc # to be able to exclude "target" later in the tar command
|
cp target/release/roc ./roc # to be able to exclude "target" later in the tar command
|
||||||
tar -czvf $1 --exclude="target" --exclude="zig-cache" roc LICENSE LEGAL_DETAILS examples/hello-world compiler/builtins/bitcode/src/ roc_std
|
tar -czvf $1 --exclude="target" --exclude="zig-cache" roc LICENSE LEGAL_DETAILS examples/hello-world crates/compiler/builtins/bitcode/src/ crates/roc_std
|
|
@ -1 +0,0 @@
|
||||||
../../../examples/interactive/cli-platform
|
|
|
@ -1,120 +0,0 @@
|
||||||
use roc_error_macros::internal_error;
|
|
||||||
use roc_module::{
|
|
||||||
ident::{Lowercase, TagName},
|
|
||||||
symbol::Symbol,
|
|
||||||
};
|
|
||||||
use roc_types::subs::{Content, FlatType, GetSubsSlice, Subs, SubsFmtContent, Variable};
|
|
||||||
|
|
||||||
#[derive(Hash)]
|
|
||||||
pub enum FlatEncodable<'a> {
|
|
||||||
Immediate(Symbol),
|
|
||||||
Key(FlatEncodableKey<'a>),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Hash, PartialEq, Eq, Debug)]
|
|
||||||
pub enum FlatEncodableKey<'a> {
|
|
||||||
List(/* takes one variable */),
|
|
||||||
Set(/* takes one variable */),
|
|
||||||
Dict(/* takes two variables */),
|
|
||||||
// Unfortunate that we must allocate here, c'est la vie
|
|
||||||
Record(Vec<&'a Lowercase>),
|
|
||||||
TagUnion(Vec<(&'a TagName, u16)>),
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! unexpected {
|
|
||||||
($subs:expr, $var:expr) => {
|
|
||||||
internal_error!(
|
|
||||||
"Invalid content for toEncoder: {:?}",
|
|
||||||
SubsFmtContent($subs.get_content_without_compacting($var), $subs)
|
|
||||||
)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FlatEncodable<'_> {
|
|
||||||
pub(crate) fn from_var(subs: &Subs, var: Variable) -> FlatEncodable {
|
|
||||||
use FlatEncodable::*;
|
|
||||||
match *subs.get_content_without_compacting(var) {
|
|
||||||
Content::Structure(flat_type) => match flat_type {
|
|
||||||
FlatType::Apply(sym, _) => match sym {
|
|
||||||
Symbol::LIST_LIST => Key(FlatEncodableKey::List()),
|
|
||||||
Symbol::SET_SET => Key(FlatEncodableKey::Set()),
|
|
||||||
Symbol::DICT_DICT => Key(FlatEncodableKey::Dict()),
|
|
||||||
Symbol::STR_STR => Immediate(Symbol::ENCODE_STRING),
|
|
||||||
_ => unexpected!(subs, var),
|
|
||||||
},
|
|
||||||
FlatType::Record(fields, ext) => {
|
|
||||||
debug_assert!(matches!(
|
|
||||||
subs.get_content_without_compacting(ext),
|
|
||||||
Content::Structure(FlatType::EmptyRecord)
|
|
||||||
));
|
|
||||||
|
|
||||||
let mut field_names: Vec<_> =
|
|
||||||
subs.get_subs_slice(fields.field_names()).iter().collect();
|
|
||||||
field_names.sort();
|
|
||||||
Key(FlatEncodableKey::Record(field_names))
|
|
||||||
}
|
|
||||||
FlatType::TagUnion(tags, ext) | FlatType::RecursiveTagUnion(_, tags, ext) => {
|
|
||||||
// The recursion var doesn't matter, because the derived implementation will only
|
|
||||||
// look on the surface of the tag union type, and more over the payloads of the
|
|
||||||
// arguments will be left generic for the monomorphizer to fill in with the
|
|
||||||
// appropriate type. That is,
|
|
||||||
// [ A t1, B t1 t2 ]
|
|
||||||
// and
|
|
||||||
// [ A t1, B t1 t2 ] as R
|
|
||||||
// look the same on the surface, because `R` is only somewhere inside of the
|
|
||||||
// `t`-prefixed payload types.
|
|
||||||
debug_assert!(matches!(
|
|
||||||
subs.get_content_without_compacting(ext),
|
|
||||||
Content::Structure(FlatType::EmptyTagUnion)
|
|
||||||
));
|
|
||||||
let mut tag_names_and_payload_sizes: Vec<_> = tags
|
|
||||||
.iter_all()
|
|
||||||
.map(|(name_index, payload_slice_index)| {
|
|
||||||
let payload_slice = subs[payload_slice_index];
|
|
||||||
let payload_size = payload_slice.length;
|
|
||||||
let name = &subs[name_index];
|
|
||||||
(name, payload_size)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
tag_names_and_payload_sizes.sort_by_key(|t| t.0);
|
|
||||||
Key(FlatEncodableKey::TagUnion(tag_names_and_payload_sizes))
|
|
||||||
}
|
|
||||||
FlatType::FunctionOrTagUnion(name_index, _, _) => {
|
|
||||||
Key(FlatEncodableKey::TagUnion(vec![(&subs[name_index], 0)]))
|
|
||||||
}
|
|
||||||
FlatType::EmptyRecord => Key(FlatEncodableKey::Record(vec![])),
|
|
||||||
FlatType::EmptyTagUnion => Key(FlatEncodableKey::TagUnion(vec![])),
|
|
||||||
//
|
|
||||||
FlatType::Erroneous(_) => unexpected!(subs, var),
|
|
||||||
FlatType::Func(..) => unexpected!(subs, var),
|
|
||||||
},
|
|
||||||
Content::Alias(sym, _, real_var, _) => match sym {
|
|
||||||
Symbol::NUM_U8 => Immediate(Symbol::ENCODE_U8),
|
|
||||||
Symbol::NUM_U16 => Immediate(Symbol::ENCODE_U16),
|
|
||||||
Symbol::NUM_U32 => Immediate(Symbol::ENCODE_U32),
|
|
||||||
Symbol::NUM_U64 => Immediate(Symbol::ENCODE_U64),
|
|
||||||
Symbol::NUM_U128 => Immediate(Symbol::ENCODE_U128),
|
|
||||||
Symbol::NUM_I8 => Immediate(Symbol::ENCODE_I8),
|
|
||||||
Symbol::NUM_I16 => Immediate(Symbol::ENCODE_I16),
|
|
||||||
Symbol::NUM_I32 => Immediate(Symbol::ENCODE_I32),
|
|
||||||
Symbol::NUM_I64 => Immediate(Symbol::ENCODE_I64),
|
|
||||||
Symbol::NUM_I128 => Immediate(Symbol::ENCODE_I128),
|
|
||||||
Symbol::NUM_DEC => Immediate(Symbol::ENCODE_DEC),
|
|
||||||
Symbol::NUM_F32 => Immediate(Symbol::ENCODE_F32),
|
|
||||||
Symbol::NUM_F64 => Immediate(Symbol::ENCODE_F64),
|
|
||||||
// TODO: I believe it is okay to unwrap opaques here because derivers are only used
|
|
||||||
// by the backend, and the backend treats opaques like structural aliases.
|
|
||||||
_ => Self::from_var(subs, real_var),
|
|
||||||
},
|
|
||||||
Content::RangedNumber(real_var, _) => Self::from_var(subs, real_var),
|
|
||||||
//
|
|
||||||
Content::RecursionVar { .. } => unexpected!(subs, var),
|
|
||||||
Content::Error => unexpected!(subs, var),
|
|
||||||
Content::FlexVar(_)
|
|
||||||
| Content::RigidVar(_)
|
|
||||||
| Content::FlexAbleVar(_, _)
|
|
||||||
| Content::RigidAbleVar(_, _) => unexpected!(subs, var),
|
|
||||||
Content::LambdaSet(_) => unexpected!(subs, var),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,63 +0,0 @@
|
||||||
//! To avoid duplicating derived implementations for the same type, derived implementations are
|
|
||||||
//! addressed by a key of their type content. However, different derived implementations can be
|
|
||||||
//! reused based on different properties of the type. For example:
|
|
||||||
//!
|
|
||||||
//! - `Eq` does not care about surface type representations; its derived implementations can be
|
|
||||||
//! uniquely addressed by the [`Layout`][crate::layout::Layout] of a type.
|
|
||||||
//! - `Encoding` must care about surface type representations; for example, `{ a: "" }` and
|
|
||||||
//! `{ b: "" }` have different derived implementations. However, it does not need to distinguish
|
|
||||||
//! between e.g. required and optional record fields.
|
|
||||||
//! - `Decoding` is like encoding, but has some differences. For one, it *does* need to distinguish
|
|
||||||
//! between required and optional record fields.
|
|
||||||
//!
|
|
||||||
//! For these reasons the content keying is based on a [`Strategy`] as well.
|
|
||||||
|
|
||||||
pub mod encoding;
|
|
||||||
|
|
||||||
use encoding::{FlatEncodable, FlatEncodableKey};
|
|
||||||
|
|
||||||
use roc_module::symbol::Symbol;
|
|
||||||
use roc_types::subs::{Subs, Variable};
|
|
||||||
|
|
||||||
#[derive(Hash, PartialEq, Eq, Debug)]
|
|
||||||
#[repr(u8)]
|
|
||||||
enum Strategy {
|
|
||||||
Encoding,
|
|
||||||
#[allow(unused)]
|
|
||||||
Decoding,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Hash, PartialEq, Eq, Debug)]
|
|
||||||
pub enum Derived<R>
|
|
||||||
where
|
|
||||||
R: std::hash::Hash + PartialEq + Eq + std::fmt::Debug,
|
|
||||||
{
|
|
||||||
/// If a derived implementation name is well-known ahead-of-time, we can inline the symbol
|
|
||||||
/// directly rather than associating a key for an implementation to be made later on.
|
|
||||||
Immediate(Symbol),
|
|
||||||
/// Key of the derived implementation to use. This allows association of derived implementation
|
|
||||||
/// names to a key, when the key is known ahead-of-time but the implementation (and it's name)
|
|
||||||
/// is yet-to-be-made.
|
|
||||||
Key(DeriveKey<R>),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Hash, PartialEq, Eq, Debug)]
|
|
||||||
pub struct DeriveKey<R>
|
|
||||||
where
|
|
||||||
R: std::hash::Hash + PartialEq + Eq + std::fmt::Debug,
|
|
||||||
{
|
|
||||||
strategy: Strategy,
|
|
||||||
pub repr: R,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Derived<FlatEncodableKey<'a>> {
|
|
||||||
pub fn encoding(subs: &'a Subs, var: Variable) -> Self {
|
|
||||||
match encoding::FlatEncodable::from_var(subs, var) {
|
|
||||||
FlatEncodable::Immediate(imm) => Derived::Immediate(imm),
|
|
||||||
FlatEncodable::Key(repr) => Derived::Key(DeriveKey {
|
|
||||||
strategy: Strategy::Encoding,
|
|
||||||
repr,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,884 +0,0 @@
|
||||||
#[macro_use]
|
|
||||||
extern crate indoc;
|
|
||||||
#[macro_use]
|
|
||||||
extern crate pretty_assertions;
|
|
||||||
#[macro_use]
|
|
||||||
extern crate maplit;
|
|
||||||
|
|
||||||
extern crate bumpalo;
|
|
||||||
extern crate roc_collections;
|
|
||||||
extern crate roc_load_internal;
|
|
||||||
extern crate roc_module;
|
|
||||||
|
|
||||||
mod helpers;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test_load {
|
|
||||||
use crate::helpers::fixtures_dir;
|
|
||||||
use bumpalo::Bump;
|
|
||||||
use roc_can::def::Declaration::*;
|
|
||||||
use roc_can::def::Def;
|
|
||||||
use roc_constrain::module::ExposedByModule;
|
|
||||||
use roc_load_internal::file::Threading;
|
|
||||||
use roc_load_internal::file::{LoadResult, LoadStart, LoadedModule, LoadingProblem, Phase};
|
|
||||||
use roc_module::ident::ModuleName;
|
|
||||||
use roc_module::symbol::{Interns, ModuleId};
|
|
||||||
use roc_problem::can::Problem;
|
|
||||||
use roc_region::all::LineInfo;
|
|
||||||
use roc_reporting::report::can_problem;
|
|
||||||
use roc_reporting::report::RenderTarget;
|
|
||||||
use roc_reporting::report::RocDocAllocator;
|
|
||||||
use roc_target::TargetInfo;
|
|
||||||
use roc_types::pretty_print::name_and_print_var;
|
|
||||||
use roc_types::pretty_print::DebugPrint;
|
|
||||||
use roc_types::subs::Subs;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
|
|
||||||
fn load_and_typecheck<'a>(
|
|
||||||
arena: &'a Bump,
|
|
||||||
filename: PathBuf,
|
|
||||||
src_dir: &Path,
|
|
||||||
exposed_types: ExposedByModule,
|
|
||||||
target_info: TargetInfo,
|
|
||||||
) -> Result<LoadedModule, LoadingProblem<'a>> {
|
|
||||||
use LoadResult::*;
|
|
||||||
|
|
||||||
let load_start = LoadStart::from_path(arena, filename, RenderTarget::Generic)?;
|
|
||||||
|
|
||||||
match roc_load_internal::file::load(
|
|
||||||
arena,
|
|
||||||
load_start,
|
|
||||||
src_dir,
|
|
||||||
exposed_types,
|
|
||||||
Phase::SolveTypes,
|
|
||||||
target_info,
|
|
||||||
Default::default(), // these tests will re-compile the builtins
|
|
||||||
RenderTarget::Generic,
|
|
||||||
Threading::Single,
|
|
||||||
)? {
|
|
||||||
Monomorphized(_) => unreachable!(""),
|
|
||||||
TypeChecked(module) => Ok(module),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const TARGET_INFO: roc_target::TargetInfo = roc_target::TargetInfo::default_x86_64();
|
|
||||||
|
|
||||||
// HELPERS
|
|
||||||
|
|
||||||
fn format_can_problems(
|
|
||||||
problems: Vec<Problem>,
|
|
||||||
home: ModuleId,
|
|
||||||
interns: &Interns,
|
|
||||||
filename: PathBuf,
|
|
||||||
src: &str,
|
|
||||||
) -> String {
|
|
||||||
use ven_pretty::DocAllocator;
|
|
||||||
|
|
||||||
let src_lines: Vec<&str> = src.split('\n').collect();
|
|
||||||
let lines = LineInfo::new(src);
|
|
||||||
let alloc = RocDocAllocator::new(&src_lines, home, interns);
|
|
||||||
let reports = problems
|
|
||||||
.into_iter()
|
|
||||||
.map(|problem| can_problem(&alloc, &lines, filename.clone(), problem).pretty(&alloc));
|
|
||||||
|
|
||||||
let mut buf = String::new();
|
|
||||||
alloc
|
|
||||||
.stack(reports)
|
|
||||||
.append(alloc.line())
|
|
||||||
.1
|
|
||||||
.render_raw(70, &mut roc_reporting::report::CiWrite::new(&mut buf))
|
|
||||||
.unwrap();
|
|
||||||
buf
|
|
||||||
}
|
|
||||||
|
|
||||||
fn multiple_modules(subdir: &str, files: Vec<(&str, &str)>) -> Result<LoadedModule, String> {
|
|
||||||
let arena = Bump::new();
|
|
||||||
let arena = &arena;
|
|
||||||
|
|
||||||
match multiple_modules_help(subdir, arena, files) {
|
|
||||||
Err(io_error) => panic!("IO trouble: {:?}", io_error),
|
|
||||||
Ok(Err(LoadingProblem::FormattedReport(buf))) => Err(buf),
|
|
||||||
Ok(Err(loading_problem)) => Err(format!("{:?}", loading_problem)),
|
|
||||||
Ok(Ok(mut loaded_module)) => {
|
|
||||||
let home = loaded_module.module_id;
|
|
||||||
let (filepath, src) = loaded_module.sources.get(&home).unwrap();
|
|
||||||
|
|
||||||
let can_problems = loaded_module.can_problems.remove(&home).unwrap_or_default();
|
|
||||||
if !can_problems.is_empty() {
|
|
||||||
return Err(format_can_problems(
|
|
||||||
can_problems,
|
|
||||||
home,
|
|
||||||
&loaded_module.interns,
|
|
||||||
filepath.clone(),
|
|
||||||
src,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
assert!(loaded_module
|
|
||||||
.type_problems
|
|
||||||
.remove(&home)
|
|
||||||
.unwrap_or_default()
|
|
||||||
.is_empty(),);
|
|
||||||
|
|
||||||
Ok(loaded_module)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn multiple_modules_help<'a>(
|
|
||||||
subdir: &str,
|
|
||||||
arena: &'a Bump,
|
|
||||||
mut files: Vec<(&str, &str)>,
|
|
||||||
) -> Result<Result<LoadedModule, roc_load_internal::file::LoadingProblem<'a>>, std::io::Error>
|
|
||||||
{
|
|
||||||
use std::fs::{self, File};
|
|
||||||
use std::io::Write;
|
|
||||||
|
|
||||||
let mut file_handles: Vec<_> = Vec::new();
|
|
||||||
|
|
||||||
// Use a deterministic temporary directory.
|
|
||||||
// We can't have all tests use "tmp" because tests run in parallel,
|
|
||||||
// so append the test name to the tmp path.
|
|
||||||
let tmp = format!("tmp/{}", subdir);
|
|
||||||
let dir = roc_test_utils::TmpDir::new(&tmp);
|
|
||||||
|
|
||||||
let app_module = files.pop().unwrap();
|
|
||||||
|
|
||||||
for (name, source) in files {
|
|
||||||
let mut filename = PathBuf::from(name);
|
|
||||||
filename.set_extension("roc");
|
|
||||||
let file_path = dir.path().join(filename.clone());
|
|
||||||
|
|
||||||
// Create any necessary intermediate directories (e.g. /platform)
|
|
||||||
fs::create_dir_all(file_path.parent().unwrap())?;
|
|
||||||
|
|
||||||
let mut file = File::create(file_path)?;
|
|
||||||
writeln!(file, "{}", source)?;
|
|
||||||
file_handles.push(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
let result = {
|
|
||||||
let (name, source) = app_module;
|
|
||||||
|
|
||||||
let filename = PathBuf::from(name);
|
|
||||||
let file_path = dir.path().join(filename);
|
|
||||||
let full_file_path = file_path.clone();
|
|
||||||
let mut file = File::create(file_path)?;
|
|
||||||
writeln!(file, "{}", source)?;
|
|
||||||
file_handles.push(file);
|
|
||||||
|
|
||||||
load_and_typecheck(
|
|
||||||
arena,
|
|
||||||
full_file_path,
|
|
||||||
dir.path(),
|
|
||||||
Default::default(),
|
|
||||||
TARGET_INFO,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_fixture(
|
|
||||||
dir_name: &str,
|
|
||||||
module_name: &str,
|
|
||||||
subs_by_module: ExposedByModule,
|
|
||||||
) -> LoadedModule {
|
|
||||||
let src_dir = fixtures_dir().join(dir_name);
|
|
||||||
let filename = src_dir.join(format!("{}.roc", module_name));
|
|
||||||
let arena = Bump::new();
|
|
||||||
let loaded = load_and_typecheck(
|
|
||||||
&arena,
|
|
||||||
filename,
|
|
||||||
src_dir.as_path(),
|
|
||||||
subs_by_module,
|
|
||||||
TARGET_INFO,
|
|
||||||
);
|
|
||||||
let mut loaded_module = match loaded {
|
|
||||||
Ok(x) => x,
|
|
||||||
Err(roc_load_internal::file::LoadingProblem::FormattedReport(report)) => {
|
|
||||||
println!("{}", report);
|
|
||||||
panic!("{}", report);
|
|
||||||
}
|
|
||||||
Err(e) => panic!("{:?}", e),
|
|
||||||
};
|
|
||||||
|
|
||||||
let home = loaded_module.module_id;
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
loaded_module.can_problems.remove(&home).unwrap_or_default(),
|
|
||||||
Vec::new()
|
|
||||||
);
|
|
||||||
assert!(loaded_module
|
|
||||||
.type_problems
|
|
||||||
.remove(&home)
|
|
||||||
.unwrap_or_default()
|
|
||||||
.is_empty());
|
|
||||||
|
|
||||||
let expected_name = loaded_module
|
|
||||||
.interns
|
|
||||||
.module_ids
|
|
||||||
.get_name(loaded_module.module_id)
|
|
||||||
.expect("Test ModuleID not found in module_ids");
|
|
||||||
|
|
||||||
// App module names are hardcoded and not based on anything user-specified
|
|
||||||
if expected_name.as_str() != ModuleName::APP {
|
|
||||||
assert_eq!(&expected_name.as_str(), &module_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
loaded_module
|
|
||||||
}
|
|
||||||
|
|
||||||
fn expect_def(
|
|
||||||
interns: &Interns,
|
|
||||||
subs: &mut Subs,
|
|
||||||
home: ModuleId,
|
|
||||||
def: &Def,
|
|
||||||
expected_types: &mut HashMap<&str, &str>,
|
|
||||||
) {
|
|
||||||
for (symbol, expr_var) in &def.pattern_vars {
|
|
||||||
let actual_str =
|
|
||||||
name_and_print_var(*expr_var, subs, home, interns, DebugPrint::NOTHING);
|
|
||||||
let fully_qualified = symbol.fully_qualified(interns, home).to_string();
|
|
||||||
let expected_type = expected_types
|
|
||||||
.remove(fully_qualified.as_str())
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
panic!("Defs included an unexpected symbol: {:?}", fully_qualified)
|
|
||||||
});
|
|
||||||
|
|
||||||
assert_eq!((&symbol, expected_type), (&symbol, actual_str.as_str()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn expect_types(mut loaded_module: LoadedModule, mut expected_types: HashMap<&str, &str>) {
|
|
||||||
let home = loaded_module.module_id;
|
|
||||||
let mut subs = loaded_module.solved.into_inner();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
loaded_module.can_problems.remove(&home).unwrap_or_default(),
|
|
||||||
Vec::new()
|
|
||||||
);
|
|
||||||
assert!(loaded_module
|
|
||||||
.type_problems
|
|
||||||
.remove(&home)
|
|
||||||
.unwrap_or_default()
|
|
||||||
.is_empty());
|
|
||||||
|
|
||||||
for decl in loaded_module.declarations_by_id.remove(&home).unwrap() {
|
|
||||||
match decl {
|
|
||||||
Declare(def) => expect_def(
|
|
||||||
&loaded_module.interns,
|
|
||||||
&mut subs,
|
|
||||||
home,
|
|
||||||
&def,
|
|
||||||
&mut expected_types,
|
|
||||||
),
|
|
||||||
DeclareRec(defs, cycle_mark) => {
|
|
||||||
assert!(!cycle_mark.is_illegal(&subs));
|
|
||||||
for def in defs {
|
|
||||||
expect_def(
|
|
||||||
&loaded_module.interns,
|
|
||||||
&mut subs,
|
|
||||||
home,
|
|
||||||
&def,
|
|
||||||
&mut expected_types,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Builtin(_) => {}
|
|
||||||
cycle @ InvalidCycle(_) => {
|
|
||||||
panic!("Unexpected cyclic def in module declarations: {:?}", cycle);
|
|
||||||
}
|
|
||||||
expects @ Expects(_) => {
|
|
||||||
// at least at the moment this does not happen
|
|
||||||
panic!("Unexpected expects in module declarations: {:?}", expects);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
expected_types,
|
|
||||||
HashMap::default(),
|
|
||||||
"Some expected types were not found in the defs"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TESTS
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn import_transitive_alias() {
|
|
||||||
// this had a bug where NodeColor was HostExposed, and it's `actual_var` conflicted
|
|
||||||
// with variables in the importee
|
|
||||||
let modules = vec![
|
|
||||||
(
|
|
||||||
"RBTree",
|
|
||||||
indoc!(
|
|
||||||
r#"
|
|
||||||
interface RBTree exposes [RedBlackTree, empty] imports []
|
|
||||||
|
|
||||||
# The color of a node. Leaves are considered Black.
|
|
||||||
NodeColor : [Red, Black]
|
|
||||||
|
|
||||||
RedBlackTree k v : [Node NodeColor k v (RedBlackTree k v) (RedBlackTree k v), Empty]
|
|
||||||
|
|
||||||
# Create an empty dictionary.
|
|
||||||
empty : RedBlackTree k v
|
|
||||||
empty =
|
|
||||||
Empty
|
|
||||||
"#
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"Main",
|
|
||||||
indoc!(
|
|
||||||
r#"
|
|
||||||
interface Other exposes [empty] imports [RBTree]
|
|
||||||
|
|
||||||
empty : RBTree.RedBlackTree I64 I64
|
|
||||||
empty = RBTree.empty
|
|
||||||
"#
|
|
||||||
),
|
|
||||||
),
|
|
||||||
];
|
|
||||||
|
|
||||||
assert!(multiple_modules("import_transitive_alias", modules).is_ok());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn interface_with_deps() {
|
|
||||||
let subs_by_module = Default::default();
|
|
||||||
let src_dir = fixtures_dir().join("interface_with_deps");
|
|
||||||
let filename = src_dir.join("Primary.roc");
|
|
||||||
let arena = Bump::new();
|
|
||||||
let loaded = load_and_typecheck(
|
|
||||||
&arena,
|
|
||||||
filename,
|
|
||||||
src_dir.as_path(),
|
|
||||||
subs_by_module,
|
|
||||||
TARGET_INFO,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut loaded_module = loaded.expect("Test module failed to load");
|
|
||||||
let home = loaded_module.module_id;
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
loaded_module.can_problems.remove(&home).unwrap_or_default(),
|
|
||||||
Vec::new()
|
|
||||||
);
|
|
||||||
assert!(loaded_module
|
|
||||||
.type_problems
|
|
||||||
.remove(&home)
|
|
||||||
.unwrap_or_default()
|
|
||||||
.is_empty(),);
|
|
||||||
|
|
||||||
let def_count: usize = loaded_module
|
|
||||||
.declarations_by_id
|
|
||||||
.remove(&loaded_module.module_id)
|
|
||||||
.unwrap()
|
|
||||||
.into_iter()
|
|
||||||
.map(|decl| decl.def_count())
|
|
||||||
.sum();
|
|
||||||
|
|
||||||
let expected_name = loaded_module
|
|
||||||
.interns
|
|
||||||
.module_ids
|
|
||||||
.get_name(loaded_module.module_id)
|
|
||||||
.expect("Test ModuleID not found in module_ids");
|
|
||||||
|
|
||||||
assert_eq!(expected_name.as_str(), "Primary");
|
|
||||||
assert_eq!(def_count, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn load_unit() {
|
|
||||||
let subs_by_module = Default::default();
|
|
||||||
let loaded_module = load_fixture("no_deps", "Unit", subs_by_module);
|
|
||||||
|
|
||||||
expect_types(
|
|
||||||
loaded_module,
|
|
||||||
hashmap! {
|
|
||||||
"unit" => "Unit",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn import_alias() {
|
|
||||||
let subs_by_module = Default::default();
|
|
||||||
let loaded_module = load_fixture("interface_with_deps", "ImportAlias", subs_by_module);
|
|
||||||
|
|
||||||
expect_types(
|
|
||||||
loaded_module,
|
|
||||||
hashmap! {
|
|
||||||
"unit" => "Dep1.Unit",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_load_and_typecheck() {
|
|
||||||
let subs_by_module = Default::default();
|
|
||||||
let loaded_module = load_fixture("interface_with_deps", "WithBuiltins", subs_by_module);
|
|
||||||
|
|
||||||
expect_types(
|
|
||||||
loaded_module,
|
|
||||||
hashmap! {
|
|
||||||
"floatTest" => "F64",
|
|
||||||
"divisionFn" => "Float a, Float a -> Float a",
|
|
||||||
"x" => "Float *",
|
|
||||||
"divisionTest" => "F64",
|
|
||||||
"intTest" => "I64",
|
|
||||||
"constantNum" => "Num *",
|
|
||||||
"divisionTest" => "F64",
|
|
||||||
"divDep1ByDep2" => "Float *",
|
|
||||||
"fromDep2" => "Float *",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn iface_quicksort() {
|
|
||||||
let subs_by_module = Default::default();
|
|
||||||
let loaded_module = load_fixture("interface_with_deps", "Quicksort", subs_by_module);
|
|
||||||
|
|
||||||
expect_types(
|
|
||||||
loaded_module,
|
|
||||||
hashmap! {
|
|
||||||
"swap" => "Nat, Nat, List a -> List a",
|
|
||||||
"partition" => "Nat, Nat, List (Num a) -> [Pair Nat (List (Num a))]",
|
|
||||||
"partitionHelp" => "Nat, Nat, List (Num a), Nat, Num a -> [Pair Nat (List (Num a))]",
|
|
||||||
"quicksort" => "List (Num a), Nat, Nat -> List (Num a)",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn quicksort_one_def() {
|
|
||||||
let subs_by_module = Default::default();
|
|
||||||
let loaded_module = load_fixture("app_with_deps", "QuicksortOneDef", subs_by_module);
|
|
||||||
|
|
||||||
expect_types(
|
|
||||||
loaded_module,
|
|
||||||
hashmap! {
|
|
||||||
"quicksort" => "List (Num a) -> List (Num a)",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn app_quicksort() {
|
|
||||||
let subs_by_module = Default::default();
|
|
||||||
let loaded_module = load_fixture("app_with_deps", "Quicksort", subs_by_module);
|
|
||||||
|
|
||||||
expect_types(
|
|
||||||
loaded_module,
|
|
||||||
hashmap! {
|
|
||||||
"swap" => "Nat, Nat, List a -> List a",
|
|
||||||
"partition" => "Nat, Nat, List (Num a) -> [Pair Nat (List (Num a))]",
|
|
||||||
"partitionHelp" => "Nat, Nat, List (Num a), Nat, Num a -> [Pair Nat (List (Num a))]",
|
|
||||||
"quicksort" => "List (Num a), Nat, Nat -> List (Num a)",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn load_astar() {
|
|
||||||
let subs_by_module = Default::default();
|
|
||||||
let loaded_module = load_fixture("interface_with_deps", "AStar", subs_by_module);
|
|
||||||
|
|
||||||
expect_types(
|
|
||||||
loaded_module,
|
|
||||||
hashmap! {
|
|
||||||
"findPath" => "{ costFunction : position, position -> F64, end : position, moveFunction : position -> Set position, start : position } -> Result (List position) [KeyNotFound]*",
|
|
||||||
"initialModel" => "position -> Model position",
|
|
||||||
"reconstructPath" => "Dict position position, position -> List position",
|
|
||||||
"updateCost" => "position, position, Model position -> Model position",
|
|
||||||
"cheapestOpen" => "(position -> F64), Model position -> Result position [KeyNotFound]*",
|
|
||||||
"astar" => "(position, position -> F64), (position -> Set position), position, Model position -> [Err [KeyNotFound]*, Ok (List position)]*",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn load_principal_types() {
|
|
||||||
let subs_by_module = Default::default();
|
|
||||||
let loaded_module = load_fixture("no_deps", "Principal", subs_by_module);
|
|
||||||
|
|
||||||
expect_types(
|
|
||||||
loaded_module,
|
|
||||||
hashmap! {
|
|
||||||
"intVal" => "Str",
|
|
||||||
"identity" => "a -> a",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn iface_dep_types() {
|
|
||||||
let subs_by_module = Default::default();
|
|
||||||
let loaded_module = load_fixture("interface_with_deps", "Primary", subs_by_module);
|
|
||||||
|
|
||||||
expect_types(
|
|
||||||
loaded_module,
|
|
||||||
hashmap! {
|
|
||||||
"blah2" => "Float *",
|
|
||||||
"blah3" => "Str",
|
|
||||||
"str" => "Str",
|
|
||||||
"alwaysThree" => "* -> Float *",
|
|
||||||
"identity" => "a -> a",
|
|
||||||
"z" => "Float *",
|
|
||||||
"w" => "Dep1.Identity {}",
|
|
||||||
"succeed" => "a -> Dep1.Identity a",
|
|
||||||
"yay" => "Res.Res {} err",
|
|
||||||
"withDefault" => "Res.Res a err, a -> a",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn app_dep_types() {
|
|
||||||
let subs_by_module = Default::default();
|
|
||||||
let loaded_module = load_fixture("app_with_deps", "Primary", subs_by_module);
|
|
||||||
|
|
||||||
expect_types(
|
|
||||||
loaded_module,
|
|
||||||
hashmap! {
|
|
||||||
"blah2" => "Float *",
|
|
||||||
"blah3" => "Str",
|
|
||||||
"str" => "Str",
|
|
||||||
"alwaysThree" => "* -> Float *",
|
|
||||||
"identity" => "a -> a",
|
|
||||||
"z" => "Float *",
|
|
||||||
"w" => "Dep1.Identity {}",
|
|
||||||
"succeed" => "a -> Dep1.Identity a",
|
|
||||||
"yay" => "Res.Res {} err",
|
|
||||||
"withDefault" => "Res.Res a err, a -> a",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn imported_dep_regression() {
|
|
||||||
let subs_by_module = Default::default();
|
|
||||||
let loaded_module = load_fixture("interface_with_deps", "OneDep", subs_by_module);
|
|
||||||
|
|
||||||
expect_types(
|
|
||||||
loaded_module,
|
|
||||||
hashmap! {
|
|
||||||
"str" => "Str",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn parse_problem() {
|
|
||||||
let modules = vec![(
|
|
||||||
"Main",
|
|
||||||
indoc!(
|
|
||||||
r#"
|
|
||||||
interface Main exposes [main] imports []
|
|
||||||
|
|
||||||
main = [
|
|
||||||
"#
|
|
||||||
),
|
|
||||||
)];
|
|
||||||
|
|
||||||
match multiple_modules("parse_problem", modules) {
|
|
||||||
Err(report) => assert_eq!(
|
|
||||||
report,
|
|
||||||
indoc!(
|
|
||||||
"
|
|
||||||
── UNFINISHED LIST ──────────────────────────────────── tmp/parse_problem/Main ─
|
|
||||||
|
|
||||||
I cannot find the end of this list:
|
|
||||||
|
|
||||||
3│ main = [
|
|
||||||
^
|
|
||||||
|
|
||||||
You could change it to something like [1, 2, 3] or even just [].
|
|
||||||
Anything where there is an open and a close square bracket, and where
|
|
||||||
the elements of the list are separated by commas.
|
|
||||||
|
|
||||||
Note: I may be confused by indentation"
|
|
||||||
)
|
|
||||||
),
|
|
||||||
Ok(_) => unreachable!("we expect failure here"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_panic(expected = "FILE NOT FOUND")]
|
|
||||||
fn file_not_found() {
|
|
||||||
let subs_by_module = Default::default();
|
|
||||||
let loaded_module = load_fixture("interface_with_deps", "invalid$name", subs_by_module);
|
|
||||||
|
|
||||||
expect_types(
|
|
||||||
loaded_module,
|
|
||||||
hashmap! {
|
|
||||||
"str" => "Str",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_panic(expected = "FILE NOT FOUND")]
|
|
||||||
fn imported_file_not_found() {
|
|
||||||
let subs_by_module = Default::default();
|
|
||||||
let loaded_module = load_fixture("no_deps", "MissingDep", subs_by_module);
|
|
||||||
|
|
||||||
expect_types(
|
|
||||||
loaded_module,
|
|
||||||
hashmap! {
|
|
||||||
"str" => "Str",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn platform_does_not_exist() {
|
|
||||||
let modules = vec![(
|
|
||||||
"Main",
|
|
||||||
indoc!(
|
|
||||||
r#"
|
|
||||||
app "example"
|
|
||||||
packages { pf: "./zzz-does-not-exist/main.roc" }
|
|
||||||
imports []
|
|
||||||
provides [main] to pf
|
|
||||||
|
|
||||||
main = ""
|
|
||||||
"#
|
|
||||||
),
|
|
||||||
)];
|
|
||||||
|
|
||||||
match multiple_modules("platform_does_not_exist", modules) {
|
|
||||||
Err(report) => {
|
|
||||||
assert!(report.contains("FILE NOT FOUND"), "report=({})", report);
|
|
||||||
assert!(
|
|
||||||
report.contains("zzz-does-not-exist/main.roc"),
|
|
||||||
"report=({})",
|
|
||||||
report
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Ok(_) => unreachable!("we expect failure here"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn platform_parse_error() {
|
|
||||||
let modules = vec![
|
|
||||||
(
|
|
||||||
"platform/main.roc",
|
|
||||||
indoc!(
|
|
||||||
r#"
|
|
||||||
platform "hello-c"
|
|
||||||
requires {} { main : Str }
|
|
||||||
exposes []
|
|
||||||
packages {}
|
|
||||||
imports []
|
|
||||||
provides [mainForHost]
|
|
||||||
blah 1 2 3 # causing a parse error on purpose
|
|
||||||
|
|
||||||
mainForHost : Str
|
|
||||||
"#
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"Main",
|
|
||||||
indoc!(
|
|
||||||
r#"
|
|
||||||
app "hello-world"
|
|
||||||
packages { pf: "platform/main.roc" }
|
|
||||||
imports []
|
|
||||||
provides [main] to pf
|
|
||||||
|
|
||||||
main = "Hello, World!\n"
|
|
||||||
"#
|
|
||||||
),
|
|
||||||
),
|
|
||||||
];
|
|
||||||
|
|
||||||
match multiple_modules("platform_parse_error", modules) {
|
|
||||||
Err(report) => {
|
|
||||||
assert!(report.contains("NOT END OF FILE"));
|
|
||||||
assert!(report.contains("blah 1 2 3 # causing a parse error on purpose"));
|
|
||||||
}
|
|
||||||
Ok(_) => unreachable!("we expect failure here"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
// See https://github.com/rtfeldman/roc/issues/2413
|
|
||||||
fn platform_exposes_main_return_by_pointer_issue() {
|
|
||||||
let modules = vec![
|
|
||||||
(
|
|
||||||
"platform/main.roc",
|
|
||||||
indoc!(
|
|
||||||
r#"
|
|
||||||
platform "hello-world"
|
|
||||||
requires {} { main : { content: Str, other: Str } }
|
|
||||||
exposes []
|
|
||||||
packages {}
|
|
||||||
imports []
|
|
||||||
provides [mainForHost]
|
|
||||||
|
|
||||||
mainForHost : { content: Str, other: Str }
|
|
||||||
mainForHost = main
|
|
||||||
"#
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"Main",
|
|
||||||
indoc!(
|
|
||||||
r#"
|
|
||||||
app "hello-world"
|
|
||||||
packages { pf: "platform/main.roc" }
|
|
||||||
imports []
|
|
||||||
provides [main] to pf
|
|
||||||
|
|
||||||
main = { content: "Hello, World!\n", other: "" }
|
|
||||||
"#
|
|
||||||
),
|
|
||||||
),
|
|
||||||
];
|
|
||||||
|
|
||||||
assert!(multiple_modules("platform_exposes_main_return_by_pointer_issue", modules).is_ok());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn opaque_wrapped_unwrapped_outside_defining_module() {
|
|
||||||
let modules = vec![
|
|
||||||
(
|
|
||||||
"Age",
|
|
||||||
indoc!(
|
|
||||||
r#"
|
|
||||||
interface Age exposes [Age] imports []
|
|
||||||
|
|
||||||
Age := U32
|
|
||||||
"#
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"Main",
|
|
||||||
indoc!(
|
|
||||||
r#"
|
|
||||||
interface Main exposes [twenty, readAge] imports [Age.{ Age }]
|
|
||||||
|
|
||||||
twenty = @Age 20
|
|
||||||
|
|
||||||
readAge = \@Age n -> n
|
|
||||||
"#
|
|
||||||
),
|
|
||||||
),
|
|
||||||
];
|
|
||||||
|
|
||||||
let err = multiple_modules("opaque_wrapped_unwrapped_outside_defining_module", modules)
|
|
||||||
.unwrap_err();
|
|
||||||
assert_eq!(
|
|
||||||
err,
|
|
||||||
indoc!(
|
|
||||||
r#"
|
|
||||||
── OPAQUE TYPE DECLARED OUTSIDE SCOPE ─ ...rapped_outside_defining_module/Main ─
|
|
||||||
|
|
||||||
The unwrapped opaque type Age referenced here:
|
|
||||||
|
|
||||||
3│ twenty = @Age 20
|
|
||||||
^^^^
|
|
||||||
|
|
||||||
is imported from another module:
|
|
||||||
|
|
||||||
1│ interface Main exposes [twenty, readAge] imports [Age.{ Age }]
|
|
||||||
^^^^^^^^^^^
|
|
||||||
|
|
||||||
Note: Opaque types can only be wrapped and unwrapped in the module they are defined in!
|
|
||||||
|
|
||||||
── OPAQUE TYPE DECLARED OUTSIDE SCOPE ─ ...rapped_outside_defining_module/Main ─
|
|
||||||
|
|
||||||
The unwrapped opaque type Age referenced here:
|
|
||||||
|
|
||||||
5│ readAge = \@Age n -> n
|
|
||||||
^^^^
|
|
||||||
|
|
||||||
is imported from another module:
|
|
||||||
|
|
||||||
1│ interface Main exposes [twenty, readAge] imports [Age.{ Age }]
|
|
||||||
^^^^^^^^^^^
|
|
||||||
|
|
||||||
Note: Opaque types can only be wrapped and unwrapped in the module they are defined in!
|
|
||||||
|
|
||||||
── UNUSED IMPORT ─── tmp/opaque_wrapped_unwrapped_outside_defining_module/Main ─
|
|
||||||
|
|
||||||
Nothing from Age is used in this module.
|
|
||||||
|
|
||||||
1│ interface Main exposes [twenty, readAge] imports [Age.{ Age }]
|
|
||||||
^^^^^^^^^^^
|
|
||||||
|
|
||||||
Since Age isn't used, you don't need to import it.
|
|
||||||
"#
|
|
||||||
),
|
|
||||||
"\n{}",
|
|
||||||
err
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn issue_2863_module_type_does_not_exist() {
|
|
||||||
let modules = vec![
|
|
||||||
(
|
|
||||||
"platform/main.roc",
|
|
||||||
indoc!(
|
|
||||||
r#"
|
|
||||||
platform "testplatform"
|
|
||||||
requires {} { main : Str }
|
|
||||||
exposes []
|
|
||||||
packages {}
|
|
||||||
imports []
|
|
||||||
provides [mainForHost]
|
|
||||||
|
|
||||||
mainForHost : Str
|
|
||||||
mainForHost = main
|
|
||||||
"#
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"Main",
|
|
||||||
indoc!(
|
|
||||||
r#"
|
|
||||||
app "test"
|
|
||||||
packages { pf: "platform/main.roc" }
|
|
||||||
provides [main] to pf
|
|
||||||
|
|
||||||
main : DoesNotExist
|
|
||||||
main = 1
|
|
||||||
"#
|
|
||||||
),
|
|
||||||
),
|
|
||||||
];
|
|
||||||
|
|
||||||
match multiple_modules("issue_2863_module_type_does_not_exist", modules) {
|
|
||||||
Err(report) => {
|
|
||||||
assert_eq!(
|
|
||||||
report,
|
|
||||||
indoc!(
|
|
||||||
"
|
|
||||||
── UNRECOGNIZED NAME ────────── tmp/issue_2863_module_type_does_not_exist/Main ─
|
|
||||||
|
|
||||||
Nothing is named `DoesNotExist` in this scope.
|
|
||||||
|
|
||||||
5│ main : DoesNotExist
|
|
||||||
^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Did you mean one of these?
|
|
||||||
|
|
||||||
Dict
|
|
||||||
Result
|
|
||||||
List
|
|
||||||
Box
|
|
||||||
"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Ok(_) => unreachable!("we expect failure here"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
//! Auto-derivers of builtin ability methods.
|
|
||||||
|
|
||||||
use roc_types::subs::{Content, Descriptor, Mark, OptVariable, Rank, Subs, Variable};
|
|
||||||
|
|
||||||
pub fn synth_var(subs: &mut Subs, content: Content) -> Variable {
|
|
||||||
let descriptor = Descriptor {
|
|
||||||
content,
|
|
||||||
// NOTE: this is incorrect, but that is irrelevant - derivers may only be called during
|
|
||||||
// monomorphization (or later), at which point we do not care about variable
|
|
||||||
// generalization. Hence ranks should not matter.
|
|
||||||
rank: Rank::toplevel(),
|
|
||||||
mark: Mark::NONE,
|
|
||||||
copy: OptVariable::NONE,
|
|
||||||
};
|
|
||||||
subs.fresh(descriptor)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod encoding;
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,17 +0,0 @@
|
||||||
procedure Test.2 (Test.6, #Attr.12):
|
|
||||||
let Test.1 : U8 = StructAtIndex 0 #Attr.12;
|
|
||||||
let Test.11 : {U8} = Struct {Test.1};
|
|
||||||
ret Test.11;
|
|
||||||
|
|
||||||
procedure Test.4 (Test.5, #Attr.12):
|
|
||||||
let Test.1 : U8 = StructAtIndex 0 #Attr.12;
|
|
||||||
ret Test.1;
|
|
||||||
|
|
||||||
procedure Test.0 ():
|
|
||||||
let Test.1 : U8 = 1i64;
|
|
||||||
let Test.8 : {} = Struct {};
|
|
||||||
let Test.10 : {} = Struct {};
|
|
||||||
let Test.14 : {U8} = Struct {Test.1};
|
|
||||||
let Test.9 : {U8} = CallByName Test.2 Test.10 Test.14;
|
|
||||||
let Test.7 : U8 = CallByName Test.4 Test.8 Test.9;
|
|
||||||
ret Test.7;
|
|
|
@ -1,30 +0,0 @@
|
||||||
procedure Test.4 (Test.30):
|
|
||||||
joinpoint Test.14 Test.5:
|
|
||||||
let Test.24 : Int1 = 1i64;
|
|
||||||
let Test.25 : Int1 = GetTagId Test.5;
|
|
||||||
let Test.26 : Int1 = lowlevel Eq Test.24 Test.25;
|
|
||||||
if Test.26 then
|
|
||||||
let Test.15 : Int1 = false;
|
|
||||||
ret Test.15;
|
|
||||||
else
|
|
||||||
let Test.20 : [C I64, C ] = UnionAtIndex (Id 0) (Index 0) Test.5;
|
|
||||||
let Test.21 : U8 = 1i64;
|
|
||||||
let Test.22 : U8 = GetTagId Test.20;
|
|
||||||
let Test.23 : Int1 = lowlevel Eq Test.21 Test.22;
|
|
||||||
if Test.23 then
|
|
||||||
let Test.16 : Int1 = true;
|
|
||||||
ret Test.16;
|
|
||||||
else
|
|
||||||
let Test.8 : [<rnu><null>, C [C I64, C ] *self] = UnionAtIndex (Id 0) (Index 1) Test.5;
|
|
||||||
jump Test.14 Test.8;
|
|
||||||
in
|
|
||||||
jump Test.14 Test.30;
|
|
||||||
|
|
||||||
procedure Test.0 ():
|
|
||||||
let Test.29 : I64 = 3i64;
|
|
||||||
let Test.27 : [C I64, C ] = Just Test.29;
|
|
||||||
let Test.28 : [<rnu><null>, C [C I64, C ] *self] = Nil ;
|
|
||||||
let Test.13 : [<rnu><null>, C [C I64, C ] *self] = Cons Test.27 Test.28;
|
|
||||||
let Test.12 : Int1 = CallByName Test.4 Test.13;
|
|
||||||
dec Test.13;
|
|
||||||
ret Test.12;
|
|
|
@ -1,40 +0,0 @@
|
||||||
procedure List.9 (#Attr.2):
|
|
||||||
let List.146 : U64 = 0i64;
|
|
||||||
let List.147 : U64 = lowlevel ListLen #Attr.2;
|
|
||||||
let List.142 : Int1 = lowlevel NotEq List.146 List.147;
|
|
||||||
if List.142 then
|
|
||||||
let List.145 : U64 = 0i64;
|
|
||||||
let List.144 : I64 = lowlevel ListGetUnsafe #Attr.2 List.145;
|
|
||||||
let List.143 : [C Int1, C I64] = Ok List.144;
|
|
||||||
ret List.143;
|
|
||||||
else
|
|
||||||
let List.141 : Int1 = true;
|
|
||||||
let List.140 : [C Int1, C I64] = Err List.141;
|
|
||||||
ret List.140;
|
|
||||||
|
|
||||||
procedure Str.27 (#Attr.2):
|
|
||||||
let #Attr.3 : {I64, U8} = lowlevel StrToNum #Attr.2;
|
|
||||||
let Str.70 : U8 = StructAtIndex 1 #Attr.3;
|
|
||||||
let Str.71 : U8 = 0i64;
|
|
||||||
let Str.67 : Int1 = lowlevel NumGt Str.70 Str.71;
|
|
||||||
if Str.67 then
|
|
||||||
let Str.69 : Int1 = false;
|
|
||||||
let Str.68 : [C Int1, C I64] = Err Str.69;
|
|
||||||
ret Str.68;
|
|
||||||
else
|
|
||||||
let Str.66 : I64 = StructAtIndex 0 #Attr.3;
|
|
||||||
let Str.65 : [C Int1, C I64] = Ok Str.66;
|
|
||||||
ret Str.65;
|
|
||||||
|
|
||||||
procedure Test.0 ():
|
|
||||||
let Test.4 : Int1 = true;
|
|
||||||
if Test.4 then
|
|
||||||
let Test.6 : List I64 = Array [];
|
|
||||||
let Test.5 : [C Int1, C I64] = CallByName List.9 Test.6;
|
|
||||||
dec Test.6;
|
|
||||||
ret Test.5;
|
|
||||||
else
|
|
||||||
let Test.3 : Str = "";
|
|
||||||
let Test.2 : [C Int1, C I64] = CallByName Str.27 Test.3;
|
|
||||||
dec Test.3;
|
|
||||||
ret Test.2;
|
|
|
@ -1,6 +0,0 @@
|
||||||
procedure Test.0 ():
|
|
||||||
let Test.19 : [C [<rnnu>C [C *self, C ]], C ] = SystemTool ;
|
|
||||||
let Test.17 : [<rnnu>C [C *self, C ]] = Job Test.19;
|
|
||||||
let Test.16 : [C [<rnnu>C [C *self, C ]], C ] = FromJob Test.17;
|
|
||||||
let Test.7 : [<rnnu>C [C *self, C ]] = Job Test.16;
|
|
||||||
ret Test.7;
|
|
|
@ -1,25 +0,0 @@
|
||||||
procedure Num.19 (#Attr.2, #Attr.3):
|
|
||||||
let Num.274 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
|
||||||
ret Num.274;
|
|
||||||
|
|
||||||
procedure Test.4 (Test.6):
|
|
||||||
let Test.16 : Int1 = 1i64;
|
|
||||||
let Test.17 : Int1 = GetTagId Test.6;
|
|
||||||
let Test.18 : Int1 = lowlevel Eq Test.16 Test.17;
|
|
||||||
if Test.18 then
|
|
||||||
let Test.12 : I64 = 0i64;
|
|
||||||
ret Test.12;
|
|
||||||
else
|
|
||||||
let Test.7 : [<rnu><null>, C I64 *self] = UnionAtIndex (Id 0) (Index 1) Test.6;
|
|
||||||
let Test.14 : I64 = 1i64;
|
|
||||||
let Test.15 : I64 = CallByName Test.4 Test.7;
|
|
||||||
let Test.13 : I64 = CallByName Num.19 Test.14 Test.15;
|
|
||||||
ret Test.13;
|
|
||||||
|
|
||||||
procedure Test.0 ():
|
|
||||||
let Test.3 : [<rnu><null>, C I64 *self] = Nil ;
|
|
||||||
let Test.9 : I64 = CallByName Test.4 Test.3;
|
|
||||||
let Test.10 : I64 = CallByName Test.4 Test.3;
|
|
||||||
dec Test.3;
|
|
||||||
let Test.8 : I64 = CallByName Num.19 Test.9 Test.10;
|
|
||||||
ret Test.8;
|
|
|
@ -1,45 +0,0 @@
|
||||||
procedure List.3 (List.64, List.65, List.66):
|
|
||||||
let List.143 : {List I64, I64} = CallByName List.57 List.64 List.65 List.66;
|
|
||||||
let List.142 : List I64 = StructAtIndex 0 List.143;
|
|
||||||
inc List.142;
|
|
||||||
dec List.143;
|
|
||||||
ret List.142;
|
|
||||||
|
|
||||||
procedure List.57 (#Attr.2, #Attr.3, #Attr.4):
|
|
||||||
let List.148 : U64 = lowlevel ListLen #Attr.2;
|
|
||||||
let List.146 : Int1 = lowlevel NumLt #Attr.3 List.148;
|
|
||||||
if List.146 then
|
|
||||||
let List.147 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4;
|
|
||||||
ret List.147;
|
|
||||||
else
|
|
||||||
let List.145 : {List I64, I64} = Struct {#Attr.2, #Attr.4};
|
|
||||||
ret List.145;
|
|
||||||
|
|
||||||
procedure List.6 (#Attr.2):
|
|
||||||
let List.141 : U64 = lowlevel ListLen #Attr.2;
|
|
||||||
ret List.141;
|
|
||||||
|
|
||||||
procedure Num.19 (#Attr.2, #Attr.3):
|
|
||||||
let Num.273 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
|
||||||
ret Num.273;
|
|
||||||
|
|
||||||
procedure Test.1 ():
|
|
||||||
let Test.8 : List I64 = Array [1i64, 2i64, 3i64];
|
|
||||||
ret Test.8;
|
|
||||||
|
|
||||||
procedure Test.2 (Test.3):
|
|
||||||
let Test.12 : U64 = 0i64;
|
|
||||||
let Test.13 : I64 = 0i64;
|
|
||||||
let Test.11 : List I64 = CallByName List.3 Test.3 Test.12 Test.13;
|
|
||||||
ret Test.11;
|
|
||||||
|
|
||||||
procedure Test.0 ():
|
|
||||||
let Test.10 : List I64 = CallByName Test.1;
|
|
||||||
let Test.9 : List I64 = CallByName Test.2 Test.10;
|
|
||||||
let Test.5 : U64 = CallByName List.6 Test.9;
|
|
||||||
dec Test.9;
|
|
||||||
let Test.7 : List I64 = CallByName Test.1;
|
|
||||||
let Test.6 : U64 = CallByName List.6 Test.7;
|
|
||||||
dec Test.7;
|
|
||||||
let Test.4 : U64 = CallByName Num.19 Test.5 Test.6;
|
|
||||||
ret Test.4;
|
|
|
@ -1,23 +0,0 @@
|
||||||
procedure List.2 (#Attr.2, #Attr.3):
|
|
||||||
let List.145 : U64 = lowlevel ListLen #Attr.2;
|
|
||||||
let List.142 : Int1 = lowlevel NumLt #Attr.3 List.145;
|
|
||||||
if List.142 then
|
|
||||||
let List.144 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
|
|
||||||
let List.143 : [C {}, C I64] = Ok List.144;
|
|
||||||
ret List.143;
|
|
||||||
else
|
|
||||||
let List.141 : {} = Struct {};
|
|
||||||
let List.140 : [C {}, C I64] = Err List.141;
|
|
||||||
ret List.140;
|
|
||||||
|
|
||||||
procedure Test.1 (Test.2):
|
|
||||||
let Test.6 : List I64 = Array [1i64, 2i64, 3i64];
|
|
||||||
let Test.7 : U64 = 0i64;
|
|
||||||
let Test.5 : [C {}, C I64] = CallByName List.2 Test.6 Test.7;
|
|
||||||
dec Test.6;
|
|
||||||
ret Test.5;
|
|
||||||
|
|
||||||
procedure Test.0 ():
|
|
||||||
let Test.4 : {} = Struct {};
|
|
||||||
let Test.3 : [C {}, C I64] = CallByName Test.1 Test.4;
|
|
||||||
ret Test.3;
|
|
|
@ -1,27 +0,0 @@
|
||||||
procedure List.3 (List.64, List.65, List.66):
|
|
||||||
let List.141 : {List I64, I64} = CallByName List.57 List.64 List.65 List.66;
|
|
||||||
let List.140 : List I64 = StructAtIndex 0 List.141;
|
|
||||||
inc List.140;
|
|
||||||
dec List.141;
|
|
||||||
ret List.140;
|
|
||||||
|
|
||||||
procedure List.57 (#Attr.2, #Attr.3, #Attr.4):
|
|
||||||
let List.146 : U64 = lowlevel ListLen #Attr.2;
|
|
||||||
let List.144 : Int1 = lowlevel NumLt #Attr.3 List.146;
|
|
||||||
if List.144 then
|
|
||||||
let List.145 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4;
|
|
||||||
ret List.145;
|
|
||||||
else
|
|
||||||
let List.143 : {List I64, I64} = Struct {#Attr.2, #Attr.4};
|
|
||||||
ret List.143;
|
|
||||||
|
|
||||||
procedure Test.2 (Test.3):
|
|
||||||
let Test.6 : U64 = 0i64;
|
|
||||||
let Test.7 : I64 = 0i64;
|
|
||||||
let Test.5 : List I64 = CallByName List.3 Test.3 Test.6 Test.7;
|
|
||||||
ret Test.5;
|
|
||||||
|
|
||||||
procedure Test.0 ():
|
|
||||||
let Test.1 : List I64 = Array [1i64, 2i64, 3i64];
|
|
||||||
let Test.4 : List I64 = CallByName Test.2 Test.1;
|
|
||||||
ret Test.4;
|
|
|
@ -1,22 +0,0 @@
|
||||||
procedure List.28 (#Attr.2, #Attr.3):
|
|
||||||
let List.143 : List I64 = lowlevel ListSortWith { xs: `#Attr.#arg1` } #Attr.2 Num.46 #Attr.3;
|
|
||||||
let Bool.14 : Int1 = lowlevel ListIsUnique #Attr.2;
|
|
||||||
if Bool.14 then
|
|
||||||
ret List.143;
|
|
||||||
else
|
|
||||||
decref #Attr.2;
|
|
||||||
ret List.143;
|
|
||||||
|
|
||||||
procedure List.54 (List.98):
|
|
||||||
let List.141 : {} = Struct {};
|
|
||||||
let List.140 : List I64 = CallByName List.28 List.98 List.141;
|
|
||||||
ret List.140;
|
|
||||||
|
|
||||||
procedure Num.46 (#Attr.2, #Attr.3):
|
|
||||||
let Num.273 : U8 = lowlevel NumCompare #Attr.2 #Attr.3;
|
|
||||||
ret Num.273;
|
|
||||||
|
|
||||||
procedure Test.0 ():
|
|
||||||
let Test.2 : List I64 = Array [4i64, 3i64, 2i64, 1i64];
|
|
||||||
let Test.1 : List I64 = CallByName List.54 Test.2;
|
|
||||||
ret Test.1;
|
|
|
@ -1,21 +0,0 @@
|
||||||
procedure Num.19 (#Attr.2, #Attr.3):
|
|
||||||
let Num.273 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
|
||||||
ret Num.273;
|
|
||||||
|
|
||||||
procedure Test.5 (Test.7, Test.8):
|
|
||||||
let Test.17 : U64 = 1i64;
|
|
||||||
ret Test.17;
|
|
||||||
|
|
||||||
procedure Test.6 (Test.7, Test.8):
|
|
||||||
let Test.14 : U64 = 1i64;
|
|
||||||
ret Test.14;
|
|
||||||
|
|
||||||
procedure Test.0 ():
|
|
||||||
let Test.15 : U8 = 100i64;
|
|
||||||
let Test.16 : U32 = 100i64;
|
|
||||||
let Test.10 : U64 = CallByName Test.5 Test.15 Test.16;
|
|
||||||
let Test.12 : U32 = 100i64;
|
|
||||||
let Test.13 : U8 = 100i64;
|
|
||||||
let Test.11 : U64 = CallByName Test.6 Test.12 Test.13;
|
|
||||||
let Test.9 : U64 = CallByName Num.19 Test.10 Test.11;
|
|
||||||
ret Test.9;
|
|
|
@ -1,6 +0,0 @@
|
||||||
procedure Test.0 ():
|
|
||||||
let Test.11 : [<rnu><null>, C *self] = Z ;
|
|
||||||
let Test.10 : [<rnu><null>, C *self] = S Test.11;
|
|
||||||
let Test.9 : [<rnu><null>, C *self] = S Test.10;
|
|
||||||
let Test.3 : [<rnu><null>, C *self] = S Test.9;
|
|
||||||
ret Test.3;
|
|
|
@ -1,53 +0,0 @@
|
||||||
procedure Num.19 (#Attr.2, #Attr.3):
|
|
||||||
let Num.274 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
|
||||||
ret Num.274;
|
|
||||||
|
|
||||||
procedure Num.21 (#Attr.2, #Attr.3):
|
|
||||||
let Num.273 : I64 = lowlevel NumMul #Attr.2 #Attr.3;
|
|
||||||
ret Num.273;
|
|
||||||
|
|
||||||
procedure Test.1 ():
|
|
||||||
let Test.26 : I64 = 1i64;
|
|
||||||
ret Test.26;
|
|
||||||
|
|
||||||
procedure Test.2 ():
|
|
||||||
let Test.22 : I64 = 2i64;
|
|
||||||
ret Test.22;
|
|
||||||
|
|
||||||
procedure Test.3 (Test.6):
|
|
||||||
let Test.25 : I64 = CallByName Test.1;
|
|
||||||
let Test.24 : I64 = CallByName Num.19 Test.6 Test.25;
|
|
||||||
ret Test.24;
|
|
||||||
|
|
||||||
procedure Test.4 (Test.7):
|
|
||||||
let Test.21 : I64 = CallByName Test.2;
|
|
||||||
let Test.20 : I64 = CallByName Num.21 Test.7 Test.21;
|
|
||||||
ret Test.20;
|
|
||||||
|
|
||||||
procedure Test.5 (Test.8, Test.9):
|
|
||||||
joinpoint Test.15 Test.14:
|
|
||||||
ret Test.14;
|
|
||||||
in
|
|
||||||
switch Test.8:
|
|
||||||
case 0:
|
|
||||||
let Test.16 : I64 = CallByName Test.3 Test.9;
|
|
||||||
jump Test.15 Test.16;
|
|
||||||
|
|
||||||
default:
|
|
||||||
let Test.17 : I64 = CallByName Test.4 Test.9;
|
|
||||||
jump Test.15 Test.17;
|
|
||||||
|
|
||||||
|
|
||||||
procedure Test.0 ():
|
|
||||||
joinpoint Test.19 Test.12:
|
|
||||||
let Test.13 : I64 = 42i64;
|
|
||||||
let Test.11 : I64 = CallByName Test.5 Test.12 Test.13;
|
|
||||||
ret Test.11;
|
|
||||||
in
|
|
||||||
let Test.23 : Int1 = true;
|
|
||||||
if Test.23 then
|
|
||||||
let Test.3 : Int1 = false;
|
|
||||||
jump Test.19 Test.3;
|
|
||||||
else
|
|
||||||
let Test.4 : Int1 = true;
|
|
||||||
jump Test.19 Test.4;
|
|
|
@ -23,7 +23,7 @@ roc_reporting = { path = "../reporting" }
|
||||||
arrayvec = "0.7.2"
|
arrayvec = "0.7.2"
|
||||||
bumpalo = { version = "3.8.0", features = ["collections"] }
|
bumpalo = { version = "3.8.0", features = ["collections"] }
|
||||||
page_size = "0.4.2"
|
page_size = "0.4.2"
|
||||||
snafu = { version = "0.6.10", features = ["backtraces"] }
|
snafu = { version = "0.7.1", features = ["backtraces"] }
|
||||||
ven_graph = { path = "../vendor/pathfinding" }
|
ven_graph = { path = "../vendor/pathfinding" }
|
||||||
libc = "0.2.106"
|
libc = "0.2.106"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
ast_error::{ASTNodeIdWithoutExprId, ASTResult},
|
ast_error::{ASTNodeIdWithoutExprIdSnafu, ASTResult},
|
||||||
mem_pool::pool::Pool,
|
mem_pool::pool::Pool,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -43,14 +43,14 @@ impl ASTNodeId {
|
||||||
pub fn to_expr_id(&self) -> ASTResult<ExprId> {
|
pub fn to_expr_id(&self) -> ASTResult<ExprId> {
|
||||||
match self {
|
match self {
|
||||||
ASTNodeId::AExprId(expr_id) => Ok(*expr_id),
|
ASTNodeId::AExprId(expr_id) => Ok(*expr_id),
|
||||||
_ => ASTNodeIdWithoutExprId { ast_node_id: *self }.fail()?,
|
_ => ASTNodeIdWithoutExprIdSnafu { ast_node_id: *self }.fail()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_def_id(&self) -> ASTResult<DefId> {
|
pub fn to_def_id(&self) -> ASTResult<DefId> {
|
||||||
match self {
|
match self {
|
||||||
ASTNodeId::ADefId(def_id) => Ok(*def_id),
|
ASTNodeId::ADefId(def_id) => Ok(*def_id),
|
||||||
_ => ASTNodeIdWithoutExprId { ast_node_id: *self }.fail()?,
|
_ => ASTNodeIdWithoutExprIdSnafu { ast_node_id: *self }.fail()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -16,7 +16,7 @@ use roc_problem::can::{MalformedPatternProblem, Problem, RuntimeError, ShadowKin
|
||||||
use roc_region::all::Region;
|
use roc_region::all::Region;
|
||||||
use roc_types::subs::Variable;
|
use roc_types::subs::Variable;
|
||||||
|
|
||||||
use crate::ast_error::{ASTResult, UnexpectedPattern2Variant};
|
use crate::ast_error::{ASTResult, UnexpectedPattern2VariantSnafu};
|
||||||
use crate::constrain::Constraint;
|
use crate::constrain::Constraint;
|
||||||
use crate::lang::core::expr::expr_to_expr2::to_expr_id;
|
use crate::lang::core::expr::expr_to_expr2::to_expr_id;
|
||||||
use crate::lang::env::Env;
|
use crate::lang::env::Env;
|
||||||
|
@ -517,7 +517,7 @@ pub fn symbols_from_pattern(pool: &Pool, initial: &Pattern2) -> Vec<Symbol> {
|
||||||
pub fn get_identifier_string(pattern: &Pattern2, interns: &Interns) -> ASTResult<String> {
|
pub fn get_identifier_string(pattern: &Pattern2, interns: &Interns) -> ASTResult<String> {
|
||||||
match pattern {
|
match pattern {
|
||||||
Pattern2::Identifier(symbol) => Ok(symbol.as_str(interns).to_string()),
|
Pattern2::Identifier(symbol) => Ok(symbol.as_str(interns).to_string()),
|
||||||
other => UnexpectedPattern2Variant {
|
other => UnexpectedPattern2VariantSnafu {
|
||||||
required_pattern2: "Identifier".to_string(),
|
required_pattern2: "Identifier".to_string(),
|
||||||
encountered_pattern2: format!("{:?}", other),
|
encountered_pattern2: format!("{:?}", other),
|
||||||
}
|
}
|
|
@ -3,7 +3,7 @@ use roc_module::{called_via::CalledVia, symbol::Symbol};
|
||||||
use roc_parse::ast::StrLiteral;
|
use roc_parse::ast::StrLiteral;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast_error::{ASTResult, UnexpectedASTNode},
|
ast_error::{ASTResult, UnexpectedASTNodeSnafu},
|
||||||
lang::{
|
lang::{
|
||||||
core::expr::{
|
core::expr::{
|
||||||
expr2::{ArrString, ARR_STRING_CAPACITY},
|
expr2::{ArrString, ARR_STRING_CAPACITY},
|
||||||
|
@ -225,7 +225,7 @@ pub fn update_str_expr(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr2::Str(old_pool_str) => Either::OldPoolStr(*old_pool_str),
|
Expr2::Str(old_pool_str) => Either::OldPoolStr(*old_pool_str),
|
||||||
other => UnexpectedASTNode {
|
other => UnexpectedASTNodeSnafu {
|
||||||
required_node_type: "SmallStr or Str",
|
required_node_type: "SmallStr or Str",
|
||||||
encountered_node_type: format!("{:?}", other),
|
encountered_node_type: format!("{:?}", other),
|
||||||
}
|
}
|
|
@ -3,7 +3,7 @@ use indexmap::IndexMap;
|
||||||
use roc_mono::layout::UnionLayout;
|
use roc_mono::layout::UnionLayout;
|
||||||
use roc_target::{Architecture, TargetInfo};
|
use roc_target::{Architecture, TargetInfo};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::fmt::Display;
|
use std::fmt::{Display, Write};
|
||||||
|
|
||||||
pub static TEMPLATE: &[u8] = include_bytes!("../templates/template.rs");
|
pub static TEMPLATE: &[u8] = include_bytes!("../templates/template.rs");
|
||||||
pub static HEADER: &[u8] = include_bytes!("../templates/header.rs");
|
pub static HEADER: &[u8] = include_bytes!("../templates/header.rs");
|
||||||
|
@ -95,24 +95,32 @@ pub fn emit(types_and_targets: &[(Types, TargetInfo)]) -> String {
|
||||||
1 => {
|
1 => {
|
||||||
let arch = arch_to_str(targets.get(0).unwrap().architecture);
|
let arch = arch_to_str(targets.get(0).unwrap().architecture);
|
||||||
|
|
||||||
buf.push_str(&format!("#[cfg(target_arch = \"{arch}\")]"));
|
write!(buf, "#[cfg(target_arch = \"{arch}\")]").unwrap();
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// We should never have a decl recorded with 0 targets!
|
// We should never have a decl recorded with 0 targets!
|
||||||
debug_assert_ne!(targets.len(), 0);
|
debug_assert_ne!(targets.len(), 0);
|
||||||
|
|
||||||
let alternatives = targets
|
let mut it = targets.iter().peekable();
|
||||||
.iter()
|
|
||||||
.map(|target_info| {
|
|
||||||
format!(
|
|
||||||
"{indent}{INDENT}target_arch = \"{}\"",
|
|
||||||
arch_to_str(target_info.architecture)
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(",\n");
|
|
||||||
|
|
||||||
buf.push_str(&format!("#[cfg(any(\n{alternatives}\n{indent}))]"));
|
writeln!(buf, "#[cfg(any(").unwrap();
|
||||||
|
|
||||||
|
while let Some(target_info) = it.next() {
|
||||||
|
write!(
|
||||||
|
buf,
|
||||||
|
"{indent}{INDENT}target_arch = \"{}\"",
|
||||||
|
arch_to_str(target_info.architecture)
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
if it.peek().is_some() {
|
||||||
|
buf.push_str(",\n");
|
||||||
|
} else {
|
||||||
|
buf.push('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write!(buf, "{indent}))]").unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,16 +373,18 @@ pub struct {name} {{
|
||||||
if let Some(payload_id) = opt_payload_id {
|
if let Some(payload_id) = opt_payload_id {
|
||||||
let payload_type = types.get_type(*payload_id);
|
let payload_type = types.get_type(*payload_id);
|
||||||
|
|
||||||
buf.push_str(&format!("{INDENT}{tag_name}: "));
|
write!(buf, "{INDENT}{tag_name}: ").unwrap();
|
||||||
|
|
||||||
if payload_type.has_pointer(types) {
|
if payload_type.has_pointer(types) {
|
||||||
// types with pointers need ManuallyDrop
|
// types with pointers need ManuallyDrop
|
||||||
// because rust unions don't (and can't)
|
// because rust unions don't (and can't)
|
||||||
// know how to drop them automatically!
|
// know how to drop them automatically!
|
||||||
buf.push_str(&format!(
|
writeln!(
|
||||||
"core::mem::ManuallyDrop<{}>,\n",
|
buf,
|
||||||
|
"core::mem::ManuallyDrop<{}>,",
|
||||||
type_name(*payload_id, types)
|
type_name(*payload_id, types)
|
||||||
));
|
)
|
||||||
|
.unwrap();
|
||||||
} else {
|
} else {
|
||||||
buf.push_str(&type_name(*payload_id, types));
|
buf.push_str(&type_name(*payload_id, types));
|
||||||
buf.push_str(",\n");
|
buf.push_str(",\n");
|
||||||
|
@ -392,9 +402,7 @@ pub struct {name} {{
|
||||||
// (Do this even if theoretically shouldn't be necessary, since
|
// (Do this even if theoretically shouldn't be necessary, since
|
||||||
// there's no runtime cost and it more explicitly syncs the
|
// there's no runtime cost and it more explicitly syncs the
|
||||||
// union's size with what we think it should be.)
|
// union's size with what we think it should be.)
|
||||||
buf.push_str(&format!(
|
writeln!(buf, "{INDENT}_sizer: [u8; {size_rounded_to_alignment}],").unwrap();
|
||||||
"{INDENT}_sizer: [u8; {size_rounded_to_alignment}],\n"
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.push('}');
|
buf.push('}');
|
||||||
|
@ -1154,9 +1162,7 @@ fn write_impl_tags<
|
||||||
|
|
||||||
write_indents(indentations + 1, buf);
|
write_indents(indentations + 1, buf);
|
||||||
|
|
||||||
buf.push_str(&format!(
|
writeln!(buf, "{discriminant_name}::{tag_name} => {branch_str}").unwrap();
|
||||||
"{discriminant_name}::{tag_name} => {branch_str}\n"
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
write_indents(indentations, buf);
|
write_indents(indentations, buf);
|
||||||
|
@ -1192,18 +1198,18 @@ fn add_enumeration<I: ExactSizeIterator<Item = S>, S: AsRef<str> + Display>(
|
||||||
);
|
);
|
||||||
|
|
||||||
for (index, tag_name) in tags.enumerate() {
|
for (index, tag_name) in tags.enumerate() {
|
||||||
buf.push_str(&format!("{INDENT}{tag_name} = {index},\n"));
|
writeln!(buf, "{INDENT}{tag_name} = {index},").unwrap();
|
||||||
|
|
||||||
write_indents(3, &mut debug_buf);
|
write_indents(3, &mut debug_buf);
|
||||||
|
|
||||||
debug_buf.push_str(&format!(
|
writeln!(
|
||||||
"Self::{tag_name} => f.write_str(\"{name}::{tag_name}\"),\n"
|
debug_buf,
|
||||||
));
|
"Self::{tag_name} => f.write_str(\"{name}::{tag_name}\"),"
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.push_str(&format!(
|
write!(buf, "}}\n\n{debug_buf}{INDENT}{INDENT}}}\n{INDENT}}}\n}}").unwrap();
|
||||||
"}}\n\n{debug_buf}{INDENT}{INDENT}}}\n{INDENT}}}\n}}"
|
|
||||||
));
|
|
||||||
|
|
||||||
add_decl(impls, None, target_info, buf);
|
add_decl(impls, None, target_info, buf);
|
||||||
}
|
}
|
||||||
|
@ -1237,7 +1243,7 @@ fn add_struct<S: Display>(
|
||||||
format!("{label}")
|
format!("{label}")
|
||||||
};
|
};
|
||||||
|
|
||||||
buf.push_str(&format!("{INDENT}pub {label}: {type_str},\n",));
|
writeln!(buf, "{INDENT}pub {label}: {type_str},",).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.push('}');
|
buf.push('}');
|
|
@ -1,9 +1,5 @@
|
||||||
use crate::types::{Env, Types};
|
use crate::types::{Env, Types};
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use roc_can::{
|
|
||||||
def::{Declaration, Def},
|
|
||||||
pattern::Pattern,
|
|
||||||
};
|
|
||||||
use roc_load::{LoadedModule, Threading};
|
use roc_load::{LoadedModule, Threading};
|
||||||
use roc_reporting::report::RenderTarget;
|
use roc_reporting::report::RenderTarget;
|
||||||
use roc_target::{Architecture, TargetInfo};
|
use roc_target::{Architecture, TargetInfo};
|
||||||
|
@ -27,7 +23,7 @@ pub fn load_types(
|
||||||
mut type_problems,
|
mut type_problems,
|
||||||
mut declarations_by_id,
|
mut declarations_by_id,
|
||||||
mut solved,
|
mut solved,
|
||||||
interns,
|
mut interns,
|
||||||
..
|
..
|
||||||
} = roc_load::load_and_typecheck(
|
} = roc_load::load_and_typecheck(
|
||||||
arena,
|
arena,
|
||||||
|
@ -54,50 +50,33 @@ pub fn load_types(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let defs_iter = decls.iter().flat_map(|decl| match decl {
|
let variables = (0..decls.len()).filter_map(|index| {
|
||||||
Declaration::Declare(def) => {
|
use roc_can::expr::DeclarationTag::*;
|
||||||
vec![def.clone()]
|
|
||||||
}
|
|
||||||
Declaration::DeclareRec(defs, cycle_mark) => {
|
|
||||||
if cycle_mark.is_illegal(subs) {
|
|
||||||
Vec::new()
|
|
||||||
} else {
|
|
||||||
defs.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Declaration::Builtin(..) => {
|
|
||||||
unreachable!("Builtin decl in userspace module?")
|
|
||||||
}
|
|
||||||
Declaration::InvalidCycle(..) => Vec::new(),
|
|
||||||
Declaration::Expects(..) => Vec::new(),
|
|
||||||
});
|
|
||||||
|
|
||||||
let vars_iter = defs_iter.filter_map(
|
match decls.declarations[index] {
|
||||||
|Def {
|
Value | Function(_) | Recursive(_) | TailRecursive(_) => Some(decls.variables[index]),
|
||||||
loc_pattern,
|
Destructure(_) => {
|
||||||
pattern_vars,
|
// figure out if we need to export non-identifier defs - when would that
|
||||||
..
|
// happen?
|
||||||
}| {
|
|
||||||
if let Pattern::Identifier(sym) = loc_pattern.value {
|
|
||||||
let var = pattern_vars
|
|
||||||
.get(&sym)
|
|
||||||
.expect("Indetifier known but it has no var?");
|
|
||||||
|
|
||||||
Some(*var)
|
|
||||||
} else {
|
|
||||||
// figure out if we need to export non-identifier defs - when
|
|
||||||
// would that happen?
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
},
|
MutualRecursion { .. } => {
|
||||||
);
|
// handled by future iterations
|
||||||
|
None
|
||||||
|
}
|
||||||
|
Expectation => {
|
||||||
|
// not publicly visible
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let types_and_targets = Architecture::iter()
|
let types_and_targets = Architecture::iter()
|
||||||
.map(|arch| {
|
.map(|arch| {
|
||||||
let target_info = arch.into();
|
let target_info = arch.into();
|
||||||
let mut env = Env::new(arena, subs, &interns, target_info);
|
let mut env = Env::new(arena, subs, &mut interns, target_info);
|
||||||
|
|
||||||
(env.vars_to_types(vars_iter.clone()), target_info)
|
(env.vars_to_types(variables.clone()), target_info)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
|
@ -419,7 +419,12 @@ pub struct Env<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Env<'a> {
|
impl<'a> Env<'a> {
|
||||||
pub fn new(arena: &'a Bump, subs: &'a Subs, interns: &'a Interns, target: TargetInfo) -> Self {
|
pub fn new(
|
||||||
|
arena: &'a Bump,
|
||||||
|
subs: &'a Subs,
|
||||||
|
interns: &'a mut Interns,
|
||||||
|
target: TargetInfo,
|
||||||
|
) -> Self {
|
||||||
Env {
|
Env {
|
||||||
arena,
|
arena,
|
||||||
subs,
|
subs,
|
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