mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-02 11:22:19 +00:00
Merge remote-tracking branch 'origin/main' into roc-dev-inline-expects
This commit is contained in:
commit
e62ab00c65
275 changed files with 4038 additions and 2432 deletions
2
.github/workflows/nightly_macos_x86_64.yml
vendored
2
.github/workflows/nightly_macos_x86_64.yml
vendored
|
@ -6,7 +6,7 @@ name: Nightly Release macOS x86_64
|
||||||
|
|
||||||
env:
|
env:
|
||||||
ZIG_VERSION: 0.9.1
|
ZIG_VERSION: 0.9.1
|
||||||
LLVM_SYS_130_PREFIX: /usr/local/opt/llvm
|
LLVM_SYS_130_PREFIX: /usr/local/opt/llvm@13
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test-build-upload:
|
test-build-upload:
|
||||||
|
|
|
@ -28,7 +28,7 @@ jobs:
|
||||||
run: ls | grep "roc_nightly.*tar\.gz" | xargs tar -xzvf
|
run: ls | grep "roc_nightly.*tar\.gz" | xargs tar -xzvf
|
||||||
|
|
||||||
- name: test roc hello world
|
- name: test roc hello world
|
||||||
run: ./roc examples/hello-world/main.roc
|
run: ./roc examples/helloWorld.roc
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
2
.github/workflows/test_nightly_many_os.yml
vendored
2
.github/workflows/test_nightly_many_os.yml
vendored
|
@ -41,7 +41,7 @@ jobs:
|
||||||
run: ls | grep "roc_nightly.*tar\.gz" | xargs tar -xzvf
|
run: ls | grep "roc_nightly.*tar\.gz" | xargs tar -xzvf
|
||||||
|
|
||||||
- name: test roc hello world
|
- name: test roc hello world
|
||||||
run: ./roc examples/hello-world/main.roc
|
run: ./roc examples/helloWorld.roc
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,13 +28,7 @@ sh <(curl -L https://nixos.org/nix/install) --no-daemon
|
||||||
sh <(curl -L https://nixos.org/nix/install) --daemon
|
sh <(curl -L https://nixos.org/nix/install) --daemon
|
||||||
```
|
```
|
||||||
|
|
||||||
Open a new terminal and install nixFlakes in your environment:
|
Open a new terminal and edit either `~/.config/nix/nix.conf` or `/etc/nix/nix.conf` and add:
|
||||||
|
|
||||||
```sh
|
|
||||||
nix-env -iA nixpkgs.nixFlakes
|
|
||||||
```
|
|
||||||
|
|
||||||
Edit either `~/.config/nix/nix.conf` or `/etc/nix/nix.conf` and add:
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
experimental-features = nix-command flakes
|
experimental-features = nix-command flakes
|
||||||
|
|
180
Cargo.lock
generated
180
Cargo.lock
generated
|
@ -75,15 +75,6 @@ dependencies = [
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ansi_term"
|
|
||||||
version = "0.12.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
|
|
||||||
dependencies = [
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "approx"
|
name = "approx"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
@ -253,34 +244,13 @@ version = "0.1.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
|
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "block-buffer"
|
|
||||||
version = "0.7.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
|
|
||||||
dependencies = [
|
|
||||||
"block-padding",
|
|
||||||
"byte-tools",
|
|
||||||
"byteorder",
|
|
||||||
"generic-array 0.12.4",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
version = "0.10.2"
|
version = "0.10.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
|
checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"generic-array 0.14.5",
|
"generic-array",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "block-padding"
|
|
||||||
version = "0.1.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
|
|
||||||
dependencies = [
|
|
||||||
"byte-tools",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -301,12 +271,6 @@ version = "3.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
|
checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "byte-tools"
|
|
||||||
version = "0.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytecheck"
|
name = "bytecheck"
|
||||||
version = "0.6.8"
|
version = "0.6.8"
|
||||||
|
@ -620,10 +584,10 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "confy"
|
name = "confy"
|
||||||
version = "0.4.0"
|
version = "0.5.0"
|
||||||
source = "git+https://github.com/rust-cli/confy#c6b62039281b8643539b436440bcea1b0d634bc7"
|
source = "git+https://github.com/rust-cli/confy#fd069f062aa3373c846f0d8c6e3b5e2a5cd0096b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"directories-next",
|
"directories",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_yaml",
|
"serde_yaml",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
@ -1023,7 +987,7 @@ version = "0.1.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2ccfd8c0ee4cce11e45b3fd6f9d5e69e0cc62912aa6a0cb1bf4617b0eba5a12f"
|
checksum = "2ccfd8c0ee4cce11e45b3fd6f9d5e69e0cc62912aa6a0cb1bf4617b0eba5a12f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"generic-array 0.14.5",
|
"generic-array",
|
||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1129,22 +1093,13 @@ version = "0.1.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
|
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "digest"
|
|
||||||
version = "0.8.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
|
|
||||||
dependencies = [
|
|
||||||
"generic-array 0.12.4",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "digest"
|
name = "digest"
|
||||||
version = "0.10.3"
|
version = "0.10.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
|
checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"block-buffer 0.10.2",
|
"block-buffer",
|
||||||
"crypto-common",
|
"crypto-common",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1160,13 +1115,13 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "directories-next"
|
name = "directories"
|
||||||
version = "2.0.0"
|
version = "2.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc"
|
checksum = "551a778172a450d7fc12e629ca3b0428d00f6afa9a43da1b630d54604e97371c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 0.1.10",
|
||||||
"dirs-sys-next",
|
"dirs-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1179,6 +1134,17 @@ dependencies = [
|
||||||
"dirs-sys-next",
|
"dirs-sys-next",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs-sys"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"redox_users",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs-sys-next"
|
name = "dirs-sys-next"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
|
@ -1231,9 +1197,9 @@ checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dunce"
|
name = "dunce"
|
||||||
version = "1.0.2"
|
version = "1.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "453440c271cf5577fd2a40e4942540cb7d0d2f85e27c8d07dd0023c925a67541"
|
checksum = "0bd4b30a6560bbd9b4620f4de34c3f14f60848e58a9b7216801afcb4c7b31c3c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dynasm"
|
name = "dynasm"
|
||||||
|
@ -1367,12 +1333,6 @@ dependencies = [
|
||||||
"str-buf",
|
"str-buf",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fake-simd"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fallible-iterator"
|
name = "fallible-iterator"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
@ -1564,15 +1524,6 @@ dependencies = [
|
||||||
"cfg-if 0.1.10",
|
"cfg-if 0.1.10",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "generic-array"
|
|
||||||
version = "0.12.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
|
|
||||||
dependencies = [
|
|
||||||
"typenum",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generic-array"
|
name = "generic-array"
|
||||||
version = "0.14.5"
|
version = "0.14.5"
|
||||||
|
@ -2438,6 +2389,16 @@ version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09f1f8e5676e1a1f2ee8b21f38238e1243c827531c9435624c7bfb305102cee4"
|
checksum = "09f1f8e5676e1a1f2ee8b21f38238e1243c827531c9435624c7bfb305102cee4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nu-ansi-term"
|
||||||
|
version = "0.46.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
|
||||||
|
dependencies = [
|
||||||
|
"overload",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-derive"
|
name = "num-derive"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
|
@ -2606,12 +2567,6 @@ version = "11.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
|
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "opaque-debug"
|
|
||||||
version = "0.2.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ordered-float"
|
name = "ordered-float"
|
||||||
version = "3.0.0"
|
version = "3.0.0"
|
||||||
|
@ -2636,6 +2591,12 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "overload"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "owned_ttf_parser"
|
name = "owned_ttf_parser"
|
||||||
version = "0.15.0"
|
version = "0.15.0"
|
||||||
|
@ -2800,9 +2761,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pest_derive"
|
name = "pest_derive"
|
||||||
version = "2.1.0"
|
version = "2.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0"
|
checksum = "502b62a6d0245378b04ffe0a7fb4f4419a4815fce813bd8a0ec89a56e07d67b1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pest",
|
"pest",
|
||||||
"pest_generator",
|
"pest_generator",
|
||||||
|
@ -2810,9 +2771,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pest_generator"
|
name = "pest_generator"
|
||||||
version = "2.1.3"
|
version = "2.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55"
|
checksum = "451e629bf49b750254da26132f1a5a9d11fd8a95a3df51d15c4abd1ba154cb6c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pest",
|
"pest",
|
||||||
"pest_meta",
|
"pest_meta",
|
||||||
|
@ -2823,13 +2784,13 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pest_meta"
|
name = "pest_meta"
|
||||||
version = "2.1.3"
|
version = "2.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d"
|
checksum = "bcec162c71c45e269dfc3fc2916eaeb97feab22993a21bcce4721d08cd7801a6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"maplit",
|
"once_cell",
|
||||||
"pest",
|
"pest",
|
||||||
"sha-1",
|
"sha1 0.10.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3467,8 +3428,6 @@ dependencies = [
|
||||||
"roc_tracing",
|
"roc_tracing",
|
||||||
"serial_test",
|
"serial_test",
|
||||||
"signal-hook",
|
"signal-hook",
|
||||||
"strum",
|
|
||||||
"strum_macros",
|
|
||||||
"target-lexicon",
|
"target-lexicon",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"ven_pretty",
|
"ven_pretty",
|
||||||
|
@ -4450,18 +4409,6 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "sha-1"
|
|
||||||
version = "0.8.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
|
|
||||||
dependencies = [
|
|
||||||
"block-buffer 0.7.3",
|
|
||||||
"digest 0.8.1",
|
|
||||||
"fake-simd",
|
|
||||||
"opaque-debug",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha1"
|
name = "sha1"
|
||||||
version = "0.6.1"
|
version = "0.6.1"
|
||||||
|
@ -4471,6 +4418,17 @@ dependencies = [
|
||||||
"sha1_smol",
|
"sha1_smol",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha1"
|
||||||
|
version = "0.10.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "006769ba83e921b3085caa8334186b00cf92b4cb1a6cf4632fbccc8eff5c7549"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha1_smol"
|
name = "sha1_smol"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -4485,7 +4443,7 @@ checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"cpufeatures",
|
"cpufeatures",
|
||||||
"digest 0.10.3",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -4728,7 +4686,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha1",
|
"sha1 0.6.1",
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -4767,9 +4725,9 @@ checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strum_macros"
|
name = "strum_macros"
|
||||||
version = "0.24.2"
|
version = "0.24.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4faebde00e8ff94316c01800f9054fd2ba77d30d9e922541913051d1d978918b"
|
checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
@ -5106,9 +5064,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-core"
|
name = "tracing-core"
|
||||||
version = "0.1.29"
|
version = "0.1.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7"
|
checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"valuable",
|
"valuable",
|
||||||
|
@ -5127,12 +5085,12 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-subscriber"
|
name = "tracing-subscriber"
|
||||||
version = "0.3.15"
|
version = "0.3.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b"
|
checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term",
|
|
||||||
"matchers",
|
"matchers",
|
||||||
|
"nu-ansi-term",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"regex",
|
"regex",
|
||||||
"sharded-slab",
|
"sharded-slab",
|
||||||
|
@ -5155,7 +5113,7 @@ version = "1.6.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
|
checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 0.1.10",
|
||||||
"rand",
|
"rand",
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
]
|
]
|
||||||
|
|
|
@ -57,9 +57,10 @@ members = [
|
||||||
"crates/wasi-libc-sys",
|
"crates/wasi-libc-sys",
|
||||||
]
|
]
|
||||||
exclude = [
|
exclude = [
|
||||||
# Examples sometimes have Rust hosts in their platforms. The compiler should ignore those.
|
|
||||||
"examples",
|
|
||||||
"ci/bench-runner",
|
"ci/bench-runner",
|
||||||
|
# Examples sometimes have Rust hosts in their platforms. The compiler should ignore those.
|
||||||
|
"crates/cli_testing_examples",
|
||||||
|
"examples",
|
||||||
# Ignore building these normally. They are only imported by tests.
|
# Ignore building these normally. They are only imported by tests.
|
||||||
# The tests will still correctly build them.
|
# The tests will still correctly build them.
|
||||||
"crates/cli_utils",
|
"crates/cli_utils",
|
||||||
|
|
|
@ -50,7 +50,7 @@ install-zig-llvm-valgrind:
|
||||||
|
|
||||||
copy-dirs:
|
copy-dirs:
|
||||||
FROM +install-zig-llvm-valgrind
|
FROM +install-zig-llvm-valgrind
|
||||||
COPY --dir crates examples Cargo.toml Cargo.lock version.txt www ./
|
COPY --dir crates Cargo.toml Cargo.lock version.txt www ./
|
||||||
|
|
||||||
# compile everything needed for benchmarks and output a self-contained dir from which benchmarks can be run.
|
# compile everything needed for benchmarks and output a self-contained dir from which benchmarks can be run.
|
||||||
prep-bench-folder:
|
prep-bench-folder:
|
||||||
|
@ -60,11 +60,11 @@ prep-bench-folder:
|
||||||
ARG BENCH_SUFFIX=branch
|
ARG BENCH_SUFFIX=branch
|
||||||
RUN cargo criterion -V
|
RUN cargo criterion -V
|
||||||
RUN --mount=type=cache,target=$SCCACHE_DIR cd crates/cli && cargo criterion --no-run
|
RUN --mount=type=cache,target=$SCCACHE_DIR cd crates/cli && cargo criterion --no-run
|
||||||
|
RUN mkdir -p bench-folder/crates/cli_testing_examples/benchmarks
|
||||||
RUN mkdir -p bench-folder/crates/compiler/builtins/bitcode/src
|
RUN mkdir -p bench-folder/crates/compiler/builtins/bitcode/src
|
||||||
RUN mkdir -p bench-folder/target/release/deps
|
RUN mkdir -p bench-folder/target/release/deps
|
||||||
RUN mkdir -p bench-folder/examples/benchmarks
|
RUN cp crates/cli_testing_examples/benchmarks/*.roc bench-folder/crates/cli_testing_examples/benchmarks/
|
||||||
RUN cp examples/benchmarks/*.roc bench-folder/examples/benchmarks/
|
RUN cp -r crates/cli_testing_examples/benchmarks/platform bench-folder/crates/cli_testing_examples/benchmarks/
|
||||||
RUN cp -r examples/benchmarks/platform bench-folder/examples/benchmarks/
|
|
||||||
RUN cp crates/compiler/builtins/bitcode/src/str.zig bench-folder/crates/compiler/builtins/bitcode/src
|
RUN cp crates/compiler/builtins/bitcode/src/str.zig bench-folder/crates/compiler/builtins/bitcode/src
|
||||||
RUN cp target/release/roc bench-folder/target/release
|
RUN cp target/release/roc bench-folder/target/release
|
||||||
# copy the most recent time bench to bench-folder
|
# copy the most recent time bench to bench-folder
|
||||||
|
|
28
TUTORIAL.md
28
TUTORIAL.md
|
@ -115,7 +115,7 @@ Create a new file called `Hello.roc` and put this inside it:
|
||||||
|
|
||||||
```coffee
|
```coffee
|
||||||
app "hello"
|
app "hello"
|
||||||
packages { pf: "examples/interactive/cli-platform/main.roc" }
|
packages { pf: "examples/cli/cli-platform/main.roc" }
|
||||||
imports [pf.Stdout, pf.Program]
|
imports [pf.Stdout, pf.Program]
|
||||||
provides [main] to pf
|
provides [main] to pf
|
||||||
|
|
||||||
|
@ -124,8 +124,8 @@ main = Stdout.line "I'm a Roc application!" |> Program.quick
|
||||||
|
|
||||||
> **NOTE:** This assumes you've put Hello.roc in the root directory of the Roc
|
> **NOTE:** This assumes you've put Hello.roc in the root directory of the Roc
|
||||||
> source code. If you'd like to put it somewhere else, you'll need to replace
|
> source code. If you'd like to put it somewhere else, you'll need to replace
|
||||||
> `"examples/interactive/cli-platform/main.roc"` with the path to the
|
> `"examples/cli/cli-platform/main.roc"` with the path to the
|
||||||
> `examples/interactive/cli-platform/main.roc` file in that source code. In the future,
|
> `examples/cli/cli-platform/main.roc` file in that source code. In the future,
|
||||||
> Roc will have the tutorial built in, and this aside will no longer be
|
> Roc will have the tutorial built in, and this aside will no longer be
|
||||||
> necessary!
|
> necessary!
|
||||||
|
|
||||||
|
@ -1273,7 +1273,7 @@ Let's take a closer look at the part of `Hello.roc` above `main`:
|
||||||
|
|
||||||
```coffee
|
```coffee
|
||||||
app "hello"
|
app "hello"
|
||||||
packages { pf: "examples/interactive/cli-platform/main.roc" }
|
packages { pf: "examples/cli/cli-platform/main.roc" }
|
||||||
imports [pf.Stdout, pf.Program]
|
imports [pf.Stdout, pf.Program]
|
||||||
provides main to pf
|
provides main to pf
|
||||||
```
|
```
|
||||||
|
@ -1291,14 +1291,14 @@ without running it by running `roc build Hello.roc`.
|
||||||
The remaining lines all involve the *platform* this application is built on:
|
The remaining lines all involve the *platform* this application is built on:
|
||||||
|
|
||||||
```coffee
|
```coffee
|
||||||
packages { pf: "examples/interactive/cli-platform/main.roc" }
|
packages { pf: "examples/cli/cli-platform/main.roc" }
|
||||||
imports [pf.Stdout, pf.Program]
|
imports [pf.Stdout, pf.Program]
|
||||||
provides main to pf
|
provides main to pf
|
||||||
```
|
```
|
||||||
|
|
||||||
The `packages { pf: "examples/interactive/cli-platform/main.roc" }` part says two things:
|
The `packages { pf: "examples/cli/cli-platform/main.roc" }` part says two things:
|
||||||
|
|
||||||
- We're going to be using a *package* (that is, a collection of modules) called `"examples/interactive/cli-platform/main.roc"`
|
- We're going to be using a *package* (that is, a collection of modules) called `"examples/cli/cli-platform/main.roc"`
|
||||||
- We're going to name that package `pf` so we can refer to it more concisely in the future.
|
- We're going to name that package `pf` so we can refer to it more concisely in the future.
|
||||||
|
|
||||||
The `imports [pf.Stdout, pf.Program]` line says that we want to import the `Stdout` and `Program` modules
|
The `imports [pf.Stdout, pf.Program]` line says that we want to import the `Stdout` and `Program` modules
|
||||||
|
@ -1320,16 +1320,16 @@ which effectively makes it a simple Roc program.
|
||||||
When we write `imports [pf.Stdout, pf.Program]`, it specifies that the `Stdout`
|
When we write `imports [pf.Stdout, pf.Program]`, it specifies that the `Stdout`
|
||||||
and `Program` modules come from the `pf` package.
|
and `Program` modules come from the `pf` package.
|
||||||
|
|
||||||
Since `pf` was the name we chose for the `examples/interactive/cli-platform/main.roc`
|
Since `pf` was the name we chose for the `examples/cli/cli-platform/main.roc`
|
||||||
package (when we wrote `packages { pf: "examples/interactive/cli-platform/main.roc" }`),
|
package (when we wrote `packages { pf: "examples/cli/cli-platform/main.roc" }`),
|
||||||
this `imports` line tells the Roc compiler that when we call `Stdout.line`, it
|
this `imports` line tells the Roc compiler that when we call `Stdout.line`, it
|
||||||
should look for that `line` function in the `Stdout` module of the
|
should look for that `line` function in the `Stdout` module of the
|
||||||
`examples/interactive/cli-platform/main.roc` package.
|
`examples/cli/cli-platform/main.roc` package.
|
||||||
|
|
||||||
## Tasks
|
## Tasks
|
||||||
|
|
||||||
Tasks are technically not part of the Roc language, but they're very common in
|
Tasks are technically not part of the Roc language, but they're very common in
|
||||||
platforms. Let's use the CLI platform in `examples/interactive/cli-platform/main.roc` as an example!
|
platforms. Let's use the CLI platform in `examples/cli/cli-platform/main.roc` as an example!
|
||||||
|
|
||||||
In the CLI platform, we have four operations we can do:
|
In the CLI platform, we have four operations we can do:
|
||||||
|
|
||||||
|
@ -1344,7 +1344,7 @@ First, let's do a basic "Hello World" using the tutorial app.
|
||||||
|
|
||||||
```coffee
|
```coffee
|
||||||
app "cli-tutorial"
|
app "cli-tutorial"
|
||||||
packages { pf: "examples/interactive/cli-platform/main.roc" }
|
packages { pf: "examples/cli/cli-platform/main.roc" }
|
||||||
imports [pf.Stdout, pf.Program]
|
imports [pf.Stdout, pf.Program]
|
||||||
provides [main] to pf
|
provides [main] to pf
|
||||||
|
|
||||||
|
@ -1382,7 +1382,7 @@ Let's change `main` to read a line from `stdin`, and then print it back out agai
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
app "cli-tutorial"
|
app "cli-tutorial"
|
||||||
packages { pf: "examples/interactive/cli-platform/main.roc" }
|
packages { pf: "examples/cli/cli-platform/main.roc" }
|
||||||
imports [pf.Stdout, pf.Stdin, pf.Task, pf.Program]
|
imports [pf.Stdout, pf.Stdin, pf.Task, pf.Program]
|
||||||
provides [main] to pf
|
provides [main] to pf
|
||||||
|
|
||||||
|
@ -1434,7 +1434,7 @@ This works, but we can make it a little nicer to read. Let's change it to the fo
|
||||||
|
|
||||||
```haskell
|
```haskell
|
||||||
app "cli-tutorial"
|
app "cli-tutorial"
|
||||||
packages { pf: "examples/interactive/cli-platform/main.roc" }
|
packages { pf: "examples/cli/cli-platform/main.roc" }
|
||||||
imports [pf.Stdout, pf.Stdin, pf.Task.{ await }, pf.Program]
|
imports [pf.Stdout, pf.Stdin, pf.Task.{ await }, pf.Program]
|
||||||
provides [main] to pf
|
provides [main] to pf
|
||||||
|
|
||||||
|
|
|
@ -227,9 +227,10 @@ fn calc_hashes_for_folder(benches_path_str: &str) -> HashMap<String, String> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_if_bench_executables_changed() -> bool {
|
fn check_if_bench_executables_changed() -> bool {
|
||||||
let bench_folder_str = "/examples/benchmarks/";
|
let bench_folder_str = "/crates/cli_testing_examples/benchmarks/";
|
||||||
|
|
||||||
let main_benches_path_str = [BENCH_FOLDER_MAIN, bench_folder_str].join("");
|
let main_benches_path_str = [BENCH_FOLDER_MAIN, bench_folder_str].join("");
|
||||||
|
|
||||||
let main_bench_hashes = calc_hashes_for_folder(&main_benches_path_str);
|
let main_bench_hashes = calc_hashes_for_folder(&main_benches_path_str);
|
||||||
|
|
||||||
let branch_benches_path_str = [BENCH_FOLDER_BRANCH, bench_folder_str].join("");
|
let branch_benches_path_str = [BENCH_FOLDER_BRANCH, bench_folder_str].join("");
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
cp target/release/roc ./roc # to be able to exclude "target" later in the tar command
|
cp target/release/roc ./roc # to be able to exclude "target" later in the tar command
|
||||||
cp -r target/release/lib ./lib
|
cp -r target/release/lib ./lib
|
||||||
tar -czvf $1 --exclude="target" --exclude="zig-cache" roc lib LICENSE LEGAL_DETAILS examples/hello-world crates/roc_std
|
tar -czvf $1 --exclude="target" --exclude="zig-cache" roc lib LICENSE LEGAL_DETAILS examples/helloWorld.roc examples/cli crates/roc_std
|
||||||
|
|
|
@ -100,8 +100,6 @@ indoc = "1.0.7"
|
||||||
serial_test = "0.9.0"
|
serial_test = "0.9.0"
|
||||||
criterion = { git = "https://github.com/Anton-4/criterion.rs"}
|
criterion = { git = "https://github.com/Anton-4/criterion.rs"}
|
||||||
cli_utils = { path = "../cli_utils" }
|
cli_utils = { path = "../cli_utils" }
|
||||||
strum = "0.24.0"
|
|
||||||
strum_macros = "0.24"
|
|
||||||
once_cell = "1.14.0"
|
once_cell = "1.14.0"
|
||||||
parking_lot = "0.12"
|
parking_lot = "0.12"
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
||||||
app "type-error"
|
app "type-error"
|
||||||
packages { pf: "../../../../examples/interactive/cli-platform/main.roc" }
|
packages { pf: "../../../../examples/cli/cli-platform/main.roc" }
|
||||||
imports [pf.Stdout.{ line }, pf.Task.{ await }, pf.Program]
|
imports [pf.Stdout.{ line }, pf.Task.{ await }, pf.Program]
|
||||||
provides [main] to pf
|
provides [main] to pf
|
||||||
|
|
||||||
|
|
6
crates/cli_testing_examples/.gitignore
vendored
Normal file
6
crates/cli_testing_examples/.gitignore
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
*.dSYM
|
||||||
|
libhost.a
|
||||||
|
libapp.so
|
||||||
|
dynhost
|
||||||
|
preprocessedhost
|
||||||
|
metadata
|
|
@ -16,7 +16,7 @@ name = "host"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
roc_std = { path = "../../../crates/roc_std" }
|
roc_std = { path = "../../../../crates/roc_std" }
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
|
@ -3,12 +3,12 @@
|
||||||
To run this website, first compile either of these identical apps:
|
To run this website, first compile either of these identical apps:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Option A: Compile examples/platform-switching/rocLovesWebAssembly.roc
|
# Option A: Compile crates/cli_testing_examples/platform-switching/rocLovesWebAssembly.roc
|
||||||
cargo run -- build --target=wasm32 examples/platform-switching/rocLovesWebAssembly.roc
|
cargo run -- build --target=wasm32 crates/cli_testing_examples/platform-switching/rocLovesWebAssembly.roc
|
||||||
|
|
||||||
# Option B: Compile examples/platform-switching/main.roc with `pf: "web-assembly-platform/main.roc"` and move the result
|
# Option B: Compile crates/cli_testing_examples/platform-switching/main.roc with `pf: "web-assembly-platform/main.roc"` and move the result
|
||||||
cargo run -- build --target=wasm32 examples/platform-switching/main.roc
|
cargo run -- build --target=wasm32 crates/cli_testing_examples/platform-switching/main.roc
|
||||||
(cd examples/platform-switching && mv rocLovesPlatforms.wasm web-assembly-platform/rocLovesWebAssembly.wasm)
|
(cd crates/cli_testing_examples/platform-switching && mv rocLovesPlatforms.wasm web-assembly-platform/rocLovesWebAssembly.wasm)
|
||||||
```
|
```
|
||||||
|
|
||||||
Then `cd` into the website directory
|
Then `cd` into the website directory
|
||||||
|
@ -16,7 +16,7 @@ and run any web server that can handle WebAssembly.
|
||||||
For example, with `http-server`:
|
For example, with `http-server`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd examples/platform-switching/web-assembly-platform
|
cd crates/cli_testing_examples/platform-switching/web-assembly-platform
|
||||||
npm install -g http-server
|
npm install -g http-server
|
||||||
http-server
|
http-server
|
||||||
```
|
```
|
File diff suppressed because one or more lines are too long
|
@ -22,7 +22,7 @@ pub struct Out {
|
||||||
pub status: ExitStatus,
|
pub status: ExitStatus,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_roc<I, S>(args: I, stdin_vals: &[&str]) -> Out
|
pub fn run_roc<I, S>(args: I, stdin_vals: &[&str], extra_env: &[(&str, &str)]) -> Out
|
||||||
where
|
where
|
||||||
I: IntoIterator<Item = S>,
|
I: IntoIterator<Item = S>,
|
||||||
S: AsRef<OsStr>,
|
S: AsRef<OsStr>,
|
||||||
|
@ -62,7 +62,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
run_with_stdin(&roc_binary_path, args, stdin_vals)
|
run_with_stdin_and_env(&roc_binary_path, args, stdin_vals, extra_env)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_glue<I, S>(args: I) -> Out
|
pub fn run_glue<I, S>(args: I) -> Out
|
||||||
|
@ -118,6 +118,19 @@ pub fn strip_colors(str: &str) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_with_stdin<I, S>(path: &Path, args: I, stdin_vals: &[&str]) -> Out
|
pub fn run_with_stdin<I, S>(path: &Path, args: I, stdin_vals: &[&str]) -> Out
|
||||||
|
where
|
||||||
|
I: IntoIterator<Item = S>,
|
||||||
|
S: AsRef<OsStr>,
|
||||||
|
{
|
||||||
|
run_with_stdin_and_env(path, args, stdin_vals, &[])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run_with_stdin_and_env<I, S>(
|
||||||
|
path: &Path,
|
||||||
|
args: I,
|
||||||
|
stdin_vals: &[&str],
|
||||||
|
extra_env: &[(&str, &str)],
|
||||||
|
) -> Out
|
||||||
where
|
where
|
||||||
I: IntoIterator<Item = S>,
|
I: IntoIterator<Item = S>,
|
||||||
S: AsRef<OsStr>,
|
S: AsRef<OsStr>,
|
||||||
|
@ -128,6 +141,10 @@ where
|
||||||
cmd.arg(arg);
|
cmd.arg(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (k, v) in extra_env {
|
||||||
|
cmd.env(k, v);
|
||||||
|
}
|
||||||
|
|
||||||
let mut child = cmd
|
let mut child = cmd
|
||||||
.stdin(Stdio::piped())
|
.stdin(Stdio::piped())
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
|
@ -364,20 +381,31 @@ pub fn root_dir() -> PathBuf {
|
||||||
path
|
path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// start the dir with crates/cli_testing_examples
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn examples_dir(dir_name: &str) -> PathBuf {
|
pub fn cli_testing_dir(dir_name: &str) -> PathBuf {
|
||||||
let mut path = root_dir();
|
let mut path = root_dir();
|
||||||
|
|
||||||
// Descend into examples/{dir_name}
|
// Descend into examples/{dir_name}
|
||||||
path.push("examples");
|
path.push("crates");
|
||||||
|
path.push("cli_testing_examples");
|
||||||
path.extend(dir_name.split("/")); // Make slashes cross-target
|
path.extend(dir_name.split("/")); // Make slashes cross-target
|
||||||
|
|
||||||
path
|
path
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn example_file(dir_name: &str, file_name: &str) -> PathBuf {
|
pub fn dir_path_from_root(dir_name: &str) -> PathBuf {
|
||||||
let mut path = examples_dir(dir_name);
|
let mut path = root_dir();
|
||||||
|
|
||||||
|
path.extend(dir_name.split("/")); // Make slashes cross-target
|
||||||
|
|
||||||
|
path
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn file_path_from_root(dir_name: &str, file_name: &str) -> PathBuf {
|
||||||
|
let mut path = dir_path_from_root(dir_name);
|
||||||
|
|
||||||
path.push(file_name);
|
path.push(file_name);
|
||||||
|
|
||||||
|
|
|
@ -374,7 +374,7 @@ pub fn build_zig_host_wasm32(
|
||||||
"c",
|
"c",
|
||||||
"-target",
|
"-target",
|
||||||
zig_target,
|
zig_target,
|
||||||
// "-femit-llvm-ir=/home/folkertdev/roc/roc/examples/benchmarks/platform/host.ll",
|
// "-femit-llvm-ir=/home/folkertdev/roc/roc/crates/cli_testing_examples/benchmarks/platform/host.ll",
|
||||||
"-fPIC",
|
"-fPIC",
|
||||||
"--strip",
|
"--strip",
|
||||||
];
|
];
|
||||||
|
@ -635,6 +635,7 @@ pub fn rebuild_host(
|
||||||
} else if cargo_host_src.exists() {
|
} else if cargo_host_src.exists() {
|
||||||
// Compile and link Cargo.toml, if it exists
|
// Compile and link Cargo.toml, if it exists
|
||||||
let cargo_dir = host_input_path.parent().unwrap();
|
let cargo_dir = host_input_path.parent().unwrap();
|
||||||
|
|
||||||
let cargo_out_dir = cargo_dir.join("target").join(
|
let cargo_out_dir = cargo_dir.join("target").join(
|
||||||
if matches!(opt_level, OptLevel::Optimize | OptLevel::Size) {
|
if matches!(opt_level, OptLevel::Optimize | OptLevel::Size) {
|
||||||
"release"
|
"release"
|
||||||
|
@ -1215,7 +1216,7 @@ fn link_wasm32(
|
||||||
"-O",
|
"-O",
|
||||||
"ReleaseSmall",
|
"ReleaseSmall",
|
||||||
// useful for debugging
|
// useful for debugging
|
||||||
// "-femit-llvm-ir=/home/folkertdev/roc/roc/examples/benchmarks/platform/host.ll",
|
// "-femit-llvm-ir=/home/folkertdev/roc/roc/crates/cli_testing_examples/benchmarks/platform/host.ll",
|
||||||
])
|
])
|
||||||
.spawn()?;
|
.spawn()?;
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ lazy_static = "1.4.0"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
# dunce can be removed once ziglang/zig#5109 is fixed
|
# dunce can be removed once ziglang/zig#5109 is fixed
|
||||||
dunce = "1.0.2"
|
dunce = "1.0.3"
|
||||||
|
|
||||||
[target.'cfg(target_os = "macos")'.build-dependencies]
|
[target.'cfg(target_os = "macos")'.build-dependencies]
|
||||||
tempfile = "3.2.0"
|
tempfile = "3.2.0"
|
||||||
|
|
|
@ -93,20 +93,6 @@ pub const RocList = extern struct {
|
||||||
return (ptr - 1)[0] == utils.REFCOUNT_ONE;
|
return (ptr - 1)[0] == utils.REFCOUNT_ONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocate(
|
|
||||||
alignment: u32,
|
|
||||||
length: usize,
|
|
||||||
element_size: usize,
|
|
||||||
) RocList {
|
|
||||||
const data_bytes = length * element_size;
|
|
||||||
|
|
||||||
return RocList{
|
|
||||||
.bytes = utils.allocateWithRefcount(data_bytes, alignment),
|
|
||||||
.length = length,
|
|
||||||
.capacity = length,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn makeUniqueExtra(self: RocList, alignment: u32, element_width: usize, update_mode: UpdateMode) RocList {
|
pub fn makeUniqueExtra(self: RocList, alignment: u32, element_width: usize, update_mode: UpdateMode) RocList {
|
||||||
if (update_mode == .InPlace) {
|
if (update_mode == .InPlace) {
|
||||||
return self;
|
return self;
|
||||||
|
@ -140,11 +126,117 @@ pub const RocList = extern struct {
|
||||||
return new_list;
|
return new_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We follow roughly the [fbvector](https://github.com/facebook/folly/blob/main/folly/docs/FBVector.md) when it comes to growing a RocList.
|
||||||
|
// Here is [their growth strategy](https://github.com/facebook/folly/blob/3e0525988fd444201b19b76b390a5927c15cb697/folly/FBVector.h#L1128) for push_back:
|
||||||
|
//
|
||||||
|
// (1) initial size
|
||||||
|
// Instead of growing to size 1 from empty, fbvector allocates at least
|
||||||
|
// 64 bytes. You may still use reserve to reserve a lesser amount of
|
||||||
|
// memory.
|
||||||
|
// (2) 1.5x
|
||||||
|
// For medium-sized vectors, the growth strategy is 1.5x. See the docs
|
||||||
|
// for details.
|
||||||
|
// This does not apply to very small or very large fbvectors. This is a
|
||||||
|
// heuristic.
|
||||||
|
//
|
||||||
|
// In our case, we exposed allocate and reallocate, which will use a smart growth stategy.
|
||||||
|
// We also expose allocateExact and reallocateExact for case where a specific number of elements is requested.
|
||||||
|
|
||||||
|
// calculateCapacity should only be called in cases the list will be growing.
|
||||||
|
// requested_length should always be greater than old_capacity.
|
||||||
|
inline fn calculateCapacity(
|
||||||
|
old_capacity: usize,
|
||||||
|
requested_length: usize,
|
||||||
|
element_width: usize,
|
||||||
|
) usize {
|
||||||
|
// TODO: there are two adjustments that would likely lead to better results for Roc.
|
||||||
|
// 1. Deal with the fact we allocate an extra u64 for refcount.
|
||||||
|
// This may lead to allocating page size + 8 bytes.
|
||||||
|
// That could mean allocating an entire page for 8 bytes of data which isn't great.
|
||||||
|
// 2. Deal with the fact that we can request more than 1 element at a time.
|
||||||
|
// fbvector assumes just appending 1 element at a time when using this algorithm.
|
||||||
|
// As such, they will generally grow in a way that should better match certain memory multiple.
|
||||||
|
// This is also the normal case for roc, but we could also grow by a much larger amount.
|
||||||
|
// We may want to round to multiples of 2 or something similar.
|
||||||
|
var new_capacity: usize = 0;
|
||||||
|
if (element_width == 0) {
|
||||||
|
return requested_length;
|
||||||
|
} else if (old_capacity == 0) {
|
||||||
|
new_capacity = 64 / element_width;
|
||||||
|
} else if (old_capacity < 4096 / element_width) {
|
||||||
|
new_capacity = old_capacity * 2;
|
||||||
|
} else if (old_capacity > 4096 * 32 / element_width) {
|
||||||
|
new_capacity = old_capacity * 2;
|
||||||
|
} else {
|
||||||
|
new_capacity = (old_capacity * 3 + 1) / 2;
|
||||||
|
}
|
||||||
|
return @maximum(new_capacity, requested_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn allocate(
|
||||||
|
alignment: u32,
|
||||||
|
length: usize,
|
||||||
|
element_width: usize,
|
||||||
|
) RocList {
|
||||||
|
if (length == 0) {
|
||||||
|
return empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
const capacity = calculateCapacity(0, length, element_width);
|
||||||
|
const data_bytes = capacity * element_width;
|
||||||
|
return RocList{
|
||||||
|
.bytes = utils.allocateWithRefcount(data_bytes, alignment),
|
||||||
|
.length = length,
|
||||||
|
.capacity = capacity,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn allocateExact(
|
||||||
|
alignment: u32,
|
||||||
|
length: usize,
|
||||||
|
element_width: usize,
|
||||||
|
) RocList {
|
||||||
|
if (length == 0) {
|
||||||
|
return empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
const data_bytes = length * element_width;
|
||||||
|
return RocList{
|
||||||
|
.bytes = utils.allocateWithRefcount(data_bytes, alignment),
|
||||||
|
.length = length,
|
||||||
|
.capacity = length,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn reallocate(
|
pub fn reallocate(
|
||||||
self: RocList,
|
self: RocList,
|
||||||
alignment: u32,
|
alignment: u32,
|
||||||
new_length: usize,
|
new_length: usize,
|
||||||
element_width: usize,
|
element_width: usize,
|
||||||
|
) RocList {
|
||||||
|
if (self.bytes) |source_ptr| {
|
||||||
|
if (self.isUnique()) {
|
||||||
|
if (self.capacity >= new_length) {
|
||||||
|
return RocList{ .bytes = self.bytes, .length = new_length, .capacity = self.capacity };
|
||||||
|
} else {
|
||||||
|
const new_capacity = calculateCapacity(self.capacity, new_length, element_width);
|
||||||
|
const new_source = utils.unsafeReallocate(source_ptr, alignment, self.len(), new_capacity, element_width);
|
||||||
|
return RocList{ .bytes = new_source, .length = new_length, .capacity = new_capacity };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: Investigate the performance of this.
|
||||||
|
// Maybe we should just always reallocate to the new_length instead of expanding capacity?
|
||||||
|
const new_capacity = if (self.capacity >= new_length) self.capacity else calculateCapacity(self.capacity, new_length, element_width);
|
||||||
|
return self.reallocateFresh(alignment, new_length, new_capacity, element_width);
|
||||||
|
}
|
||||||
|
return RocList.allocate(alignment, new_length, element_width);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reallocateExact(
|
||||||
|
self: RocList,
|
||||||
|
alignment: u32,
|
||||||
|
new_length: usize,
|
||||||
|
element_width: usize,
|
||||||
) RocList {
|
) RocList {
|
||||||
if (self.bytes) |source_ptr| {
|
if (self.bytes) |source_ptr| {
|
||||||
if (self.isUnique()) {
|
if (self.isUnique()) {
|
||||||
|
@ -155,9 +247,9 @@ pub const RocList = extern struct {
|
||||||
return RocList{ .bytes = new_source, .length = new_length, .capacity = new_length };
|
return RocList{ .bytes = new_source, .length = new_length, .capacity = new_length };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return self.reallocateFresh(alignment, new_length, new_length, element_width);
|
||||||
}
|
}
|
||||||
|
return RocList.allocateExact(alignment, new_length, element_width);
|
||||||
return self.reallocateFresh(alignment, new_length, element_width);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// reallocate by explicitly making a new allocation and copying elements over
|
/// reallocate by explicitly making a new allocation and copying elements over
|
||||||
|
@ -165,16 +257,16 @@ pub const RocList = extern struct {
|
||||||
self: RocList,
|
self: RocList,
|
||||||
alignment: u32,
|
alignment: u32,
|
||||||
new_length: usize,
|
new_length: usize,
|
||||||
|
new_capacity: usize,
|
||||||
element_width: usize,
|
element_width: usize,
|
||||||
) RocList {
|
) RocList {
|
||||||
const old_length = self.length;
|
const old_length = self.length;
|
||||||
const delta_length = new_length - old_length;
|
const delta_length = new_length - old_length;
|
||||||
|
|
||||||
const data_bytes = new_length * element_width;
|
const data_bytes = new_capacity * element_width;
|
||||||
const first_slot = utils.allocateWithRefcount(data_bytes, alignment);
|
const first_slot = utils.allocateWithRefcount(data_bytes, alignment);
|
||||||
|
|
||||||
// transfer the memory
|
// transfer the memory
|
||||||
|
|
||||||
if (self.bytes) |source_ptr| {
|
if (self.bytes) |source_ptr| {
|
||||||
const dest_ptr = first_slot;
|
const dest_ptr = first_slot;
|
||||||
|
|
||||||
|
@ -185,7 +277,7 @@ pub const RocList = extern struct {
|
||||||
const result = RocList{
|
const result = RocList{
|
||||||
.bytes = first_slot,
|
.bytes = first_slot,
|
||||||
.length = new_length,
|
.length = new_length,
|
||||||
.capacity = new_length,
|
.capacity = new_capacity,
|
||||||
};
|
};
|
||||||
|
|
||||||
utils.decref(self.bytes, old_length * element_width, alignment);
|
utils.decref(self.bytes, old_length * element_width, alignment);
|
||||||
|
@ -412,7 +504,7 @@ pub fn listWithCapacity(
|
||||||
alignment: u32,
|
alignment: u32,
|
||||||
element_width: usize,
|
element_width: usize,
|
||||||
) callconv(.C) RocList {
|
) callconv(.C) RocList {
|
||||||
var output = RocList.allocate(alignment, capacity, element_width);
|
var output = RocList.allocateExact(alignment, capacity, element_width);
|
||||||
output.length = 0;
|
output.length = 0;
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
@ -517,17 +609,25 @@ pub fn listSublist(
|
||||||
len: usize,
|
len: usize,
|
||||||
dec: Dec,
|
dec: Dec,
|
||||||
) callconv(.C) RocList {
|
) callconv(.C) RocList {
|
||||||
if (len == 0) {
|
const size = list.len();
|
||||||
|
if (len == 0 or start >= size) {
|
||||||
|
if (list.isUnique()) {
|
||||||
|
// Decrement the reference counts of all elements.
|
||||||
|
if (list.bytes) |source_ptr| {
|
||||||
|
var i: usize = 0;
|
||||||
|
while (i < size) : (i += 1) {
|
||||||
|
const element = source_ptr + i * element_width;
|
||||||
|
dec(element);
|
||||||
|
}
|
||||||
|
var output = list;
|
||||||
|
output.length = 0;
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
return RocList.empty();
|
return RocList.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list.bytes) |source_ptr| {
|
if (list.bytes) |source_ptr| {
|
||||||
const size = list.len();
|
|
||||||
|
|
||||||
if (start >= size) {
|
|
||||||
return RocList.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
const keep_len = std.math.min(len, size - start);
|
const keep_len = std.math.min(len, size - start);
|
||||||
const drop_start_len = start;
|
const drop_start_len = start;
|
||||||
const drop_end_len = size - (start + keep_len);
|
const drop_end_len = size - (start + keep_len);
|
||||||
|
@ -546,10 +646,17 @@ pub fn listSublist(
|
||||||
dec(element);
|
dec(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (start == 0 and list.isUnique()) {
|
if (list.isUnique()) {
|
||||||
var output = list;
|
var output = list;
|
||||||
output.length = keep_len;
|
output.length = keep_len;
|
||||||
return output;
|
if (start == 0) {
|
||||||
|
return output;
|
||||||
|
} else {
|
||||||
|
// We want memmove due to aliasing. Zig does not expose it directly.
|
||||||
|
// Instead use copy which can write to aliases as long as the dest is before the source.
|
||||||
|
mem.copy(u8, source_ptr[0 .. keep_len * element_width], source_ptr[start * element_width .. (start + keep_len) * element_width]);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const output = RocList.allocate(alignment, keep_len, element_width);
|
const output = RocList.allocate(alignment, keep_len, element_width);
|
||||||
const target_ptr = output.bytes orelse unreachable;
|
const target_ptr = output.bytes orelse unreachable;
|
||||||
|
|
|
@ -144,6 +144,7 @@ comptime {
|
||||||
exportStrFn(str.strTrimLeft, "trim_left");
|
exportStrFn(str.strTrimLeft, "trim_left");
|
||||||
exportStrFn(str.strTrimRight, "trim_right");
|
exportStrFn(str.strTrimRight, "trim_right");
|
||||||
exportStrFn(str.strCloneTo, "clone_to");
|
exportStrFn(str.strCloneTo, "clone_to");
|
||||||
|
exportStrFn(str.withCapacity, "with_capacity");
|
||||||
|
|
||||||
inline for (INTEGERS) |T| {
|
inline for (INTEGERS) |T| {
|
||||||
str.exportFromInt(T, ROC_BUILTINS ++ "." ++ STR ++ ".from_int.");
|
str.exportFromInt(T, ROC_BUILTINS ++ "." ++ STR ++ ".from_int.");
|
||||||
|
|
|
@ -2596,6 +2596,10 @@ pub fn reserve(string: RocStr, capacity: usize) callconv(.C) RocStr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn withCapacity(capacity: usize) callconv(.C) RocStr {
|
||||||
|
return RocStr.allocate(0, capacity);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn getScalarUnsafe(string: RocStr, index: usize) callconv(.C) extern struct { bytesParsed: usize, scalar: u32 } {
|
pub fn getScalarUnsafe(string: RocStr, index: usize) callconv(.C) extern struct { bytesParsed: usize, scalar: u32 } {
|
||||||
const slice = string.asSlice();
|
const slice = string.asSlice();
|
||||||
const bytesParsed = @intCast(usize, std.unicode.utf8ByteSequenceLength(slice[index]) catch unreachable);
|
const bytesParsed = @intCast(usize, std.unicode.utf8ByteSequenceLength(slice[index]) catch unreachable);
|
||||||
|
|
|
@ -30,6 +30,23 @@ interface Decode
|
||||||
]
|
]
|
||||||
imports [
|
imports [
|
||||||
List,
|
List,
|
||||||
|
Result.{ Result },
|
||||||
|
Num.{
|
||||||
|
U8,
|
||||||
|
U16,
|
||||||
|
U32,
|
||||||
|
U64,
|
||||||
|
U128,
|
||||||
|
I8,
|
||||||
|
I16,
|
||||||
|
I32,
|
||||||
|
I64,
|
||||||
|
I128,
|
||||||
|
F32,
|
||||||
|
F64,
|
||||||
|
Dec,
|
||||||
|
},
|
||||||
|
Bool.{ Bool },
|
||||||
]
|
]
|
||||||
|
|
||||||
DecodeError : [TooShort]
|
DecodeError : [TooShort]
|
||||||
|
|
|
@ -20,6 +20,7 @@ interface Dict
|
||||||
Bool.{ Bool },
|
Bool.{ Bool },
|
||||||
Result.{ Result },
|
Result.{ Result },
|
||||||
List,
|
List,
|
||||||
|
Num.{ Nat },
|
||||||
]
|
]
|
||||||
|
|
||||||
## A [dictionary](https://en.wikipedia.org/wiki/Associative_array) that lets you can associate keys with values.
|
## A [dictionary](https://en.wikipedia.org/wiki/Associative_array) that lets you can associate keys with values.
|
||||||
|
|
|
@ -27,7 +27,24 @@ interface Encode
|
||||||
append,
|
append,
|
||||||
toBytes,
|
toBytes,
|
||||||
]
|
]
|
||||||
imports []
|
imports [
|
||||||
|
Num.{
|
||||||
|
U8,
|
||||||
|
U16,
|
||||||
|
U32,
|
||||||
|
U64,
|
||||||
|
U128,
|
||||||
|
I8,
|
||||||
|
I16,
|
||||||
|
I32,
|
||||||
|
I64,
|
||||||
|
I128,
|
||||||
|
F32,
|
||||||
|
F64,
|
||||||
|
Dec,
|
||||||
|
},
|
||||||
|
Bool.{ Bool },
|
||||||
|
]
|
||||||
|
|
||||||
Encoder fmt := List U8, fmt -> List U8 | fmt has EncoderFormatting
|
Encoder fmt := List U8, fmt -> List U8 | fmt has EncoderFormatting
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ interface Hash
|
||||||
] imports [
|
] imports [
|
||||||
List,
|
List,
|
||||||
Str,
|
Str,
|
||||||
|
Num.{ U8, U16, U32, U64, U128, I8, I16, I32, I64, I128 },
|
||||||
]
|
]
|
||||||
|
|
||||||
## A value that can hashed.
|
## A value that can hashed.
|
||||||
|
|
|
@ -18,6 +18,23 @@ interface Json
|
||||||
DecoderFormatting,
|
DecoderFormatting,
|
||||||
DecodeResult,
|
DecodeResult,
|
||||||
},
|
},
|
||||||
|
Num.{
|
||||||
|
U8,
|
||||||
|
U16,
|
||||||
|
U32,
|
||||||
|
U64,
|
||||||
|
U128,
|
||||||
|
I8,
|
||||||
|
I16,
|
||||||
|
I32,
|
||||||
|
I64,
|
||||||
|
I128,
|
||||||
|
F32,
|
||||||
|
F64,
|
||||||
|
Dec,
|
||||||
|
},
|
||||||
|
Bool.{ Bool },
|
||||||
|
Result,
|
||||||
]
|
]
|
||||||
|
|
||||||
Json := {} has [
|
Json := {} has [
|
||||||
|
@ -187,9 +204,8 @@ takeWhile = \list, predicate ->
|
||||||
|
|
||||||
helper { taken: [], rest: list }
|
helper { taken: [], rest: list }
|
||||||
|
|
||||||
asciiByte = \b -> Num.toU8 b
|
digits : List U8
|
||||||
|
digits = List.range '0' ('9' + 1)
|
||||||
digits = List.range (asciiByte '0') (asciiByte '9' + 1)
|
|
||||||
|
|
||||||
takeDigits = \bytes ->
|
takeDigits = \bytes ->
|
||||||
takeWhile bytes \n -> List.contains digits n
|
takeWhile bytes \n -> List.contains digits n
|
||||||
|
@ -198,10 +214,10 @@ takeFloat = \bytes ->
|
||||||
{ taken: intPart, rest } = takeDigits bytes
|
{ taken: intPart, rest } = takeDigits bytes
|
||||||
|
|
||||||
when List.get rest 0 is
|
when List.get rest 0 is
|
||||||
Ok 46 -> # 46 = .
|
Ok '.' ->
|
||||||
{ taken: floatPart, rest: afterAll } = takeDigits (List.split rest 1).others
|
{ taken: floatPart, rest: afterAll } = takeDigits (List.split rest 1).others
|
||||||
builtFloat =
|
builtFloat =
|
||||||
List.concat (List.append intPart (asciiByte '.')) floatPart
|
List.concat (List.append intPart '.') floatPart
|
||||||
|
|
||||||
{ taken: builtFloat, rest: afterAll }
|
{ taken: builtFloat, rest: afterAll }
|
||||||
|
|
||||||
|
@ -305,14 +321,14 @@ decodeBool = Decode.custom \bytes, @Json {} ->
|
||||||
# Note: this could be more performant by traversing both branches char-by-char.
|
# Note: this could be more performant by traversing both branches char-by-char.
|
||||||
# Doing that would also make `rest` more correct in the erroring case.
|
# Doing that would also make `rest` more correct in the erroring case.
|
||||||
if
|
if
|
||||||
maybeFalse == [asciiByte 'f', asciiByte 'a', asciiByte 'l', asciiByte 's', asciiByte 'e']
|
maybeFalse == ['f', 'a', 'l', 's', 'e']
|
||||||
then
|
then
|
||||||
{ result: Ok Bool.false, rest: afterFalse }
|
{ result: Ok Bool.false, rest: afterFalse }
|
||||||
else
|
else
|
||||||
{ before: maybeTrue, others: afterTrue } = List.split bytes 4
|
{ before: maybeTrue, others: afterTrue } = List.split bytes 4
|
||||||
|
|
||||||
if
|
if
|
||||||
maybeTrue == [asciiByte 't', asciiByte 'r', asciiByte 'u', asciiByte 'e']
|
maybeTrue == ['t', 'r', 'u', 'e']
|
||||||
then
|
then
|
||||||
{ result: Ok Bool.true, rest: afterTrue }
|
{ result: Ok Bool.true, rest: afterTrue }
|
||||||
else
|
else
|
||||||
|
@ -323,10 +339,10 @@ jsonString = \bytes ->
|
||||||
{ before, others: afterStartingQuote } = List.split bytes 1
|
{ before, others: afterStartingQuote } = List.split bytes 1
|
||||||
|
|
||||||
if
|
if
|
||||||
before == [asciiByte '"']
|
before == ['"']
|
||||||
then
|
then
|
||||||
# TODO: handle escape sequences
|
# TODO: handle escape sequences
|
||||||
{ taken: strSequence, rest } = takeWhile afterStartingQuote \n -> n != asciiByte '"'
|
{ taken: strSequence, rest } = takeWhile afterStartingQuote \n -> n != '"'
|
||||||
|
|
||||||
when Str.fromUtf8 strSequence is
|
when Str.fromUtf8 strSequence is
|
||||||
Ok s ->
|
Ok s ->
|
||||||
|
@ -351,7 +367,7 @@ decodeList = \decodeElem -> Decode.custom \bytes, @Json {} ->
|
||||||
{ before: afterElem, others } = List.split rest 1
|
{ before: afterElem, others } = List.split rest 1
|
||||||
|
|
||||||
if
|
if
|
||||||
afterElem == [asciiByte ',']
|
afterElem == [',']
|
||||||
then
|
then
|
||||||
decodeElems others (List.append accum val)
|
decodeElems others (List.append accum val)
|
||||||
else
|
else
|
||||||
|
@ -362,7 +378,7 @@ decodeList = \decodeElem -> Decode.custom \bytes, @Json {} ->
|
||||||
{ before, others: afterStartingBrace } = List.split bytes 1
|
{ before, others: afterStartingBrace } = List.split bytes 1
|
||||||
|
|
||||||
if
|
if
|
||||||
before == [asciiByte '[']
|
before == ['[']
|
||||||
then
|
then
|
||||||
# TODO: empty lists
|
# TODO: empty lists
|
||||||
when decodeElems afterStartingBrace [] is
|
when decodeElems afterStartingBrace [] is
|
||||||
|
@ -371,7 +387,7 @@ decodeList = \decodeElem -> Decode.custom \bytes, @Json {} ->
|
||||||
{ before: maybeEndingBrace, others: afterEndingBrace } = List.split rest 1
|
{ before: maybeEndingBrace, others: afterEndingBrace } = List.split rest 1
|
||||||
|
|
||||||
if
|
if
|
||||||
maybeEndingBrace == [asciiByte ']']
|
maybeEndingBrace == [']']
|
||||||
then
|
then
|
||||||
{ result: Ok vals, rest: afterEndingBrace }
|
{ result: Ok vals, rest: afterEndingBrace }
|
||||||
else
|
else
|
||||||
|
@ -393,10 +409,10 @@ parseExactChar = \bytes, char ->
|
||||||
Err _ -> { result: Err TooShort, rest: bytes }
|
Err _ -> { result: Err TooShort, rest: bytes }
|
||||||
|
|
||||||
openBrace : List U8 -> DecodeResult {}
|
openBrace : List U8 -> DecodeResult {}
|
||||||
openBrace = \bytes -> parseExactChar bytes (asciiByte '{')
|
openBrace = \bytes -> parseExactChar bytes '{'
|
||||||
|
|
||||||
closingBrace : List U8 -> DecodeResult {}
|
closingBrace : List U8 -> DecodeResult {}
|
||||||
closingBrace = \bytes -> parseExactChar bytes (asciiByte '}')
|
closingBrace = \bytes -> parseExactChar bytes '}'
|
||||||
|
|
||||||
recordKey : List U8 -> DecodeResult Str
|
recordKey : List U8 -> DecodeResult Str
|
||||||
recordKey = \bytes -> jsonString bytes
|
recordKey = \bytes -> jsonString bytes
|
||||||
|
@ -405,10 +421,10 @@ anything : List U8 -> DecodeResult {}
|
||||||
anything = \bytes -> { result: Err TooShort, rest: bytes }
|
anything = \bytes -> { result: Err TooShort, rest: bytes }
|
||||||
|
|
||||||
colon : List U8 -> DecodeResult {}
|
colon : List U8 -> DecodeResult {}
|
||||||
colon = \bytes -> parseExactChar bytes (asciiByte ':')
|
colon = \bytes -> parseExactChar bytes ':'
|
||||||
|
|
||||||
comma : List U8 -> DecodeResult {}
|
comma : List U8 -> DecodeResult {}
|
||||||
comma = \bytes -> parseExactChar bytes (asciiByte ',')
|
comma = \bytes -> parseExactChar bytes ','
|
||||||
|
|
||||||
tryDecode : DecodeResult a, ({ val : a, rest : List U8 } -> DecodeResult b) -> DecodeResult b
|
tryDecode : DecodeResult a, ({ val : a, rest : List U8 } -> DecodeResult b) -> DecodeResult b
|
||||||
tryDecode = \{ result, rest }, mapper ->
|
tryDecode = \{ result, rest }, mapper ->
|
||||||
|
|
|
@ -39,6 +39,7 @@ interface List
|
||||||
max,
|
max,
|
||||||
map4,
|
map4,
|
||||||
mapTry,
|
mapTry,
|
||||||
|
walkTry,
|
||||||
dropFirst,
|
dropFirst,
|
||||||
joinMap,
|
joinMap,
|
||||||
any,
|
any,
|
||||||
|
@ -60,9 +61,12 @@ interface List
|
||||||
sortAsc,
|
sortAsc,
|
||||||
sortDesc,
|
sortDesc,
|
||||||
reserve,
|
reserve,
|
||||||
|
walkBackwardsUntil,
|
||||||
]
|
]
|
||||||
imports [
|
imports [
|
||||||
Bool.{ Bool },
|
Bool.{ Bool },
|
||||||
|
Result.{ Result },
|
||||||
|
Num.{ Nat, Num, Int },
|
||||||
]
|
]
|
||||||
|
|
||||||
## Types
|
## Types
|
||||||
|
@ -85,9 +89,8 @@ interface List
|
||||||
##
|
##
|
||||||
## ## Performance Details
|
## ## Performance Details
|
||||||
##
|
##
|
||||||
## Under the hood, a list is a record containing a `len : Nat` field as well
|
## Under the hood, a list is a record containing a `len : Nat` field, a `capacity : Nat`
|
||||||
## as a pointer to a reference count and a flat array of bytes. Unique lists
|
## field, and a pointer to a reference count and a flat array of bytes.
|
||||||
## store a capacity #Nat instead of a reference count.
|
|
||||||
##
|
##
|
||||||
## ## Shared Lists
|
## ## Shared Lists
|
||||||
##
|
##
|
||||||
|
@ -109,9 +112,8 @@ interface List
|
||||||
## begins with a refcount of 1, because so far only `ratings` is referencing it.
|
## begins with a refcount of 1, because so far only `ratings` is referencing it.
|
||||||
##
|
##
|
||||||
## The second line alters this refcount. `{ foo: ratings` references
|
## The second line alters this refcount. `{ foo: ratings` references
|
||||||
## the `ratings` list, which will result in its refcount getting incremented
|
## the `ratings` list, and so does `bar: ratings }`. This will result in its
|
||||||
## from 0 to 1. Similarly, `bar: ratings }` also references the `ratings` list,
|
## refcount getting incremented from 1 to 3.
|
||||||
## which will result in its refcount getting incremented from 1 to 2.
|
|
||||||
##
|
##
|
||||||
## Let's turn this example into a function.
|
## Let's turn this example into a function.
|
||||||
##
|
##
|
||||||
|
@ -129,11 +131,11 @@ interface List
|
||||||
##
|
##
|
||||||
## Since `ratings` represented a way to reference the list, and that way is no
|
## Since `ratings` represented a way to reference the list, and that way is no
|
||||||
## longer accessible, the list's refcount gets decremented when `ratings` goes
|
## longer accessible, the list's refcount gets decremented when `ratings` goes
|
||||||
## out of scope. It will decrease from 2 back down to 1.
|
## out of scope. It will decrease from 3 back down to 2.
|
||||||
##
|
##
|
||||||
## Putting these together, when we call `getRatings 5`, what we get back is
|
## Putting these together, when we call `getRatings 5`, what we get back is
|
||||||
## a record with two fields, `foo`, and `bar`, each of which refers to the same
|
## a record with two fields, `foo`, and `bar`, each of which refers to the same
|
||||||
## list, and that list has a refcount of 1.
|
## list, and that list has a refcount of 2.
|
||||||
##
|
##
|
||||||
## Let's change the last line to be `(getRatings 5).bar` instead of `getRatings 5`:
|
## Let's change the last line to be `(getRatings 5).bar` instead of `getRatings 5`:
|
||||||
##
|
##
|
||||||
|
@ -433,6 +435,13 @@ walkUntil = \list, initial, step ->
|
||||||
Continue new -> new
|
Continue new -> new
|
||||||
Break new -> new
|
Break new -> new
|
||||||
|
|
||||||
|
## Same as [List.walkUntil], but does it from the end of the list instead.
|
||||||
|
walkBackwardsUntil : List elem, state, (state, elem -> [Continue state, Break state]) -> state
|
||||||
|
walkBackwardsUntil = \list, initial, func ->
|
||||||
|
when List.iterateBackwards list initial func is
|
||||||
|
Continue new -> new
|
||||||
|
Break new -> new
|
||||||
|
|
||||||
sum : List (Num a) -> Num a
|
sum : List (Num a) -> Num a
|
||||||
sum = \list ->
|
sum = \list ->
|
||||||
List.walk list 0 Num.add
|
List.walk list 0 Num.add
|
||||||
|
@ -957,9 +966,8 @@ mapTry = \list, toResult ->
|
||||||
Result.map (toResult elem) \ok ->
|
Result.map (toResult elem) \ok ->
|
||||||
List.append state ok
|
List.append state ok
|
||||||
|
|
||||||
## This is the same as `iterate` but with Result instead of [Continue, Break].
|
## This is the same as `iterate` but with [Result] instead of `[Continue, Break]`.
|
||||||
## Using `Result` saves a conditional in `mapTry`.
|
## Using `Result` saves a conditional in `mapTry`.
|
||||||
## It might be useful to expose this in userspace?
|
|
||||||
walkTry : List elem, state, (state, elem -> Result state err) -> Result state err
|
walkTry : List elem, state, (state, elem -> Result state err) -> Result state err
|
||||||
walkTry = \list, init, func ->
|
walkTry = \list, init, func ->
|
||||||
walkTryHelp list init func 0 (List.len list)
|
walkTryHelp list init func 0 (List.len list)
|
||||||
|
|
|
@ -145,6 +145,7 @@ interface Num
|
||||||
]
|
]
|
||||||
imports [
|
imports [
|
||||||
Bool.{ Bool },
|
Bool.{ Bool },
|
||||||
|
Result.{ Result },
|
||||||
]
|
]
|
||||||
|
|
||||||
## Represents a number that could be either an [Int] or a [Frac].
|
## Represents a number that could be either an [Int] or a [Frac].
|
||||||
|
@ -574,7 +575,6 @@ isGte : Num a, Num a -> Bool
|
||||||
|
|
||||||
## Returns `Bool.true` if the number is `0`, and `Bool.false` otherwise.
|
## Returns `Bool.true` if the number is `0`, and `Bool.false` otherwise.
|
||||||
isZero : Num a -> Bool
|
isZero : Num a -> Bool
|
||||||
isZero = \x -> x == 0
|
|
||||||
|
|
||||||
## A number is even if dividing it by 2 gives a remainder of 0.
|
## A number is even if dividing it by 2 gives a remainder of 0.
|
||||||
##
|
##
|
||||||
|
|
|
@ -14,7 +14,7 @@ interface Set
|
||||||
intersection,
|
intersection,
|
||||||
difference,
|
difference,
|
||||||
]
|
]
|
||||||
imports [List, Bool.{ Bool }, Dict.{ Dict }]
|
imports [List, Bool.{ Bool }, Dict.{ Dict }, Num.{ Nat }]
|
||||||
|
|
||||||
Set k := Dict.Dict k {}
|
Set k := Dict.Dict k {}
|
||||||
|
|
||||||
|
|
|
@ -43,8 +43,14 @@ interface Str
|
||||||
appendScalar,
|
appendScalar,
|
||||||
walkScalars,
|
walkScalars,
|
||||||
walkScalarsUntil,
|
walkScalarsUntil,
|
||||||
|
withCapacity,
|
||||||
|
]
|
||||||
|
imports [
|
||||||
|
Bool.{ Bool },
|
||||||
|
Result.{ Result },
|
||||||
|
List,
|
||||||
|
Num.{ Nat, Num, U8, U16, U32, U64, U128, I8, I16, I32, I64, I128, F32, F64, Dec },
|
||||||
]
|
]
|
||||||
imports [Bool.{ Bool }, Result.{ Result }, List]
|
|
||||||
|
|
||||||
## # Types
|
## # Types
|
||||||
##
|
##
|
||||||
|
@ -139,6 +145,9 @@ Utf8Problem : { byteIndex : Nat, problem : Utf8ByteProblem }
|
||||||
isEmpty : Str -> Bool
|
isEmpty : Str -> Bool
|
||||||
concat : Str, Str -> Str
|
concat : Str, Str -> Str
|
||||||
|
|
||||||
|
## Returns a string of the specified capacity without any content
|
||||||
|
withCapacity : Nat -> Str
|
||||||
|
|
||||||
## Combine a list of strings into a single string, with a separator
|
## Combine a list of strings into a single string, with a separator
|
||||||
## string in between each.
|
## string in between each.
|
||||||
##
|
##
|
||||||
|
|
|
@ -361,6 +361,7 @@ pub const STR_RESERVE: &str = "roc_builtins.str.reserve";
|
||||||
pub const STR_APPEND_SCALAR: &str = "roc_builtins.str.append_scalar";
|
pub const STR_APPEND_SCALAR: &str = "roc_builtins.str.append_scalar";
|
||||||
pub const STR_GET_SCALAR_UNSAFE: &str = "roc_builtins.str.get_scalar_unsafe";
|
pub const STR_GET_SCALAR_UNSAFE: &str = "roc_builtins.str.get_scalar_unsafe";
|
||||||
pub const STR_CLONE_TO: &str = "roc_builtins.str.clone_to";
|
pub const STR_CLONE_TO: &str = "roc_builtins.str.clone_to";
|
||||||
|
pub const STR_WITH_CAPACITY: &str = "roc_builtins.str.with_capacity";
|
||||||
|
|
||||||
pub const LIST_MAP: &str = "roc_builtins.list.map";
|
pub const LIST_MAP: &str = "roc_builtins.list.map";
|
||||||
pub const LIST_MAP2: &str = "roc_builtins.list.map2";
|
pub const LIST_MAP2: &str = "roc_builtins.list.map2";
|
||||||
|
|
|
@ -55,6 +55,8 @@ macro_rules! map_symbol_to_lowlevel_and_arity {
|
||||||
Symbol::NUM_TO_F32_CHECKED => Some(to_num_checked(Symbol::NUM_TO_F32_CHECKED, var_store, LowLevel::NumToFloatChecked)),
|
Symbol::NUM_TO_F32_CHECKED => Some(to_num_checked(Symbol::NUM_TO_F32_CHECKED, var_store, LowLevel::NumToFloatChecked)),
|
||||||
Symbol::NUM_TO_F64_CHECKED => Some(to_num_checked(Symbol::NUM_TO_F64_CHECKED, var_store, LowLevel::NumToFloatChecked)),
|
Symbol::NUM_TO_F64_CHECKED => Some(to_num_checked(Symbol::NUM_TO_F64_CHECKED, var_store, LowLevel::NumToFloatChecked)),
|
||||||
|
|
||||||
|
Symbol::NUM_IS_ZERO => Some(to_num_is_zero(Symbol::NUM_IS_ZERO, var_store)),
|
||||||
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,6 +123,7 @@ map_symbol_to_lowlevel_and_arity! {
|
||||||
StrGetScalarUnsafe; STR_GET_SCALAR_UNSAFE; 2,
|
StrGetScalarUnsafe; STR_GET_SCALAR_UNSAFE; 2,
|
||||||
StrToNum; STR_TO_NUM; 1,
|
StrToNum; STR_TO_NUM; 1,
|
||||||
StrGetCapacity; STR_CAPACITY; 1,
|
StrGetCapacity; STR_CAPACITY; 1,
|
||||||
|
StrWithCapacity; STR_WITH_CAPACITY; 1,
|
||||||
|
|
||||||
ListLen; LIST_LEN; 1,
|
ListLen; LIST_LEN; 1,
|
||||||
ListWithCapacity; LIST_WITH_CAPACITY; 1,
|
ListWithCapacity; LIST_WITH_CAPACITY; 1,
|
||||||
|
@ -535,3 +538,33 @@ fn to_num_checked(symbol: Symbol, var_store: &mut VarStore, lowlevel: LowLevel)
|
||||||
ret_var,
|
ret_var,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn to_num_is_zero(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
|
let bool_var = var_store.fresh();
|
||||||
|
let num_var = var_store.fresh();
|
||||||
|
|
||||||
|
let body = Expr::RunLowLevel {
|
||||||
|
op: LowLevel::Eq,
|
||||||
|
args: vec![
|
||||||
|
(num_var, Var(Symbol::ARG_1)),
|
||||||
|
(
|
||||||
|
num_var,
|
||||||
|
Num(
|
||||||
|
var_store.fresh(),
|
||||||
|
"0".to_string().into_boxed_str(),
|
||||||
|
crate::expr::IntValue::I128(0i128.to_ne_bytes()),
|
||||||
|
roc_types::num::NumBound::None,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
ret_var: bool_var,
|
||||||
|
};
|
||||||
|
|
||||||
|
defn(
|
||||||
|
symbol,
|
||||||
|
vec![(num_var, Symbol::ARG_1)],
|
||||||
|
var_store,
|
||||||
|
body,
|
||||||
|
bool_var,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -60,8 +60,6 @@ trait CopyEnv {
|
||||||
|
|
||||||
fn clone_name(&mut self, name: SubsIndex<Lowercase>) -> SubsIndex<Lowercase>;
|
fn clone_name(&mut self, name: SubsIndex<Lowercase>) -> SubsIndex<Lowercase>;
|
||||||
|
|
||||||
fn clone_tag_name(&mut self, tag_name: SubsIndex<TagName>) -> SubsIndex<TagName>;
|
|
||||||
|
|
||||||
fn clone_field_names(&mut self, field_names: SubsSlice<Lowercase>) -> SubsSlice<Lowercase>;
|
fn clone_field_names(&mut self, field_names: SubsSlice<Lowercase>) -> SubsSlice<Lowercase>;
|
||||||
|
|
||||||
fn clone_tag_names(&mut self, tag_names: SubsSlice<TagName>) -> SubsSlice<TagName>;
|
fn clone_tag_names(&mut self, tag_names: SubsSlice<TagName>) -> SubsSlice<TagName>;
|
||||||
|
@ -95,11 +93,6 @@ impl CopyEnv for Subs {
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn clone_tag_name(&mut self, tag_name: SubsIndex<TagName>) -> SubsIndex<TagName> {
|
|
||||||
tag_name
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn clone_field_names(&mut self, field_names: SubsSlice<Lowercase>) -> SubsSlice<Lowercase> {
|
fn clone_field_names(&mut self, field_names: SubsSlice<Lowercase>) -> SubsSlice<Lowercase> {
|
||||||
field_names
|
field_names
|
||||||
|
@ -150,11 +143,6 @@ impl<'a> CopyEnv for AcrossSubs<'a> {
|
||||||
SubsIndex::push_new(&mut self.target.field_names, self.source[name].clone())
|
SubsIndex::push_new(&mut self.target.field_names, self.source[name].clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn clone_tag_name(&mut self, tag_name: SubsIndex<TagName>) -> SubsIndex<TagName> {
|
|
||||||
SubsIndex::push_new(&mut self.target.tag_names, self.source[tag_name].clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn clone_field_names(&mut self, field_names: SubsSlice<Lowercase>) -> SubsSlice<Lowercase> {
|
fn clone_field_names(&mut self, field_names: SubsSlice<Lowercase>) -> SubsSlice<Lowercase> {
|
||||||
SubsSlice::extend_new(
|
SubsSlice::extend_new(
|
||||||
|
@ -259,7 +247,7 @@ fn deep_copy_expr_help<C: CopyEnv>(env: &mut C, copied: &mut Vec<Variable>, expr
|
||||||
Int(v1, v2, str, val, bound) => Int(sub!(*v1), sub!(*v2), str.clone(), *val, *bound),
|
Int(v1, v2, str, val, bound) => Int(sub!(*v1), sub!(*v2), str.clone(), *val, *bound),
|
||||||
Float(v1, v2, str, val, bound) => Float(sub!(*v1), sub!(*v2), str.clone(), *val, *bound),
|
Float(v1, v2, str, val, bound) => Float(sub!(*v1), sub!(*v2), str.clone(), *val, *bound),
|
||||||
Str(str) => Str(str.clone()),
|
Str(str) => Str(str.clone()),
|
||||||
SingleQuote(char) => SingleQuote(*char),
|
SingleQuote(v1, v2, char, bound) => SingleQuote(sub!(*v1), sub!(*v2), *char, *bound),
|
||||||
List {
|
List {
|
||||||
elem_var,
|
elem_var,
|
||||||
loc_elems,
|
loc_elems,
|
||||||
|
@ -725,7 +713,7 @@ fn deep_copy_pattern_help<C: CopyEnv>(
|
||||||
FloatLiteral(sub!(*v1), sub!(*v2), s.clone(), *n, *bound)
|
FloatLiteral(sub!(*v1), sub!(*v2), s.clone(), *n, *bound)
|
||||||
}
|
}
|
||||||
StrLiteral(s) => StrLiteral(s.clone()),
|
StrLiteral(s) => StrLiteral(s.clone()),
|
||||||
SingleQuote(c) => SingleQuote(*c),
|
SingleQuote(v1, v2, c, bound) => SingleQuote(sub!(*v1), sub!(*v2), *c, *bound),
|
||||||
Underscore => Underscore,
|
Underscore => Underscore,
|
||||||
AbilityMemberSpecialization { ident, specializes } => AbilityMemberSpecialization {
|
AbilityMemberSpecialization { ident, specializes } => AbilityMemberSpecialization {
|
||||||
ident: *ident,
|
ident: *ident,
|
||||||
|
@ -935,12 +923,13 @@ fn deep_copy_type_vars<C: CopyEnv>(
|
||||||
Structure(RecursiveTagUnion(new_rec_var, new_union_tags, new_ext_var))
|
Structure(RecursiveTagUnion(new_rec_var, new_union_tags, new_ext_var))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
FunctionOrTagUnion(tag_name, symbol, ext_var) => {
|
FunctionOrTagUnion(tag_names, symbols, ext_var) => {
|
||||||
let new_ext_var = descend_var!(ext_var);
|
let new_ext_var = descend_var!(ext_var);
|
||||||
let new_tag_name = env.clone_tag_name(tag_name);
|
let new_tag_names = env.clone_tag_names(tag_names);
|
||||||
|
let new_symbols = env.clone_lambda_names(symbols);
|
||||||
perform_clone!(Structure(FunctionOrTagUnion(
|
perform_clone!(Structure(FunctionOrTagUnion(
|
||||||
new_tag_name,
|
new_tag_names,
|
||||||
symbol,
|
new_symbols,
|
||||||
new_ext_var
|
new_ext_var
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1884,7 +1884,7 @@ fn pattern_to_vars_by_symbol(
|
||||||
| IntLiteral(..)
|
| IntLiteral(..)
|
||||||
| FloatLiteral(..)
|
| FloatLiteral(..)
|
||||||
| StrLiteral(_)
|
| StrLiteral(_)
|
||||||
| SingleQuote(_)
|
| SingleQuote(..)
|
||||||
| Underscore
|
| Underscore
|
||||||
| MalformedPattern(_, _)
|
| MalformedPattern(_, _)
|
||||||
| UnsupportedPattern(_)
|
| UnsupportedPattern(_)
|
||||||
|
|
|
@ -253,7 +253,7 @@ fn sketch_pattern(pattern: &crate::pattern::Pattern) -> SketchedPattern {
|
||||||
}
|
}
|
||||||
&FloatLiteral(_, _, _, f, _) => SP::Literal(Literal::Float(f64::to_bits(f))),
|
&FloatLiteral(_, _, _, f, _) => SP::Literal(Literal::Float(f64::to_bits(f))),
|
||||||
StrLiteral(v) => SP::Literal(Literal::Str(v.clone())),
|
StrLiteral(v) => SP::Literal(Literal::Str(v.clone())),
|
||||||
&SingleQuote(c) => SP::Literal(Literal::Byte(c as u8)),
|
&SingleQuote(_, _, c, _) => SP::Literal(Literal::Byte(c as u8)),
|
||||||
RecordDestructure { destructs, .. } => {
|
RecordDestructure { destructs, .. } => {
|
||||||
let tag_id = TagId(0);
|
let tag_id = TagId(0);
|
||||||
let mut patterns = std::vec::Vec::with_capacity(destructs.len());
|
let mut patterns = std::vec::Vec::with_capacity(destructs.len());
|
||||||
|
|
|
@ -22,6 +22,7 @@ use roc_parse::ast::{self, Defs, EscapedChar, StrLiteral};
|
||||||
use roc_parse::pattern::PatternType::*;
|
use roc_parse::pattern::PatternType::*;
|
||||||
use roc_problem::can::{PrecedenceProblem, Problem, RuntimeError};
|
use roc_problem::can::{PrecedenceProblem, Problem, RuntimeError};
|
||||||
use roc_region::all::{Loc, Region};
|
use roc_region::all::{Loc, Region};
|
||||||
|
use roc_types::num::SingleQuoteBound;
|
||||||
use roc_types::subs::{ExhaustiveMark, IllegalCycleMark, RedundantMark, VarStore, Variable};
|
use roc_types::subs::{ExhaustiveMark, IllegalCycleMark, RedundantMark, VarStore, Variable};
|
||||||
use roc_types::types::{Alias, Category, LambdaSet, OptAbleVar, Type};
|
use roc_types::types::{Alias, Category, LambdaSet, OptAbleVar, Type};
|
||||||
use std::fmt::{Debug, Display};
|
use std::fmt::{Debug, Display};
|
||||||
|
@ -91,7 +92,8 @@ pub enum Expr {
|
||||||
Int(Variable, Variable, Box<str>, IntValue, IntBound),
|
Int(Variable, Variable, Box<str>, IntValue, IntBound),
|
||||||
Float(Variable, Variable, Box<str>, f64, FloatBound),
|
Float(Variable, Variable, Box<str>, f64, FloatBound),
|
||||||
Str(Box<str>),
|
Str(Box<str>),
|
||||||
SingleQuote(char),
|
// Number variable, precision variable, value, bound
|
||||||
|
SingleQuote(Variable, Variable, char, SingleQuoteBound),
|
||||||
List {
|
List {
|
||||||
elem_var: Variable,
|
elem_var: Variable,
|
||||||
loc_elems: Vec<Loc<Expr>>,
|
loc_elems: Vec<Loc<Expr>>,
|
||||||
|
@ -637,7 +639,15 @@ pub fn canonicalize_expr<'a>(
|
||||||
let mut it = string.chars().peekable();
|
let mut it = string.chars().peekable();
|
||||||
if let Some(char) = it.next() {
|
if let Some(char) = it.next() {
|
||||||
if it.peek().is_none() {
|
if it.peek().is_none() {
|
||||||
(Expr::SingleQuote(char), Output::default())
|
(
|
||||||
|
Expr::SingleQuote(
|
||||||
|
var_store.fresh(),
|
||||||
|
var_store.fresh(),
|
||||||
|
char,
|
||||||
|
SingleQuoteBound::from_char(char),
|
||||||
|
),
|
||||||
|
Output::default(),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
// multiple chars is found
|
// multiple chars is found
|
||||||
let error = roc_problem::can::RuntimeError::MultipleCharsInSingleQuote(region);
|
let error = roc_problem::can::RuntimeError::MultipleCharsInSingleQuote(region);
|
||||||
|
@ -1642,7 +1652,7 @@ pub fn inline_calls(var_store: &mut VarStore, scope: &mut Scope, expr: Expr) ->
|
||||||
| other @ Int(..)
|
| other @ Int(..)
|
||||||
| other @ Float(..)
|
| other @ Float(..)
|
||||||
| other @ Str { .. }
|
| other @ Str { .. }
|
||||||
| other @ SingleQuote(_)
|
| other @ SingleQuote(..)
|
||||||
| other @ RuntimeError(_)
|
| other @ RuntimeError(_)
|
||||||
| other @ EmptyRecord
|
| other @ EmptyRecord
|
||||||
| other @ Accessor { .. }
|
| other @ Accessor { .. }
|
||||||
|
@ -2703,7 +2713,7 @@ fn get_lookup_symbols(expr: &Expr, var_store: &mut VarStore) -> Vec<(Symbol, Var
|
||||||
| Expr::Str(_)
|
| Expr::Str(_)
|
||||||
| Expr::ZeroArgumentTag { .. }
|
| Expr::ZeroArgumentTag { .. }
|
||||||
| Expr::Accessor(_)
|
| Expr::Accessor(_)
|
||||||
| Expr::SingleQuote(_)
|
| Expr::SingleQuote(..)
|
||||||
| Expr::EmptyRecord
|
| Expr::EmptyRecord
|
||||||
| Expr::TypedHole(_)
|
| Expr::TypedHole(_)
|
||||||
| Expr::RuntimeError(_)
|
| Expr::RuntimeError(_)
|
||||||
|
|
|
@ -899,7 +899,7 @@ fn fix_values_captured_in_closure_pattern(
|
||||||
| IntLiteral(..)
|
| IntLiteral(..)
|
||||||
| FloatLiteral(..)
|
| FloatLiteral(..)
|
||||||
| StrLiteral(_)
|
| StrLiteral(_)
|
||||||
| SingleQuote(_)
|
| SingleQuote(..)
|
||||||
| Underscore
|
| Underscore
|
||||||
| Shadowed(..)
|
| Shadowed(..)
|
||||||
| MalformedPattern(_, _)
|
| MalformedPattern(_, _)
|
||||||
|
@ -1038,7 +1038,7 @@ fn fix_values_captured_in_closure_expr(
|
||||||
| Int(..)
|
| Int(..)
|
||||||
| Float(..)
|
| Float(..)
|
||||||
| Str(_)
|
| Str(_)
|
||||||
| SingleQuote(_)
|
| SingleQuote(..)
|
||||||
| Var(_)
|
| Var(_)
|
||||||
| AbilityMember(..)
|
| AbilityMember(..)
|
||||||
| EmptyRecord
|
| EmptyRecord
|
||||||
|
|
|
@ -12,6 +12,7 @@ use roc_parse::ast::{self, StrLiteral, StrSegment};
|
||||||
use roc_parse::pattern::PatternType;
|
use roc_parse::pattern::PatternType;
|
||||||
use roc_problem::can::{MalformedPatternProblem, Problem, RuntimeError, ShadowKind};
|
use roc_problem::can::{MalformedPatternProblem, Problem, RuntimeError, ShadowKind};
|
||||||
use roc_region::all::{Loc, Region};
|
use roc_region::all::{Loc, Region};
|
||||||
|
use roc_types::num::SingleQuoteBound;
|
||||||
use roc_types::subs::{VarStore, Variable};
|
use roc_types::subs::{VarStore, Variable};
|
||||||
use roc_types::types::{LambdaSet, OptAbleVar, PatternCategory, Type};
|
use roc_types::types::{LambdaSet, OptAbleVar, PatternCategory, Type};
|
||||||
|
|
||||||
|
@ -59,7 +60,7 @@ pub enum Pattern {
|
||||||
IntLiteral(Variable, Variable, Box<str>, IntValue, IntBound),
|
IntLiteral(Variable, Variable, Box<str>, IntValue, IntBound),
|
||||||
FloatLiteral(Variable, Variable, Box<str>, f64, FloatBound),
|
FloatLiteral(Variable, Variable, Box<str>, f64, FloatBound),
|
||||||
StrLiteral(Box<str>),
|
StrLiteral(Box<str>),
|
||||||
SingleQuote(char),
|
SingleQuote(Variable, Variable, char, SingleQuoteBound),
|
||||||
Underscore,
|
Underscore,
|
||||||
|
|
||||||
/// An identifier that marks a specialization of an ability member.
|
/// An identifier that marks a specialization of an ability member.
|
||||||
|
@ -95,7 +96,7 @@ impl Pattern {
|
||||||
IntLiteral(var, ..) => Some(*var),
|
IntLiteral(var, ..) => Some(*var),
|
||||||
FloatLiteral(var, ..) => Some(*var),
|
FloatLiteral(var, ..) => Some(*var),
|
||||||
StrLiteral(_) => None,
|
StrLiteral(_) => None,
|
||||||
SingleQuote(_) => None,
|
SingleQuote(..) => None,
|
||||||
Underscore => None,
|
Underscore => None,
|
||||||
|
|
||||||
AbilityMemberSpecialization { .. } => None,
|
AbilityMemberSpecialization { .. } => None,
|
||||||
|
@ -148,7 +149,7 @@ impl Pattern {
|
||||||
IntLiteral(..) => C::Int,
|
IntLiteral(..) => C::Int,
|
||||||
FloatLiteral(..) => C::Float,
|
FloatLiteral(..) => C::Float,
|
||||||
StrLiteral(_) => C::Str,
|
StrLiteral(_) => C::Str,
|
||||||
SingleQuote(_) => C::Character,
|
SingleQuote(..) => C::Character,
|
||||||
Underscore => C::PatternDefault,
|
Underscore => C::PatternDefault,
|
||||||
|
|
||||||
AbilityMemberSpecialization { .. } => C::PatternDefault,
|
AbilityMemberSpecialization { .. } => C::PatternDefault,
|
||||||
|
@ -456,7 +457,12 @@ pub fn canonicalize_pattern<'a>(
|
||||||
let mut it = string.chars().peekable();
|
let mut it = string.chars().peekable();
|
||||||
if let Some(char) = it.next() {
|
if let Some(char) = it.next() {
|
||||||
if it.peek().is_none() {
|
if it.peek().is_none() {
|
||||||
Pattern::SingleQuote(char)
|
Pattern::SingleQuote(
|
||||||
|
var_store.fresh(),
|
||||||
|
var_store.fresh(),
|
||||||
|
char,
|
||||||
|
SingleQuoteBound::from_char(char),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
// multiple chars is found
|
// multiple chars is found
|
||||||
let problem = MalformedPatternProblem::MultipleCharsInSingleQuote;
|
let problem = MalformedPatternProblem::MultipleCharsInSingleQuote;
|
||||||
|
@ -724,7 +730,7 @@ impl<'a> BindingsFromPattern<'a> {
|
||||||
| IntLiteral(..)
|
| IntLiteral(..)
|
||||||
| FloatLiteral(..)
|
| FloatLiteral(..)
|
||||||
| StrLiteral(_)
|
| StrLiteral(_)
|
||||||
| SingleQuote(_)
|
| SingleQuote(..)
|
||||||
| Underscore
|
| Underscore
|
||||||
| Shadowed(_, _, _)
|
| Shadowed(_, _, _)
|
||||||
| MalformedPattern(_, _)
|
| MalformedPattern(_, _)
|
||||||
|
|
|
@ -4,7 +4,7 @@ use roc_can::expected::Expected::{self, *};
|
||||||
use roc_can::num::{FloatBound, FloatWidth, IntBound, IntLitWidth, NumBound, SignDemand};
|
use roc_can::num::{FloatBound, FloatWidth, IntBound, IntLitWidth, NumBound, SignDemand};
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_region::all::Region;
|
use roc_region::all::Region;
|
||||||
use roc_types::num::NumericRange;
|
use roc_types::num::{NumericRange, SingleQuoteBound};
|
||||||
use roc_types::subs::Variable;
|
use roc_types::subs::Variable;
|
||||||
use roc_types::types::Type::{self, *};
|
use roc_types::types::Type::{self, *};
|
||||||
use roc_types::types::{AliasKind, Category};
|
use roc_types::types::{AliasKind, Category};
|
||||||
|
@ -99,6 +99,42 @@ pub fn int_literal(
|
||||||
constraints.exists([num_var], and_constraint)
|
constraints.exists([num_var], and_constraint)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn single_quote_literal(
|
||||||
|
constraints: &mut Constraints,
|
||||||
|
num_var: Variable,
|
||||||
|
precision_var: Variable,
|
||||||
|
expected: Expected<Type>,
|
||||||
|
region: Region,
|
||||||
|
bound: SingleQuoteBound,
|
||||||
|
) -> Constraint {
|
||||||
|
let reason = Reason::IntLiteral;
|
||||||
|
|
||||||
|
// Always add the bound first; this improves the resolved type quality in case it's an alias like "U8".
|
||||||
|
let mut constrs = ArrayVec::<_, 3>::new();
|
||||||
|
let num_type = add_numeric_bound_constr(
|
||||||
|
constraints,
|
||||||
|
&mut constrs,
|
||||||
|
num_var,
|
||||||
|
precision_var,
|
||||||
|
bound,
|
||||||
|
region,
|
||||||
|
Category::Character,
|
||||||
|
);
|
||||||
|
|
||||||
|
constrs.extend([
|
||||||
|
constraints.equal_types(
|
||||||
|
num_type.clone(),
|
||||||
|
ForReason(reason, num_int(Type::Variable(precision_var)), region),
|
||||||
|
Category::Character,
|
||||||
|
region,
|
||||||
|
),
|
||||||
|
constraints.equal_types(num_type, expected, Category::Character, region),
|
||||||
|
]);
|
||||||
|
|
||||||
|
let and_constraint = constraints.and_constraint(constrs);
|
||||||
|
constraints.exists([num_var], and_constraint)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn float_literal(
|
pub fn float_literal(
|
||||||
constraints: &mut Constraints,
|
constraints: &mut Constraints,
|
||||||
|
@ -332,6 +368,16 @@ impl TypedNumericBound for NumBound {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TypedNumericBound for SingleQuoteBound {
|
||||||
|
fn numeric_bound(&self) -> NumericBound {
|
||||||
|
match self {
|
||||||
|
&SingleQuoteBound::AtLeast { width } => {
|
||||||
|
NumericBound::Range(NumericRange::IntAtLeastEitherSign(width))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A bound placed on a number because of its literal value.
|
/// A bound placed on a number because of its literal value.
|
||||||
/// e.g. `-5` cannot be unsigned, and 300 does not fit in a U8
|
/// e.g. `-5` cannot be unsigned, and 300 does not fit in a U8
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
use crate::builtins::{
|
use crate::builtins::{
|
||||||
empty_list_type, float_literal, int_literal, list_type, num_literal, num_u32, str_type,
|
empty_list_type, float_literal, int_literal, list_type, num_literal, single_quote_literal,
|
||||||
|
str_type,
|
||||||
};
|
};
|
||||||
use crate::pattern::{constrain_pattern, PatternState};
|
use crate::pattern::{constrain_pattern, PatternState};
|
||||||
use roc_can::annotation::IntroducedVariables;
|
use roc_can::annotation::IntroducedVariables;
|
||||||
|
@ -292,7 +293,14 @@ pub fn constrain_expr(
|
||||||
constraints.exists(vars, and_constraint)
|
constraints.exists(vars, and_constraint)
|
||||||
}
|
}
|
||||||
Str(_) => constraints.equal_types(str_type(), expected, Category::Str, region),
|
Str(_) => constraints.equal_types(str_type(), expected, Category::Str, region),
|
||||||
SingleQuote(_) => constraints.equal_types(num_u32(), expected, Category::Character, region),
|
SingleQuote(num_var, precision_var, _, bound) => single_quote_literal(
|
||||||
|
constraints,
|
||||||
|
*num_var,
|
||||||
|
*precision_var,
|
||||||
|
expected,
|
||||||
|
region,
|
||||||
|
*bound,
|
||||||
|
),
|
||||||
List {
|
List {
|
||||||
elem_var,
|
elem_var,
|
||||||
loc_elems,
|
loc_elems,
|
||||||
|
|
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