mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 03:42:17 +00:00
Merge remote-tracking branch 'remote/main' into list-splitting
This commit is contained in:
commit
69c2fef943
244 changed files with 3601 additions and 5671 deletions
3
.gitattributes
vendored
3
.gitattributes
vendored
|
@ -1,4 +1,5 @@
|
||||||
# Require roc files to be checked out with Unix line endings, even on windows
|
# Require roc files to be checked out with Unix line endings, even on windows
|
||||||
*.roc text eol=lf
|
*.roc text eol=lf
|
||||||
|
* text=auto eol=lf
|
||||||
|
|
||||||
crates/compiler/test_mono/generated/* linguist-generated=true
|
crates/compiler/test_mono/generated/* linguist-generated=true
|
|
@ -2,7 +2,7 @@ on:
|
||||||
#pull_request:
|
#pull_request:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 9 * * *'
|
- cron: "0 9 * * *"
|
||||||
|
|
||||||
name: Nightly Release macOS Apple Silicon
|
name: Nightly Release macOS Apple Silicon
|
||||||
|
|
||||||
|
@ -30,15 +30,15 @@ jobs:
|
||||||
run: cargo test --locked --release
|
run: cargo test --locked --release
|
||||||
|
|
||||||
- name: get commit SHA
|
- name: get commit SHA
|
||||||
run: echo "SHA=$(git rev-parse --short "$GITHUB_SHA")" >> $GITHUB_ENV
|
run: echo "SHA=$(git rev-parse --short "$GITHUB_SHA")" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: get date
|
- name: get date
|
||||||
run: echo "DATE=$(date "+%Y-%m-%d")" >> $GITHUB_ENV
|
run: echo "DATE=$(date "+%Y-%m-%d")" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: build file name
|
- name: build file name
|
||||||
env:
|
env:
|
||||||
DATE: ${{ env.DATE }}
|
DATE: ${{ env.DATE }}
|
||||||
SHA: ${{ env.SHA }}
|
SHA: ${{ env.SHA }}
|
||||||
run: echo "RELEASE_FOLDER_NAME=roc_nightly-macos_apple_silicon-$DATE-$SHA" >> $GITHUB_ENV
|
run: echo "RELEASE_FOLDER_NAME=roc_nightly-macos_apple_silicon-$DATE-$SHA" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: write version to file
|
- name: write version to file
|
||||||
|
@ -56,8 +56,9 @@ jobs:
|
||||||
- name: extract tar for a quick test
|
- name: extract tar for a quick test
|
||||||
run: ls | grep tar | xargs tar -xf
|
run: ls | grep tar | xargs tar -xf
|
||||||
|
|
||||||
- name: test with rust platform
|
- name: test with zig platform
|
||||||
run: cd ${{ env.RELEASE_FOLDER_NAME }} && ./roc examples/platform-switching/rocLovesRust.roc
|
run: |
|
||||||
|
cd ${{ env.RELEASE_FOLDER_NAME }} && ./roc --build-host --suppress-build-host-warning crates/cli/tests/test-projects/test-platform-simple-zig/app.roc
|
||||||
|
|
||||||
- name: print short commit SHA
|
- name: print short commit SHA
|
||||||
run: git rev-parse --short "$GITHUB_SHA"
|
run: git rev-parse --short "$GITHUB_SHA"
|
||||||
|
@ -66,6 +67,6 @@ jobs:
|
||||||
- name: Upload artifact Actually uploading to github releases has to be done manually
|
- name: Upload artifact Actually uploading to github releases has to be done manually
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ env.RELEASE_FOLDER_NAME }}.tar.gz
|
name: ${{ env.RELEASE_FOLDER_NAME }}.tar.gz
|
||||||
path: ${{ env.RELEASE_FOLDER_NAME }}.tar.gz
|
path: ${{ env.RELEASE_FOLDER_NAME }}.tar.gz
|
||||||
retention-days: 4
|
retention-days: 4
|
||||||
|
|
2
.github/workflows/nix_linux_x86_64.yml
vendored
2
.github/workflows/nix_linux_x86_64.yml
vendored
|
@ -23,7 +23,7 @@ jobs:
|
||||||
- name: roc test all builtins
|
- name: roc test all builtins
|
||||||
run: nix develop -c ./ci/roc_test_builtins.sh
|
run: nix develop -c ./ci/roc_test_builtins.sh
|
||||||
|
|
||||||
- name: test wasm32 cli_run
|
- name: test wasm32 cli_tests
|
||||||
run: nix develop -c cargo test --locked --release --features="wasm32-cli-run"
|
run: nix develop -c cargo test --locked --release --features="wasm32-cli-run"
|
||||||
|
|
||||||
- name: test the dev backend # these tests require an explicit feature flag
|
- name: test the dev backend # these tests require an explicit feature flag
|
||||||
|
|
|
@ -34,17 +34,11 @@ jobs:
|
||||||
|
|
||||||
# for skipped tests: see issue 6274
|
# for skipped tests: see issue 6274
|
||||||
- name: execute tests with --release
|
- name: execute tests with --release
|
||||||
run: nix develop -c cargo test --locked --release -- --skip cli_run::inspect_gui --skip cli_run::hello_gui
|
run: nix develop -c cargo test --locked --release -- --skip cli_tests::inspect_gui --skip cli_tests::hello_gui
|
||||||
|
|
||||||
- name: roc test all builtins
|
- name: roc test all builtins
|
||||||
run: nix develop -c ./ci/roc_test_builtins.sh
|
run: nix develop -c ./ci/roc_test_builtins.sh
|
||||||
|
|
||||||
- name: make a libapp.so for the next step
|
|
||||||
run: nix develop -c cargo run -- gen-stub-lib examples/platform-switching/rocLovesRust.roc
|
|
||||||
|
|
||||||
- name: check that the platform`s produced dylib is loadable
|
|
||||||
run: cd examples/platform-switching/rust-platform && nix develop -c cargo test --release --locked
|
|
||||||
|
|
||||||
- name: test aarch64 dev backend
|
- name: test aarch64 dev backend
|
||||||
run: nix develop -c cargo nextest-gen-dev --locked --release --no-fail-fast
|
run: nix develop -c cargo nextest-gen-dev --locked --release --no-fail-fast
|
||||||
|
|
||||||
|
|
8
.github/workflows/nix_macos_x86_64.yml
vendored
8
.github/workflows/nix_macos_x86_64.yml
vendored
|
@ -16,15 +16,9 @@ jobs:
|
||||||
|
|
||||||
- uses: cachix/install-nix-action@v22
|
- uses: cachix/install-nix-action@v22
|
||||||
|
|
||||||
- name: execute cli_run tests only, the full tests take too long but are run nightly
|
- name: execute cli_tests tests only, the full tests take too long but are run nightly
|
||||||
run: nix develop -c cargo test --locked --release -p roc_cli -- --skip hello_gui
|
run: nix develop -c cargo test --locked --release -p roc_cli -- --skip hello_gui
|
||||||
# see 5932 for hello_gui
|
# see 5932 for hello_gui
|
||||||
|
|
||||||
- name: roc test all builtins
|
- name: roc test all builtins
|
||||||
run: nix develop -c ./ci/roc_test_builtins.sh
|
run: nix develop -c ./ci/roc_test_builtins.sh
|
||||||
|
|
||||||
- name: make a libapp.so for the next step
|
|
||||||
run: nix develop -c cargo run -- gen-stub-lib examples/platform-switching/rocLovesRust.roc
|
|
||||||
|
|
||||||
- name: check that the platform`s produced dylib is loadable
|
|
||||||
run: cd examples/platform-switching/rust-platform && nix develop -c cargo test --release --locked
|
|
||||||
|
|
|
@ -29,9 +29,6 @@ jobs:
|
||||||
- name: test roc hello world
|
- name: test roc hello world
|
||||||
run: cd roc_nightly && ./roc examples/helloWorld.roc
|
run: cd roc_nightly && ./roc examples/helloWorld.roc
|
||||||
|
|
||||||
- name: test platform switching rust
|
|
||||||
run: cd roc_nightly && ./roc examples/platform-switching/rocLovesRust.roc
|
|
||||||
|
|
||||||
- name: test platform switching zig
|
- name: test platform switching zig
|
||||||
run: cd roc_nightly && ./roc examples/platform-switching/rocLovesZig.roc
|
run: cd roc_nightly && ./roc examples/platform-switching/rocLovesZig.roc
|
||||||
|
|
||||||
|
|
7
.github/workflows/ubuntu_x86_64.yml
vendored
7
.github/workflows/ubuntu_x86_64.yml
vendored
|
@ -37,13 +37,10 @@ jobs:
|
||||||
|
|
||||||
- name: regular rust tests
|
- name: regular rust tests
|
||||||
# see #5904 for skipped test
|
# see #5904 for skipped test
|
||||||
run: cargo test --locked --release -- --skip cli_run::expects_dev_and_test
|
run: cargo test --locked --release -- --skip cli_tests::expects_dev_and_test
|
||||||
|
|
||||||
- name: tests examples in docs
|
- name: tests examples in docs
|
||||||
run: cargo test --doc --release
|
run: cargo test --doc --release
|
||||||
|
|
||||||
- name: check that the platform`s produced dylib is loadable
|
|
||||||
run: cd examples/platform-switching/rust-platform && LD_LIBRARY_PATH=. cargo test --release --locked
|
|
||||||
|
|
||||||
- name: test the dev backend # these tests require an explicit feature flag
|
- name: test the dev backend # these tests require an explicit feature flag
|
||||||
run: cargo test --locked --release --package test_gen --no-default-features --features gen-dev
|
run: cargo test --locked --release --package test_gen --no-default-features --features gen-dev
|
||||||
|
|
33
Cargo.lock
generated
33
Cargo.lock
generated
|
@ -463,20 +463,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961"
|
checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cli_utils"
|
name = "cli_test_utils"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
|
"const_format",
|
||||||
"criterion",
|
"criterion",
|
||||||
|
"lazy_static",
|
||||||
"regex",
|
"regex",
|
||||||
"rlimit",
|
"rlimit",
|
||||||
|
"roc_cli",
|
||||||
"roc_collections",
|
"roc_collections",
|
||||||
"roc_command_utils",
|
"roc_command_utils",
|
||||||
"roc_load",
|
"roc_load",
|
||||||
"roc_module",
|
"roc_module",
|
||||||
"roc_reporting",
|
"roc_reporting",
|
||||||
"serde",
|
"serde",
|
||||||
"serde-xml-rs",
|
|
||||||
"tempfile",
|
"tempfile",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2383,13 +2385,14 @@ dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap 4.4.6",
|
"clap 4.4.6",
|
||||||
"cli_utils",
|
"cli_test_utils",
|
||||||
"const_format",
|
"const_format",
|
||||||
"criterion",
|
"criterion",
|
||||||
"distance",
|
"distance",
|
||||||
"errno",
|
"errno",
|
||||||
"indoc",
|
"indoc",
|
||||||
"inkwell",
|
"inkwell",
|
||||||
|
"insta",
|
||||||
"libc",
|
"libc",
|
||||||
"libloading",
|
"libloading",
|
||||||
"mimalloc",
|
"mimalloc",
|
||||||
|
@ -2418,10 +2421,8 @@ dependencies = [
|
||||||
"roc_repl_expect",
|
"roc_repl_expect",
|
||||||
"roc_reporting",
|
"roc_reporting",
|
||||||
"roc_target",
|
"roc_target",
|
||||||
"roc_test_utils",
|
|
||||||
"roc_tracing",
|
"roc_tracing",
|
||||||
"roc_wasm_interp",
|
"roc_wasm_interp",
|
||||||
"serial_test",
|
|
||||||
"signal-hook",
|
"signal-hook",
|
||||||
"strum",
|
"strum",
|
||||||
"target-lexicon",
|
"target-lexicon",
|
||||||
|
@ -2626,7 +2627,7 @@ name = "roc_glue"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"cli_utils",
|
"cli_test_utils",
|
||||||
"dircpy",
|
"dircpy",
|
||||||
"fnv",
|
"fnv",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
|
@ -3445,18 +3446,6 @@ dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde-xml-rs"
|
|
||||||
version = "0.6.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fb3aa78ecda1ebc9ec9847d5d3aba7d618823446a049ba2491940506da6e2782"
|
|
||||||
dependencies = [
|
|
||||||
"log",
|
|
||||||
"serde",
|
|
||||||
"thiserror",
|
|
||||||
"xml-rs",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_cbor"
|
name = "serde_cbor"
|
||||||
version = "0.11.2"
|
version = "0.11.2"
|
||||||
|
@ -4362,7 +4351,7 @@ name = "valgrind"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"cli_utils",
|
"cli_test_utils",
|
||||||
"indoc",
|
"indoc",
|
||||||
"roc_build",
|
"roc_build",
|
||||||
"roc_command_utils",
|
"roc_command_utils",
|
||||||
|
@ -4828,12 +4817,6 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "xml-rs"
|
|
||||||
version = "0.8.19"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yaml-rust"
|
name = "yaml-rust"
|
||||||
version = "0.4.5"
|
version = "0.4.5"
|
||||||
|
|
|
@ -5,7 +5,7 @@ members = [
|
||||||
"crates/fs",
|
"crates/fs",
|
||||||
"crates/glue",
|
"crates/glue",
|
||||||
"crates/cli",
|
"crates/cli",
|
||||||
"crates/cli_utils",
|
"crates/cli_test_utils",
|
||||||
"crates/highlight",
|
"crates/highlight",
|
||||||
"crates/error_macros",
|
"crates/error_macros",
|
||||||
"crates/reporting",
|
"crates/reporting",
|
||||||
|
@ -19,7 +19,7 @@ members = [
|
||||||
"crates/roc_std",
|
"crates/roc_std",
|
||||||
"crates/test_utils",
|
"crates/test_utils",
|
||||||
"crates/test_utils_dir",
|
"crates/test_utils_dir",
|
||||||
"crates/valgrind",
|
"crates/valgrind_tests",
|
||||||
"crates/tracing",
|
"crates/tracing",
|
||||||
"crates/utils/*",
|
"crates/utils/*",
|
||||||
"crates/soa",
|
"crates/soa",
|
||||||
|
@ -173,7 +173,6 @@ schemars = "0.8.12"
|
||||||
serde = { version = "1.0.153", features = [
|
serde = { version = "1.0.153", features = [
|
||||||
"derive",
|
"derive",
|
||||||
] } # update roc_std/Cargo.toml on change
|
] } # update roc_std/Cargo.toml on change
|
||||||
serde-xml-rs = "0.6.0"
|
|
||||||
serde_json = "1.0.94" # update roc_std/Cargo.toml on change
|
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"
|
||||||
|
|
|
@ -5,14 +5,14 @@ set -euxo pipefail
|
||||||
|
|
||||||
# if to prevent unset vars errror
|
# if to prevent unset vars errror
|
||||||
if [ -n "$(ls | grep -v "roc_nightly.*tar\.gz" | grep -v "^ci$")" ]; then
|
if [ -n "$(ls | grep -v "roc_nightly.*tar\.gz" | grep -v "^ci$")" ]; then
|
||||||
|
|
||||||
# Remove everything in this dir except the tar and ci folder.
|
# Remove everything in this dir except the tar and ci folder.
|
||||||
# We want to test like a user who would have downloaded the release, so we clean up all files from the repo checkout.
|
# We want to test like a user who would have downloaded the release, so we clean up all files from the repo checkout.
|
||||||
to_delete=$(ls | grep -v "roc_nightly.*tar\.gz" | grep -v "^ci$")
|
to_delete=$(ls | grep -v "roc_nightly.*tar\.gz" | grep -v "^ci$")
|
||||||
|
|
||||||
for file_or_dir in $to_delete
|
for file_or_dir in $to_delete
|
||||||
do
|
do
|
||||||
echo "Removing: $file_or_dir"
|
echo "Removing: $file_or_dir"
|
||||||
rm -rf "$file_or_dir"
|
rm -rf "$file_or_dir"
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
@ -31,7 +31,8 @@ cd roc_nightly
|
||||||
# test roc hello world
|
# test roc hello world
|
||||||
./roc examples/helloWorld.roc
|
./roc examples/helloWorld.roc
|
||||||
|
|
||||||
# test rust platform
|
# test rust platform (first prebuild the host)
|
||||||
|
examples/platform-switching/rust-platform/build.sh
|
||||||
./roc examples/platform-switching/rocLovesRust.roc
|
./roc examples/platform-switching/rocLovesRust.roc
|
||||||
|
|
||||||
# test zig platform
|
# test zig platform
|
||||||
|
|
|
@ -12,9 +12,9 @@ cargo doc --package roc_ast --open
|
||||||
|
|
||||||
The `roc` binary that brings together all functionality in the Roc toolset.
|
The `roc` binary that brings together all functionality in the Roc toolset.
|
||||||
|
|
||||||
## `cli_utils/` - `cli_utils`
|
## `cli_test_utils/` - `cli_test_utils`
|
||||||
|
|
||||||
Provides shared code for cli tests and benchmarks.
|
Provides shared code for cli tests, cli benchmarks, glue tests, valgrind crate.
|
||||||
|
|
||||||
## `compiler/`
|
## `compiler/`
|
||||||
|
|
||||||
|
|
|
@ -32,11 +32,11 @@ target-x86 = ["roc_build/target-x86", "roc_repl_cli/target-x86"]
|
||||||
target-x86_64 = ["roc_build/target-x86_64", "roc_repl_cli/target-x86_64"]
|
target-x86_64 = ["roc_build/target-x86_64", "roc_repl_cli/target-x86_64"]
|
||||||
|
|
||||||
target-all = [
|
target-all = [
|
||||||
"target-aarch64",
|
"target-aarch64",
|
||||||
"target-arm",
|
"target-arm",
|
||||||
"target-x86",
|
"target-x86",
|
||||||
"target-x86_64",
|
"target-x86_64",
|
||||||
"target-wasm32",
|
"target-wasm32",
|
||||||
]
|
]
|
||||||
|
|
||||||
sanitizers = ["roc_build/sanitizers"]
|
sanitizers = ["roc_build/sanitizers"]
|
||||||
|
@ -90,15 +90,14 @@ roc_repl_expect = { path = "../repl_expect" }
|
||||||
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
cli_utils = { path = "../cli_utils" }
|
cli_test_utils = { path = "../cli_test_utils" }
|
||||||
roc_test_utils = { path = "../test_utils" }
|
|
||||||
roc_command_utils = { path = "../utils/command" }
|
roc_command_utils = { path = "../utils/command" }
|
||||||
|
|
||||||
criterion.workspace = true
|
criterion.workspace = true
|
||||||
indoc.workspace = true
|
indoc.workspace = true
|
||||||
parking_lot.workspace = true
|
parking_lot.workspace = true
|
||||||
pretty_assertions.workspace = true
|
pretty_assertions.workspace = true
|
||||||
serial_test.workspace = true
|
insta.workspace = true
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
chrono.workspace = true
|
chrono.workspace = true
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use cli_utils::bench_utils::{
|
use cli_test_utils::bench_utils::{
|
||||||
bench_cfold, bench_deriv, bench_nqueens, bench_quicksort, bench_rbtree_ck,
|
bench_cfold, bench_deriv, bench_nqueens, bench_quicksort, bench_rbtree_ck,
|
||||||
};
|
};
|
||||||
use criterion::{measurement::WallTime, BenchmarkGroup, Criterion, SamplingMode};
|
use criterion::{measurement::WallTime, BenchmarkGroup, Criterion, SamplingMode};
|
||||||
|
|
|
@ -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.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br" }
|
const FORMATTED_ROC: &str = r#"app [main] { pf: platform "platform/main.roc" }
|
||||||
|
|
||||||
import pf.Stdout
|
import pf.Stdout
|
||||||
import pf.Stdin
|
import pf.Stdin
|
||||||
|
@ -273,11 +273,7 @@ main =
|
||||||
name = Stdin.line!
|
name = Stdin.line!
|
||||||
Stdout.line! "Hi $(name)!""#;
|
Stdout.line! "Hi $(name)!""#;
|
||||||
|
|
||||||
const UNFORMATTED_ROC: &str = r#"app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br" }
|
const UNFORMATTED_ROC: &str = r#"app [main] { pf: platform "platform/main.roc" }
|
||||||
|
|
||||||
|
|
||||||
import pf.Stdout
|
|
||||||
import pf.Stdin
|
|
||||||
|
|
||||||
main =
|
main =
|
||||||
Stdout.line! "What's your name?"
|
Stdout.line! "What's your name?"
|
||||||
|
|
|
@ -54,7 +54,6 @@ pub const CMD_VERSION: &str = "version";
|
||||||
pub const CMD_FORMAT: &str = "format";
|
pub const CMD_FORMAT: &str = "format";
|
||||||
pub const CMD_TEST: &str = "test";
|
pub const CMD_TEST: &str = "test";
|
||||||
pub const CMD_GLUE: &str = "glue";
|
pub const CMD_GLUE: &str = "glue";
|
||||||
pub const CMD_GEN_STUB_LIB: &str = "gen-stub-lib";
|
|
||||||
pub const CMD_PREPROCESS_HOST: &str = "preprocess-host";
|
pub const CMD_PREPROCESS_HOST: &str = "preprocess-host";
|
||||||
|
|
||||||
pub const FLAG_EMIT_LLVM_IR: &str = "emit-llvm-ir";
|
pub const FLAG_EMIT_LLVM_IR: &str = "emit-llvm-ir";
|
||||||
|
@ -72,7 +71,8 @@ pub const FLAG_VERBOSE: &str = "verbose";
|
||||||
pub const FLAG_NO_COLOR: &str = "no-color";
|
pub const FLAG_NO_COLOR: &str = "no-color";
|
||||||
pub const FLAG_NO_HEADER: &str = "no-header";
|
pub const FLAG_NO_HEADER: &str = "no-header";
|
||||||
pub const FLAG_LINKER: &str = "linker";
|
pub const FLAG_LINKER: &str = "linker";
|
||||||
pub const FLAG_PREBUILT: &str = "prebuilt-platform";
|
pub const FLAG_BUILD_HOST: &str = "build-host";
|
||||||
|
pub const FLAG_SUPPRESS_BUILD_HOST_WARNING: &str = "suppress-build-host-warning";
|
||||||
pub const FLAG_CHECK: &str = "check";
|
pub const FLAG_CHECK: &str = "check";
|
||||||
pub const FLAG_STDIN: &str = "stdin";
|
pub const FLAG_STDIN: &str = "stdin";
|
||||||
pub const FLAG_STDOUT: &str = "stdout";
|
pub const FLAG_STDOUT: &str = "stdout";
|
||||||
|
@ -142,9 +142,15 @@ pub fn build_app() -> Command {
|
||||||
.value_parser(["surgical", "legacy"])
|
.value_parser(["surgical", "legacy"])
|
||||||
.required(false);
|
.required(false);
|
||||||
|
|
||||||
let flag_prebuilt = Arg::new(FLAG_PREBUILT)
|
let flag_build_host = Arg::new(FLAG_BUILD_HOST)
|
||||||
.long(FLAG_PREBUILT)
|
.long(FLAG_BUILD_HOST)
|
||||||
.help("Assume the platform has been prebuilt and skip rebuilding the platform\n(This is enabled implicitly when using `roc build` with a --target other than `--target <current machine>`, unless the target is wasm.)")
|
.help("WARNING: platforms are responsible for building hosts, this flag will be removed when internal test platforms have a build script")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.required(false);
|
||||||
|
|
||||||
|
let flag_suppress_build_host_warning = Arg::new(FLAG_SUPPRESS_BUILD_HOST_WARNING)
|
||||||
|
.long(FLAG_SUPPRESS_BUILD_HOST_WARNING)
|
||||||
|
.help("WARNING: platforms are responsible for building hosts, this flag will be removed when internal test platforms have a build script")
|
||||||
.action(ArgAction::SetTrue)
|
.action(ArgAction::SetTrue)
|
||||||
.required(false);
|
.required(false);
|
||||||
|
|
||||||
|
@ -201,7 +207,8 @@ pub fn build_app() -> Command {
|
||||||
.arg(flag_profiling.clone())
|
.arg(flag_profiling.clone())
|
||||||
.arg(flag_time.clone())
|
.arg(flag_time.clone())
|
||||||
.arg(flag_linker.clone())
|
.arg(flag_linker.clone())
|
||||||
.arg(flag_prebuilt.clone())
|
.arg(flag_build_host.clone())
|
||||||
|
.arg(flag_suppress_build_host_warning.clone())
|
||||||
.arg(flag_fuzz.clone())
|
.arg(flag_fuzz.clone())
|
||||||
.arg(flag_wasm_stack_size_kb)
|
.arg(flag_wasm_stack_size_kb)
|
||||||
.arg(
|
.arg(
|
||||||
|
@ -253,7 +260,8 @@ pub fn build_app() -> Command {
|
||||||
.arg(flag_profiling.clone())
|
.arg(flag_profiling.clone())
|
||||||
.arg(flag_time.clone())
|
.arg(flag_time.clone())
|
||||||
.arg(flag_linker.clone())
|
.arg(flag_linker.clone())
|
||||||
.arg(flag_prebuilt.clone())
|
.arg(flag_build_host.clone())
|
||||||
|
.arg(flag_suppress_build_host_warning.clone())
|
||||||
.arg(flag_fuzz.clone())
|
.arg(flag_fuzz.clone())
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(FLAG_VERBOSE)
|
Arg::new(FLAG_VERBOSE)
|
||||||
|
@ -298,7 +306,8 @@ pub fn build_app() -> Command {
|
||||||
.arg(flag_profiling.clone())
|
.arg(flag_profiling.clone())
|
||||||
.arg(flag_time.clone())
|
.arg(flag_time.clone())
|
||||||
.arg(flag_linker.clone())
|
.arg(flag_linker.clone())
|
||||||
.arg(flag_prebuilt.clone())
|
.arg(flag_build_host.clone())
|
||||||
|
.arg(flag_suppress_build_host_warning.clone())
|
||||||
.arg(flag_fuzz.clone())
|
.arg(flag_fuzz.clone())
|
||||||
.arg(roc_file_to_run.clone())
|
.arg(roc_file_to_run.clone())
|
||||||
.arg(args_for_app.clone().last(true))
|
.arg(args_for_app.clone().last(true))
|
||||||
|
@ -313,7 +322,8 @@ pub fn build_app() -> Command {
|
||||||
.arg(flag_profiling.clone())
|
.arg(flag_profiling.clone())
|
||||||
.arg(flag_time.clone())
|
.arg(flag_time.clone())
|
||||||
.arg(flag_linker.clone())
|
.arg(flag_linker.clone())
|
||||||
.arg(flag_prebuilt.clone())
|
.arg(flag_build_host.clone())
|
||||||
|
.arg(flag_suppress_build_host_warning.clone())
|
||||||
.arg(flag_fuzz.clone())
|
.arg(flag_fuzz.clone())
|
||||||
.arg(roc_file_to_run.clone())
|
.arg(roc_file_to_run.clone())
|
||||||
.arg(args_for_app.clone().last(true))
|
.arg(args_for_app.clone().last(true))
|
||||||
|
@ -404,23 +414,6 @@ pub fn build_app() -> Command {
|
||||||
.default_value(DEFAULT_ROC_FILENAME)
|
.default_value(DEFAULT_ROC_FILENAME)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.subcommand(Command::new(CMD_GEN_STUB_LIB)
|
|
||||||
.about("Generate a stubbed shared library that can be used for linking a platform binary.\nThe stubbed library has prototypes, but no function bodies.\n\nNote: This command will be removed in favor of just using `roc build` once all platforms support the surgical linker")
|
|
||||||
.arg(
|
|
||||||
Arg::new(ROC_FILE)
|
|
||||||
.help("The .roc file for an app using the platform")
|
|
||||||
.value_parser(value_parser!(PathBuf))
|
|
||||||
.required(true)
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::new(FLAG_TARGET)
|
|
||||||
.long(FLAG_TARGET)
|
|
||||||
.help("Choose a different target")
|
|
||||||
.default_value(Into::<&'static str>::into(Target::default()))
|
|
||||||
.value_parser(build_target_values_parser.clone())
|
|
||||||
.required(false),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.subcommand(Command::new(CMD_PREPROCESS_HOST)
|
.subcommand(Command::new(CMD_PREPROCESS_HOST)
|
||||||
.about("Runs the surgical linker preprocessor to generate `.rh` and `.rm` files.")
|
.about("Runs the surgical linker preprocessor to generate `.rh` and `.rm` files.")
|
||||||
.arg(
|
.arg(
|
||||||
|
@ -465,7 +458,8 @@ pub fn build_app() -> Command {
|
||||||
.arg(flag_profiling)
|
.arg(flag_profiling)
|
||||||
.arg(flag_time)
|
.arg(flag_time)
|
||||||
.arg(flag_linker)
|
.arg(flag_linker)
|
||||||
.arg(flag_prebuilt)
|
.arg(flag_build_host)
|
||||||
|
.arg(flag_suppress_build_host_warning)
|
||||||
.arg(flag_fuzz)
|
.arg(flag_fuzz)
|
||||||
.arg(roc_file_to_run)
|
.arg(roc_file_to_run)
|
||||||
.arg(args_for_app.trailing_var_arg(true))
|
.arg(args_for_app.trailing_var_arg(true))
|
||||||
|
@ -731,7 +725,6 @@ pub fn build(
|
||||||
roc_cache_dir: RocCacheDir<'_>,
|
roc_cache_dir: RocCacheDir<'_>,
|
||||||
link_type: LinkType,
|
link_type: LinkType,
|
||||||
) -> io::Result<i32> {
|
) -> io::Result<i32> {
|
||||||
use roc_build::program::build_file;
|
|
||||||
use BuildConfig::*;
|
use BuildConfig::*;
|
||||||
|
|
||||||
let path = matches.get_one::<PathBuf>(ROC_FILE).unwrap();
|
let path = matches.get_one::<PathBuf>(ROC_FILE).unwrap();
|
||||||
|
@ -879,17 +872,10 @@ pub fn build(
|
||||||
LinkingStrategy::Surgical
|
LinkingStrategy::Surgical
|
||||||
};
|
};
|
||||||
|
|
||||||
let prebuilt = {
|
// All hosts should be prebuilt, this flag keeps the rebuilding behvaiour
|
||||||
let cross_compile = target != Target::default();
|
// as required for internal tests
|
||||||
let targeting_wasm = matches!(target.architecture(), Architecture::Wasm32);
|
let build_host = matches.get_flag(FLAG_BUILD_HOST);
|
||||||
|
let suppress_build_host_warning = matches.get_flag(FLAG_SUPPRESS_BUILD_HOST_WARNING);
|
||||||
matches.get_flag(FLAG_PREBUILT) ||
|
|
||||||
// When compiling for a different target, assume a prebuilt platform.
|
|
||||||
// Otherwise compilation would most likely fail because many toolchains
|
|
||||||
// assume you're compiling for the current machine. We make an exception
|
|
||||||
// for Wasm, because cross-compiling is the norm in that case.
|
|
||||||
(cross_compile && !targeting_wasm)
|
|
||||||
};
|
|
||||||
|
|
||||||
let fuzz = matches.get_flag(FLAG_FUZZ);
|
let fuzz = matches.get_flag(FLAG_FUZZ);
|
||||||
if fuzz && !matches!(code_gen_backend, CodeGenBackend::Llvm(_)) {
|
if fuzz && !matches!(code_gen_backend, CodeGenBackend::Llvm(_)) {
|
||||||
|
@ -917,7 +903,7 @@ pub fn build(
|
||||||
|
|
||||||
let load_config = standard_load_config(target, build_ordering, threading);
|
let load_config = standard_load_config(target, build_ordering, threading);
|
||||||
|
|
||||||
let res_binary_path = build_file(
|
let res_binary_path = roc_build::program::build_file(
|
||||||
&arena,
|
&arena,
|
||||||
target,
|
target,
|
||||||
path.to_owned(),
|
path.to_owned(),
|
||||||
|
@ -925,7 +911,8 @@ pub fn build(
|
||||||
emit_timings,
|
emit_timings,
|
||||||
link_type,
|
link_type,
|
||||||
linking_strategy,
|
linking_strategy,
|
||||||
prebuilt,
|
build_host,
|
||||||
|
suppress_build_host_warning,
|
||||||
wasm_dev_stack_bytes,
|
wasm_dev_stack_bytes,
|
||||||
roc_cache_dir,
|
roc_cache_dir,
|
||||||
load_config,
|
load_config,
|
||||||
|
|
|
@ -4,17 +4,16 @@ use roc_build::link::LinkType;
|
||||||
use roc_build::program::{check_file, CodeGenBackend};
|
use roc_build::program::{check_file, CodeGenBackend};
|
||||||
use roc_cli::{
|
use roc_cli::{
|
||||||
build_app, format_files, format_src, test, BuildConfig, FormatMode, CMD_BUILD, CMD_CHECK,
|
build_app, format_files, format_src, test, BuildConfig, FormatMode, CMD_BUILD, CMD_CHECK,
|
||||||
CMD_DEV, CMD_DOCS, CMD_FORMAT, CMD_GEN_STUB_LIB, CMD_GLUE, CMD_PREPROCESS_HOST, CMD_REPL,
|
CMD_DEV, CMD_DOCS, CMD_FORMAT, CMD_GLUE, CMD_PREPROCESS_HOST, CMD_REPL, CMD_RUN, CMD_TEST,
|
||||||
CMD_RUN, CMD_TEST, CMD_VERSION, DIRECTORY_OR_FILES, FLAG_CHECK, FLAG_DEV, FLAG_LIB, FLAG_MAIN,
|
CMD_VERSION, DIRECTORY_OR_FILES, FLAG_CHECK, FLAG_DEV, FLAG_LIB, FLAG_MAIN, FLAG_NO_COLOR,
|
||||||
FLAG_NO_COLOR, FLAG_NO_HEADER, FLAG_NO_LINK, FLAG_OUTPUT, FLAG_PP_DYLIB, FLAG_PP_HOST,
|
FLAG_NO_HEADER, FLAG_NO_LINK, FLAG_OUTPUT, FLAG_PP_DYLIB, FLAG_PP_HOST, FLAG_PP_PLATFORM,
|
||||||
FLAG_PP_PLATFORM, FLAG_STDIN, FLAG_STDOUT, FLAG_TARGET, FLAG_TIME, GLUE_DIR, GLUE_SPEC,
|
FLAG_STDIN, FLAG_STDOUT, FLAG_TARGET, FLAG_TIME, GLUE_DIR, GLUE_SPEC, ROC_FILE, VERSION,
|
||||||
ROC_FILE, VERSION,
|
|
||||||
};
|
};
|
||||||
use roc_docs::generate_docs_html;
|
use roc_docs::generate_docs_html;
|
||||||
use roc_error_macros::user_error;
|
use roc_error_macros::user_error;
|
||||||
use roc_gen_dev::AssemblyBackendMode;
|
use roc_gen_dev::AssemblyBackendMode;
|
||||||
use roc_gen_llvm::llvm::build::LlvmBackendMode;
|
use roc_gen_llvm::llvm::build::LlvmBackendMode;
|
||||||
use roc_load::{FunctionKind, LoadingProblem, Threading};
|
use roc_load::{LoadingProblem, Threading};
|
||||||
use roc_packaging::cache::{self, RocCacheDir};
|
use roc_packaging::cache::{self, RocCacheDir};
|
||||||
use roc_target::Target;
|
use roc_target::Target;
|
||||||
use std::fs::{self, FileType};
|
use std::fs::{self, FileType};
|
||||||
|
@ -120,21 +119,6 @@ fn main() -> io::Result<()> {
|
||||||
Ok(1)
|
Ok(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some((CMD_GEN_STUB_LIB, matches)) => {
|
|
||||||
let input_path = matches.get_one::<PathBuf>(ROC_FILE).unwrap();
|
|
||||||
let target = matches
|
|
||||||
.get_one::<String>(FLAG_TARGET)
|
|
||||||
.and_then(|s| Target::from_str(s).ok())
|
|
||||||
.unwrap_or_default();
|
|
||||||
let function_kind = FunctionKind::from_env();
|
|
||||||
roc_linker::generate_stub_lib(
|
|
||||||
input_path,
|
|
||||||
RocCacheDir::Persistent(cache::roc_cache_packages_dir().as_path()),
|
|
||||||
target,
|
|
||||||
function_kind,
|
|
||||||
);
|
|
||||||
Ok(0)
|
|
||||||
}
|
|
||||||
Some((CMD_PREPROCESS_HOST, matches)) => {
|
Some((CMD_PREPROCESS_HOST, matches)) => {
|
||||||
let preprocess_host_err =
|
let preprocess_host_err =
|
||||||
{ |msg: String| user_error!("\n\n ERROR PRE-PROCESSING HOST: {}\n\n", msg) };
|
{ |msg: String| user_error!("\n\n ERROR PRE-PROCESSING HOST: {}\n\n", msg) };
|
||||||
|
@ -169,10 +153,14 @@ fn main() -> io::Result<()> {
|
||||||
|
|
||||||
let verbose_and_time = matches.get_one::<bool>(roc_cli::FLAG_VERBOSE).unwrap();
|
let verbose_and_time = matches.get_one::<bool>(roc_cli::FLAG_VERBOSE).unwrap();
|
||||||
|
|
||||||
|
let preprocessed_path = platform_path.with_file_name(target.prebuilt_surgical_host());
|
||||||
|
let metadata_path = platform_path.with_file_name(target.metadata_file_name());
|
||||||
|
|
||||||
roc_linker::preprocess_host(
|
roc_linker::preprocess_host(
|
||||||
target,
|
target,
|
||||||
host_path,
|
host_path,
|
||||||
platform_path,
|
metadata_path.as_path(),
|
||||||
|
preprocessed_path.as_path(),
|
||||||
dylib_path,
|
dylib_path,
|
||||||
*verbose_and_time,
|
*verbose_and_time,
|
||||||
*verbose_and_time,
|
*verbose_and_time,
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
app [main] { pf: platform "platform/main.roc" }
|
app [main] { pf: platform "platform/main.roc" }
|
||||||
|
|
||||||
# see https://github.com/roc-lang/roc/issues/985
|
|
||||||
main : Task {} []
|
main : Task {} []
|
||||||
main = closure1 {}
|
main =
|
||||||
# |> Task.after (\_ -> closure2 {})
|
closure1 {}
|
||||||
# |> Task.after (\_ -> closure3 {})
|
|> Task.await (\_ -> closure2 {})
|
||||||
# |> Task.after (\_ -> closure4 {})
|
|> Task.await (\_ -> closure3 {})
|
||||||
|
|> Task.await (\_ -> closure4 {})
|
||||||
# ---
|
# ---
|
||||||
closure1 : {} -> Task {} []
|
closure1 : {} -> Task {} []
|
||||||
closure1 = \_ ->
|
closure1 = \_ ->
|
||||||
|
@ -17,32 +17,32 @@ toUnitBorrowed = \x -> Str.countUtf8Bytes x
|
||||||
foo = \f, x -> f x
|
foo = \f, x -> f x
|
||||||
|
|
||||||
# ---
|
# ---
|
||||||
# closure2 : {} -> Task.Task {} []
|
closure2 : {} -> Task {} []
|
||||||
# closure2 = \_ ->
|
closure2 = \_ ->
|
||||||
# x : Str
|
x : Str
|
||||||
# x = "a long string such that it's malloced"
|
x = "a long string such that it's malloced"
|
||||||
#
|
|
||||||
# Task.succeed {}
|
Task.ok {}
|
||||||
# |> Task.map (\_ -> x)
|
|> Task.map (\_ -> x)
|
||||||
# |> Task.map toUnit
|
|> Task.map toUnit
|
||||||
#
|
|
||||||
# toUnit = \_ -> {}
|
toUnit = \_ -> {}
|
||||||
#
|
|
||||||
# # ---
|
# # ---
|
||||||
# closure3 : {} -> Task.Task {} []
|
closure3 : {} -> Task {} []
|
||||||
# closure3 = \_ ->
|
closure3 = \_ ->
|
||||||
# x : Str
|
x : Str
|
||||||
# x = "a long string such that it's malloced"
|
x = "a long string such that it's malloced"
|
||||||
#
|
|
||||||
# Task.succeed {}
|
Task.ok {}
|
||||||
# |> Task.after (\_ -> Task.succeed x |> Task.map (\_ -> {}))
|
|> Task.await (\_ -> Task.ok x |> Task.map (\_ -> {}))
|
||||||
#
|
|
||||||
# # ---
|
# # ---
|
||||||
# closure4 : {} -> Task.Task {} []
|
closure4 : {} -> Task {} []
|
||||||
# closure4 = \_ ->
|
closure4 = \_ ->
|
||||||
# x : Str
|
x : Str
|
||||||
# x = "a long string such that it's malloced"
|
x = "a long string such that it's malloced"
|
||||||
#
|
|
||||||
# Task.succeed {}
|
Task.ok {}
|
||||||
# |> Task.after (\_ -> Task.succeed x)
|
|> Task.await (\_ -> Task.ok x)
|
||||||
# |> Task.map (\_ -> {})
|
|> Task.map (\_ -> {})
|
||||||
|
|
3
crates/cli/tests/benchmarks/platform/app.roc
Normal file
3
crates/cli/tests/benchmarks/platform/app.roc
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
app [main] { pf: platform "main.roc" }
|
||||||
|
|
||||||
|
main = Task.ok {}
|
|
@ -112,8 +112,6 @@ comptime {
|
||||||
const Unit = extern struct {};
|
const Unit = extern struct {};
|
||||||
|
|
||||||
pub fn main() !u8 {
|
pub fn main() !u8 {
|
||||||
const stderr = std.io.getStdErr().writer();
|
|
||||||
|
|
||||||
// The size might be zero; if so, make it at least 8 so that we don't have a nullptr
|
// The size might be zero; if so, make it at least 8 so that we don't have a nullptr
|
||||||
const size = @max(@as(usize, @intCast(roc__mainForHost_1_exposed_size())), 8);
|
const size = @max(@as(usize, @intCast(roc__mainForHost_1_exposed_size())), 8);
|
||||||
const raw_output = roc_alloc(@as(usize, @intCast(size)), @alignOf(u64)).?;
|
const raw_output = roc_alloc(@as(usize, @intCast(size)), @alignOf(u64)).?;
|
||||||
|
@ -123,26 +121,15 @@ pub fn main() !u8 {
|
||||||
roc_dealloc(raw_output, @alignOf(u64));
|
roc_dealloc(raw_output, @alignOf(u64));
|
||||||
}
|
}
|
||||||
|
|
||||||
var timer = std.time.Timer.start() catch unreachable;
|
|
||||||
|
|
||||||
roc__mainForHost_1_exposed_generic(output);
|
roc__mainForHost_1_exposed_generic(output);
|
||||||
|
|
||||||
const closure_data_pointer = @as([*]u8, @ptrCast(output));
|
const closure_data_pointer = @as([*]u8, @ptrCast(output));
|
||||||
|
|
||||||
call_the_closure(closure_data_pointer);
|
call_the_closure(closure_data_pointer);
|
||||||
|
|
||||||
const nanos = timer.read();
|
|
||||||
const seconds = (@as(f64, @floatFromInt(nanos)) / 1_000_000_000.0);
|
|
||||||
|
|
||||||
stderr.print("runtime: {d:.3}ms\n", .{seconds * 1000}) catch unreachable;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_seconds(tms: std.os.timespec) f64 {
|
|
||||||
return @as(f64, @floatFromInt(tms.tv_sec)) + (@as(f64, @floatFromInt(tms.tv_nsec)) / 1_000_000_000.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call_the_closure(closure_data_pointer: [*]u8) void {
|
fn call_the_closure(closure_data_pointer: [*]u8) void {
|
||||||
const allocator = std.heap.page_allocator;
|
const allocator = std.heap.page_allocator;
|
||||||
|
|
||||||
|
|
|
@ -1,255 +0,0 @@
|
||||||
app [main] { pf: platform "platform/main.roc" }
|
|
||||||
|
|
||||||
import pf.PlatformTasks
|
|
||||||
|
|
||||||
Color : [Red, Black]
|
|
||||||
|
|
||||||
Tree a b : [Leaf, Node Color (Tree a b) a b (Tree a b)]
|
|
||||||
|
|
||||||
Map : Tree I64 Bool
|
|
||||||
|
|
||||||
ConsList a : [Nil, Cons a (ConsList a)]
|
|
||||||
|
|
||||||
main : Task {} []
|
|
||||||
main =
|
|
||||||
{ value, isError } = PlatformTasks.getInt!
|
|
||||||
inputResult =
|
|
||||||
if isError then
|
|
||||||
Err GetIntError
|
|
||||||
else
|
|
||||||
Ok value
|
|
||||||
|
|
||||||
when inputResult is
|
|
||||||
Ok n ->
|
|
||||||
m = makeMap n # koka original n = 4_200_000
|
|
||||||
val = fold (\_, v, r -> if v then r + 1 else r) m 0
|
|
||||||
|
|
||||||
val
|
|
||||||
|> Num.toStr
|
|
||||||
|> PlatformTasks.putLine
|
|
||||||
|
|
||||||
Err GetIntError ->
|
|
||||||
PlatformTasks.putLine "Error: Failed to get Integer from stdin."
|
|
||||||
|
|
||||||
boom : Str -> a
|
|
||||||
boom = \_ -> boom ""
|
|
||||||
|
|
||||||
makeMap : I64 -> Map
|
|
||||||
makeMap = \n ->
|
|
||||||
makeMapHelp n n Leaf
|
|
||||||
|
|
||||||
makeMapHelp : I64, I64, Map -> Map
|
|
||||||
makeMapHelp = \total, n, m ->
|
|
||||||
when n is
|
|
||||||
0 -> m
|
|
||||||
_ ->
|
|
||||||
n1 = n - 1
|
|
||||||
|
|
||||||
powerOf10 =
|
|
||||||
n |> Num.isMultipleOf 10
|
|
||||||
|
|
||||||
t1 = insert m n powerOf10
|
|
||||||
|
|
||||||
isFrequency =
|
|
||||||
n |> Num.isMultipleOf 4
|
|
||||||
|
|
||||||
key = n1 + ((total - n1) // 5)
|
|
||||||
t2 = if isFrequency then delete t1 key else t1
|
|
||||||
|
|
||||||
makeMapHelp total n1 t2
|
|
||||||
|
|
||||||
fold : (a, b, omega -> omega), Tree a b, omega -> omega
|
|
||||||
fold = \f, tree, b ->
|
|
||||||
when tree is
|
|
||||||
Leaf -> b
|
|
||||||
Node _ l k v r -> fold f r (f k v (fold f l b))
|
|
||||||
|
|
||||||
depth : Tree * * -> I64
|
|
||||||
depth = \tree ->
|
|
||||||
when tree is
|
|
||||||
Leaf -> 1
|
|
||||||
Node _ l _ _ r -> 1 + depth l + depth r
|
|
||||||
|
|
||||||
insert : Map, I64, Bool -> Map
|
|
||||||
insert = \t, k, v -> if isRed t then setBlack (ins t k v) else ins t k v
|
|
||||||
|
|
||||||
setBlack : Tree a b -> Tree a b
|
|
||||||
setBlack = \tree ->
|
|
||||||
when tree is
|
|
||||||
Node _ l k v r -> Node Black l k v r
|
|
||||||
_ -> tree
|
|
||||||
|
|
||||||
isRed : Tree a b -> Bool
|
|
||||||
isRed = \tree ->
|
|
||||||
when tree is
|
|
||||||
Node Red _ _ _ _ -> Bool.true
|
|
||||||
_ -> Bool.false
|
|
||||||
|
|
||||||
ins : Tree I64 Bool, I64, Bool -> Tree I64 Bool
|
|
||||||
ins = \tree, kx, vx ->
|
|
||||||
when tree is
|
|
||||||
Leaf ->
|
|
||||||
Node Red Leaf kx vx Leaf
|
|
||||||
|
|
||||||
Node Red a ky vy b ->
|
|
||||||
when Num.compare kx ky is
|
|
||||||
LT -> Node Red (ins a kx vx) ky vy b
|
|
||||||
GT -> Node Red a ky vy (ins b kx vx)
|
|
||||||
EQ -> Node Red a ky vy (ins b kx vx)
|
|
||||||
|
|
||||||
Node Black a ky vy b ->
|
|
||||||
when Num.compare kx ky is
|
|
||||||
LT ->
|
|
||||||
when isRed a is
|
|
||||||
Bool.true -> balanceLeft (ins a kx vx) ky vy b
|
|
||||||
Bool.false -> Node Black (ins a kx vx) ky vy b
|
|
||||||
|
|
||||||
GT ->
|
|
||||||
when isRed b is
|
|
||||||
Bool.true -> balanceRight a ky vy (ins b kx vx)
|
|
||||||
Bool.false -> Node Black a ky vy (ins b kx vx)
|
|
||||||
|
|
||||||
EQ ->
|
|
||||||
Node Black a kx vx b
|
|
||||||
|
|
||||||
balanceLeft : Tree a b, a, b, Tree a b -> Tree a b
|
|
||||||
balanceLeft = \l, k, v, r ->
|
|
||||||
when l is
|
|
||||||
Leaf ->
|
|
||||||
Leaf
|
|
||||||
|
|
||||||
Node _ (Node Red lx kx vx rx) ky vy ry ->
|
|
||||||
Node Red (Node Black lx kx vx rx) ky vy (Node Black ry k v r)
|
|
||||||
|
|
||||||
Node _ ly ky vy (Node Red lx kx vx rx) ->
|
|
||||||
Node Red (Node Black ly ky vy lx) kx vx (Node Black rx k v r)
|
|
||||||
|
|
||||||
Node _ lx kx vx rx ->
|
|
||||||
Node Black (Node Red lx kx vx rx) k v r
|
|
||||||
|
|
||||||
balanceRight : Tree a b, a, b, Tree a b -> Tree a b
|
|
||||||
balanceRight = \l, k, v, r ->
|
|
||||||
when r is
|
|
||||||
Leaf ->
|
|
||||||
Leaf
|
|
||||||
|
|
||||||
Node _ (Node Red lx kx vx rx) ky vy ry ->
|
|
||||||
Node Red (Node Black l k v lx) kx vx (Node Black rx ky vy ry)
|
|
||||||
|
|
||||||
Node _ lx kx vx (Node Red ly ky vy ry) ->
|
|
||||||
Node Red (Node Black l k v lx) kx vx (Node Black ly ky vy ry)
|
|
||||||
|
|
||||||
Node _ lx kx vx rx ->
|
|
||||||
Node Black l k v (Node Red lx kx vx rx)
|
|
||||||
|
|
||||||
isBlack : Color -> Bool
|
|
||||||
isBlack = \c ->
|
|
||||||
when c is
|
|
||||||
Black -> Bool.true
|
|
||||||
Red -> Bool.false
|
|
||||||
|
|
||||||
Del a b : [Del (Tree a b) Bool]
|
|
||||||
|
|
||||||
setRed : Map -> Map
|
|
||||||
setRed = \t ->
|
|
||||||
when t is
|
|
||||||
Node _ l k v r ->
|
|
||||||
Node Red l k v r
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
t
|
|
||||||
|
|
||||||
makeBlack : Map -> Del I64 Bool
|
|
||||||
makeBlack = \t ->
|
|
||||||
when t is
|
|
||||||
Node Red l k v r ->
|
|
||||||
Del (Node Black l k v r) Bool.false
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
Del t Bool.true
|
|
||||||
|
|
||||||
rebalanceLeft = \c, l, k, v, r ->
|
|
||||||
when l is
|
|
||||||
Node Black _ _ _ _ ->
|
|
||||||
Del (balanceLeft (setRed l) k v r) (isBlack c)
|
|
||||||
|
|
||||||
Node Red lx kx vx rx ->
|
|
||||||
Del (Node Black lx kx vx (balanceLeft (setRed rx) k v r)) Bool.false
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
boom "unreachable"
|
|
||||||
|
|
||||||
rebalanceRight = \c, l, k, v, r ->
|
|
||||||
when r is
|
|
||||||
Node Black _ _ _ _ ->
|
|
||||||
Del (balanceRight l k v (setRed r)) (isBlack c)
|
|
||||||
|
|
||||||
Node Red lx kx vx rx ->
|
|
||||||
Del (Node Black (balanceRight l k v (setRed lx)) kx vx rx) Bool.false
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
boom "unreachable"
|
|
||||||
|
|
||||||
delMin = \t ->
|
|
||||||
when t is
|
|
||||||
Node Black Leaf k v r ->
|
|
||||||
when r is
|
|
||||||
Leaf ->
|
|
||||||
Delmin (Del Leaf Bool.true) k v
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
Delmin (Del (setBlack r) Bool.false) k v
|
|
||||||
|
|
||||||
Node Red Leaf k v r ->
|
|
||||||
Delmin (Del r Bool.false) k v
|
|
||||||
|
|
||||||
Node c l k v r ->
|
|
||||||
when delMin l is
|
|
||||||
Delmin (Del lx Bool.true) kx vx ->
|
|
||||||
Delmin (rebalanceRight c lx k v r) kx vx
|
|
||||||
|
|
||||||
Delmin (Del lx Bool.false) kx vx ->
|
|
||||||
Delmin (Del (Node c lx k v r) Bool.false) kx vx
|
|
||||||
|
|
||||||
Leaf ->
|
|
||||||
Delmin (Del t Bool.false) 0 Bool.false
|
|
||||||
|
|
||||||
delete : Tree I64 Bool, I64 -> Tree I64 Bool
|
|
||||||
delete = \t, k ->
|
|
||||||
when del t k is
|
|
||||||
Del tx _ ->
|
|
||||||
setBlack tx
|
|
||||||
|
|
||||||
del : Tree I64 Bool, I64 -> Del I64 Bool
|
|
||||||
del = \t, k ->
|
|
||||||
when t is
|
|
||||||
Leaf ->
|
|
||||||
Del Leaf Bool.false
|
|
||||||
|
|
||||||
Node cx lx kx vx rx ->
|
|
||||||
if (k < kx) then
|
|
||||||
when del lx k is
|
|
||||||
Del ly Bool.true ->
|
|
||||||
rebalanceRight cx ly kx vx rx
|
|
||||||
|
|
||||||
Del ly Bool.false ->
|
|
||||||
Del (Node cx ly kx vx rx) Bool.false
|
|
||||||
else if (k > kx) then
|
|
||||||
when del rx k is
|
|
||||||
Del ry Bool.true ->
|
|
||||||
rebalanceLeft cx lx kx vx ry
|
|
||||||
|
|
||||||
Del ry Bool.false ->
|
|
||||||
Del (Node cx lx kx vx ry) Bool.false
|
|
||||||
else
|
|
||||||
when rx is
|
|
||||||
Leaf ->
|
|
||||||
if isBlack cx then makeBlack lx else Del lx Bool.false
|
|
||||||
|
|
||||||
Node _ _ _ _ _ ->
|
|
||||||
when delMin rx is
|
|
||||||
Delmin (Del ry Bool.true) ky vy ->
|
|
||||||
rebalanceLeft cx lx ky vy ry
|
|
||||||
|
|
||||||
Delmin (Del ry Bool.false) ky vy ->
|
|
||||||
Del (Node cx lx ky vy ry) Bool.false
|
|
|
@ -3,7 +3,6 @@ app [main] { pf: platform "platform/main.roc" }
|
||||||
import pf.PlatformTasks
|
import pf.PlatformTasks
|
||||||
import AStar
|
import AStar
|
||||||
|
|
||||||
#main : Task {} *
|
|
||||||
main =
|
main =
|
||||||
PlatformTasks.putLine! (showBool test1)
|
PlatformTasks.putLine! (showBool test1)
|
||||||
|
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
app [main] {
|
|
||||||
pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br",
|
|
||||||
}
|
|
||||||
|
|
||||||
import pf.Stdout
|
|
||||||
import pf.Arg
|
|
||||||
|
|
||||||
main =
|
|
||||||
args = Arg.list! {}
|
|
||||||
when List.first args is
|
|
||||||
Ok argv0 -> Stdout.line argv0
|
|
||||||
Err ListWasEmpty -> Stdout.line "Failed: argv was empty"
|
|
|
@ -1,18 +0,0 @@
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br" }
|
|
||||||
|
|
||||||
import pf.Stdin
|
|
||||||
import pf.Stdout
|
|
||||||
|
|
||||||
main =
|
|
||||||
Stdout.line! "\nLet's count down from 3 together - all you have to do is press <ENTER>."
|
|
||||||
_ = Stdin.line!
|
|
||||||
Task.loop 3 tick
|
|
||||||
|
|
||||||
tick = \n ->
|
|
||||||
if n == 0 then
|
|
||||||
Stdout.line! "🎉 SURPRISE! Happy Birthday! 🎂"
|
|
||||||
Task.ok (Done {})
|
|
||||||
else
|
|
||||||
Stdout.line! (n |> Num.toStr |> \s -> "$(s)...")
|
|
||||||
_ = Stdin.line!
|
|
||||||
Task.ok (Step (n - 1))
|
|
|
@ -1,35 +0,0 @@
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br" }
|
|
||||||
|
|
||||||
import pf.Stdin
|
|
||||||
import pf.Stdout
|
|
||||||
|
|
||||||
main =
|
|
||||||
Stdout.line! "🗣 Shout into this cave and hear the echo! 👂👂👂"
|
|
||||||
|
|
||||||
Task.loop {} tick
|
|
||||||
|
|
||||||
tick : {} -> Task [Step {}, Done {}] _
|
|
||||||
tick = \{} ->
|
|
||||||
when Stdin.line |> Task.result! is
|
|
||||||
Ok str -> Stdout.line (echo str) |> Task.map Step
|
|
||||||
Err (StdinErr EndOfFile) -> Stdout.line (echo "Received end of input (EOF).") |> Task.map Done
|
|
||||||
Err (StdinErr err) -> Stdout.line (echo "Unable to read input $(Inspect.toStr err)") |> Task.map Done
|
|
||||||
|
|
||||||
echo : Str -> Str
|
|
||||||
echo = \shout ->
|
|
||||||
silence = \length ->
|
|
||||||
spaceInUtf8 = 32
|
|
||||||
|
|
||||||
List.repeat spaceInUtf8 length
|
|
||||||
|
|
||||||
shout
|
|
||||||
|> Str.toUtf8
|
|
||||||
|> List.mapWithIndex
|
|
||||||
(\_, i ->
|
|
||||||
length = (List.len (Str.toUtf8 shout) - i)
|
|
||||||
phrase = (List.splitAt (Str.toUtf8 shout) length).before
|
|
||||||
|
|
||||||
List.concat (silence (if i == 0 then 2 * length else length)) phrase)
|
|
||||||
|> List.join
|
|
||||||
|> Str.fromUtf8
|
|
||||||
|> Result.withDefault ""
|
|
|
@ -1,30 +0,0 @@
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br" }
|
|
||||||
|
|
||||||
import pf.Stdout
|
|
||||||
import pf.Stderr
|
|
||||||
import pf.Env
|
|
||||||
|
|
||||||
main =
|
|
||||||
task =
|
|
||||||
Env.decode "EDITOR"
|
|
||||||
|> Task.await (\editor -> Stdout.line "Your favorite editor is $(editor)!")
|
|
||||||
|> Task.await (\{} -> Env.decode "SHLVL")
|
|
||||||
|> Task.await
|
|
||||||
(\lvl ->
|
|
||||||
when lvl is
|
|
||||||
1u8 -> Stdout.line "You're running this in a root shell!"
|
|
||||||
n ->
|
|
||||||
lvlStr = Num.toStr n
|
|
||||||
|
|
||||||
Stdout.line "Your current shell level is $(lvlStr)!")
|
|
||||||
|> Task.await \{} -> Env.decode "LETTERS"
|
|
||||||
|
|
||||||
Task.attempt task \result ->
|
|
||||||
when result is
|
|
||||||
Ok letters ->
|
|
||||||
joinedLetters = Str.joinWith letters " "
|
|
||||||
|
|
||||||
Stdout.line "Your favorite letters are: $(joinedLetters)"
|
|
||||||
|
|
||||||
Err _ ->
|
|
||||||
Stderr.line "I couldn't find your favorite letters in the environment variables!"
|
|
|
@ -1,36 +0,0 @@
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br" }
|
|
||||||
|
|
||||||
import pf.Stdout
|
|
||||||
import pf.File
|
|
||||||
import pf.Path
|
|
||||||
import pf.Env
|
|
||||||
|
|
||||||
main : Task {} [Exit I32 Str]_
|
|
||||||
main =
|
|
||||||
pathStr = "out.txt"
|
|
||||||
|
|
||||||
task =
|
|
||||||
cwdPath = Env.cwd!
|
|
||||||
cwdStr = Path.display cwdPath
|
|
||||||
Stdout.line! "Current working directory: $(cwdStr)"
|
|
||||||
|
|
||||||
dirEntries = Path.listDir! cwdPath
|
|
||||||
contentsStr = Str.joinWith (List.map dirEntries Path.display) "\n "
|
|
||||||
Stdout.line! "Directory contents:\n $(contentsStr)\n"
|
|
||||||
Stdout.line! "Writing a string to out.txt"
|
|
||||||
File.writeUtf8! pathStr "a string!"
|
|
||||||
contents = File.readUtf8! pathStr
|
|
||||||
Stdout.line! "I read the file back. Its contents: \"$(contents)\""
|
|
||||||
|
|
||||||
when Task.result! task is
|
|
||||||
Ok {} -> Stdout.line! "Successfully wrote a string to out.txt"
|
|
||||||
Err err ->
|
|
||||||
msg =
|
|
||||||
when err is
|
|
||||||
FileWriteErr _ PermissionDenied -> "PermissionDenied"
|
|
||||||
FileWriteErr _ Unsupported -> "Unsupported"
|
|
||||||
FileWriteErr _ (Unrecognized _ other) -> other
|
|
||||||
FileReadErr _ _ -> "Error reading file"
|
|
||||||
_ -> "Uh oh, there was an error!"
|
|
||||||
|
|
||||||
Task.err (Exit 1 msg)
|
|
|
@ -1,35 +0,0 @@
|
||||||
# A Simple Markdown Example
|
|
||||||
|
|
||||||
This file contains `form.roc` embedded as a block in Markdown. It lets us test that `roc check` works with Markdown.
|
|
||||||
|
|
||||||
```roc
|
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br" }
|
|
||||||
|
|
||||||
import pf.Stdin
|
|
||||||
import pf.Stdout
|
|
||||||
|
|
||||||
main =
|
|
||||||
Stdout.line! "What's your first name?"
|
|
||||||
firstName = Stdin.line!
|
|
||||||
Stdout.line! "What's your last name?"
|
|
||||||
lastName = Stdin.line!
|
|
||||||
|
|
||||||
Stdout.line "Hi, $(firstName) $(lastName)! 👋"
|
|
||||||
```
|
|
||||||
|
|
||||||
Excitingly, we can have another block of Roc code as well! (In this case it is the same one...)
|
|
||||||
|
|
||||||
```roc
|
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br" }
|
|
||||||
|
|
||||||
import pf.Stdin
|
|
||||||
import pf.Stdout
|
|
||||||
|
|
||||||
main =
|
|
||||||
Stdout.line! "What's your first name?"
|
|
||||||
firstName = Stdin.line!
|
|
||||||
Stdout.line! "What's your last name?"
|
|
||||||
lastName = Stdin.line!
|
|
||||||
|
|
||||||
Stdout.line "Hi, $(firstName) $(lastName)! 👋"
|
|
||||||
```
|
|
|
@ -1,12 +0,0 @@
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br" }
|
|
||||||
|
|
||||||
import pf.Stdin
|
|
||||||
import pf.Stdout
|
|
||||||
|
|
||||||
main =
|
|
||||||
Stdout.line! "What's your first name?"
|
|
||||||
firstName = Stdin.line!
|
|
||||||
Stdout.line! "What's your last name?"
|
|
||||||
lastName = Stdin.line!
|
|
||||||
|
|
||||||
Stdout.line "Hi, $(firstName) $(lastName)! 👋"
|
|
|
@ -1,23 +0,0 @@
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br" }
|
|
||||||
|
|
||||||
import pf.Http
|
|
||||||
import pf.Stdout
|
|
||||||
|
|
||||||
main =
|
|
||||||
request = {
|
|
||||||
method: Get,
|
|
||||||
headers: [],
|
|
||||||
url: "http://www.example.com",
|
|
||||||
mimeType: "",
|
|
||||||
body: [],
|
|
||||||
timeout: TimeoutMilliseconds 5000,
|
|
||||||
}
|
|
||||||
|
|
||||||
resp = Http.send! request
|
|
||||||
|
|
||||||
output =
|
|
||||||
when resp |> Http.handleStringResponse is
|
|
||||||
Err err -> crash (Http.errorToString err)
|
|
||||||
Ok body -> body
|
|
||||||
|
|
||||||
Stdout.line output
|
|
|
@ -1,12 +0,0 @@
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br" }
|
|
||||||
|
|
||||||
import pf.Stdout
|
|
||||||
import "test-file.txt" as testFile
|
|
||||||
|
|
||||||
main =
|
|
||||||
# Due to the functions we apply on testFile, it will be inferred as a List U8.
|
|
||||||
testFile
|
|
||||||
|> List.map Num.toU64
|
|
||||||
|> List.sum
|
|
||||||
|> Num.toStr
|
|
||||||
|> Stdout.line!
|
|
|
@ -1,12 +0,0 @@
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br" }
|
|
||||||
|
|
||||||
import pf.Stdout
|
|
||||||
import "test-file.txt" as testFile : _ # the _ is optional
|
|
||||||
|
|
||||||
main =
|
|
||||||
# Due to the functions we apply on testFile, it will be inferred as a List U8.
|
|
||||||
testFile
|
|
||||||
|> List.map Num.toU64
|
|
||||||
|> List.sum
|
|
||||||
|> Num.toStr
|
|
||||||
|> Stdout.line!
|
|
|
@ -1,7 +0,0 @@
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br" }
|
|
||||||
|
|
||||||
import pf.Stdout
|
|
||||||
import "ingested-file.roc" as ownCode : Str
|
|
||||||
|
|
||||||
main =
|
|
||||||
Stdout.line! "\nThis roc file can print its own source code. The source is:\n\n$(ownCode)"
|
|
|
@ -1,85 +0,0 @@
|
||||||
app [main] {
|
|
||||||
pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br",
|
|
||||||
}
|
|
||||||
|
|
||||||
import pf.Stdout
|
|
||||||
|
|
||||||
main =
|
|
||||||
file = strParam { name: "file" }
|
|
||||||
argParser =
|
|
||||||
{ cliBuild <-
|
|
||||||
file,
|
|
||||||
count: numParam { name: "count" },
|
|
||||||
doubled: numParam { name: "doubled" }
|
|
||||||
|> cliMap \d -> d * 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
args = ["parse-args", "file.txt", "5", "7"]
|
|
||||||
when argParser |> parseArgs args is
|
|
||||||
Ok data -> Stdout.line "Success: $(Inspect.toStr data)"
|
|
||||||
Err (FailedToParse message) -> Stdout.line "Failed: $(message)"
|
|
||||||
|
|
||||||
ArgParseErr : [NoMoreArgs, InvalidParam ParamConfig]
|
|
||||||
|
|
||||||
ParamConfig : {
|
|
||||||
name : Str,
|
|
||||||
type : [Num, Str],
|
|
||||||
}
|
|
||||||
|
|
||||||
ArgParser out : {
|
|
||||||
params : List ParamConfig,
|
|
||||||
parser : List Str -> Result (out, List Str) ArgParseErr,
|
|
||||||
}
|
|
||||||
|
|
||||||
strParam : { name : Str } -> ArgParser Str
|
|
||||||
strParam = \{ name } ->
|
|
||||||
parser = \args ->
|
|
||||||
when args is
|
|
||||||
[] -> Err NoMoreArgs
|
|
||||||
[first, .. as rest] -> Ok (first, rest)
|
|
||||||
|
|
||||||
{ params: [{ name, type: Str }], parser }
|
|
||||||
|
|
||||||
numParam : { name : Str } -> ArgParser U64
|
|
||||||
numParam = \{ name } ->
|
|
||||||
param = { name, type: Num }
|
|
||||||
parser = \args ->
|
|
||||||
when args is
|
|
||||||
[] -> Err NoMoreArgs
|
|
||||||
[first, .. as rest] ->
|
|
||||||
when Str.toU64 first is
|
|
||||||
Ok num -> Ok (num, rest)
|
|
||||||
Err InvalidNumStr -> Err (InvalidParam param)
|
|
||||||
|
|
||||||
{ params: [param], parser }
|
|
||||||
|
|
||||||
cliMap : ArgParser a, (a -> b) -> ArgParser b
|
|
||||||
cliMap = \{ params, parser }, mapper ->
|
|
||||||
mappedParser = \args ->
|
|
||||||
(data, afterData) = parser? args
|
|
||||||
|
|
||||||
Ok (mapper data, afterData)
|
|
||||||
|
|
||||||
{
|
|
||||||
params,
|
|
||||||
parser: mappedParser,
|
|
||||||
}
|
|
||||||
|
|
||||||
cliBuild : ArgParser a, ArgParser b, (a, b -> c) -> ArgParser c
|
|
||||||
cliBuild = \firstWeaver, secondWeaver, combine ->
|
|
||||||
allParams = List.concat firstWeaver.params secondWeaver.params
|
|
||||||
combinedParser = \args ->
|
|
||||||
(firstValue, afterFirst) = firstWeaver.parser? args
|
|
||||||
(secondValue, afterSecond) = secondWeaver.parser? afterFirst
|
|
||||||
|
|
||||||
Ok (combine firstValue secondValue, afterSecond)
|
|
||||||
|
|
||||||
{ params: allParams, parser: combinedParser }
|
|
||||||
|
|
||||||
parseArgs : ArgParser a, List Str -> Result a [FailedToParse Str]
|
|
||||||
parseArgs = \{ params: _, parser }, args ->
|
|
||||||
when parser (List.dropFirst args 1) is
|
|
||||||
Ok (data, []) -> Ok data
|
|
||||||
Ok (_data, extraArgs) -> Err (FailedToParse "Got $(List.len extraArgs |> Inspect.toStr) extra args")
|
|
||||||
Err NoMoreArgs -> Err (FailedToParse "I needed more args")
|
|
||||||
Err (InvalidParam param) -> Err (FailedToParse "Parameter '$(param.name)' needed a $(Inspect.toStr param.type)")
|
|
|
@ -1,51 +0,0 @@
|
||||||
app [main] {
|
|
||||||
cli: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br",
|
|
||||||
parser: "https://github.com/lukewilliamboswell/roc-parser/releases/download/0.5.2/9VrPjwfQQ1QeSL3CfmWr2Pr9DESdDIXy97pwpuq84Ck.tar.br",
|
|
||||||
}
|
|
||||||
|
|
||||||
import cli.Stdout
|
|
||||||
import cli.Stderr
|
|
||||||
import parser.Core exposing [Parser, buildPrimitiveParser, many]
|
|
||||||
import parser.String exposing [parseStr]
|
|
||||||
|
|
||||||
main =
|
|
||||||
lettersInput = "AAAiBByAABBwBtCCCiAyArBBx"
|
|
||||||
ifLetterA = \l -> l == A
|
|
||||||
when parseStr (many letterParser) lettersInput is
|
|
||||||
Ok letters ->
|
|
||||||
letters
|
|
||||||
|> List.keepIf ifLetterA
|
|
||||||
|> List.map \_ -> 1
|
|
||||||
|> List.sum
|
|
||||||
|> Num.toStr
|
|
||||||
|> \countLetterA -> Stdout.line "I counted $(countLetterA) letter A's!"
|
|
||||||
|
|
||||||
Err _ -> Stderr.line "Ooops, something went wrong parsing letters"
|
|
||||||
|
|
||||||
Letter : [A, B, C, Other]
|
|
||||||
|
|
||||||
letterParser : Parser (List U8) Letter
|
|
||||||
letterParser =
|
|
||||||
buildPrimitiveParser \input ->
|
|
||||||
valResult =
|
|
||||||
when input is
|
|
||||||
[] -> 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
|
|
||||||
input = "B"
|
|
||||||
parser = letterParser
|
|
||||||
result = parseStr parser input
|
|
||||||
result == Ok B
|
|
||||||
|
|
||||||
expect
|
|
||||||
input = "BCXA"
|
|
||||||
parser = many letterParser
|
|
||||||
result = parseStr parser input
|
|
||||||
result == Ok [B, C, Other, A]
|
|
|
@ -1,63 +0,0 @@
|
||||||
app [main] {
|
|
||||||
pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br",
|
|
||||||
parser: "https://github.com/lukewilliamboswell/roc-parser/releases/download/0.5.2/9VrPjwfQQ1QeSL3CfmWr2Pr9DESdDIXy97pwpuq84Ck.tar.br",
|
|
||||||
}
|
|
||||||
|
|
||||||
import pf.Stdout
|
|
||||||
import pf.Stderr
|
|
||||||
import parser.Core exposing [map, keep]
|
|
||||||
import parser.String exposing [strFromUtf8]
|
|
||||||
import parser.CSV
|
|
||||||
|
|
||||||
input : Str
|
|
||||||
input = "Airplane!,1980,\"Robert Hays,Julie Hagerty\"\r\nCaddyshack,1980,\"Chevy Chase,Rodney Dangerfield,Ted Knight,Michael O'Keefe,Bill Murray\""
|
|
||||||
|
|
||||||
main =
|
|
||||||
when CSV.parseStr movieInfoParser input is
|
|
||||||
Ok movies ->
|
|
||||||
moviesString =
|
|
||||||
movies
|
|
||||||
|> List.map movieInfoExplanation
|
|
||||||
|> Str.joinWith ("\n")
|
|
||||||
nMovies = List.len movies |> Num.toStr
|
|
||||||
|
|
||||||
Stdout.line "$(nMovies) movies were found:\n\n$(moviesString)\n\nParse success!\n"
|
|
||||||
|
|
||||||
Err problem ->
|
|
||||||
when problem is
|
|
||||||
ParsingFailure failure ->
|
|
||||||
Stderr.line "Parsing failure: $(failure)\n"
|
|
||||||
|
|
||||||
ParsingIncomplete leftover ->
|
|
||||||
leftoverStr = leftover |> List.map strFromUtf8 |> List.map (\val -> "\"$(val)\"") |> Str.joinWith ", "
|
|
||||||
|
|
||||||
Stderr.line "Parsing incomplete. Following leftover fields while parsing a record: $(leftoverStr)\n"
|
|
||||||
|
|
||||||
SyntaxError error ->
|
|
||||||
Stderr.line "Parsing failure. Syntax error in the CSV: $(error)"
|
|
||||||
|
|
||||||
MovieInfo := { title : Str, releaseYear : U64, actors : List Str }
|
|
||||||
|
|
||||||
movieInfoParser =
|
|
||||||
CSV.record (\title -> \releaseYear -> \actors -> @MovieInfo { title, releaseYear, actors })
|
|
||||||
|> keep (CSV.field CSV.string)
|
|
||||||
|> keep (CSV.field CSV.u64)
|
|
||||||
|> keep (CSV.field actorsParser)
|
|
||||||
|
|
||||||
actorsParser =
|
|
||||||
CSV.string
|
|
||||||
|> map \val -> Str.split val ","
|
|
||||||
|
|
||||||
movieInfoExplanation = \@MovieInfo { title, releaseYear, actors } ->
|
|
||||||
enumeratedActors = enumerate actors
|
|
||||||
releaseYearStr = Num.toStr releaseYear
|
|
||||||
|
|
||||||
"The movie '$(title)' was released in $(releaseYearStr) and stars $(enumeratedActors)"
|
|
||||||
|
|
||||||
enumerate : List Str -> Str
|
|
||||||
enumerate = \elements ->
|
|
||||||
{ before: inits, others: last } = List.splitAt elements (List.len elements - 1)
|
|
||||||
|
|
||||||
last
|
|
||||||
|> List.prepend (inits |> Str.joinWith ", ")
|
|
||||||
|> Str.joinWith " and "
|
|
|
@ -1 +0,0 @@
|
||||||
Used by ingested-file-bytes.roc and ingested-file-bytes-no-ann.roc
|
|
File diff suppressed because it is too large
Load diff
1435
crates/cli/tests/cli_tests.rs
Normal file
1435
crates/cli/tests/cli_tests.rs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,9 +0,0 @@
|
||||||
interface Transitive
|
|
||||||
exposes [
|
|
||||||
add,
|
|
||||||
]
|
|
||||||
imports []
|
|
||||||
|
|
||||||
add = \num1, num2 -> (num1 + num2)
|
|
||||||
|
|
||||||
expect add 1 2 == 3
|
|
|
@ -1,5 +0,0 @@
|
||||||
package "transitive-tests"
|
|
||||||
exposes [
|
|
||||||
Direct,
|
|
||||||
]
|
|
||||||
packages {}
|
|
|
@ -1,4 +0,0 @@
|
||||||
interface Dep1 exposes [str1] imports [Dep2]
|
|
||||||
|
|
||||||
str1 : Str
|
|
||||||
str1 = Dep2.str2
|
|
|
@ -1,4 +0,0 @@
|
||||||
interface Dep2 exposes [str2] imports []
|
|
||||||
|
|
||||||
str2 : Str
|
|
||||||
str2 = "I am Dep2.str2"
|
|
|
@ -1,7 +0,0 @@
|
||||||
app "multi-dep-str"
|
|
||||||
packages { pf: "platform/main.roc" }
|
|
||||||
imports [Dep1]
|
|
||||||
provides [main] to pf
|
|
||||||
|
|
||||||
main : Str
|
|
||||||
main = Dep1.str1
|
|
|
@ -1,119 +0,0 @@
|
||||||
const std = @import("std");
|
|
||||||
const builtin = @import("builtin");
|
|
||||||
const str = @import("glue").str;
|
|
||||||
const RocStr = str.RocStr;
|
|
||||||
const testing = std.testing;
|
|
||||||
const expectEqual = testing.expectEqual;
|
|
||||||
const expect = testing.expect;
|
|
||||||
|
|
||||||
const mem = std.mem;
|
|
||||||
const Allocator = mem.Allocator;
|
|
||||||
|
|
||||||
extern fn roc__mainForHost_1_exposed_generic(*RocStr) void;
|
|
||||||
|
|
||||||
const Align = 2 * @alignOf(usize);
|
|
||||||
extern fn malloc(size: usize) callconv(.C) ?*align(Align) anyopaque;
|
|
||||||
extern fn realloc(c_ptr: [*]align(Align) u8, size: usize) callconv(.C) ?*anyopaque;
|
|
||||||
extern fn free(c_ptr: [*]align(Align) u8) callconv(.C) void;
|
|
||||||
extern fn memcpy(dst: [*]u8, src: [*]u8, size: usize) callconv(.C) void;
|
|
||||||
extern fn memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void;
|
|
||||||
|
|
||||||
export fn roc_alloc(size: usize, alignment: u32) callconv(.C) ?*anyopaque {
|
|
||||||
_ = alignment;
|
|
||||||
return malloc(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn roc_realloc(c_ptr: *anyopaque, new_size: usize, old_size: usize, alignment: u32) callconv(.C) ?*anyopaque {
|
|
||||||
_ = old_size;
|
|
||||||
_ = alignment;
|
|
||||||
return realloc(@as([*]align(Align) u8, @alignCast(@ptrCast(c_ptr))), new_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn roc_dealloc(c_ptr: *anyopaque, alignment: u32) callconv(.C) void {
|
|
||||||
_ = alignment;
|
|
||||||
free(@as([*]align(Align) u8, @alignCast(@ptrCast(c_ptr))));
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn roc_memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void {
|
|
||||||
return memset(dst, value, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn roc_panic(msg: *RocStr, tag_id: u32) callconv(.C) void {
|
|
||||||
const stderr = std.io.getStdErr().writer();
|
|
||||||
switch (tag_id) {
|
|
||||||
0 => {
|
|
||||||
stderr.print("Roc standard library crashed with message\n\n {s}\n\nShutting down\n", .{msg.asSlice()}) catch unreachable;
|
|
||||||
},
|
|
||||||
1 => {
|
|
||||||
stderr.print("Application crashed with message\n\n {s}\n\nShutting down\n", .{msg.asSlice()}) catch unreachable;
|
|
||||||
},
|
|
||||||
else => unreachable,
|
|
||||||
}
|
|
||||||
std.process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn roc_dbg(loc: *RocStr, msg: *RocStr, src: *RocStr) callconv(.C) void {
|
|
||||||
const stderr = std.io.getStdErr().writer();
|
|
||||||
stderr.print("[{s}] {s} = {s}\n", .{ loc.asSlice(), src.asSlice(), msg.asSlice() }) catch unreachable;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern fn kill(pid: c_int, sig: c_int) c_int;
|
|
||||||
extern fn shm_open(name: *const i8, oflag: c_int, mode: c_uint) c_int;
|
|
||||||
extern fn mmap(addr: ?*anyopaque, length: c_uint, prot: c_int, flags: c_int, fd: c_int, offset: c_uint) *anyopaque;
|
|
||||||
extern fn getppid() c_int;
|
|
||||||
|
|
||||||
fn roc_getppid() callconv(.C) c_int {
|
|
||||||
return getppid();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn roc_getppid_windows_stub() callconv(.C) c_int {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn roc_shm_open(name: *const i8, oflag: c_int, mode: c_uint) callconv(.C) c_int {
|
|
||||||
return shm_open(name, oflag, mode);
|
|
||||||
}
|
|
||||||
fn roc_mmap(addr: ?*anyopaque, length: c_uint, prot: c_int, flags: c_int, fd: c_int, offset: c_uint) callconv(.C) *anyopaque {
|
|
||||||
return mmap(addr, length, prot, flags, fd, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
comptime {
|
|
||||||
if (builtin.os.tag == .macos or builtin.os.tag == .linux) {
|
|
||||||
@export(roc_getppid, .{ .name = "roc_getppid", .linkage = .Strong });
|
|
||||||
@export(roc_mmap, .{ .name = "roc_mmap", .linkage = .Strong });
|
|
||||||
@export(roc_shm_open, .{ .name = "roc_shm_open", .linkage = .Strong });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (builtin.os.tag == .windows) {
|
|
||||||
@export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .Strong });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const Unit = extern struct {};
|
|
||||||
|
|
||||||
pub export fn main() i32 {
|
|
||||||
const stdout = std.io.getStdOut().writer();
|
|
||||||
const stderr = std.io.getStdErr().writer();
|
|
||||||
|
|
||||||
var timer = std.time.Timer.start() catch unreachable;
|
|
||||||
|
|
||||||
// actually call roc to populate the callresult
|
|
||||||
var callresult = RocStr.empty();
|
|
||||||
roc__mainForHost_1_exposed_generic(&callresult);
|
|
||||||
|
|
||||||
const nanos = timer.read();
|
|
||||||
const seconds = (@as(f64, @floatFromInt(nanos)) / 1_000_000_000.0);
|
|
||||||
|
|
||||||
// stdout the result
|
|
||||||
stdout.print("{s}\n", .{callresult.asSlice()}) catch unreachable;
|
|
||||||
|
|
||||||
callresult.decref();
|
|
||||||
|
|
||||||
stderr.print("runtime: {d:.3}ms\n", .{seconds * 1000}) catch unreachable;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_seconds(tms: std.os.timespec) f64 {
|
|
||||||
return @as(f64, @floatFromInt(tms.tv_sec)) + (@as(f64, @floatFromInt(tms.tv_nsec)) / 1_000_000_000.0);
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
platform "multi-module"
|
|
||||||
requires {}{ main : Str }
|
|
||||||
exposes []
|
|
||||||
packages {}
|
|
||||||
imports []
|
|
||||||
provides [mainForHost]
|
|
||||||
|
|
||||||
mainForHost : Str
|
|
||||||
mainForHost = main
|
|
|
@ -1,7 +0,0 @@
|
||||||
app "multi-dep-thunk"
|
|
||||||
packages { pf: "platform/main.roc" }
|
|
||||||
imports [Dep1]
|
|
||||||
provides [main] to pf
|
|
||||||
|
|
||||||
main : Str
|
|
||||||
main = Dep1.value1 {}
|
|
|
@ -1,119 +0,0 @@
|
||||||
const std = @import("std");
|
|
||||||
const builtin = @import("builtin");
|
|
||||||
const str = @import("glue").str;
|
|
||||||
const RocStr = str.RocStr;
|
|
||||||
const testing = std.testing;
|
|
||||||
const expectEqual = testing.expectEqual;
|
|
||||||
const expect = testing.expect;
|
|
||||||
|
|
||||||
const mem = std.mem;
|
|
||||||
const Allocator = mem.Allocator;
|
|
||||||
|
|
||||||
extern fn roc__mainForHost_1_exposed_generic(*RocStr) void;
|
|
||||||
|
|
||||||
const Align = 2 * @alignOf(usize);
|
|
||||||
extern fn malloc(size: usize) callconv(.C) ?*anyopaque;
|
|
||||||
extern fn realloc(c_ptr: [*]align(@alignOf(u128)) u8, size: usize) callconv(.C) ?*anyopaque;
|
|
||||||
extern fn free(c_ptr: [*]align(@alignOf(u128)) u8) callconv(.C) void;
|
|
||||||
extern fn memcpy(dst: [*]u8, src: [*]u8, size: usize) callconv(.C) void;
|
|
||||||
extern fn memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void;
|
|
||||||
|
|
||||||
export fn roc_alloc(size: usize, alignment: u32) callconv(.C) ?*anyopaque {
|
|
||||||
_ = alignment;
|
|
||||||
return malloc(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn roc_realloc(c_ptr: *anyopaque, new_size: usize, old_size: usize, alignment: u32) callconv(.C) ?*anyopaque {
|
|
||||||
_ = old_size;
|
|
||||||
_ = alignment;
|
|
||||||
return realloc(@as([*]align(Align) u8, @alignCast(@ptrCast(c_ptr))), new_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn roc_dealloc(c_ptr: *anyopaque, alignment: u32) callconv(.C) void {
|
|
||||||
_ = alignment;
|
|
||||||
free(@as([*]align(Align) u8, @alignCast(@ptrCast(c_ptr))));
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn roc_memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void {
|
|
||||||
return memset(dst, value, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn roc_panic(msg: *RocStr, tag_id: u32) callconv(.C) void {
|
|
||||||
const stderr = std.io.getStdErr().writer();
|
|
||||||
switch (tag_id) {
|
|
||||||
0 => {
|
|
||||||
stderr.print("Roc standard library crashed with message\n\n {s}\n\nShutting down\n", .{msg.asSlice()}) catch unreachable;
|
|
||||||
},
|
|
||||||
1 => {
|
|
||||||
stderr.print("Application crashed with message\n\n {s}\n\nShutting down\n", .{msg.asSlice()}) catch unreachable;
|
|
||||||
},
|
|
||||||
else => unreachable,
|
|
||||||
}
|
|
||||||
std.process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn roc_dbg(loc: *RocStr, msg: *RocStr, src: *RocStr) callconv(.C) void {
|
|
||||||
const stderr = std.io.getStdErr().writer();
|
|
||||||
stderr.print("[{s}] {s} = {s}\n", .{ loc.asSlice(), src.asSlice(), msg.asSlice() }) catch unreachable;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern fn kill(pid: c_int, sig: c_int) c_int;
|
|
||||||
extern fn shm_open(name: *const i8, oflag: c_int, mode: c_uint) c_int;
|
|
||||||
extern fn mmap(addr: ?*anyopaque, length: c_uint, prot: c_int, flags: c_int, fd: c_int, offset: c_uint) *anyopaque;
|
|
||||||
extern fn getppid() c_int;
|
|
||||||
|
|
||||||
fn roc_getppid() callconv(.C) c_int {
|
|
||||||
return getppid();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn roc_getppid_windows_stub() callconv(.C) c_int {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn roc_shm_open(name: *const i8, oflag: c_int, mode: c_uint) callconv(.C) c_int {
|
|
||||||
return shm_open(name, oflag, mode);
|
|
||||||
}
|
|
||||||
fn roc_mmap(addr: ?*anyopaque, length: c_uint, prot: c_int, flags: c_int, fd: c_int, offset: c_uint) callconv(.C) *anyopaque {
|
|
||||||
return mmap(addr, length, prot, flags, fd, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
comptime {
|
|
||||||
if (builtin.os.tag == .macos or builtin.os.tag == .linux) {
|
|
||||||
@export(roc_getppid, .{ .name = "roc_getppid", .linkage = .Strong });
|
|
||||||
@export(roc_mmap, .{ .name = "roc_mmap", .linkage = .Strong });
|
|
||||||
@export(roc_shm_open, .{ .name = "roc_shm_open", .linkage = .Strong });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (builtin.os.tag == .windows) {
|
|
||||||
@export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .Strong });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const Unit = extern struct {};
|
|
||||||
|
|
||||||
pub export fn main() i32 {
|
|
||||||
const stdout = std.io.getStdOut().writer();
|
|
||||||
const stderr = std.io.getStdErr().writer();
|
|
||||||
|
|
||||||
var timer = std.time.Timer.start() catch unreachable;
|
|
||||||
|
|
||||||
// actually call roc to populate the callresult
|
|
||||||
var callresult = RocStr.empty();
|
|
||||||
roc__mainForHost_1_exposed_generic(&callresult);
|
|
||||||
|
|
||||||
const nanos = timer.read();
|
|
||||||
const seconds = (@as(f64, @floatFromInt(nanos)) / 1_000_000_000.0);
|
|
||||||
|
|
||||||
// stdout the result
|
|
||||||
stdout.print("{s}\n", .{callresult.asSlice()}) catch unreachable;
|
|
||||||
|
|
||||||
callresult.decref();
|
|
||||||
|
|
||||||
stderr.print("runtime: {d:.3}ms\n", .{seconds * 1000}) catch unreachable;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_seconds(tms: std.os.timespec) f64 {
|
|
||||||
return @as(f64, @floatFromInt(tms.tv_sec)) + (@as(f64, @floatFromInt(tms.tv_nsec)) / 1_000_000_000.0);
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
platform "multi-dep-thunk"
|
|
||||||
requires {}{ main : Str }
|
|
||||||
exposes []
|
|
||||||
packages {}
|
|
||||||
imports []
|
|
||||||
provides [mainForHost]
|
|
||||||
|
|
||||||
mainForHost : Str
|
|
||||||
mainForHost = main
|
|
6
crates/cli/tests/fixtures/packages/app.roc
vendored
6
crates/cli/tests/fixtures/packages/app.roc
vendored
|
@ -1,6 +0,0 @@
|
||||||
app "packages-test"
|
|
||||||
packages { pf: "platform/main.roc", json: "json/main.roc", csv: "csv/main.roc" }
|
|
||||||
imports [json.JsonParser, csv.Csv]
|
|
||||||
provides [main] to pf
|
|
||||||
|
|
||||||
main = "Hello, World! $(JsonParser.example) $(Csv.example)"
|
|
|
@ -1,6 +0,0 @@
|
||||||
interface Csv
|
|
||||||
exposes [example]
|
|
||||||
imports []
|
|
||||||
|
|
||||||
example : Str
|
|
||||||
example = "This text came from a CSV package!"
|
|
|
@ -1,6 +0,0 @@
|
||||||
interface JsonParser
|
|
||||||
exposes [example]
|
|
||||||
imports []
|
|
||||||
|
|
||||||
example : Str
|
|
||||||
example = "This text came from a package!"
|
|
|
@ -1,9 +0,0 @@
|
||||||
platform "multi-module"
|
|
||||||
requires {}{ main : Str }
|
|
||||||
exposes []
|
|
||||||
packages {}
|
|
||||||
imports []
|
|
||||||
provides [mainForHost]
|
|
||||||
|
|
||||||
mainForHost : Str
|
|
||||||
mainForHost = main
|
|
|
@ -1,10 +0,0 @@
|
||||||
app [main] {
|
|
||||||
pf: platform "../packages/platform/main.roc",
|
|
||||||
one: "one/main.roc",
|
|
||||||
two: "two/main.roc",
|
|
||||||
}
|
|
||||||
|
|
||||||
import one.One
|
|
||||||
import two.Two
|
|
||||||
|
|
||||||
main = "$(One.example) | $(Two.example)"
|
|
|
@ -1,8 +0,0 @@
|
||||||
app [main] {
|
|
||||||
pf: platform "../packages/platform/main.roc",
|
|
||||||
one: "one/main.roc",
|
|
||||||
}
|
|
||||||
|
|
||||||
import one.One
|
|
||||||
|
|
||||||
main = One.example
|
|
|
@ -1,8 +0,0 @@
|
||||||
app [main] {
|
|
||||||
pf: platform "../packages/platform/main.roc",
|
|
||||||
zero: "zero/main.roc",
|
|
||||||
}
|
|
||||||
|
|
||||||
import zero.Zero
|
|
||||||
|
|
||||||
main = Zero.example
|
|
|
@ -1,3 +0,0 @@
|
||||||
package [Zero] {
|
|
||||||
one: "../one/main.roc"
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
interface ExposedNotDefined
|
|
||||||
exposes [bar]
|
|
||||||
imports []
|
|
|
@ -1,7 +0,0 @@
|
||||||
interface UnusedImport
|
|
||||||
exposes [plainText, emText]
|
|
||||||
imports [Symbol.{ Ident }]
|
|
||||||
|
|
||||||
plainText = \str -> PlainText str
|
|
||||||
|
|
||||||
emText = \str -> EmText str
|
|
|
@ -1,7 +0,0 @@
|
||||||
interface UnusedImportButWithALongFileNameForTesting
|
|
||||||
exposes [plainText, emText]
|
|
||||||
imports [Symbol.{ Ident }]
|
|
||||||
|
|
||||||
plainText = \str -> PlainText str
|
|
||||||
|
|
||||||
emText = \str -> EmText str
|
|
17
crates/cli/tests/markdown/form.md
Normal file
17
crates/cli/tests/markdown/form.md
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
# A Simple Markdown Example
|
||||||
|
|
||||||
|
This file contains `form.roc` embedded as a block in Markdown. It lets us test that `roc check` works with Markdown.
|
||||||
|
|
||||||
|
```roc
|
||||||
|
module [foo]
|
||||||
|
|
||||||
|
foo = "Foo"
|
||||||
|
```
|
||||||
|
|
||||||
|
Excitingly, we can have another block of Roc code as well! (In this case it is the same one...)
|
||||||
|
|
||||||
|
```roc
|
||||||
|
module [bar]
|
||||||
|
|
||||||
|
bar = "Bar"
|
||||||
|
```
|
|
@ -1,8 +0,0 @@
|
||||||
module {
|
|
||||||
sendHttpReq,
|
|
||||||
getEnvVar
|
|
||||||
} -> [hi]
|
|
||||||
|
|
||||||
hi : Str
|
|
||||||
hi =
|
|
||||||
"hi"
|
|
|
@ -1,8 +0,0 @@
|
||||||
app [main] {
|
|
||||||
pf: platform "../fixtures/multi-dep-str/platform/main.roc",
|
|
||||||
}
|
|
||||||
|
|
||||||
import BadAnn { appId: "one" }
|
|
||||||
|
|
||||||
main =
|
|
||||||
""
|
|
|
@ -1,6 +0,0 @@
|
||||||
app [main] {
|
|
||||||
pf: platform "./platform/main.roc"
|
|
||||||
}
|
|
||||||
|
|
||||||
main =
|
|
||||||
"from app"
|
|
|
@ -1,129 +0,0 @@
|
||||||
const std = @import("std");
|
|
||||||
const builtin = @import("builtin");
|
|
||||||
const str = @import("glue").str;
|
|
||||||
const RocStr = str.RocStr;
|
|
||||||
const testing = std.testing;
|
|
||||||
const expectEqual = testing.expectEqual;
|
|
||||||
const expect = testing.expect;
|
|
||||||
|
|
||||||
const Align = 2 * @alignOf(usize);
|
|
||||||
extern fn malloc(size: usize) callconv(.C) ?*align(Align) anyopaque;
|
|
||||||
extern fn realloc(c_ptr: [*]align(Align) u8, size: usize) callconv(.C) ?*anyopaque;
|
|
||||||
extern fn free(c_ptr: [*]align(Align) u8) callconv(.C) void;
|
|
||||||
extern fn memcpy(dst: [*]u8, src: [*]u8, size: usize) callconv(.C) void;
|
|
||||||
extern fn memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void;
|
|
||||||
|
|
||||||
const DEBUG: bool = false;
|
|
||||||
|
|
||||||
export fn roc_alloc(size: usize, alignment: u32) callconv(.C) ?*anyopaque {
|
|
||||||
if (DEBUG) {
|
|
||||||
var ptr = malloc(size);
|
|
||||||
const stdout = std.io.getStdOut().writer();
|
|
||||||
stdout.print("alloc: {d} (alignment {d}, size {d})\n", .{ ptr, alignment, size }) catch unreachable;
|
|
||||||
return ptr;
|
|
||||||
} else {
|
|
||||||
return malloc(size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn roc_realloc(c_ptr: *anyopaque, new_size: usize, old_size: usize, alignment: u32) callconv(.C) ?*anyopaque {
|
|
||||||
if (DEBUG) {
|
|
||||||
const stdout = std.io.getStdOut().writer();
|
|
||||||
stdout.print("realloc: {d} (alignment {d}, old_size {d})\n", .{ c_ptr, alignment, old_size }) catch unreachable;
|
|
||||||
}
|
|
||||||
|
|
||||||
return realloc(@as([*]align(Align) u8, @alignCast(@ptrCast(c_ptr))), new_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn roc_dealloc(c_ptr: *anyopaque, alignment: u32) callconv(.C) void {
|
|
||||||
if (DEBUG) {
|
|
||||||
const stdout = std.io.getStdOut().writer();
|
|
||||||
stdout.print("dealloc: {d} (alignment {d})\n", .{ c_ptr, alignment }) catch unreachable;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(@as([*]align(Align) u8, @alignCast(@ptrCast(c_ptr))));
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn roc_panic(msg: *RocStr, tag_id: u32) callconv(.C) void {
|
|
||||||
_ = tag_id;
|
|
||||||
|
|
||||||
const stderr = std.io.getStdErr().writer();
|
|
||||||
stderr.print("Application crashed with message\n\n {s}\n\nShutting down\n", .{msg.asSlice()}) catch unreachable;
|
|
||||||
std.process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn roc_dbg(loc: *RocStr, msg: *RocStr, src: *RocStr) callconv(.C) void {
|
|
||||||
// This platform uses stdout for testing purposes instead of the normal stderr.
|
|
||||||
const stdout = std.io.getStdOut().writer();
|
|
||||||
stdout.print("[{s}] {s} = {s}\n", .{ loc.asSlice(), src.asSlice(), msg.asSlice() }) catch unreachable;
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn roc_memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void {
|
|
||||||
return memset(dst, value, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern fn kill(pid: c_int, sig: c_int) c_int;
|
|
||||||
extern fn shm_open(name: *const i8, oflag: c_int, mode: c_uint) c_int;
|
|
||||||
extern fn mmap(addr: ?*anyopaque, length: c_uint, prot: c_int, flags: c_int, fd: c_int, offset: c_uint) *anyopaque;
|
|
||||||
extern fn getppid() c_int;
|
|
||||||
|
|
||||||
fn roc_getppid() callconv(.C) c_int {
|
|
||||||
return getppid();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn roc_getppid_windows_stub() callconv(.C) c_int {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn roc_send_signal(pid: c_int, sig: c_int) callconv(.C) c_int {
|
|
||||||
return kill(pid, sig);
|
|
||||||
}
|
|
||||||
fn roc_shm_open(name: *const i8, oflag: c_int, mode: c_uint) callconv(.C) c_int {
|
|
||||||
return shm_open(name, oflag, mode);
|
|
||||||
}
|
|
||||||
fn roc_mmap(addr: ?*anyopaque, length: c_uint, prot: c_int, flags: c_int, fd: c_int, offset: c_uint) callconv(.C) *anyopaque {
|
|
||||||
return mmap(addr, length, prot, flags, fd, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
comptime {
|
|
||||||
if (builtin.os.tag == .macos or builtin.os.tag == .linux) {
|
|
||||||
@export(roc_getppid, .{ .name = "roc_getppid", .linkage = .Strong });
|
|
||||||
@export(roc_mmap, .{ .name = "roc_mmap", .linkage = .Strong });
|
|
||||||
@export(roc_send_signal, .{ .name = "roc_send_signal", .linkage = .Strong });
|
|
||||||
@export(roc_shm_open, .{ .name = "roc_shm_open", .linkage = .Strong });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (builtin.os.tag == .windows) {
|
|
||||||
@export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .Strong });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const mem = std.mem;
|
|
||||||
const Allocator = mem.Allocator;
|
|
||||||
|
|
||||||
extern fn roc__mainForHost_1_exposed_generic(*RocStr) void;
|
|
||||||
|
|
||||||
const Unit = extern struct {};
|
|
||||||
|
|
||||||
pub fn main() u8 {
|
|
||||||
const stdout = std.io.getStdOut().writer();
|
|
||||||
const stderr = std.io.getStdErr().writer();
|
|
||||||
|
|
||||||
var timer = std.time.Timer.start() catch unreachable;
|
|
||||||
|
|
||||||
// actually call roc to populate the callresult
|
|
||||||
var callresult = RocStr.empty();
|
|
||||||
roc__mainForHost_1_exposed_generic(&callresult);
|
|
||||||
|
|
||||||
const nanos = timer.read();
|
|
||||||
const seconds = (@as(f64, @floatFromInt(nanos)) / 1_000_000_000.0);
|
|
||||||
|
|
||||||
// stdout the result
|
|
||||||
stdout.print("{s}", .{callresult.asSlice()}) catch unreachable;
|
|
||||||
|
|
||||||
callresult.decref();
|
|
||||||
|
|
||||||
stderr.print("runtime: {d:.3}ms\n", .{seconds * 1000}) catch unreachable;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
---
|
||||||
|
source: crates/cli/tests/cli_tests.rs
|
||||||
|
expression: cli_check_out.normalize_stdout_and_stderr()
|
||||||
|
---
|
||||||
|
|
||||||
|
── MISSING DEFINITION in tests/test-projects/known_bad/ExposedNotDefined.roc ───
|
||||||
|
|
||||||
|
bar is listed as exposed, but it isn't defined in this module.
|
||||||
|
|
||||||
|
You can fix this by adding a definition for bar, or by removing it
|
||||||
|
from exposes.
|
||||||
|
|
||||||
|
────────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
1 error and 0 warning found in <ignored for test> ms
|
|
@ -0,0 +1,28 @@
|
||||||
|
---
|
||||||
|
source: crates/cli/tests/cli_tests.rs
|
||||||
|
expression: cli_check_out.normalize_stdout_and_stderr()
|
||||||
|
---
|
||||||
|
|
||||||
|
── TYPE MISMATCH in tests/test-projects/known_bad/TypeError.roc ────────────────
|
||||||
|
|
||||||
|
Something is off with the body of the main definition:
|
||||||
|
|
||||||
|
3│ main : Str -> Task {} []
|
||||||
|
4│ main = \_ ->
|
||||||
|
5│ "this is a string, not a Task {} [] function like the platform expects."
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The body is a string of type:
|
||||||
|
|
||||||
|
Str
|
||||||
|
|
||||||
|
But the type annotation on main says it should be:
|
||||||
|
|
||||||
|
Task {} []
|
||||||
|
|
||||||
|
Tip: Add type annotations to functions or values to help you figure
|
||||||
|
this out.
|
||||||
|
|
||||||
|
────────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
1 error and 0 warning found in <ignored for test> ms
|
|
@ -0,0 +1,17 @@
|
||||||
|
---
|
||||||
|
source: crates/cli/tests/cli_tests.rs
|
||||||
|
expression: cli_check_out.normalize_stdout_and_stderr()
|
||||||
|
---
|
||||||
|
|
||||||
|
── UNUSED IMPORT in ...nown_bad/UnusedImportButWithALongFileNameForTesting.roc ─
|
||||||
|
|
||||||
|
Symbol is imported but not used.
|
||||||
|
|
||||||
|
3│ import Symbol exposing [Ident]
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Since Symbol isn't used, you don't need to import it.
|
||||||
|
|
||||||
|
────────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
0 error and 1 warning found in <ignored for test> ms
|
|
@ -0,0 +1,18 @@
|
||||||
|
---
|
||||||
|
source: crates/cli/tests/cli_tests.rs
|
||||||
|
expression: cli_test_out.normalize_stdout_and_stderr()
|
||||||
|
---
|
||||||
|
── UNRECOGNIZED PACKAGE in tests/test-projects/module_imports_pkg/Module.roc ───
|
||||||
|
|
||||||
|
This module is trying to import from `pkg`:
|
||||||
|
|
||||||
|
3│ import pkg.Foo
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
A lowercase name indicates a package shorthand, but I don't know which
|
||||||
|
packages are available.
|
||||||
|
|
||||||
|
When checking a module directly, I look for a `main.roc` app or
|
||||||
|
package to resolve shorthands from.
|
||||||
|
|
||||||
|
You can create it, or specify an existing one with the --main flag.
|
|
@ -0,0 +1,21 @@
|
||||||
|
---
|
||||||
|
source: crates/cli/tests/cli_tests.rs
|
||||||
|
expression: cli_test_out.normalize_stdout_and_stderr()
|
||||||
|
---
|
||||||
|
── UNRECOGNIZED PACKAGE in ...rojects/module_imports_pkg/ImportsUnknownPkg.roc ─
|
||||||
|
|
||||||
|
This module is trying to import from `cli`:
|
||||||
|
|
||||||
|
3│ import cli.Foo
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
A lowercase name indicates a package shorthand, but I don't recognize
|
||||||
|
this one. Did you mean one of these?
|
||||||
|
|
||||||
|
pkg
|
||||||
|
|
||||||
|
Note: I'm using the following module to resolve package shorthands:
|
||||||
|
|
||||||
|
tests/test-projects/module_imports_pkg/app.roc
|
||||||
|
|
||||||
|
You can specify a different one with the --main flag.
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
source: crates/cli/tests/cli_tests.rs
|
||||||
|
expression: out.normalize_stdout_and_stderr()
|
||||||
|
---
|
||||||
|
(@Community {friends: [{2}, {2}, {0, 1}], people: [(@Person {age: 27, favoriteColor: Blue, firstName: \"John\", hasBeard: Bool.true, lastName: \"Smith\"}), (@Person {age: 47, favoriteColor: Green, firstName: \"Debby\", hasBeard: Bool.false, lastName: \"Johnson\"}), (@Person {age: 33, favoriteColor: (RGB (255, 255, 0)), firstName: \"Jane\", hasBeard: Bool.false, lastName: \"Doe\"})]})
|
|
@ -0,0 +1,24 @@
|
||||||
|
---
|
||||||
|
source: crates/cli/tests/cli_tests.rs
|
||||||
|
expression: cli_dev_out.normalize_stdout_and_stderr()
|
||||||
|
---
|
||||||
|
── EXPECT FAILED in tests/test-projects/expects/expects.roc ────────────────────
|
||||||
|
|
||||||
|
This expectation failed:
|
||||||
|
|
||||||
|
25│ expect words == []
|
||||||
|
^^^^^^^^^^^
|
||||||
|
|
||||||
|
When it failed, these variables had these values:
|
||||||
|
|
||||||
|
words : List Str
|
||||||
|
words = ["this", "will", "for", "sure", "be", "a", "large", "string", "so", "when", "we", "split", "it", "it", "will", "use", "seamless", "slices", "which", "affect", "printing"]
|
||||||
|
|
||||||
|
Program finished!
|
||||||
|
|
||||||
|
[<ignored for tests>:28] x = 42
|
||||||
|
[<ignored for tests>:30] "Fjoer en ferdjer frieten oan dyn geve lea" = "Fjoer en ferdjer frieten oan dyn geve lea"
|
||||||
|
[<ignored for tests>:32] "this is line 24" = "this is line 24"
|
||||||
|
[<ignored for tests>:18] x = "abc"
|
||||||
|
[<ignored for tests>:18] x = 10
|
||||||
|
[<ignored for tests>:18] x = (A (B C))
|
|
@ -0,0 +1,48 @@
|
||||||
|
---
|
||||||
|
source: crates/cli/tests/cli_tests.rs
|
||||||
|
expression: cli_test_out.normalize_stdout_and_stderr()
|
||||||
|
---
|
||||||
|
── EXPECT FAILED in tests/test-projects/expects/expects.roc ────────────────────
|
||||||
|
|
||||||
|
This expectation failed:
|
||||||
|
|
||||||
|
6│ expect a == 2
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
When it failed, these variables had these values:
|
||||||
|
|
||||||
|
a : Num *
|
||||||
|
a = 1
|
||||||
|
|
||||||
|
── EXPECT FAILED in tests/test-projects/expects/expects.roc ────────────────────
|
||||||
|
|
||||||
|
This expectation failed:
|
||||||
|
|
||||||
|
7│ expect a == 3
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
When it failed, these variables had these values:
|
||||||
|
|
||||||
|
a : Num *
|
||||||
|
a = 1
|
||||||
|
|
||||||
|
── EXPECT FAILED in tests/test-projects/expects/expects.roc ────────────────────
|
||||||
|
|
||||||
|
This expectation failed:
|
||||||
|
|
||||||
|
11│> expect
|
||||||
|
12│> a = makeA
|
||||||
|
13│> b = 2i64
|
||||||
|
14│>
|
||||||
|
15│> a == b
|
||||||
|
|
||||||
|
When it failed, these variables had these values:
|
||||||
|
|
||||||
|
a : Int Signed64
|
||||||
|
a = 1
|
||||||
|
|
||||||
|
b : I64
|
||||||
|
b = 2
|
||||||
|
|
||||||
|
|
||||||
|
1 failed and 0 passed in <ignored for test> ms.
|
|
@ -0,0 +1,33 @@
|
||||||
|
---
|
||||||
|
source: crates/cli/tests/cli_tests.rs
|
||||||
|
expression: cli_dev_out.normalize_stdout_and_stderr()
|
||||||
|
---
|
||||||
|
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"]
|
|
@ -0,0 +1,43 @@
|
||||||
|
---
|
||||||
|
source: crates/cli/tests/cli_tests.rs
|
||||||
|
assertion_line: 429
|
||||||
|
expression: cli_dev_out.normalize_stdout_and_stderr()
|
||||||
|
---
|
||||||
|
|
||||||
|
── TOO MANY ARGS in tests/test-projects/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/test-projects/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/test-projects/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 error and 0 warning found in <ignored for test> ms
|
||||||
|
.
|
||||||
|
|
||||||
|
You can run <ignored for tests>
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
---
|
||||||
|
source: crates/cli/tests/cli_tests.rs
|
||||||
|
assertion_line: 445
|
||||||
|
expression: cli_dev_out.normalize_stdout_and_stderr()
|
||||||
|
---
|
||||||
|
|
||||||
|
── TYPE MISMATCH in tests/test-projects/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/test-projects/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 error and 1 warning found in <ignored for test> ms
|
||||||
|
.
|
||||||
|
|
||||||
|
You can run <ignored for tests>
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
---
|
||||||
|
source: crates/cli/tests/cli_tests.rs
|
||||||
|
assertion_line: 476
|
||||||
|
expression: cli_dev_out.normalize_stdout_and_stderr()
|
||||||
|
---
|
||||||
|
|
||||||
|
── TYPE MISMATCH in tests/test-projects/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 warning found in <ignored for test> ms
|
||||||
|
.
|
||||||
|
|
||||||
|
You can run <ignored for tests>
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
---
|
||||||
|
source: crates/cli/tests/cli_tests.rs
|
||||||
|
expression: cli_test_out.normalize_stdout_and_stderr()
|
||||||
|
---
|
||||||
|
Compiled in <ignored for test> ms.
|
||||||
|
|
||||||
|
Direct.roc:
|
||||||
|
0 failed and 2 passed in <ignored for test> ms.
|
||||||
|
|
||||||
|
Transitive.roc:
|
||||||
|
0 failed and 1 passed in <ignored for test> ms.
|
|
@ -0,0 +1,17 @@
|
||||||
|
---
|
||||||
|
source: crates/cli/tests/cli_tests.rs
|
||||||
|
expression: cli_check_out.normalize_stdout_and_stderr()
|
||||||
|
---
|
||||||
|
|
||||||
|
── UNUSED IMPORT in tests/test-projects/known_bad/UnusedImport.roc ─────────────
|
||||||
|
|
||||||
|
Symbol is imported but not used.
|
||||||
|
|
||||||
|
3│ import Symbol exposing [Ident]
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Since Symbol isn't used, you don't need to import it.
|
||||||
|
|
||||||
|
────────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
0 error and 1 warning found in <ignored for test> ms
|
|
@ -110,18 +110,10 @@ comptime {
|
||||||
pub export fn main() u8 {
|
pub export fn main() u8 {
|
||||||
const stdout = std.io.getStdOut().writer();
|
const stdout = std.io.getStdOut().writer();
|
||||||
|
|
||||||
var timer = std.time.Timer.start() catch unreachable;
|
|
||||||
|
|
||||||
const result = roc__mainForHost_1_exposed(10);
|
const result = roc__mainForHost_1_exposed(10);
|
||||||
|
|
||||||
const nanos = timer.read();
|
|
||||||
const seconds = (@as(f64, @floatFromInt(nanos)) / 1_000_000_000.0);
|
|
||||||
|
|
||||||
stdout.print("{d}\n", .{result}) catch unreachable;
|
stdout.print("{d}\n", .{result}) catch unreachable;
|
||||||
|
|
||||||
const stderr = std.io.getStdErr().writer();
|
|
||||||
stderr.print("runtime: {d:.3}ms\n", .{seconds * 1000}) catch unreachable;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,8 +127,6 @@ pub export fn main() u8 {
|
||||||
|
|
||||||
var roc_list = RocList{ .elements = numbers, .length = NUM_NUMS, .capacity = NUM_NUMS };
|
var roc_list = RocList{ .elements = numbers, .length = NUM_NUMS, .capacity = NUM_NUMS };
|
||||||
|
|
||||||
var timer = std.time.Timer.start() catch unreachable;
|
|
||||||
|
|
||||||
// actually call roc to populate the callresult
|
// actually call roc to populate the callresult
|
||||||
const callresult: RocList = roc__mainForHost_1_exposed(roc_list);
|
const callresult: RocList = roc__mainForHost_1_exposed(roc_list);
|
||||||
|
|
||||||
|
@ -136,9 +134,6 @@ pub export fn main() u8 {
|
||||||
const length = @min(20, callresult.length);
|
const length = @min(20, callresult.length);
|
||||||
var result = callresult.elements[0..length];
|
var result = callresult.elements[0..length];
|
||||||
|
|
||||||
const nanos = timer.read();
|
|
||||||
const seconds = (@as(f64, @floatFromInt(nanos)) / 1_000_000_000.0);
|
|
||||||
|
|
||||||
for (result, 0..) |x, i| {
|
for (result, 0..) |x, i| {
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
stdout.print("[{}, ", .{x}) catch unreachable;
|
stdout.print("[{}, ", .{x}) catch unreachable;
|
||||||
|
@ -149,12 +144,5 @@ pub export fn main() u8 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const stderr = std.io.getStdErr().writer();
|
|
||||||
stderr.print("runtime: {d:.3}ms\n", .{seconds * 1000}) catch unreachable;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_seconds(tms: std.os.timespec) f64 {
|
|
||||||
return @as(f64, @floatFromInt(tms.tv_sec)) + (@as(f64, @floatFromInt(tms.tv_nsec)) / 1_000_000_000.0);
|
|
||||||
}
|
|
|
@ -1,7 +1,4 @@
|
||||||
app "quicksort"
|
app [quicksort] { pf: platform "quicksort-platform/main.roc" }
|
||||||
packages { pf: "quicksort-platform/main.roc" }
|
|
||||||
imports []
|
|
||||||
provides [quicksort] to pf
|
|
||||||
|
|
||||||
quicksort = \originalList ->
|
quicksort = \originalList ->
|
||||||
n = List.len originalList
|
n = List.len originalList
|
|
@ -1,4 +1,4 @@
|
||||||
app [main!] { pf: platform "../../../../examples/cli/effects-platform/main.roc" }
|
app [main!] { pf: platform "../test-platform-effects-zig/main.roc" }
|
||||||
|
|
||||||
import pf.Effect
|
import pf.Effect
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
app [main!] { pf: platform "../../../../examples/cli/effects-platform/main.roc" }
|
app [main!] { pf: platform "../test-platform-effects-zig/main.roc" }
|
||||||
|
|
||||||
import pf.Effect
|
import pf.Effect
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
app [main!] { pf: platform "../../../../examples/cli/effects-platform/main.roc" }
|
app [main!] { pf: platform "../test-platform-effects-zig/main.roc" }
|
||||||
|
|
||||||
import pf.Effect
|
import pf.Effect
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
#
|
#
|
||||||
# Shows how Roc values can be logged
|
# Shows how Roc values can be logged
|
||||||
#
|
#
|
||||||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.tar.br" }
|
app [main!] { pf: platform "../test-platform-effects-zig/main.roc" }
|
||||||
|
|
||||||
import pf.Stdout
|
import pf.Effect
|
||||||
import Community
|
import Community
|
||||||
|
|
||||||
main =
|
main! = \{} ->
|
||||||
Community.empty
|
Community.empty
|
||||||
|> Community.addPerson {
|
|> Community.addPerson {
|
||||||
firstName: "John",
|
firstName: "John",
|
||||||
|
@ -32,4 +32,4 @@ main =
|
||||||
|> Community.addFriend 0 2
|
|> Community.addFriend 0 2
|
||||||
|> Community.addFriend 1 2
|
|> Community.addFriend 1 2
|
||||||
|> Inspect.toStr
|
|> Inspect.toStr
|
||||||
|> Stdout.line!
|
|> Effect.putLine!
|
|
@ -1,4 +1,4 @@
|
||||||
app [main!] { pf: platform "../../../../examples/cli/effects-platform/main.roc" }
|
app [main!] { pf: platform "../test-platform-effects-zig/main.roc" }
|
||||||
|
|
||||||
import pf.Effect
|
import pf.Effect
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
app [main!] { pf: platform "effects-platform/main.roc" }
|
app [main!] { pf: platform "../test-platform-effects-zig/main.roc" }
|
||||||
|
|
||||||
import pf.Effect
|
import pf.Effect
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
app [main!] { pf: platform "../../../../examples/cli/effects-platform/main.roc" }
|
app [main!] { pf: platform "../test-platform-effects-zig/main.roc" }
|
||||||
|
|
||||||
import pf.Effect
|
import pf.Effect
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
app "expects-test"
|
app [main] { pf: platform "../test-platform-simple-zig/main.roc" }
|
||||||
packages { pf: "zig-platform/main.roc" }
|
|
||||||
imports []
|
|
||||||
provides [main] to pf
|
|
||||||
|
|
||||||
makeA =
|
makeA =
|
||||||
a = 1
|
a = 1
|
|
@ -1,10 +1,8 @@
|
||||||
interface Direct
|
module [
|
||||||
exposes [
|
addAndStringify,
|
||||||
addAndStringify,
|
]
|
||||||
]
|
|
||||||
imports [
|
import Transitive
|
||||||
Transitive,
|
|
||||||
]
|
|
||||||
|
|
||||||
addAndStringify = \num1, num2 ->
|
addAndStringify = \num1, num2 ->
|
||||||
Num.toStr (Transitive.add num1 num2)
|
Num.toStr (Transitive.add num1 num2)
|
|
@ -0,0 +1,7 @@
|
||||||
|
module [
|
||||||
|
add,
|
||||||
|
]
|
||||||
|
|
||||||
|
add = \num1, num2 -> (num1 + num2)
|
||||||
|
|
||||||
|
expect add 1 2 == 3
|
|
@ -0,0 +1,3 @@
|
||||||
|
package [
|
||||||
|
Direct,
|
||||||
|
] {}
|
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