mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 08:34:33 +00:00
Merge remote-tracking branch 'origin/main' into tutorial-syntax
This commit is contained in:
commit
7dd5ae3830
62 changed files with 4781 additions and 1647 deletions
2
.github/workflows/nightly_linux_x86_64.yml
vendored
2
.github/workflows/nightly_linux_x86_64.yml
vendored
|
@ -17,7 +17,7 @@ jobs:
|
||||||
run: ./ci/write_version.sh
|
run: ./ci/write_version.sh
|
||||||
|
|
||||||
- name: build release
|
- name: build release
|
||||||
run: RUSTFLAGS="-C target-cpu=x86-64" cargo build --features with_sound --release --locked
|
run: RUSTFLAGS="-C target-cpu=x86-64" cargo build --release --locked
|
||||||
# target-cpu=x86-64 -> For maximal compatibility for all CPU's. Note that this setting will likely make the compiler slower.
|
# target-cpu=x86-64 -> For maximal compatibility for all CPU's. Note that this setting will likely make the compiler slower.
|
||||||
|
|
||||||
- name: get commit SHA
|
- name: get commit SHA
|
||||||
|
|
2
.github/workflows/nightly_macos_x86_64.yml
vendored
2
.github/workflows/nightly_macos_x86_64.yml
vendored
|
@ -22,7 +22,7 @@ jobs:
|
||||||
# this issue may be caused by using older versions of XCode
|
# this issue may be caused by using older versions of XCode
|
||||||
|
|
||||||
- name: build release
|
- name: build release
|
||||||
run: RUSTFLAGS="-C target-cpu=x86-64" cargo build --features with_sound --release --locked
|
run: RUSTFLAGS="-C target-cpu=x86-64" cargo build --release --locked
|
||||||
# target-cpu=x86-64 -> For maximal compatibility for all CPU's. Note that this setting will likely make the compiler slower.
|
# target-cpu=x86-64 -> For maximal compatibility for all CPU's. Note that this setting will likely make the compiler slower.
|
||||||
|
|
||||||
- name: get commit SHA
|
- name: get commit SHA
|
||||||
|
|
346
Cargo.lock
generated
346
Cargo.lock
generated
|
@ -68,28 +68,6 @@ dependencies = [
|
||||||
"alloc-no-stdlib",
|
"alloc-no-stdlib",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "alsa"
|
|
||||||
version = "0.6.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5915f52fe2cf65e83924d037b6c5290b7cee097c6b5c8700746e6168a343fd6b"
|
|
||||||
dependencies = [
|
|
||||||
"alsa-sys",
|
|
||||||
"bitflags",
|
|
||||||
"libc",
|
|
||||||
"nix 0.23.1",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "alsa-sys"
|
|
||||||
version = "0.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"pkg-config",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "approx"
|
name = "approx"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
@ -198,25 +176,6 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bindgen"
|
|
||||||
version = "0.59.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
"cexpr",
|
|
||||||
"clang-sys",
|
|
||||||
"lazy_static",
|
|
||||||
"lazycell",
|
|
||||||
"peeking_take_while",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"regex",
|
|
||||||
"rustc-hash",
|
|
||||||
"shlex",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bit-set"
|
name = "bit-set"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
|
@ -415,24 +374,6 @@ name = "cc"
|
||||||
version = "1.0.73"
|
version = "1.0.73"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
||||||
dependencies = [
|
|
||||||
"jobserver",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cesu8"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cexpr"
|
|
||||||
version = "0.6.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
|
|
||||||
dependencies = [
|
|
||||||
"nom",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
|
@ -462,17 +403,6 @@ dependencies = [
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "clang-sys"
|
|
||||||
version = "1.3.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5a050e2153c5be08febd6734e29298e844fdb0fa21aeddd63b4eb7baa106c69b"
|
|
||||||
dependencies = [
|
|
||||||
"glob",
|
|
||||||
"libc",
|
|
||||||
"libloading",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "2.34.0"
|
version = "2.34.0"
|
||||||
|
@ -523,12 +453,6 @@ dependencies = [
|
||||||
"os_str_bytes",
|
"os_str_bytes",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "claxon"
|
|
||||||
version = "0.4.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cli_utils"
|
name = "cli_utils"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
|
@ -620,16 +544,6 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "combine"
|
|
||||||
version = "4.6.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2a604e93b79d1808327a6fca85a6f2d69de66461e7620f5a4cbf5fb4d1d7c948"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"memchr",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "confy"
|
name = "confy"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
|
@ -792,50 +706,6 @@ dependencies = [
|
||||||
"objc",
|
"objc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "coreaudio-rs"
|
|
||||||
version = "0.10.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "11894b20ebfe1ff903cbdc52259693389eea03b94918a2def2c30c3bf227ad88"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
"coreaudio-sys",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "coreaudio-sys"
|
|
||||||
version = "0.2.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3dff444d80630d7073077d38d40b4501fd518bd2b922c2a55edcc8b0f7be57e6"
|
|
||||||
dependencies = [
|
|
||||||
"bindgen",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cpal"
|
|
||||||
version = "0.13.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "74117836a5124f3629e4b474eed03e479abaf98988b4bb317e29f08cfe0e4116"
|
|
||||||
dependencies = [
|
|
||||||
"alsa",
|
|
||||||
"core-foundation-sys 0.8.3",
|
|
||||||
"coreaudio-rs",
|
|
||||||
"jni",
|
|
||||||
"js-sys",
|
|
||||||
"lazy_static",
|
|
||||||
"libc",
|
|
||||||
"mach",
|
|
||||||
"ndk 0.6.0",
|
|
||||||
"ndk-glue 0.6.2",
|
|
||||||
"nix 0.23.1",
|
|
||||||
"oboe",
|
|
||||||
"parking_lot 0.11.2",
|
|
||||||
"stdweb",
|
|
||||||
"thiserror",
|
|
||||||
"web-sys",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cpufeatures"
|
name = "cpufeatures"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
|
@ -1471,12 +1341,6 @@ version = "0.26.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4"
|
checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "glob"
|
|
||||||
version = "0.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glow"
|
name = "glow"
|
||||||
version = "0.11.2"
|
version = "0.11.2"
|
||||||
|
@ -1632,12 +1496,6 @@ version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
|
checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hound"
|
|
||||||
version = "3.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8a164bb2ceaeff4f42542bdb847c41517c78a60f5649671b2a07312b6e117549"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "http"
|
name = "http"
|
||||||
version = "0.2.8"
|
version = "0.2.8"
|
||||||
|
@ -1876,35 +1734,12 @@ version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
|
checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "jni"
|
|
||||||
version = "0.19.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec"
|
|
||||||
dependencies = [
|
|
||||||
"cesu8",
|
|
||||||
"combine",
|
|
||||||
"jni-sys",
|
|
||||||
"log",
|
|
||||||
"thiserror",
|
|
||||||
"walkdir",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jni-sys"
|
name = "jni-sys"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
|
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "jobserver"
|
|
||||||
version = "0.1.24"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.60"
|
version = "0.3.60"
|
||||||
|
@ -1946,23 +1781,6 @@ version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lazycell"
|
|
||||||
version = "1.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lewton"
|
|
||||||
version = "0.10.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030"
|
|
||||||
dependencies = [
|
|
||||||
"byteorder",
|
|
||||||
"ogg",
|
|
||||||
"tinyvec",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.135"
|
version = "0.2.135"
|
||||||
|
@ -2032,15 +1850,6 @@ dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "mach"
|
|
||||||
version = "0.3.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mach_object"
|
name = "mach_object"
|
||||||
version = "0.1.17"
|
version = "0.1.17"
|
||||||
|
@ -2155,26 +1964,6 @@ version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "minimp3"
|
|
||||||
version = "0.5.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "985438f75febf74c392071a975a29641b420dd84431135a6e6db721de4b74372"
|
|
||||||
dependencies = [
|
|
||||||
"minimp3-sys",
|
|
||||||
"slice-deque",
|
|
||||||
"thiserror",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "minimp3-sys"
|
|
||||||
version = "0.3.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e21c73734c69dc95696c9ed8926a2b393171d98b3f5f5935686a26a487ab9b90"
|
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miniz_oxide"
|
name = "miniz_oxide"
|
||||||
version = "0.5.3"
|
version = "0.5.3"
|
||||||
|
@ -2232,20 +2021,7 @@ checksum = "96d868f654c72e75f8687572699cdabe755f03effbb62542768e995d5b8d699d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"jni-sys",
|
"jni-sys",
|
||||||
"ndk-sys 0.2.2",
|
"ndk-sys",
|
||||||
"num_enum",
|
|
||||||
"thiserror",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ndk"
|
|
||||||
version = "0.6.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2032c77e030ddee34a6787a64166008da93f6a352b629261d0fee232b8742dd4"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
"jni-sys",
|
|
||||||
"ndk-sys 0.3.0",
|
|
||||||
"num_enum",
|
"num_enum",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
@ -2265,25 +2041,10 @@ dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"ndk 0.5.0",
|
"ndk",
|
||||||
"ndk-context",
|
"ndk-context",
|
||||||
"ndk-macro",
|
"ndk-macro",
|
||||||
"ndk-sys 0.2.2",
|
"ndk-sys",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ndk-glue"
|
|
||||||
version = "0.6.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0d0c4a7b83860226e6b4183edac21851f05d5a51756e97a1144b7f5a6b63e65f"
|
|
||||||
dependencies = [
|
|
||||||
"lazy_static",
|
|
||||||
"libc",
|
|
||||||
"log",
|
|
||||||
"ndk 0.6.0",
|
|
||||||
"ndk-context",
|
|
||||||
"ndk-macro",
|
|
||||||
"ndk-sys 0.3.0",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2305,15 +2066,6 @@ version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121"
|
checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ndk-sys"
|
|
||||||
version = "0.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6e5a6ae77c8ee183dcbbba6150e2e6b9f3f4196a7666c02a715a95692ec1fa97"
|
|
||||||
dependencies = [
|
|
||||||
"jni-sys",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nibble_vec"
|
name = "nibble_vec"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -2386,17 +2138,6 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num-derive"
|
|
||||||
version = "0.3.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.15"
|
version = "0.2.15"
|
||||||
|
@ -2498,38 +2239,6 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "oboe"
|
|
||||||
version = "0.4.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "27f63c358b4fa0fbcfefd7c8be5cfc39c08ce2389f5325687e7762a48d30a5c1"
|
|
||||||
dependencies = [
|
|
||||||
"jni",
|
|
||||||
"ndk 0.6.0",
|
|
||||||
"ndk-context",
|
|
||||||
"num-derive",
|
|
||||||
"num-traits",
|
|
||||||
"oboe-sys",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "oboe-sys"
|
|
||||||
version = "0.4.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3370abb7372ed744232c12954d920d1a40f1c4686de9e79e800021ef492294bd"
|
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ogg"
|
|
||||||
version = "0.8.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e"
|
|
||||||
dependencies = [
|
|
||||||
"byteorder",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.17.0"
|
version = "1.17.0"
|
||||||
|
@ -2685,12 +2394,6 @@ dependencies = [
|
||||||
"windows-sys 0.36.1",
|
"windows-sys 0.36.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "peeking_take_while"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "peg"
|
name = "peg"
|
||||||
version = "0.8.1"
|
version = "0.8.1"
|
||||||
|
@ -3570,7 +3273,6 @@ dependencies = [
|
||||||
"roc_types",
|
"roc_types",
|
||||||
"roc_unify",
|
"roc_unify",
|
||||||
"roc_utils",
|
"roc_utils",
|
||||||
"rodio",
|
|
||||||
"serde",
|
"serde",
|
||||||
"snafu",
|
"snafu",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
|
@ -4187,19 +3889,6 @@ dependencies = [
|
||||||
"roc_error_macros",
|
"roc_error_macros",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rodio"
|
|
||||||
version = "0.15.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ec0939e9f626e6c6f1989adb6226a039c855ca483053f0ee7c98b90e41cf731e"
|
|
||||||
dependencies = [
|
|
||||||
"claxon",
|
|
||||||
"cpal",
|
|
||||||
"hound",
|
|
||||||
"lewton",
|
|
||||||
"minimp3",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
version = "0.1.21"
|
version = "0.1.21"
|
||||||
|
@ -4501,12 +4190,6 @@ dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "shlex"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook"
|
name = "signal-hook"
|
||||||
version = "0.3.14"
|
version = "0.3.14"
|
||||||
|
@ -4554,17 +4237,6 @@ version = "0.4.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32"
|
checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "slice-deque"
|
|
||||||
version = "0.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "31ef6ee280cdefba6d2d0b4b78a84a1c1a3f3a4cec98c2d4231c8bc225de0f25"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"mach",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slotmap"
|
name = "slotmap"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
|
@ -4682,12 +4354,6 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "stdweb"
|
|
||||||
version = "0.1.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "str-buf"
|
name = "str-buf"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
|
@ -5792,9 +5458,9 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"mio",
|
"mio",
|
||||||
"ndk 0.5.0",
|
"ndk",
|
||||||
"ndk-glue 0.5.2",
|
"ndk-glue",
|
||||||
"ndk-sys 0.2.2",
|
"ndk-sys",
|
||||||
"objc",
|
"objc",
|
||||||
"parking_lot 0.11.2",
|
"parking_lot 0.11.2",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
|
|
|
@ -748,6 +748,7 @@ sqrtChecked = \x ->
|
||||||
else
|
else
|
||||||
Ok (Num.sqrt x)
|
Ok (Num.sqrt x)
|
||||||
|
|
||||||
|
## Natural logarithm
|
||||||
log : Frac a -> Frac a
|
log : Frac a -> Frac a
|
||||||
|
|
||||||
logChecked : Frac a -> Result (Frac a) [LogNeedsPositive]
|
logChecked : Frac a -> Result (Frac a) [LogNeedsPositive]
|
||||||
|
|
|
@ -385,7 +385,15 @@ fn expr<'a>(c: &Ctx, p: EPrec, f: &'a Arena<'a>, e: &'a Expr) -> DocBuilder<'a,
|
||||||
),
|
),
|
||||||
Crash { .. } => todo!(),
|
Crash { .. } => todo!(),
|
||||||
ZeroArgumentTag { .. } => todo!(),
|
ZeroArgumentTag { .. } => todo!(),
|
||||||
OpaqueRef { .. } => todo!(),
|
OpaqueRef { name, argument, .. } => maybe_paren!(
|
||||||
|
Free,
|
||||||
|
p,
|
||||||
|
|| true,
|
||||||
|
pp_sym(c, f, *name)
|
||||||
|
.append(f.space())
|
||||||
|
.append(expr(c, AppArg, f, &argument.1.value))
|
||||||
|
.group()
|
||||||
|
),
|
||||||
Dbg { .. } => todo!(),
|
Dbg { .. } => todo!(),
|
||||||
Expect { .. } => todo!(),
|
Expect { .. } => todo!(),
|
||||||
ExpectFx { .. } => todo!(),
|
ExpectFx { .. } => todo!(),
|
||||||
|
|
|
@ -105,7 +105,7 @@ This is the general procedure I follow with some helpful links:
|
||||||
Also, sometimes it doesn't seem to generate things quite as you expect.
|
Also, sometimes it doesn't seem to generate things quite as you expect.
|
||||||
- [Alternative Online Assembler](http://shell-storm.org/online/Online-Assembler-and-Disassembler/) -
|
- [Alternative Online Assembler](http://shell-storm.org/online/Online-Assembler-and-Disassembler/) -
|
||||||
Like previous but with more architecture options.
|
Like previous but with more architecture options.
|
||||||
- [x86 and amd64 instruction reference](https://www.felixcloutier.com/x86/) -
|
- [x86 and amd64 instruction reference](https://web.archive.org/web/20230221053750/https://www.felixcloutier.com/x86/) -
|
||||||
Great for looking up x86_64 instructions and there bytes.
|
Great for looking up x86_64 instructions and there bytes.
|
||||||
Definitely missing information if you aren't used to reading it.
|
Definitely missing information if you aren't used to reading it.
|
||||||
- [Intel 64 ISA Reference](https://software.intel.com/content/dam/develop/public/us/en/documents/325383-sdm-vol-2abcd.pdf) -
|
- [Intel 64 ISA Reference](https://software.intel.com/content/dam/develop/public/us/en/documents/325383-sdm-vol-2abcd.pdf) -
|
||||||
|
|
|
@ -2,10 +2,13 @@ use crate::generic64::{storage::StorageManager, Assembler, CallConv, RegTrait};
|
||||||
use crate::Relocation;
|
use crate::Relocation;
|
||||||
use bumpalo::collections::Vec;
|
use bumpalo::collections::Vec;
|
||||||
use packed_struct::prelude::*;
|
use packed_struct::prelude::*;
|
||||||
|
use roc_builtins::bitcode::FloatWidth;
|
||||||
use roc_error_macros::internal_error;
|
use roc_error_macros::internal_error;
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_mono::layout::{InLayout, STLayoutInterner};
|
use roc_mono::layout::{InLayout, STLayoutInterner};
|
||||||
|
|
||||||
|
use super::CompareOperation;
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub enum AArch64GeneralReg {
|
pub enum AArch64GeneralReg {
|
||||||
|
@ -609,9 +612,31 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> for AArch64Assembler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
fn mov_reg32_base32(_buf: &mut Vec<'_, u8>, _dst: AArch64GeneralReg, _offset: i32) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn mov_reg16_base32(_buf: &mut Vec<'_, u8>, _dst: AArch64GeneralReg, _offset: i32) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn mov_reg8_base32(_buf: &mut Vec<'_, u8>, _dst: AArch64GeneralReg, _offset: i32) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
fn mov_base32_freg64(_buf: &mut Vec<'_, u8>, _offset: i32, _src: AArch64FloatReg) {
|
fn mov_base32_freg64(_buf: &mut Vec<'_, u8>, _offset: i32, _src: AArch64FloatReg) {
|
||||||
todo!("saving floating point reg to base offset for AArch64");
|
todo!("saving floating point reg to base offset for AArch64");
|
||||||
}
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn movesd_mem64_offset32_freg64(
|
||||||
|
_buf: &mut Vec<'_, u8>,
|
||||||
|
_ptr: AArch64GeneralReg,
|
||||||
|
_offset: i32,
|
||||||
|
_src: AArch64FloatReg,
|
||||||
|
) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn mov_base32_reg64(buf: &mut Vec<'_, u8>, offset: i32, src: AArch64GeneralReg) {
|
fn mov_base32_reg64(buf: &mut Vec<'_, u8>, offset: i32, src: AArch64GeneralReg) {
|
||||||
if offset < 0 {
|
if offset < 0 {
|
||||||
|
@ -624,6 +649,19 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> for AArch64Assembler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn mov_base32_reg32(_buf: &mut Vec<'_, u8>, _offset: i32, _src: AArch64GeneralReg) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn mov_base32_reg16(_buf: &mut Vec<'_, u8>, _offset: i32, _src: AArch64GeneralReg) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn mov_base32_reg8(_buf: &mut Vec<'_, u8>, _offset: i32, _src: AArch64GeneralReg) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn mov_reg64_mem64_offset32(
|
fn mov_reg64_mem64_offset32(
|
||||||
buf: &mut Vec<'_, u8>,
|
buf: &mut Vec<'_, u8>,
|
||||||
|
@ -640,6 +678,41 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> for AArch64Assembler {
|
||||||
todo!("mem offsets over 32k for AArch64");
|
todo!("mem offsets over 32k for AArch64");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn mov_reg32_mem32_offset32(
|
||||||
|
buf: &mut Vec<'_, u8>,
|
||||||
|
dst: AArch64GeneralReg,
|
||||||
|
src: AArch64GeneralReg,
|
||||||
|
offset: i32,
|
||||||
|
) {
|
||||||
|
if offset < 0 {
|
||||||
|
todo!("negative mem offsets for AArch64");
|
||||||
|
} else if offset < (0xFFF << 8) {
|
||||||
|
debug_assert!(offset % 8 == 0);
|
||||||
|
ldr_reg64_reg64_imm12(buf, dst, src, (offset as u16) >> 3);
|
||||||
|
} else {
|
||||||
|
todo!("mem offsets over 32k for AArch64");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn mov_reg16_mem16_offset32(
|
||||||
|
_buf: &mut Vec<'_, u8>,
|
||||||
|
_dst: AArch64GeneralReg,
|
||||||
|
_src: AArch64GeneralReg,
|
||||||
|
_offset: i32,
|
||||||
|
) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn mov_reg8_mem8_offset32(
|
||||||
|
_buf: &mut Vec<'_, u8>,
|
||||||
|
_dst: AArch64GeneralReg,
|
||||||
|
_src: AArch64GeneralReg,
|
||||||
|
_offset: i32,
|
||||||
|
) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn mov_mem64_offset32_reg64(
|
fn mov_mem64_offset32_reg64(
|
||||||
buf: &mut Vec<'_, u8>,
|
buf: &mut Vec<'_, u8>,
|
||||||
|
@ -657,6 +730,36 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> for AArch64Assembler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn mov_mem32_offset32_reg32(
|
||||||
|
_buf: &mut Vec<'_, u8>,
|
||||||
|
_dst: AArch64GeneralReg,
|
||||||
|
_offset: i32,
|
||||||
|
_src: AArch64GeneralReg,
|
||||||
|
) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn mov_mem16_offset32_reg16(
|
||||||
|
_buf: &mut Vec<'_, u8>,
|
||||||
|
_dst: AArch64GeneralReg,
|
||||||
|
_offset: i32,
|
||||||
|
_src: AArch64GeneralReg,
|
||||||
|
) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn mov_mem8_offset32_reg8(
|
||||||
|
_buf: &mut Vec<'_, u8>,
|
||||||
|
_dst: AArch64GeneralReg,
|
||||||
|
_offset: i32,
|
||||||
|
_src: AArch64GeneralReg,
|
||||||
|
) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn movsx_reg64_base32(buf: &mut Vec<'_, u8>, dst: AArch64GeneralReg, offset: i32, size: u8) {
|
fn movsx_reg64_base32(buf: &mut Vec<'_, u8>, dst: AArch64GeneralReg, offset: i32, size: u8) {
|
||||||
debug_assert!(size <= 8);
|
debug_assert!(size <= 8);
|
||||||
|
@ -788,6 +891,18 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> for AArch64Assembler {
|
||||||
todo!("registers unsigned less than for AArch64");
|
todo!("registers unsigned less than for AArch64");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn cmp_freg_freg_reg64(
|
||||||
|
_buf: &mut Vec<'_, u8>,
|
||||||
|
_dst: AArch64GeneralReg,
|
||||||
|
_src1: AArch64FloatReg,
|
||||||
|
_src2: AArch64FloatReg,
|
||||||
|
_width: FloatWidth,
|
||||||
|
_operation: CompareOperation,
|
||||||
|
) {
|
||||||
|
todo!("registers float comparison for AArch64");
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn igt_reg64_reg64_reg64(
|
fn igt_reg64_reg64_reg64(
|
||||||
_buf: &mut Vec<'_, u8>,
|
_buf: &mut Vec<'_, u8>,
|
||||||
|
@ -938,6 +1053,14 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> for AArch64Assembler {
|
||||||
{
|
{
|
||||||
todo!("sar for AArch64")
|
todo!("sar for AArch64")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn sqrt_freg64_freg64(_buf: &mut Vec<'_, u8>, _dst: AArch64FloatReg, _src: AArch64FloatReg) {
|
||||||
|
todo!("sqrt")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sqrt_freg32_freg32(_buf: &mut Vec<'_, u8>, _dst: AArch64FloatReg, _src: AArch64FloatReg) {
|
||||||
|
todo!("sqrt")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AArch64Assembler {}
|
impl AArch64Assembler {}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
||||||
single_register_floats, single_register_int_builtins, single_register_integers, Backend, Env,
|
single_register_floats, single_register_int_builtins, single_register_integers, Backend, Env,
|
||||||
Relocation,
|
Relocation,
|
||||||
};
|
};
|
||||||
use bumpalo::collections::Vec;
|
use bumpalo::collections::{CollectIn, Vec};
|
||||||
use roc_builtins::bitcode::{self, FloatWidth, IntWidth};
|
use roc_builtins::bitcode::{self, FloatWidth, IntWidth};
|
||||||
use roc_collections::all::MutMap;
|
use roc_collections::all::MutMap;
|
||||||
use roc_error_macros::internal_error;
|
use roc_error_macros::internal_error;
|
||||||
|
@ -113,6 +113,13 @@ pub trait CallConv<GeneralReg: RegTrait, FloatReg: RegTrait, ASM: Assembler<Gene
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum CompareOperation {
|
||||||
|
LessThan,
|
||||||
|
LessThanOrEqual,
|
||||||
|
GreaterThan,
|
||||||
|
GreaterThanOrEqual,
|
||||||
|
}
|
||||||
|
|
||||||
/// Assembler contains calls to the backend assembly generator.
|
/// Assembler contains calls to the backend assembly generator.
|
||||||
/// These calls do not necessarily map directly to a single assembly instruction.
|
/// These calls do not necessarily map directly to a single assembly instruction.
|
||||||
/// They are higher level in cases where an instruction would not be common and shared between multiple architectures.
|
/// They are higher level in cases where an instruction would not be common and shared between multiple architectures.
|
||||||
|
@ -236,22 +243,67 @@ pub trait Assembler<GeneralReg: RegTrait, FloatReg: RegTrait>: Sized + Copy {
|
||||||
|
|
||||||
// base32 is similar to stack based instructions but they reference the base/frame pointer.
|
// base32 is similar to stack based instructions but they reference the base/frame pointer.
|
||||||
fn mov_freg64_base32(buf: &mut Vec<'_, u8>, dst: FloatReg, offset: i32);
|
fn mov_freg64_base32(buf: &mut Vec<'_, u8>, dst: FloatReg, offset: i32);
|
||||||
fn mov_reg64_base32(buf: &mut Vec<'_, u8>, dst: GeneralReg, offset: i32);
|
|
||||||
fn mov_base32_freg64(buf: &mut Vec<'_, u8>, offset: i32, src: FloatReg);
|
|
||||||
fn mov_base32_reg64(buf: &mut Vec<'_, u8>, offset: i32, src: GeneralReg);
|
|
||||||
|
|
||||||
|
fn mov_reg64_base32(buf: &mut Vec<'_, u8>, dst: GeneralReg, offset: i32);
|
||||||
|
fn mov_reg32_base32(buf: &mut Vec<'_, u8>, dst: GeneralReg, offset: i32);
|
||||||
|
fn mov_reg16_base32(buf: &mut Vec<'_, u8>, dst: GeneralReg, offset: i32);
|
||||||
|
fn mov_reg8_base32(buf: &mut Vec<'_, u8>, dst: GeneralReg, offset: i32);
|
||||||
|
|
||||||
|
fn mov_base32_freg64(buf: &mut Vec<'_, u8>, offset: i32, src: FloatReg);
|
||||||
|
|
||||||
|
fn mov_base32_reg64(buf: &mut Vec<'_, u8>, offset: i32, src: GeneralReg);
|
||||||
|
fn mov_base32_reg32(buf: &mut Vec<'_, u8>, offset: i32, src: GeneralReg);
|
||||||
|
fn mov_base32_reg16(buf: &mut Vec<'_, u8>, offset: i32, src: GeneralReg);
|
||||||
|
fn mov_base32_reg8(buf: &mut Vec<'_, u8>, offset: i32, src: GeneralReg);
|
||||||
|
|
||||||
|
// move from memory (a pointer) to register
|
||||||
fn mov_reg64_mem64_offset32(
|
fn mov_reg64_mem64_offset32(
|
||||||
buf: &mut Vec<'_, u8>,
|
buf: &mut Vec<'_, u8>,
|
||||||
dst: GeneralReg,
|
dst: GeneralReg,
|
||||||
src: GeneralReg,
|
src: GeneralReg,
|
||||||
offset: i32,
|
offset: i32,
|
||||||
);
|
);
|
||||||
|
fn mov_reg32_mem32_offset32(
|
||||||
|
buf: &mut Vec<'_, u8>,
|
||||||
|
dst: GeneralReg,
|
||||||
|
src: GeneralReg,
|
||||||
|
offset: i32,
|
||||||
|
);
|
||||||
|
fn mov_reg16_mem16_offset32(
|
||||||
|
buf: &mut Vec<'_, u8>,
|
||||||
|
dst: GeneralReg,
|
||||||
|
src: GeneralReg,
|
||||||
|
offset: i32,
|
||||||
|
);
|
||||||
|
fn mov_reg8_mem8_offset32(buf: &mut Vec<'_, u8>, dst: GeneralReg, src: GeneralReg, offset: i32);
|
||||||
|
|
||||||
|
// move from register to memory
|
||||||
fn mov_mem64_offset32_reg64(
|
fn mov_mem64_offset32_reg64(
|
||||||
buf: &mut Vec<'_, u8>,
|
buf: &mut Vec<'_, u8>,
|
||||||
dst: GeneralReg,
|
dst: GeneralReg,
|
||||||
offset: i32,
|
offset: i32,
|
||||||
src: GeneralReg,
|
src: GeneralReg,
|
||||||
);
|
);
|
||||||
|
fn mov_mem32_offset32_reg32(
|
||||||
|
buf: &mut Vec<'_, u8>,
|
||||||
|
dst: GeneralReg,
|
||||||
|
offset: i32,
|
||||||
|
src: GeneralReg,
|
||||||
|
);
|
||||||
|
fn mov_mem16_offset32_reg16(
|
||||||
|
buf: &mut Vec<'_, u8>,
|
||||||
|
dst: GeneralReg,
|
||||||
|
offset: i32,
|
||||||
|
src: GeneralReg,
|
||||||
|
);
|
||||||
|
fn mov_mem8_offset32_reg8(buf: &mut Vec<'_, u8>, dst: GeneralReg, offset: i32, src: GeneralReg);
|
||||||
|
|
||||||
|
fn movesd_mem64_offset32_freg64(
|
||||||
|
buf: &mut Vec<'_, u8>,
|
||||||
|
ptr: GeneralReg,
|
||||||
|
offset: i32,
|
||||||
|
src: FloatReg,
|
||||||
|
);
|
||||||
|
|
||||||
/// Sign extends the data at `offset` with `size` as it copies it to `dst`
|
/// Sign extends the data at `offset` with `size` as it copies it to `dst`
|
||||||
/// size must be less than or equal to 8.
|
/// size must be less than or equal to 8.
|
||||||
|
@ -265,6 +317,9 @@ pub trait Assembler<GeneralReg: RegTrait, FloatReg: RegTrait>: Sized + Copy {
|
||||||
fn mov_stack32_freg64(buf: &mut Vec<'_, u8>, offset: i32, src: FloatReg);
|
fn mov_stack32_freg64(buf: &mut Vec<'_, u8>, offset: i32, src: FloatReg);
|
||||||
fn mov_stack32_reg64(buf: &mut Vec<'_, u8>, offset: i32, src: GeneralReg);
|
fn mov_stack32_reg64(buf: &mut Vec<'_, u8>, offset: i32, src: GeneralReg);
|
||||||
|
|
||||||
|
fn sqrt_freg64_freg64(buf: &mut Vec<'_, u8>, dst: FloatReg, src: FloatReg);
|
||||||
|
fn sqrt_freg32_freg32(buf: &mut Vec<'_, u8>, dst: FloatReg, src: FloatReg);
|
||||||
|
|
||||||
fn neg_reg64_reg64(buf: &mut Vec<'_, u8>, dst: GeneralReg, src: GeneralReg);
|
fn neg_reg64_reg64(buf: &mut Vec<'_, u8>, dst: GeneralReg, src: GeneralReg);
|
||||||
fn mul_freg32_freg32_freg32(
|
fn mul_freg32_freg32_freg32(
|
||||||
buf: &mut Vec<'_, u8>,
|
buf: &mut Vec<'_, u8>,
|
||||||
|
@ -361,6 +416,15 @@ pub trait Assembler<GeneralReg: RegTrait, FloatReg: RegTrait>: Sized + Copy {
|
||||||
src2: GeneralReg,
|
src2: GeneralReg,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
fn cmp_freg_freg_reg64(
|
||||||
|
buf: &mut Vec<'_, u8>,
|
||||||
|
dst: GeneralReg,
|
||||||
|
src1: FloatReg,
|
||||||
|
src2: FloatReg,
|
||||||
|
width: FloatWidth,
|
||||||
|
operation: CompareOperation,
|
||||||
|
);
|
||||||
|
|
||||||
fn igt_reg64_reg64_reg64(
|
fn igt_reg64_reg64_reg64(
|
||||||
buf: &mut Vec<'_, u8>,
|
buf: &mut Vec<'_, u8>,
|
||||||
dst: GeneralReg,
|
dst: GeneralReg,
|
||||||
|
@ -958,6 +1022,30 @@ impl<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn build_num_sub_checked(
|
||||||
|
&mut self,
|
||||||
|
dst: &Symbol,
|
||||||
|
src1: &Symbol,
|
||||||
|
src2: &Symbol,
|
||||||
|
num_layout: &InLayout<'a>,
|
||||||
|
return_layout: &InLayout<'a>,
|
||||||
|
) {
|
||||||
|
let function_name = match self.interner().get(*num_layout) {
|
||||||
|
Layout::Builtin(Builtin::Int(width)) => &bitcode::NUM_SUB_CHECKED_INT[width],
|
||||||
|
Layout::Builtin(Builtin::Float(width)) => &bitcode::NUM_SUB_CHECKED_FLOAT[width],
|
||||||
|
Layout::Builtin(Builtin::Decimal) => bitcode::DEC_SUB_WITH_OVERFLOW,
|
||||||
|
x => internal_error!("NumSubChecked is not defined for {:?}", x),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.build_fn_call(
|
||||||
|
dst,
|
||||||
|
function_name.to_string(),
|
||||||
|
&[*src1, *src2],
|
||||||
|
&[*num_layout, *num_layout],
|
||||||
|
return_layout,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn build_num_mul(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &InLayout<'a>) {
|
fn build_num_mul(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &InLayout<'a>) {
|
||||||
use Builtin::Int;
|
use Builtin::Int;
|
||||||
|
|
||||||
|
@ -1112,6 +1200,16 @@ impl<
|
||||||
.load_to_general_reg(&mut self.buf, src2);
|
.load_to_general_reg(&mut self.buf, src2);
|
||||||
ASM::eq_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
ASM::eq_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
||||||
}
|
}
|
||||||
|
Layout::STR => {
|
||||||
|
// use a zig call
|
||||||
|
self.build_fn_call(
|
||||||
|
dst,
|
||||||
|
bitcode::STR_EQUAL.to_string(),
|
||||||
|
&[*src1, *src2],
|
||||||
|
&[Layout::STR, Layout::STR],
|
||||||
|
&Layout::BOOL,
|
||||||
|
)
|
||||||
|
}
|
||||||
x => todo!("NumEq: layout, {:?}", x),
|
x => todo!("NumEq: layout, {:?}", x),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1128,42 +1226,27 @@ impl<
|
||||||
.load_to_general_reg(&mut self.buf, src2);
|
.load_to_general_reg(&mut self.buf, src2);
|
||||||
ASM::neq_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
ASM::neq_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
||||||
}
|
}
|
||||||
|
Layout::STR => {
|
||||||
|
self.build_fn_call(
|
||||||
|
dst,
|
||||||
|
bitcode::STR_EQUAL.to_string(),
|
||||||
|
&[*src1, *src2],
|
||||||
|
&[Layout::STR, Layout::STR],
|
||||||
|
&Layout::BOOL,
|
||||||
|
);
|
||||||
|
|
||||||
|
// negate the result
|
||||||
|
let tmp = &Symbol::DEV_TMP;
|
||||||
|
let tmp_reg = self.storage_manager.claim_general_reg(&mut self.buf, tmp);
|
||||||
|
ASM::mov_reg64_imm64(&mut self.buf, tmp_reg, 164);
|
||||||
|
|
||||||
|
let dst_reg = self.storage_manager.load_to_general_reg(&mut self.buf, dst);
|
||||||
|
ASM::neq_reg64_reg64_reg64(&mut self.buf, dst_reg, dst_reg, tmp_reg);
|
||||||
|
}
|
||||||
x => todo!("NumNeq: layout, {:?}", x),
|
x => todo!("NumNeq: layout, {:?}", x),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_and(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, arg_layout: &InLayout<'a>) {
|
|
||||||
match *arg_layout {
|
|
||||||
Layout::BOOL => {
|
|
||||||
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
|
||||||
let src1_reg = self
|
|
||||||
.storage_manager
|
|
||||||
.load_to_general_reg(&mut self.buf, src1);
|
|
||||||
let src2_reg = self
|
|
||||||
.storage_manager
|
|
||||||
.load_to_general_reg(&mut self.buf, src2);
|
|
||||||
ASM::and_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
|
||||||
}
|
|
||||||
x => todo!("And: layout, {:?}", x),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_or(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, arg_layout: &InLayout<'a>) {
|
|
||||||
match *arg_layout {
|
|
||||||
Layout::BOOL => {
|
|
||||||
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
|
||||||
let src1_reg = self
|
|
||||||
.storage_manager
|
|
||||||
.load_to_general_reg(&mut self.buf, src1);
|
|
||||||
let src2_reg = self
|
|
||||||
.storage_manager
|
|
||||||
.load_to_general_reg(&mut self.buf, src2);
|
|
||||||
ASM::or_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
|
||||||
}
|
|
||||||
x => todo!("Or: layout, {:?}", x),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_not(&mut self, dst: &Symbol, src: &Symbol, arg_layout: &InLayout<'a>) {
|
fn build_not(&mut self, dst: &Symbol, src: &Symbol, arg_layout: &InLayout<'a>) {
|
||||||
match *arg_layout {
|
match *arg_layout {
|
||||||
Layout::BOOL => {
|
Layout::BOOL => {
|
||||||
|
@ -1209,6 +1292,20 @@ impl<
|
||||||
.load_to_general_reg(&mut self.buf, src2);
|
.load_to_general_reg(&mut self.buf, src2);
|
||||||
ASM::ult_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
ASM::ult_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
||||||
}
|
}
|
||||||
|
Layout::Builtin(Builtin::Float(width)) => {
|
||||||
|
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
||||||
|
let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1);
|
||||||
|
let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2);
|
||||||
|
|
||||||
|
ASM::cmp_freg_freg_reg64(
|
||||||
|
&mut self.buf,
|
||||||
|
dst_reg,
|
||||||
|
src1_reg,
|
||||||
|
src2_reg,
|
||||||
|
width,
|
||||||
|
CompareOperation::LessThan,
|
||||||
|
);
|
||||||
|
}
|
||||||
x => todo!("NumLt: layout, {:?}", x),
|
x => todo!("NumLt: layout, {:?}", x),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1241,6 +1338,20 @@ impl<
|
||||||
.load_to_general_reg(&mut self.buf, src2);
|
.load_to_general_reg(&mut self.buf, src2);
|
||||||
ASM::ugt_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
ASM::ugt_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
||||||
}
|
}
|
||||||
|
Layout::Builtin(Builtin::Float(width)) => {
|
||||||
|
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
||||||
|
let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1);
|
||||||
|
let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2);
|
||||||
|
|
||||||
|
ASM::cmp_freg_freg_reg64(
|
||||||
|
&mut self.buf,
|
||||||
|
dst_reg,
|
||||||
|
src1_reg,
|
||||||
|
src2_reg,
|
||||||
|
width,
|
||||||
|
CompareOperation::GreaterThan,
|
||||||
|
);
|
||||||
|
}
|
||||||
x => todo!("NumGt: layout, {:?}", x),
|
x => todo!("NumGt: layout, {:?}", x),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1321,6 +1432,26 @@ impl<
|
||||||
.load_to_general_reg(&mut self.buf, src2);
|
.load_to_general_reg(&mut self.buf, src2);
|
||||||
ASM::lte_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
ASM::lte_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
||||||
}
|
}
|
||||||
|
Layout::F64 | Layout::F32 => {
|
||||||
|
let width = if *arg_layout == Layout::F64 {
|
||||||
|
FloatWidth::F64
|
||||||
|
} else {
|
||||||
|
FloatWidth::F32
|
||||||
|
};
|
||||||
|
|
||||||
|
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
||||||
|
let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1);
|
||||||
|
let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2);
|
||||||
|
|
||||||
|
ASM::cmp_freg_freg_reg64(
|
||||||
|
&mut self.buf,
|
||||||
|
dst_reg,
|
||||||
|
src1_reg,
|
||||||
|
src2_reg,
|
||||||
|
width,
|
||||||
|
CompareOperation::LessThanOrEqual,
|
||||||
|
);
|
||||||
|
}
|
||||||
x => todo!("NumLte: layout, {:?}", x),
|
x => todo!("NumLte: layout, {:?}", x),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1343,6 +1474,26 @@ impl<
|
||||||
.load_to_general_reg(&mut self.buf, src2);
|
.load_to_general_reg(&mut self.buf, src2);
|
||||||
ASM::gte_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
ASM::gte_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
||||||
}
|
}
|
||||||
|
Layout::F64 | Layout::F32 => {
|
||||||
|
let width = if *arg_layout == Layout::F64 {
|
||||||
|
FloatWidth::F64
|
||||||
|
} else {
|
||||||
|
FloatWidth::F32
|
||||||
|
};
|
||||||
|
|
||||||
|
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
||||||
|
let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1);
|
||||||
|
let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2);
|
||||||
|
|
||||||
|
ASM::cmp_freg_freg_reg64(
|
||||||
|
&mut self.buf,
|
||||||
|
dst_reg,
|
||||||
|
src1_reg,
|
||||||
|
src2_reg,
|
||||||
|
width,
|
||||||
|
CompareOperation::GreaterThanOrEqual,
|
||||||
|
);
|
||||||
|
}
|
||||||
x => todo!("NumGte: layout, {:?}", x),
|
x => todo!("NumGte: layout, {:?}", x),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1567,43 +1718,14 @@ impl<
|
||||||
ASM::add_reg64_reg64_reg64(buf, tmp, tmp, list_ptr);
|
ASM::add_reg64_reg64_reg64(buf, tmp, tmp, list_ptr);
|
||||||
let element_ptr = tmp;
|
let element_ptr = tmp;
|
||||||
|
|
||||||
match *ret_layout {
|
Self::ptr_read(
|
||||||
single_register_integers!() if ret_stack_size == 8 => {
|
|
||||||
let dst_reg = storage_manager.claim_general_reg(buf, dst);
|
|
||||||
ASM::mov_reg64_mem64_offset32(buf, dst_reg, element_ptr, 0);
|
|
||||||
}
|
|
||||||
single_register_floats!() => {
|
|
||||||
let dst_reg = storage_manager.claim_float_reg(buf, dst);
|
|
||||||
ASM::mov_freg64_freg64(buf, dst_reg, CC::FLOAT_RETURN_REGS[0]);
|
|
||||||
}
|
|
||||||
Layout::STR => {
|
|
||||||
// the `list_ptr` register is now unused, and we can use it as scratch space
|
|
||||||
let tmp_reg = list_ptr;
|
|
||||||
|
|
||||||
Self::unbox_str_or_list(
|
|
||||||
buf,
|
buf,
|
||||||
storage_manager,
|
storage_manager,
|
||||||
*dst,
|
self.layout_interner,
|
||||||
element_ptr,
|
element_ptr,
|
||||||
tmp_reg,
|
*ret_layout,
|
||||||
|
*dst,
|
||||||
);
|
);
|
||||||
}
|
|
||||||
other => {
|
|
||||||
//
|
|
||||||
match self.layout_interner.get(other) {
|
|
||||||
Layout::Boxed(_) => {
|
|
||||||
let dst_reg = storage_manager.claim_general_reg(buf, dst);
|
|
||||||
ASM::mov_reg64_reg64(buf, dst_reg, CC::GENERAL_RETURN_REGS[0]);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
todo!(
|
|
||||||
"cannot load {} from the heap yet",
|
|
||||||
self.layout_interner.dbg(other)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -1871,10 +1993,11 @@ impl<
|
||||||
fn create_array(
|
fn create_array(
|
||||||
&mut self,
|
&mut self,
|
||||||
sym: &Symbol,
|
sym: &Symbol,
|
||||||
element_layout: &InLayout<'a>,
|
element_in_layout: &InLayout<'a>,
|
||||||
elements: &'a [ListLiteralElement<'a>],
|
elements: &[ListLiteralElement<'a>],
|
||||||
) {
|
) {
|
||||||
let element_width = self.layout_interner.stack_size(*element_layout) as u64;
|
let element_layout = self.layout_interner.get(*element_in_layout);
|
||||||
|
let element_width = self.layout_interner.stack_size(*element_in_layout) as u64;
|
||||||
|
|
||||||
// load the total size of the data we want to store (excludes refcount)
|
// load the total size of the data we want to store (excludes refcount)
|
||||||
let data_bytes_symbol = Symbol::DEV_TMP;
|
let data_bytes_symbol = Symbol::DEV_TMP;
|
||||||
|
@ -1904,54 +2027,34 @@ impl<
|
||||||
.load_to_general_reg(&mut self.buf, &Symbol::DEV_TMP3);
|
.load_to_general_reg(&mut self.buf, &Symbol::DEV_TMP3);
|
||||||
|
|
||||||
// Copy everything into output array.
|
// Copy everything into output array.
|
||||||
let mut elem_offset = 0;
|
let mut element_offset = 0;
|
||||||
for elem in elements {
|
for elem in elements {
|
||||||
// TODO: this could be a lot faster when loading large lists
|
// TODO: this could be a lot faster when loading large lists
|
||||||
// if we move matching on the element layout to outside this loop.
|
// if we move matching on the element layout to outside this loop.
|
||||||
// It also greatly bloats the code here.
|
// It also greatly bloats the code here.
|
||||||
// Refactor this and switch to one external match.
|
// Refactor this and switch to one external match.
|
||||||
// We also could make loadining indivitual literals much faster
|
// We also could make loadining indivitual literals much faster
|
||||||
let elem_sym = match elem {
|
let element_symbol = match elem {
|
||||||
ListLiteralElement::Symbol(sym) => sym,
|
ListLiteralElement::Symbol(sym) => *sym,
|
||||||
ListLiteralElement::Literal(lit) => {
|
ListLiteralElement::Literal(lit) => {
|
||||||
self.load_literal(&Symbol::DEV_TMP, element_layout, lit);
|
self.load_literal(&Symbol::DEV_TMP, element_in_layout, lit);
|
||||||
&Symbol::DEV_TMP
|
Symbol::DEV_TMP
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// TODO: Expand to all types.
|
|
||||||
match self.layout_interner.get(*element_layout) {
|
Self::ptr_write(
|
||||||
Layout::Builtin(Builtin::Int(IntWidth::I64 | IntWidth::U64) | Builtin::Bool) => {
|
|
||||||
let sym_reg = self
|
|
||||||
.storage_manager
|
|
||||||
.load_to_general_reg(&mut self.buf, elem_sym);
|
|
||||||
ASM::mov_mem64_offset32_reg64(&mut self.buf, ptr_reg, elem_offset, sym_reg);
|
|
||||||
}
|
|
||||||
_ if element_width == 0 => {}
|
|
||||||
_ if element_width > 8 => {
|
|
||||||
let (from_offset, size) = self.storage_manager.stack_offset_and_size(elem_sym);
|
|
||||||
debug_assert!(from_offset % 8 == 0);
|
|
||||||
debug_assert!(size % 8 == 0);
|
|
||||||
debug_assert_eq!(size as u64, element_width);
|
|
||||||
self.storage_manager.with_tmp_general_reg(
|
|
||||||
&mut self.buf,
|
&mut self.buf,
|
||||||
|_storage_manager, buf, tmp_reg| {
|
&mut self.storage_manager,
|
||||||
for i in (0..size as i32).step_by(8) {
|
|
||||||
ASM::mov_reg64_base32(buf, tmp_reg, from_offset + i);
|
|
||||||
ASM::mov_mem64_offset32_reg64(
|
|
||||||
buf,
|
|
||||||
ptr_reg,
|
ptr_reg,
|
||||||
elem_offset + i,
|
element_offset,
|
||||||
tmp_reg,
|
element_width,
|
||||||
|
element_layout,
|
||||||
|
element_symbol,
|
||||||
);
|
);
|
||||||
}
|
|
||||||
},
|
element_offset += element_width as i32;
|
||||||
);
|
if element_symbol == Symbol::DEV_TMP {
|
||||||
}
|
self.free_symbol(&element_symbol);
|
||||||
x => todo!("copying data to list with layout, {:?}", x),
|
|
||||||
}
|
|
||||||
elem_offset += element_width as i32;
|
|
||||||
if elem_sym == &Symbol::DEV_TMP {
|
|
||||||
self.free_symbol(elem_sym);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2049,38 +2152,15 @@ impl<
|
||||||
let element_width = self.layout_interner.stack_size(element_layout) as u64;
|
let element_width = self.layout_interner.stack_size(element_layout) as u64;
|
||||||
let element_offset = 0;
|
let element_offset = 0;
|
||||||
|
|
||||||
// TODO: Expand to all types.
|
Self::ptr_write(
|
||||||
match self.layout_interner.get(element_layout) {
|
|
||||||
Layout::Builtin(Builtin::Int(IntWidth::I64 | IntWidth::U64)) => {
|
|
||||||
let sym_reg = self
|
|
||||||
.storage_manager
|
|
||||||
.load_to_general_reg(&mut self.buf, &value);
|
|
||||||
ASM::mov_mem64_offset32_reg64(&mut self.buf, ptr_reg, element_offset, sym_reg);
|
|
||||||
}
|
|
||||||
_ if element_width == 0 => {}
|
|
||||||
_ if element_width > 8 => {
|
|
||||||
let (from_offset, size) = self.storage_manager.stack_offset_and_size(&value);
|
|
||||||
debug_assert!(from_offset % 8 == 0);
|
|
||||||
debug_assert!(size % 8 == 0);
|
|
||||||
debug_assert_eq!(size as u64, element_width);
|
|
||||||
self.storage_manager.with_tmp_general_reg(
|
|
||||||
&mut self.buf,
|
&mut self.buf,
|
||||||
|_storage_manager, buf, tmp_reg| {
|
&mut self.storage_manager,
|
||||||
// a crude memcpy
|
|
||||||
for i in (0..size as i32).step_by(8) {
|
|
||||||
ASM::mov_reg64_base32(buf, tmp_reg, from_offset + i);
|
|
||||||
ASM::mov_mem64_offset32_reg64(
|
|
||||||
buf,
|
|
||||||
ptr_reg,
|
ptr_reg,
|
||||||
element_offset + i,
|
element_offset,
|
||||||
tmp_reg,
|
element_width,
|
||||||
|
self.layout_interner.get(element_layout),
|
||||||
|
value,
|
||||||
);
|
);
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
x => todo!("copying data to list with layout, {:?}", x),
|
|
||||||
}
|
|
||||||
|
|
||||||
if value == Symbol::DEV_TMP {
|
if value == Symbol::DEV_TMP {
|
||||||
self.free_symbol(&value);
|
self.free_symbol(&value);
|
||||||
|
@ -2098,26 +2178,15 @@ impl<
|
||||||
.storage_manager
|
.storage_manager
|
||||||
.load_to_general_reg(&mut self.buf, &ptr);
|
.load_to_general_reg(&mut self.buf, &ptr);
|
||||||
|
|
||||||
let ret_stack_size = self.layout_interner.stack_size(element_layout);
|
Self::ptr_read(
|
||||||
|
|
||||||
match element_layout {
|
|
||||||
single_register_integers!() if ret_stack_size == 8 => {
|
|
||||||
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, &dst);
|
|
||||||
ASM::mov_reg64_mem64_offset32(&mut self.buf, dst_reg, ptr_reg, 0);
|
|
||||||
}
|
|
||||||
Layout::STR => {
|
|
||||||
self.storage_manager.with_tmp_general_reg(
|
|
||||||
&mut self.buf,
|
&mut self.buf,
|
||||||
|storage_manager, buf, tmp_reg| {
|
&mut self.storage_manager,
|
||||||
Self::unbox_str_or_list(buf, storage_manager, dst, ptr_reg, tmp_reg);
|
self.layout_interner,
|
||||||
},
|
ptr_reg,
|
||||||
|
element_layout,
|
||||||
|
dst,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ => {
|
|
||||||
todo!("unboxing of {:?}", self.layout_interner.dbg(element_layout))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_tag_id(&mut self, sym: &Symbol, structure: &Symbol, union_layout: &UnionLayout<'a>) {
|
fn get_tag_id(&mut self, sym: &Symbol, structure: &Symbol, union_layout: &UnionLayout<'a>) {
|
||||||
self.storage_manager.load_union_tag_id(
|
self.storage_manager.load_union_tag_id(
|
||||||
|
@ -2165,6 +2234,33 @@ impl<
|
||||||
let val = *x;
|
let val = *x;
|
||||||
ASM::mov_reg64_imm64(&mut self.buf, reg, i128::from_ne_bytes(val) as i64);
|
ASM::mov_reg64_imm64(&mut self.buf, reg, i128::from_ne_bytes(val) as i64);
|
||||||
}
|
}
|
||||||
|
(
|
||||||
|
Literal::Int(bytes),
|
||||||
|
Layout::Builtin(Builtin::Int(IntWidth::I128 | IntWidth::U128)),
|
||||||
|
) => {
|
||||||
|
self.storage_manager.with_tmp_general_reg(
|
||||||
|
&mut self.buf,
|
||||||
|
|storage_manager, buf, reg| {
|
||||||
|
let base_offset = storage_manager.claim_stack_area(sym, 16);
|
||||||
|
|
||||||
|
let mut num_bytes = [0; 8];
|
||||||
|
num_bytes.copy_from_slice(&bytes[..8]);
|
||||||
|
let num = i64::from_ne_bytes(num_bytes);
|
||||||
|
ASM::mov_reg64_imm64(buf, reg, num);
|
||||||
|
ASM::mov_base32_reg64(buf, base_offset, reg);
|
||||||
|
|
||||||
|
num_bytes.copy_from_slice(&bytes[8..16]);
|
||||||
|
let num = i64::from_ne_bytes(num_bytes);
|
||||||
|
ASM::mov_reg64_imm64(buf, reg, num);
|
||||||
|
ASM::mov_base32_reg64(buf, base_offset + 8, reg);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
(Literal::Byte(x), Layout::Builtin(Builtin::Int(IntWidth::U8 | IntWidth::I8))) => {
|
||||||
|
let reg = self.storage_manager.claim_general_reg(&mut self.buf, sym);
|
||||||
|
let val = *x;
|
||||||
|
ASM::mov_reg64_imm64(&mut self.buf, reg, val as i64);
|
||||||
|
}
|
||||||
(Literal::Bool(x), Layout::Builtin(Builtin::Bool)) => {
|
(Literal::Bool(x), Layout::Builtin(Builtin::Bool)) => {
|
||||||
let reg = self.storage_manager.claim_general_reg(&mut self.buf, sym);
|
let reg = self.storage_manager.claim_general_reg(&mut self.buf, sym);
|
||||||
let val = [*x as u8; 16];
|
let val = [*x as u8; 16];
|
||||||
|
@ -2180,7 +2276,27 @@ impl<
|
||||||
let val = *x as f32;
|
let val = *x as f32;
|
||||||
ASM::mov_freg32_imm32(&mut self.buf, &mut self.relocs, reg, val);
|
ASM::mov_freg32_imm32(&mut self.buf, &mut self.relocs, reg, val);
|
||||||
}
|
}
|
||||||
(Literal::Str(x), Layout::Builtin(Builtin::Str)) if x.len() < 24 => {
|
(Literal::Decimal(bytes), Layout::Builtin(Builtin::Decimal)) => {
|
||||||
|
self.storage_manager.with_tmp_general_reg(
|
||||||
|
&mut self.buf,
|
||||||
|
|storage_manager, buf, reg| {
|
||||||
|
let base_offset = storage_manager.claim_stack_area(sym, 16);
|
||||||
|
|
||||||
|
let mut num_bytes = [0; 8];
|
||||||
|
num_bytes.copy_from_slice(&bytes[..8]);
|
||||||
|
let num = i64::from_ne_bytes(num_bytes);
|
||||||
|
ASM::mov_reg64_imm64(buf, reg, num);
|
||||||
|
ASM::mov_base32_reg64(buf, base_offset, reg);
|
||||||
|
|
||||||
|
num_bytes.copy_from_slice(&bytes[8..16]);
|
||||||
|
let num = i64::from_ne_bytes(num_bytes);
|
||||||
|
ASM::mov_reg64_imm64(buf, reg, num);
|
||||||
|
ASM::mov_base32_reg64(buf, base_offset + 8, reg);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
(Literal::Str(x), Layout::Builtin(Builtin::Str)) => {
|
||||||
|
if x.len() < 24 {
|
||||||
// Load small string.
|
// Load small string.
|
||||||
self.storage_manager.with_tmp_general_reg(
|
self.storage_manager.with_tmp_general_reg(
|
||||||
&mut self.buf,
|
&mut self.buf,
|
||||||
|
@ -2207,6 +2323,17 @@ impl<
|
||||||
ASM::mov_base32_reg64(buf, base_offset + 16, reg);
|
ASM::mov_base32_reg64(buf, base_offset + 16, reg);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
// load large string (pretend it's a `List U8`). We should move this data into
|
||||||
|
// the binary eventually because our RC algorithm won't free this value
|
||||||
|
let elements: Vec<_> = x
|
||||||
|
.as_bytes()
|
||||||
|
.iter()
|
||||||
|
.map(|b| ListLiteralElement::Literal(Literal::Byte(*b)))
|
||||||
|
.collect_in(self.storage_manager.env.arena);
|
||||||
|
|
||||||
|
self.create_array(sym, &Layout::U8, elements.into_bump_slice())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
x => todo!("loading literal, {:?}", x),
|
x => todo!("loading literal, {:?}", x),
|
||||||
}
|
}
|
||||||
|
@ -2447,6 +2574,18 @@ impl<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn build_num_sqrt(&mut self, dst: Symbol, src: Symbol, float_width: FloatWidth) {
|
||||||
|
let buf = &mut self.buf;
|
||||||
|
|
||||||
|
let dst_reg = self.storage_manager.claim_float_reg(buf, &dst);
|
||||||
|
let src_reg = self.storage_manager.load_to_float_reg(buf, &src);
|
||||||
|
|
||||||
|
match float_width {
|
||||||
|
FloatWidth::F32 => ASM::sqrt_freg32_freg32(buf, dst_reg, src_reg),
|
||||||
|
FloatWidth::F64 => ASM::sqrt_freg64_freg64(buf, dst_reg, src_reg),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This impl block is for ir related instructions that need backend specific information.
|
/// This impl block is for ir related instructions that need backend specific information.
|
||||||
|
@ -2494,6 +2633,115 @@ impl<
|
||||||
ASM::mov_base32_reg64(buf, base_offset + 16, tmp_reg);
|
ASM::mov_base32_reg64(buf, base_offset + 16, tmp_reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ptr_read(
|
||||||
|
buf: &mut Vec<'a, u8>,
|
||||||
|
storage_manager: &mut StorageManager<'a, 'r, GeneralReg, FloatReg, ASM, CC>,
|
||||||
|
layout_interner: &STLayoutInterner<'a>,
|
||||||
|
ptr_reg: GeneralReg,
|
||||||
|
element_in_layout: InLayout<'a>,
|
||||||
|
dst: Symbol,
|
||||||
|
) {
|
||||||
|
match layout_interner.get(element_in_layout) {
|
||||||
|
Layout::Builtin(builtin) => match builtin {
|
||||||
|
Builtin::Int(int_width) => match int_width {
|
||||||
|
IntWidth::I128 | IntWidth::U128 => {
|
||||||
|
// can we treat this as 2 u64's?
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
IntWidth::I64 | IntWidth::U64 => {
|
||||||
|
let dst_reg = storage_manager.claim_general_reg(buf, &dst);
|
||||||
|
ASM::mov_reg64_mem64_offset32(buf, dst_reg, ptr_reg, 0);
|
||||||
|
}
|
||||||
|
IntWidth::I32 | IntWidth::U32 => {
|
||||||
|
let dst_reg = storage_manager.claim_general_reg(buf, &dst);
|
||||||
|
ASM::mov_reg32_mem32_offset32(buf, dst_reg, ptr_reg, 0);
|
||||||
|
}
|
||||||
|
IntWidth::I16 | IntWidth::U16 => {
|
||||||
|
let dst_reg = storage_manager.claim_general_reg(buf, &dst);
|
||||||
|
ASM::mov_reg16_mem16_offset32(buf, dst_reg, ptr_reg, 0);
|
||||||
|
}
|
||||||
|
IntWidth::I8 | IntWidth::U8 => {
|
||||||
|
let dst_reg = storage_manager.claim_general_reg(buf, &dst);
|
||||||
|
ASM::mov_reg8_mem8_offset32(buf, dst_reg, ptr_reg, 0);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Builtin::Float(_) => {
|
||||||
|
let dst_reg = storage_manager.claim_float_reg(buf, &dst);
|
||||||
|
ASM::mov_freg64_freg64(buf, dst_reg, CC::FLOAT_RETURN_REGS[0]);
|
||||||
|
}
|
||||||
|
Builtin::Bool => {
|
||||||
|
// the same as an 8-bit integer
|
||||||
|
let dst_reg = storage_manager.claim_general_reg(buf, &dst);
|
||||||
|
ASM::mov_reg8_mem8_offset32(buf, dst_reg, ptr_reg, 0);
|
||||||
|
}
|
||||||
|
Builtin::Decimal => {
|
||||||
|
// same as 128-bit integer
|
||||||
|
}
|
||||||
|
Builtin::Str | Builtin::List(_) => {
|
||||||
|
storage_manager.with_tmp_general_reg(buf, |storage_manager, buf, tmp_reg| {
|
||||||
|
Self::unbox_str_or_list(buf, storage_manager, dst, ptr_reg, tmp_reg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
Layout::Boxed(_) => {
|
||||||
|
// the same as 64-bit integer (for 64-bit targets)
|
||||||
|
let dst_reg = storage_manager.claim_general_reg(buf, &dst);
|
||||||
|
ASM::mov_reg64_mem64_offset32(buf, dst_reg, ptr_reg, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => todo!("unboxing of {:?}", layout_interner.dbg(element_in_layout)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ptr_write(
|
||||||
|
buf: &mut Vec<'a, u8>,
|
||||||
|
storage_manager: &mut StorageManager<'a, 'r, GeneralReg, FloatReg, ASM, CC>,
|
||||||
|
ptr_reg: GeneralReg,
|
||||||
|
element_offset: i32,
|
||||||
|
element_width: u64,
|
||||||
|
element_layout: Layout<'a>,
|
||||||
|
value: Symbol,
|
||||||
|
) {
|
||||||
|
match element_layout {
|
||||||
|
Layout::Builtin(Builtin::Int(IntWidth::I64 | IntWidth::U64)) => {
|
||||||
|
let sym_reg = storage_manager.load_to_general_reg(buf, &value);
|
||||||
|
ASM::mov_mem64_offset32_reg64(buf, ptr_reg, element_offset, sym_reg);
|
||||||
|
}
|
||||||
|
Layout::Builtin(Builtin::Int(IntWidth::I32 | IntWidth::U32)) => {
|
||||||
|
let sym_reg = storage_manager.load_to_general_reg(buf, &value);
|
||||||
|
ASM::mov_mem32_offset32_reg32(buf, ptr_reg, element_offset, sym_reg);
|
||||||
|
}
|
||||||
|
Layout::Builtin(Builtin::Int(IntWidth::I16 | IntWidth::U16)) => {
|
||||||
|
let sym_reg = storage_manager.load_to_general_reg(buf, &value);
|
||||||
|
ASM::mov_mem16_offset32_reg16(buf, ptr_reg, element_offset, sym_reg);
|
||||||
|
}
|
||||||
|
Layout::Builtin(Builtin::Int(IntWidth::I8 | IntWidth::U8) | Builtin::Bool) => {
|
||||||
|
let sym_reg = storage_manager.load_to_general_reg(buf, &value);
|
||||||
|
ASM::mov_mem8_offset32_reg8(buf, ptr_reg, element_offset, sym_reg);
|
||||||
|
}
|
||||||
|
Layout::Builtin(Builtin::Float(FloatWidth::F64 | FloatWidth::F32)) => {
|
||||||
|
let sym_reg = storage_manager.load_to_float_reg(buf, &value);
|
||||||
|
ASM::movesd_mem64_offset32_freg64(buf, ptr_reg, element_offset, sym_reg);
|
||||||
|
}
|
||||||
|
_ if element_width == 0 => {}
|
||||||
|
_ if element_width > 8 => {
|
||||||
|
let (from_offset, size) = storage_manager.stack_offset_and_size(&value);
|
||||||
|
debug_assert!(from_offset % 8 == 0);
|
||||||
|
debug_assert!(size % 8 == 0);
|
||||||
|
debug_assert_eq!(size as u64, element_width);
|
||||||
|
storage_manager.with_tmp_general_reg(buf, |_storage_manager, buf, tmp_reg| {
|
||||||
|
// a crude memcpy
|
||||||
|
for i in (0..size as i32).step_by(8) {
|
||||||
|
ASM::mov_reg64_base32(buf, tmp_reg, from_offset + i);
|
||||||
|
ASM::mov_mem64_offset32_reg64(buf, ptr_reg, element_offset + i, tmp_reg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
x => todo!("copying data to list with layout, {:?}", x),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Updates a jump instruction to a new offset and returns the number of bytes written.
|
/// Updates a jump instruction to a new offset and returns the number of bytes written.
|
||||||
fn update_jmp_imm32_offset(
|
fn update_jmp_imm32_offset(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
@ -9,7 +9,6 @@ use roc_collections::all::{MutMap, MutSet};
|
||||||
use roc_error_macros::internal_error;
|
use roc_error_macros::internal_error;
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_mono::{
|
use roc_mono::{
|
||||||
borrow::Ownership,
|
|
||||||
ir::{JoinPointId, Param},
|
ir::{JoinPointId, Param},
|
||||||
layout::{
|
layout::{
|
||||||
Builtin, InLayout, Layout, LayoutInterner, STLayoutInterner, TagIdIntType, UnionLayout,
|
Builtin, InLayout, Layout, LayoutInterner, STLayoutInterner, TagIdIntType, UnionLayout,
|
||||||
|
@ -315,7 +314,7 @@ impl<
|
||||||
reg: Some(Float(_)),
|
reg: Some(Float(_)),
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
internal_error!("Cannot load floating point symbol into GeneralReg: {}", sym)
|
internal_error!("Cannot load floating point symbol into GeneralReg: {sym:?}")
|
||||||
}
|
}
|
||||||
Stack(Primitive {
|
Stack(Primitive {
|
||||||
reg: None,
|
reg: None,
|
||||||
|
@ -350,8 +349,10 @@ impl<
|
||||||
self.free_reference(sym);
|
self.free_reference(sym);
|
||||||
reg
|
reg
|
||||||
}
|
}
|
||||||
Stack(Complex { .. }) => {
|
Stack(Complex { size, .. }) => {
|
||||||
internal_error!("Cannot load large values into general registers: {}", sym)
|
internal_error!(
|
||||||
|
"Cannot load large values (size {size}) into general registers: {sym:?}",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
NoData => {
|
NoData => {
|
||||||
internal_error!("Cannot load no data into general registers: {}", sym)
|
internal_error!("Cannot load no data into general registers: {}", sym)
|
||||||
|
@ -448,7 +449,7 @@ impl<
|
||||||
reg: Some(Float(_)),
|
reg: Some(Float(_)),
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
internal_error!("Cannot load floating point symbol into GeneralReg: {}", sym)
|
internal_error!("Cannot load floating point symbol into GeneralReg: {sym:?}",)
|
||||||
}
|
}
|
||||||
Stack(Primitive {
|
Stack(Primitive {
|
||||||
reg: None,
|
reg: None,
|
||||||
|
@ -458,19 +459,25 @@ impl<
|
||||||
ASM::mov_reg64_base32(buf, reg, *base_offset);
|
ASM::mov_reg64_base32(buf, reg, *base_offset);
|
||||||
}
|
}
|
||||||
Stack(ReferencedPrimitive {
|
Stack(ReferencedPrimitive {
|
||||||
base_offset, size, ..
|
base_offset,
|
||||||
}) if base_offset % 8 == 0 && *size == 8 => {
|
size,
|
||||||
// The primitive is aligned and the data is exactly 8 bytes, treat it like regular stack.
|
sign_extend,
|
||||||
ASM::mov_reg64_base32(buf, reg, *base_offset);
|
}) => {
|
||||||
|
debug_assert!(*size <= 8);
|
||||||
|
|
||||||
|
if *sign_extend {
|
||||||
|
ASM::movsx_reg64_base32(buf, reg, *base_offset, *size as u8)
|
||||||
|
} else {
|
||||||
|
ASM::movzx_reg64_base32(buf, reg, *base_offset, *size as u8)
|
||||||
}
|
}
|
||||||
Stack(ReferencedPrimitive { .. }) => {
|
|
||||||
todo!("loading referenced primitives")
|
|
||||||
}
|
}
|
||||||
Stack(Complex { .. }) => {
|
Stack(Complex { size, .. }) => {
|
||||||
internal_error!("Cannot load large values into general registers: {}", sym)
|
internal_error!(
|
||||||
|
"Cannot load large values (size {size}) into general registers: {sym:?}",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
NoData => {
|
NoData => {
|
||||||
internal_error!("Cannot load no data into general registers: {}", sym)
|
internal_error!("Cannot load no data into general registers: {:?}", sym)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -553,7 +560,7 @@ impl<
|
||||||
self.allocation_map.insert(*sym, owned_data);
|
self.allocation_map.insert(*sym, owned_data);
|
||||||
self.symbol_storage_map.insert(
|
self.symbol_storage_map.insert(
|
||||||
*sym,
|
*sym,
|
||||||
Stack(if is_primitive(layout) {
|
Stack(if is_primitive(layout_interner, layout) {
|
||||||
ReferencedPrimitive {
|
ReferencedPrimitive {
|
||||||
base_offset: data_offset,
|
base_offset: data_offset,
|
||||||
size,
|
size,
|
||||||
|
@ -739,16 +746,74 @@ impl<
|
||||||
layout: &InLayout<'a>,
|
layout: &InLayout<'a>,
|
||||||
) {
|
) {
|
||||||
match layout_interner.get(*layout) {
|
match layout_interner.get(*layout) {
|
||||||
Layout::Builtin(Builtin::Int(IntWidth::I64 | IntWidth::U64)) => {
|
Layout::Builtin(builtin) => match builtin {
|
||||||
|
Builtin::Int(int_width) => match int_width {
|
||||||
|
IntWidth::I128 | IntWidth::U128 => {
|
||||||
|
let (from_offset, size) = self.stack_offset_and_size(sym);
|
||||||
|
debug_assert_eq!(from_offset % 8, 0);
|
||||||
|
debug_assert_eq!(size % 8, 0);
|
||||||
|
debug_assert_eq!(size, layout_interner.stack_size(*layout));
|
||||||
|
self.copy_to_stack_offset(buf, size, from_offset, to_offset)
|
||||||
|
}
|
||||||
|
IntWidth::I64 | IntWidth::U64 => {
|
||||||
debug_assert_eq!(to_offset % 8, 0);
|
debug_assert_eq!(to_offset % 8, 0);
|
||||||
let reg = self.load_to_general_reg(buf, sym);
|
let reg = self.load_to_general_reg(buf, sym);
|
||||||
ASM::mov_base32_reg64(buf, to_offset, reg);
|
ASM::mov_base32_reg64(buf, to_offset, reg);
|
||||||
}
|
}
|
||||||
Layout::Builtin(Builtin::Float(FloatWidth::F64)) => {
|
IntWidth::I32 | IntWidth::U32 => {
|
||||||
|
debug_assert_eq!(to_offset % 4, 0);
|
||||||
|
let reg = self.load_to_general_reg(buf, sym);
|
||||||
|
ASM::mov_base32_reg32(buf, to_offset, reg);
|
||||||
|
}
|
||||||
|
IntWidth::I16 | IntWidth::U16 => {
|
||||||
|
debug_assert_eq!(to_offset % 2, 0);
|
||||||
|
let reg = self.load_to_general_reg(buf, sym);
|
||||||
|
ASM::mov_base32_reg16(buf, to_offset, reg);
|
||||||
|
}
|
||||||
|
IntWidth::I8 | IntWidth::U8 => {
|
||||||
|
let reg = self.load_to_general_reg(buf, sym);
|
||||||
|
ASM::mov_base32_reg8(buf, to_offset, reg);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
Builtin::Float(float_width) => match float_width {
|
||||||
|
FloatWidth::F64 => {
|
||||||
debug_assert_eq!(to_offset % 8, 0);
|
debug_assert_eq!(to_offset % 8, 0);
|
||||||
let reg = self.load_to_float_reg(buf, sym);
|
let reg = self.load_to_float_reg(buf, sym);
|
||||||
ASM::mov_base32_freg64(buf, to_offset, reg);
|
ASM::mov_base32_freg64(buf, to_offset, reg);
|
||||||
}
|
}
|
||||||
|
FloatWidth::F32 => todo!(),
|
||||||
|
},
|
||||||
|
Builtin::Bool => {
|
||||||
|
// same as 8-bit integer
|
||||||
|
let reg = self.load_to_general_reg(buf, sym);
|
||||||
|
ASM::mov_base32_reg8(buf, to_offset, reg);
|
||||||
|
}
|
||||||
|
Builtin::Decimal => todo!(),
|
||||||
|
Builtin::Str | Builtin::List(_) => {
|
||||||
|
let (from_offset, size) = self.stack_offset_and_size(sym);
|
||||||
|
debug_assert_eq!(from_offset % 8, 0);
|
||||||
|
debug_assert_eq!(size % 8, 0);
|
||||||
|
debug_assert_eq!(size, layout_interner.stack_size(*layout));
|
||||||
|
self.copy_to_stack_offset(buf, size, from_offset, to_offset)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Layout::Boxed(_) => {
|
||||||
|
// like a 64-bit integer
|
||||||
|
debug_assert_eq!(to_offset % 8, 0);
|
||||||
|
let reg = self.load_to_general_reg(buf, sym);
|
||||||
|
ASM::mov_base32_reg64(buf, to_offset, reg);
|
||||||
|
}
|
||||||
|
Layout::LambdaSet(lambda_set) => {
|
||||||
|
// like its runtime representation
|
||||||
|
self.copy_symbol_to_stack_offset(
|
||||||
|
layout_interner,
|
||||||
|
buf,
|
||||||
|
to_offset,
|
||||||
|
sym,
|
||||||
|
&lambda_set.runtime_representation(),
|
||||||
|
)
|
||||||
|
}
|
||||||
_ if layout_interner.stack_size(*layout) == 0 => {}
|
_ if layout_interner.stack_size(*layout) == 0 => {}
|
||||||
// TODO: Verify this is always true.
|
// TODO: Verify this is always true.
|
||||||
// The dev backend does not deal with refcounting and does not care about if data is safe to memcpy.
|
// The dev backend does not deal with refcounting and does not care about if data is safe to memcpy.
|
||||||
|
@ -756,20 +821,64 @@ impl<
|
||||||
// Later, it will be reloaded and stored in refcounted as needed.
|
// Later, it will be reloaded and stored in refcounted as needed.
|
||||||
_ if layout_interner.stack_size(*layout) > 8 => {
|
_ if layout_interner.stack_size(*layout) > 8 => {
|
||||||
let (from_offset, size) = self.stack_offset_and_size(sym);
|
let (from_offset, size) = self.stack_offset_and_size(sym);
|
||||||
debug_assert!(from_offset % 8 == 0);
|
debug_assert_eq!(from_offset % 8, 0);
|
||||||
debug_assert!(size % 8 == 0);
|
debug_assert_eq!(size % 8, 0);
|
||||||
debug_assert_eq!(size, layout_interner.stack_size(*layout));
|
debug_assert_eq!(size, layout_interner.stack_size(*layout));
|
||||||
self.with_tmp_general_reg(buf, |_storage_manager, buf, reg| {
|
self.copy_to_stack_offset(buf, size, from_offset, to_offset)
|
||||||
for i in (0..size as i32).step_by(8) {
|
|
||||||
ASM::mov_reg64_base32(buf, reg, from_offset + i);
|
|
||||||
ASM::mov_base32_reg64(buf, to_offset + i, reg);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
x => todo!("copying data to the stack with layout, {:?}", x),
|
x => todo!("copying data to the stack with layout, {:?}", x),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn copy_to_stack_offset(
|
||||||
|
&mut self,
|
||||||
|
buf: &mut Vec<'a, u8>,
|
||||||
|
size: u32,
|
||||||
|
from_offset: i32,
|
||||||
|
to_offset: i32,
|
||||||
|
) {
|
||||||
|
let mut copied = 0;
|
||||||
|
let size = size as i32;
|
||||||
|
|
||||||
|
self.with_tmp_general_reg(buf, |_storage_manager, buf, reg| {
|
||||||
|
if size - copied >= 8 {
|
||||||
|
for _ in (0..(size - copied)).step_by(8) {
|
||||||
|
ASM::mov_reg64_base32(buf, reg, from_offset + copied);
|
||||||
|
ASM::mov_base32_reg64(buf, to_offset + copied, reg);
|
||||||
|
|
||||||
|
copied += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if size - copied >= 4 {
|
||||||
|
for _ in (0..(size - copied)).step_by(4) {
|
||||||
|
ASM::mov_reg32_base32(buf, reg, from_offset + copied);
|
||||||
|
ASM::mov_base32_reg32(buf, to_offset + copied, reg);
|
||||||
|
|
||||||
|
copied += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if size - copied >= 2 {
|
||||||
|
for _ in (0..(size - copied)).step_by(2) {
|
||||||
|
ASM::mov_reg16_base32(buf, reg, from_offset + copied);
|
||||||
|
ASM::mov_base32_reg16(buf, to_offset + copied, reg);
|
||||||
|
|
||||||
|
copied += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if size - copied >= 1 {
|
||||||
|
for _ in (0..(size - copied)).step_by(1) {
|
||||||
|
ASM::mov_reg8_base32(buf, reg, from_offset + copied);
|
||||||
|
ASM::mov_base32_reg8(buf, to_offset + copied, reg);
|
||||||
|
|
||||||
|
copied += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
/// Ensures that a register is free. If it is not free, data will be moved to make it free.
|
/// Ensures that a register is free. If it is not free, data will be moved to make it free.
|
||||||
pub fn ensure_reg_free(
|
pub fn ensure_reg_free(
|
||||||
|
@ -1008,15 +1117,10 @@ impl<
|
||||||
param_storage.reserve(params.len());
|
param_storage.reserve(params.len());
|
||||||
for Param {
|
for Param {
|
||||||
symbol,
|
symbol,
|
||||||
ownership,
|
ownership: _,
|
||||||
layout,
|
layout,
|
||||||
} in params
|
} in params
|
||||||
{
|
{
|
||||||
if *ownership == Ownership::Borrowed {
|
|
||||||
// These probably need to be passed by pointer/reference?
|
|
||||||
// Otherwise, we probably need to copy back to the param at the end of the joinpoint.
|
|
||||||
todo!("joinpoints with borrowed parameters");
|
|
||||||
}
|
|
||||||
// Claim a location for every join point parameter to be loaded at.
|
// Claim a location for every join point parameter to be loaded at.
|
||||||
// Put everything on the stack for simplicity.
|
// Put everything on the stack for simplicity.
|
||||||
match *layout {
|
match *layout {
|
||||||
|
@ -1331,6 +1435,15 @@ impl<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_primitive(layout: InLayout<'_>) -> bool {
|
fn is_primitive(layout_interner: &mut STLayoutInterner<'_>, layout: InLayout<'_>) -> bool {
|
||||||
matches!(layout, single_register_layouts!())
|
match layout {
|
||||||
|
single_register_layouts!() => true,
|
||||||
|
_ => match layout_interner.get(layout) {
|
||||||
|
Layout::Boxed(_) => true,
|
||||||
|
Layout::LambdaSet(lambda_set) => {
|
||||||
|
is_primitive(layout_interner, lambda_set.runtime_representation())
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -447,6 +447,9 @@ trait Backend<'a> {
|
||||||
LowLevel::NumAddChecked => {
|
LowLevel::NumAddChecked => {
|
||||||
self.build_num_add_checked(sym, &args[0], &args[1], &arg_layouts[0], ret_layout)
|
self.build_num_add_checked(sym, &args[0], &args[1], &arg_layouts[0], ret_layout)
|
||||||
}
|
}
|
||||||
|
LowLevel::NumSubChecked => {
|
||||||
|
self.build_num_sub_checked(sym, &args[0], &args[1], &arg_layouts[0], ret_layout)
|
||||||
|
}
|
||||||
LowLevel::NumAcos => self.build_fn_call(
|
LowLevel::NumAcos => self.build_fn_call(
|
||||||
sym,
|
sym,
|
||||||
bitcode::NUM_ACOS[FloatWidth::F64].to_string(),
|
bitcode::NUM_ACOS[FloatWidth::F64].to_string(),
|
||||||
|
@ -551,6 +554,27 @@ trait Backend<'a> {
|
||||||
);
|
);
|
||||||
self.build_num_sub_wrap(sym, &args[0], &args[1], ret_layout)
|
self.build_num_sub_wrap(sym, &args[0], &args[1], ret_layout)
|
||||||
}
|
}
|
||||||
|
LowLevel::NumSubSaturated => match self.interner().get(*ret_layout) {
|
||||||
|
Layout::Builtin(Builtin::Int(int_width)) => self.build_fn_call(
|
||||||
|
sym,
|
||||||
|
bitcode::NUM_SUB_SATURATED_INT[int_width].to_string(),
|
||||||
|
args,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
|
Layout::Builtin(Builtin::Float(FloatWidth::F32)) => {
|
||||||
|
self.build_num_sub(sym, &args[0], &args[1], ret_layout)
|
||||||
|
}
|
||||||
|
Layout::Builtin(Builtin::Float(FloatWidth::F64)) => {
|
||||||
|
// saturated sub is just normal sub
|
||||||
|
self.build_num_sub(sym, &args[0], &args[1], ret_layout)
|
||||||
|
}
|
||||||
|
Layout::Builtin(Builtin::Decimal) => {
|
||||||
|
// self.load_args_and_call_zig(backend, bitcode::DEC_SUB_SATURATED)
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
_ => internal_error!("invalid return type"),
|
||||||
|
},
|
||||||
LowLevel::NumBitwiseAnd => {
|
LowLevel::NumBitwiseAnd => {
|
||||||
if let Layout::Builtin(Builtin::Int(int_width)) = self.interner().get(*ret_layout) {
|
if let Layout::Builtin(Builtin::Int(int_width)) = self.interner().get(*ret_layout) {
|
||||||
self.build_int_bitwise_and(sym, &args[0], &args[1], int_width)
|
self.build_int_bitwise_and(sym, &args[0], &args[1], int_width)
|
||||||
|
@ -572,6 +596,20 @@ trait Backend<'a> {
|
||||||
internal_error!("bitwise xor on a non-integer")
|
internal_error!("bitwise xor on a non-integer")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
LowLevel::And => {
|
||||||
|
if let Layout::Builtin(Builtin::Bool) = self.interner().get(*ret_layout) {
|
||||||
|
self.build_int_bitwise_and(sym, &args[0], &args[1], IntWidth::U8)
|
||||||
|
} else {
|
||||||
|
internal_error!("bitwise and on a non-integer")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LowLevel::Or => {
|
||||||
|
if let Layout::Builtin(Builtin::Bool) = self.interner().get(*ret_layout) {
|
||||||
|
self.build_int_bitwise_or(sym, &args[0], &args[1], IntWidth::U8)
|
||||||
|
} else {
|
||||||
|
internal_error!("bitwise or on a non-integer")
|
||||||
|
}
|
||||||
|
}
|
||||||
LowLevel::NumShiftLeftBy => {
|
LowLevel::NumShiftLeftBy => {
|
||||||
if let Layout::Builtin(Builtin::Int(int_width)) = self.interner().get(*ret_layout) {
|
if let Layout::Builtin(Builtin::Int(int_width)) = self.interner().get(*ret_layout) {
|
||||||
self.build_int_shift_left(sym, &args[0], &args[1], int_width)
|
self.build_int_shift_left(sym, &args[0], &args[1], int_width)
|
||||||
|
@ -623,32 +661,6 @@ trait Backend<'a> {
|
||||||
);
|
);
|
||||||
self.build_neq(sym, &args[0], &args[1], &arg_layouts[0])
|
self.build_neq(sym, &args[0], &args[1], &arg_layouts[0])
|
||||||
}
|
}
|
||||||
LowLevel::And => {
|
|
||||||
debug_assert_eq!(2, args.len(), "And: expected to have exactly two argument");
|
|
||||||
debug_assert_eq!(
|
|
||||||
arg_layouts[0], arg_layouts[1],
|
|
||||||
"And: expected all arguments of to have the same layout"
|
|
||||||
);
|
|
||||||
debug_assert_eq!(
|
|
||||||
Layout::BOOL,
|
|
||||||
*ret_layout,
|
|
||||||
"And: expected to have return layout of type Bool"
|
|
||||||
);
|
|
||||||
self.build_and(sym, &args[0], &args[1], &arg_layouts[0])
|
|
||||||
}
|
|
||||||
LowLevel::Or => {
|
|
||||||
debug_assert_eq!(2, args.len(), "Or: expected to have exactly two argument");
|
|
||||||
debug_assert_eq!(
|
|
||||||
arg_layouts[0], arg_layouts[1],
|
|
||||||
"Or: expected all arguments of to have the same layout"
|
|
||||||
);
|
|
||||||
debug_assert_eq!(
|
|
||||||
Layout::BOOL,
|
|
||||||
*ret_layout,
|
|
||||||
"Or: expected to have return layout of type Bool"
|
|
||||||
);
|
|
||||||
self.build_or(sym, &args[0], &args[1], &arg_layouts[0])
|
|
||||||
}
|
|
||||||
LowLevel::Not => {
|
LowLevel::Not => {
|
||||||
debug_assert_eq!(1, args.len(), "Not: expected to have exactly one argument");
|
debug_assert_eq!(1, args.len(), "Not: expected to have exactly one argument");
|
||||||
debug_assert_eq!(
|
debug_assert_eq!(
|
||||||
|
@ -739,6 +751,30 @@ trait Backend<'a> {
|
||||||
);
|
);
|
||||||
self.build_num_gte(sym, &args[0], &args[1], &arg_layouts[0])
|
self.build_num_gte(sym, &args[0], &args[1], &arg_layouts[0])
|
||||||
}
|
}
|
||||||
|
LowLevel::NumLogUnchecked => {
|
||||||
|
let float_width = match arg_layouts[0] {
|
||||||
|
Layout::F64 => FloatWidth::F64,
|
||||||
|
Layout::F32 => FloatWidth::F32,
|
||||||
|
_ => unreachable!("invalid layout for sqrt"),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.build_fn_call(
|
||||||
|
sym,
|
||||||
|
bitcode::NUM_LOG[float_width].to_string(),
|
||||||
|
args,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
LowLevel::NumSqrtUnchecked => {
|
||||||
|
let float_width = match arg_layouts[0] {
|
||||||
|
Layout::F64 => FloatWidth::F64,
|
||||||
|
Layout::F32 => FloatWidth::F32,
|
||||||
|
_ => unreachable!("invalid layout for sqrt"),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.build_num_sqrt(*sym, args[0], float_width);
|
||||||
|
}
|
||||||
LowLevel::NumRound => self.build_fn_call(
|
LowLevel::NumRound => self.build_fn_call(
|
||||||
sym,
|
sym,
|
||||||
bitcode::NUM_ROUND_F64[IntWidth::I64].to_string(),
|
bitcode::NUM_ROUND_F64[IntWidth::I64].to_string(),
|
||||||
|
@ -819,6 +855,13 @@ trait Backend<'a> {
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
ret_layout,
|
ret_layout,
|
||||||
),
|
),
|
||||||
|
LowLevel::StrJoinWith => self.build_fn_call(
|
||||||
|
sym,
|
||||||
|
bitcode::STR_JOIN_WITH.to_string(),
|
||||||
|
args,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
LowLevel::StrSplit => self.build_fn_call(
|
LowLevel::StrSplit => self.build_fn_call(
|
||||||
sym,
|
sym,
|
||||||
bitcode::STR_SPLIT.to_string(),
|
bitcode::STR_SPLIT.to_string(),
|
||||||
|
@ -840,6 +883,13 @@ trait Backend<'a> {
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
ret_layout,
|
ret_layout,
|
||||||
),
|
),
|
||||||
|
LowLevel::StrAppendScalar => self.build_fn_call(
|
||||||
|
sym,
|
||||||
|
bitcode::STR_APPEND_SCALAR.to_string(),
|
||||||
|
args,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
LowLevel::StrEndsWith => self.build_fn_call(
|
LowLevel::StrEndsWith => self.build_fn_call(
|
||||||
sym,
|
sym,
|
||||||
bitcode::STR_ENDS_WITH.to_string(),
|
bitcode::STR_ENDS_WITH.to_string(),
|
||||||
|
@ -854,6 +904,122 @@ trait Backend<'a> {
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
ret_layout,
|
ret_layout,
|
||||||
),
|
),
|
||||||
|
LowLevel::StrSubstringUnsafe => self.build_fn_call(
|
||||||
|
sym,
|
||||||
|
bitcode::STR_SUBSTRING_UNSAFE.to_string(),
|
||||||
|
args,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
|
LowLevel::StrToUtf8 => self.build_fn_call(
|
||||||
|
sym,
|
||||||
|
bitcode::STR_TO_UTF8.to_string(),
|
||||||
|
args,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
|
LowLevel::StrCountUtf8Bytes => self.build_fn_call(
|
||||||
|
sym,
|
||||||
|
bitcode::STR_COUNT_UTF8_BYTES.to_string(),
|
||||||
|
args,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
|
LowLevel::StrFromUtf8Range => self.build_fn_call(
|
||||||
|
sym,
|
||||||
|
bitcode::STR_FROM_UTF8_RANGE.to_string(),
|
||||||
|
args,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
|
// LowLevel::StrToUtf8 => self.build_fn_call(
|
||||||
|
// sym,
|
||||||
|
// bitcode::STR_TO_UTF8.to_string(),
|
||||||
|
// args,
|
||||||
|
// arg_layouts,
|
||||||
|
// ret_layout,
|
||||||
|
// ),
|
||||||
|
LowLevel::StrRepeat => self.build_fn_call(
|
||||||
|
sym,
|
||||||
|
bitcode::STR_REPEAT.to_string(),
|
||||||
|
args,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
|
LowLevel::StrTrim => self.build_fn_call(
|
||||||
|
sym,
|
||||||
|
bitcode::STR_TRIM.to_string(),
|
||||||
|
args,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
|
LowLevel::StrTrimLeft => self.build_fn_call(
|
||||||
|
sym,
|
||||||
|
bitcode::STR_TRIM_LEFT.to_string(),
|
||||||
|
args,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
|
LowLevel::StrTrimRight => self.build_fn_call(
|
||||||
|
sym,
|
||||||
|
bitcode::STR_TRIM_RIGHT.to_string(),
|
||||||
|
args,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
|
LowLevel::StrReserve => self.build_fn_call(
|
||||||
|
sym,
|
||||||
|
bitcode::STR_RESERVE.to_string(),
|
||||||
|
args,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
|
LowLevel::StrWithCapacity => self.build_fn_call(
|
||||||
|
sym,
|
||||||
|
bitcode::STR_WITH_CAPACITY.to_string(),
|
||||||
|
args,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
|
LowLevel::StrToScalars => self.build_fn_call(
|
||||||
|
sym,
|
||||||
|
bitcode::STR_TO_SCALARS.to_string(),
|
||||||
|
args,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
|
LowLevel::StrGetUnsafe => self.build_fn_call(
|
||||||
|
sym,
|
||||||
|
bitcode::STR_GET_UNSAFE.to_string(),
|
||||||
|
args,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
|
LowLevel::StrGetScalarUnsafe => self.build_fn_call(
|
||||||
|
sym,
|
||||||
|
bitcode::STR_GET_SCALAR_UNSAFE.to_string(),
|
||||||
|
args,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
|
LowLevel::StrToNum => {
|
||||||
|
let number_layout = match self.interner().get(*ret_layout) {
|
||||||
|
Layout::Struct { field_layouts, .. } => field_layouts[0], // TODO: why is it sometimes a struct?
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// match on the return layout to figure out which zig builtin we need
|
||||||
|
let intrinsic = match self.interner().get(number_layout) {
|
||||||
|
Layout::Builtin(Builtin::Int(int_width)) => &bitcode::STR_TO_INT[int_width],
|
||||||
|
Layout::Builtin(Builtin::Float(float_width)) => {
|
||||||
|
&bitcode::STR_TO_FLOAT[float_width]
|
||||||
|
}
|
||||||
|
Layout::Builtin(Builtin::Decimal) => bitcode::DEC_FROM_STR,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.build_fn_call(sym, intrinsic.to_string(), args, arg_layouts, ret_layout)
|
||||||
|
}
|
||||||
LowLevel::PtrCast => {
|
LowLevel::PtrCast => {
|
||||||
debug_assert_eq!(
|
debug_assert_eq!(
|
||||||
1,
|
1,
|
||||||
|
@ -920,13 +1086,6 @@ trait Backend<'a> {
|
||||||
self.load_literal_symbols(args);
|
self.load_literal_symbols(args);
|
||||||
self.build_fn_call(sym, fn_name, args, arg_layouts, ret_layout)
|
self.build_fn_call(sym, fn_name, args, arg_layouts, ret_layout)
|
||||||
}
|
}
|
||||||
Symbol::NUM_ADD_CHECKED => {
|
|
||||||
let layout_id = LayoutIds::default().get(func_sym, ret_layout);
|
|
||||||
let fn_name = self.symbol_to_string(func_sym, layout_id);
|
|
||||||
// Now that the arguments are needed, load them if they are literals.
|
|
||||||
self.load_literal_symbols(args);
|
|
||||||
self.build_fn_call(sym, fn_name, args, arg_layouts, ret_layout)
|
|
||||||
}
|
|
||||||
Symbol::BOOL_TRUE => {
|
Symbol::BOOL_TRUE => {
|
||||||
let bool_layout = Layout::BOOL;
|
let bool_layout = Layout::BOOL;
|
||||||
self.load_literal(&Symbol::DEV_TMP, &bool_layout, &Literal::Bool(true));
|
self.load_literal(&Symbol::DEV_TMP, &bool_layout, &Literal::Bool(true));
|
||||||
|
@ -939,7 +1098,24 @@ trait Backend<'a> {
|
||||||
self.return_symbol(&Symbol::DEV_TMP, &bool_layout);
|
self.return_symbol(&Symbol::DEV_TMP, &bool_layout);
|
||||||
self.free_symbol(&Symbol::DEV_TMP)
|
self.free_symbol(&Symbol::DEV_TMP)
|
||||||
}
|
}
|
||||||
_ => todo!("the function, {:?}", func_sym),
|
Symbol::STR_IS_VALID_SCALAR => {
|
||||||
|
// just call the function
|
||||||
|
let layout_id = LayoutIds::default().get(func_sym, ret_layout);
|
||||||
|
let fn_name = self.symbol_to_string(func_sym, layout_id);
|
||||||
|
// Now that the arguments are needed, load them if they are literals.
|
||||||
|
self.load_literal_symbols(args);
|
||||||
|
self.build_fn_call(sym, fn_name, args, arg_layouts, ret_layout)
|
||||||
|
}
|
||||||
|
other => {
|
||||||
|
eprintln!("maybe {other:?} should have a custom implementation?");
|
||||||
|
|
||||||
|
// just call the function
|
||||||
|
let layout_id = LayoutIds::default().get(func_sym, ret_layout);
|
||||||
|
let fn_name = self.symbol_to_string(func_sym, layout_id);
|
||||||
|
// Now that the arguments are needed, load them if they are literals.
|
||||||
|
self.load_literal_symbols(args);
|
||||||
|
self.build_fn_call(sym, fn_name, args, arg_layouts, ret_layout)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -970,6 +1146,16 @@ trait Backend<'a> {
|
||||||
return_layout: &InLayout<'a>,
|
return_layout: &InLayout<'a>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// build_num_sub_checked stores the sum of src1 and src2 into dst.
|
||||||
|
fn build_num_sub_checked(
|
||||||
|
&mut self,
|
||||||
|
dst: &Symbol,
|
||||||
|
src1: &Symbol,
|
||||||
|
src2: &Symbol,
|
||||||
|
num_layout: &InLayout<'a>,
|
||||||
|
return_layout: &InLayout<'a>,
|
||||||
|
);
|
||||||
|
|
||||||
/// build_num_mul stores `src1 * src2` into dst.
|
/// build_num_mul stores `src1 * src2` into dst.
|
||||||
fn build_num_mul(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &InLayout<'a>);
|
fn build_num_mul(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &InLayout<'a>);
|
||||||
|
|
||||||
|
@ -1051,12 +1237,6 @@ trait Backend<'a> {
|
||||||
/// build_neq stores the result of `src1 != src2` into dst.
|
/// build_neq stores the result of `src1 != src2` into dst.
|
||||||
fn build_neq(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, arg_layout: &InLayout<'a>);
|
fn build_neq(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, arg_layout: &InLayout<'a>);
|
||||||
|
|
||||||
/// build_and stores the result of `src1 && src2` into dst.
|
|
||||||
fn build_and(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, arg_layout: &InLayout<'a>);
|
|
||||||
|
|
||||||
/// build_or stores the result of `src1 || src2` into dst.
|
|
||||||
fn build_or(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, arg_layout: &InLayout<'a>);
|
|
||||||
|
|
||||||
/// build_not stores the result of `!src` into dst.
|
/// build_not stores the result of `!src` into dst.
|
||||||
fn build_not(&mut self, dst: &Symbol, src: &Symbol, arg_layout: &InLayout<'a>);
|
fn build_not(&mut self, dst: &Symbol, src: &Symbol, arg_layout: &InLayout<'a>);
|
||||||
|
|
||||||
|
@ -1105,6 +1285,9 @@ trait Backend<'a> {
|
||||||
arg_layout: &InLayout<'a>,
|
arg_layout: &InLayout<'a>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// build_sqrt stores the result of `sqrt(src)` into dst.
|
||||||
|
fn build_num_sqrt(&mut self, dst: Symbol, src: Symbol, float_width: FloatWidth);
|
||||||
|
|
||||||
/// build_list_len returns the length of a list.
|
/// build_list_len returns the length of a list.
|
||||||
fn build_list_len(&mut self, dst: &Symbol, list: &Symbol);
|
fn build_list_len(&mut self, dst: &Symbol, list: &Symbol);
|
||||||
|
|
||||||
|
|
|
@ -1319,6 +1319,7 @@ define_builtins! {
|
||||||
53 STR_WITH_CAPACITY: "withCapacity"
|
53 STR_WITH_CAPACITY: "withCapacity"
|
||||||
54 STR_WITH_PREFIX: "withPrefix"
|
54 STR_WITH_PREFIX: "withPrefix"
|
||||||
55 STR_GRAPHEMES: "graphemes"
|
55 STR_GRAPHEMES: "graphemes"
|
||||||
|
56 STR_IS_VALID_SCALAR: "isValidScalar"
|
||||||
}
|
}
|
||||||
6 LIST: "List" => {
|
6 LIST: "List" => {
|
||||||
0 LIST_LIST: "List" exposed_apply_type=true // the List.List type alias
|
0 LIST_LIST: "List" exposed_apply_type=true // the List.List type alias
|
||||||
|
@ -1401,6 +1402,7 @@ define_builtins! {
|
||||||
77 LIST_COUNT_IF: "countIf"
|
77 LIST_COUNT_IF: "countIf"
|
||||||
78 LIST_WALK_FROM: "walkFrom"
|
78 LIST_WALK_FROM: "walkFrom"
|
||||||
79 LIST_WALK_FROM_UNTIL: "walkFromUntil"
|
79 LIST_WALK_FROM_UNTIL: "walkFromUntil"
|
||||||
|
80 LIST_ITER_HELP: "iterHelp"
|
||||||
}
|
}
|
||||||
7 RESULT: "Result" => {
|
7 RESULT: "Result" => {
|
||||||
0 RESULT_RESULT: "Result" exposed_type=true // the Result.Result type alias
|
0 RESULT_RESULT: "Result" exposed_type=true // the Result.Result type alias
|
||||||
|
|
|
@ -100,8 +100,14 @@ pub fn infer_borrow<'a>(
|
||||||
// host-exposed functions must always own their arguments.
|
// host-exposed functions must always own their arguments.
|
||||||
let is_host_exposed = host_exposed_procs.contains(&key.0);
|
let is_host_exposed = host_exposed_procs.contains(&key.0);
|
||||||
|
|
||||||
let param_offset = param_map.get_param_offset(key.0, key.1);
|
let param_offset = param_map.get_param_offset(interner, key.0, key.1);
|
||||||
env.collect_proc(&mut param_map, proc, param_offset, is_host_exposed);
|
env.collect_proc(
|
||||||
|
interner,
|
||||||
|
&mut param_map,
|
||||||
|
proc,
|
||||||
|
param_offset,
|
||||||
|
is_host_exposed,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !env.modified {
|
if !env.modified {
|
||||||
|
@ -167,6 +173,7 @@ impl<'a> DeclarationToIndex<'a> {
|
||||||
|
|
||||||
fn get_param_offset(
|
fn get_param_offset(
|
||||||
&self,
|
&self,
|
||||||
|
interner: &STLayoutInterner<'a>,
|
||||||
needle_symbol: Symbol,
|
needle_symbol: Symbol,
|
||||||
needle_layout: ProcLayout<'a>,
|
needle_layout: ProcLayout<'a>,
|
||||||
) -> ParamOffset {
|
) -> ParamOffset {
|
||||||
|
@ -181,12 +188,14 @@ impl<'a> DeclarationToIndex<'a> {
|
||||||
.elements
|
.elements
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(Declaration { symbol, layout }, _)| {
|
.filter_map(|(Declaration { symbol, layout }, _)| {
|
||||||
(*symbol == needle_symbol).then_some(layout)
|
(*symbol == needle_symbol)
|
||||||
|
.then_some(layout)
|
||||||
|
.map(|l| l.dbg_deep(interner))
|
||||||
})
|
})
|
||||||
.collect::<std::vec::Vec<_>>();
|
.collect::<std::vec::Vec<_>>();
|
||||||
unreachable!(
|
unreachable!(
|
||||||
"symbol/layout {:?} {:#?} combo must be in DeclarationToIndex\nHowever {} similar layouts were found:\n{:#?}",
|
"symbol/layout {:?} {:#?} combo must be in DeclarationToIndex\nHowever {} similar layouts were found:\n{:#?}",
|
||||||
needle_symbol, needle_layout, similar.len(), similar
|
needle_symbol, needle_layout.dbg_deep(interner), similar.len(), similar,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -206,13 +215,24 @@ pub struct ParamMap<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ParamMap<'a> {
|
impl<'a> ParamMap<'a> {
|
||||||
pub fn get_param_offset(&self, symbol: Symbol, layout: ProcLayout<'a>) -> ParamOffset {
|
pub fn get_param_offset(
|
||||||
self.declaration_to_index.get_param_offset(symbol, layout)
|
&self,
|
||||||
|
interner: &STLayoutInterner<'a>,
|
||||||
|
symbol: Symbol,
|
||||||
|
layout: ProcLayout<'a>,
|
||||||
|
) -> ParamOffset {
|
||||||
|
self.declaration_to_index
|
||||||
|
.get_param_offset(interner, symbol, layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_symbol(&self, symbol: Symbol, layout: ProcLayout<'a>) -> Option<&[Param<'a>]> {
|
pub fn get_symbol(
|
||||||
|
&self,
|
||||||
|
interner: &STLayoutInterner<'a>,
|
||||||
|
symbol: Symbol,
|
||||||
|
layout: ProcLayout<'a>,
|
||||||
|
) -> Option<&[Param<'a>]> {
|
||||||
// let index: usize = self.declaration_to_index[&(symbol, layout)].into();
|
// let index: usize = self.declaration_to_index[&(symbol, layout)].into();
|
||||||
let index: usize = self.get_param_offset(symbol, layout).into();
|
let index: usize = self.get_param_offset(interner, symbol, layout).into();
|
||||||
|
|
||||||
self.declarations.get(index..index + layout.arguments.len())
|
self.declarations.get(index..index + layout.arguments.len())
|
||||||
}
|
}
|
||||||
|
@ -292,7 +312,7 @@ impl<'a> ParamMap<'a> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let index: usize = self.get_param_offset(key.0, key.1).into();
|
let index: usize = self.get_param_offset(interner, key.0, key.1).into();
|
||||||
|
|
||||||
for (i, param) in Self::init_borrow_args(arena, interner, proc.args)
|
for (i, param) in Self::init_borrow_args(arena, interner, proc.args)
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -312,7 +332,7 @@ impl<'a> ParamMap<'a> {
|
||||||
proc: &Proc<'a>,
|
proc: &Proc<'a>,
|
||||||
key: (Symbol, ProcLayout<'a>),
|
key: (Symbol, ProcLayout<'a>),
|
||||||
) {
|
) {
|
||||||
let index: usize = self.get_param_offset(key.0, key.1).into();
|
let index: usize = self.get_param_offset(interner, key.0, key.1).into();
|
||||||
|
|
||||||
for (i, param) in Self::init_borrow_args_always_owned(arena, proc.args)
|
for (i, param) in Self::init_borrow_args_always_owned(arena, proc.args)
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -534,7 +554,13 @@ impl<'a> BorrowInfState<'a> {
|
||||||
///
|
///
|
||||||
/// and determines whether z and which of the symbols used in e
|
/// and determines whether z and which of the symbols used in e
|
||||||
/// must be taken as owned parameters
|
/// must be taken as owned parameters
|
||||||
fn collect_call(&mut self, param_map: &mut ParamMap<'a>, z: Symbol, e: &crate::ir::Call<'a>) {
|
fn collect_call(
|
||||||
|
&mut self,
|
||||||
|
interner: &STLayoutInterner<'a>,
|
||||||
|
param_map: &mut ParamMap<'a>,
|
||||||
|
z: Symbol,
|
||||||
|
e: &crate::ir::Call<'a>,
|
||||||
|
) {
|
||||||
use crate::ir::CallType::*;
|
use crate::ir::CallType::*;
|
||||||
|
|
||||||
let crate::ir::Call {
|
let crate::ir::Call {
|
||||||
|
@ -553,7 +579,7 @@ impl<'a> BorrowInfState<'a> {
|
||||||
|
|
||||||
// get the borrow signature of the applied function
|
// get the borrow signature of the applied function
|
||||||
let ps = param_map
|
let ps = param_map
|
||||||
.get_symbol(name.name(), top_level)
|
.get_symbol(interner, name.name(), top_level)
|
||||||
.expect("function is defined");
|
.expect("function is defined");
|
||||||
|
|
||||||
// the return value will be owned
|
// the return value will be owned
|
||||||
|
@ -595,8 +621,11 @@ impl<'a> BorrowInfState<'a> {
|
||||||
niche: passed_function.name.niche(),
|
niche: passed_function.name.niche(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let function_ps =
|
let function_ps = match param_map.get_symbol(
|
||||||
match param_map.get_symbol(passed_function.name.name(), closure_layout) {
|
interner,
|
||||||
|
passed_function.name.name(),
|
||||||
|
closure_layout,
|
||||||
|
) {
|
||||||
Some(function_ps) => function_ps,
|
Some(function_ps) => function_ps,
|
||||||
None => unreachable!(),
|
None => unreachable!(),
|
||||||
};
|
};
|
||||||
|
@ -671,7 +700,13 @@ impl<'a> BorrowInfState<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_expr(&mut self, param_map: &mut ParamMap<'a>, z: Symbol, e: &Expr<'a>) {
|
fn collect_expr(
|
||||||
|
&mut self,
|
||||||
|
interner: &STLayoutInterner<'a>,
|
||||||
|
param_map: &mut ParamMap<'a>,
|
||||||
|
z: Symbol,
|
||||||
|
e: &Expr<'a>,
|
||||||
|
) {
|
||||||
use Expr::*;
|
use Expr::*;
|
||||||
|
|
||||||
match e {
|
match e {
|
||||||
|
@ -724,7 +759,7 @@ impl<'a> BorrowInfState<'a> {
|
||||||
self.own_var(z);
|
self.own_var(z);
|
||||||
}
|
}
|
||||||
|
|
||||||
Call(call) => self.collect_call(param_map, z, call),
|
Call(call) => self.collect_call(interner, param_map, z, call),
|
||||||
|
|
||||||
Literal(_) | RuntimeErrorFunction(_) => {}
|
Literal(_) | RuntimeErrorFunction(_) => {}
|
||||||
|
|
||||||
|
@ -757,6 +792,7 @@ impl<'a> BorrowInfState<'a> {
|
||||||
#[allow(clippy::many_single_char_names)]
|
#[allow(clippy::many_single_char_names)]
|
||||||
fn preserve_tail_call(
|
fn preserve_tail_call(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
interner: &STLayoutInterner<'a>,
|
||||||
param_map: &mut ParamMap<'a>,
|
param_map: &mut ParamMap<'a>,
|
||||||
x: Symbol,
|
x: Symbol,
|
||||||
v: &Expr<'a>,
|
v: &Expr<'a>,
|
||||||
|
@ -782,7 +818,7 @@ impl<'a> BorrowInfState<'a> {
|
||||||
if self.current_proc == g.name() && x == *z {
|
if self.current_proc == g.name() && x == *z {
|
||||||
// anonymous functions (for which the ps may not be known)
|
// anonymous functions (for which the ps may not be known)
|
||||||
// can never be tail-recursive, so this is fine
|
// can never be tail-recursive, so this is fine
|
||||||
if let Some(ps) = param_map.get_symbol(g.name(), top_level) {
|
if let Some(ps) = param_map.get_symbol(interner, g.name(), top_level) {
|
||||||
self.own_params_using_args(ys, ps)
|
self.own_params_using_args(ys, ps)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -801,7 +837,12 @@ impl<'a> BorrowInfState<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_stmt(&mut self, param_map: &mut ParamMap<'a>, stmt: &Stmt<'a>) {
|
fn collect_stmt(
|
||||||
|
&mut self,
|
||||||
|
interner: &STLayoutInterner<'a>,
|
||||||
|
param_map: &mut ParamMap<'a>,
|
||||||
|
stmt: &Stmt<'a>,
|
||||||
|
) {
|
||||||
use Stmt::*;
|
use Stmt::*;
|
||||||
|
|
||||||
match stmt {
|
match stmt {
|
||||||
|
@ -813,11 +854,11 @@ impl<'a> BorrowInfState<'a> {
|
||||||
} => {
|
} => {
|
||||||
let old = self.param_set.clone();
|
let old = self.param_set.clone();
|
||||||
self.update_param_set(ys);
|
self.update_param_set(ys);
|
||||||
self.collect_stmt(param_map, v);
|
self.collect_stmt(interner, param_map, v);
|
||||||
self.param_set = old;
|
self.param_set = old;
|
||||||
self.update_param_map_join_point(param_map, *j);
|
self.update_param_map_join_point(param_map, *j);
|
||||||
|
|
||||||
self.collect_stmt(param_map, b);
|
self.collect_stmt(interner, param_map, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
Let(x, v, _, mut b) => {
|
Let(x, v, _, mut b) => {
|
||||||
|
@ -830,17 +871,17 @@ impl<'a> BorrowInfState<'a> {
|
||||||
stack.push((*symbol, expr));
|
stack.push((*symbol, expr));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.collect_stmt(param_map, b);
|
self.collect_stmt(interner, param_map, b);
|
||||||
|
|
||||||
let mut it = stack.into_iter().rev();
|
let mut it = stack.into_iter().rev();
|
||||||
|
|
||||||
// collect the final expr, and see if we need to preserve a tail call
|
// collect the final expr, and see if we need to preserve a tail call
|
||||||
let (x, v) = it.next().unwrap();
|
let (x, v) = it.next().unwrap();
|
||||||
self.collect_expr(param_map, x, v);
|
self.collect_expr(interner, param_map, x, v);
|
||||||
self.preserve_tail_call(param_map, x, v, b);
|
self.preserve_tail_call(interner, param_map, x, v, b);
|
||||||
|
|
||||||
for (x, v) in it {
|
for (x, v) in it {
|
||||||
self.collect_expr(param_map, x, v);
|
self.collect_expr(interner, param_map, x, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -859,21 +900,21 @@ impl<'a> BorrowInfState<'a> {
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
for (_, _, b) in branches.iter() {
|
for (_, _, b) in branches.iter() {
|
||||||
self.collect_stmt(param_map, b);
|
self.collect_stmt(interner, param_map, b);
|
||||||
}
|
}
|
||||||
self.collect_stmt(param_map, default_branch.1);
|
self.collect_stmt(interner, param_map, default_branch.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Dbg { remainder, .. } => {
|
Dbg { remainder, .. } => {
|
||||||
self.collect_stmt(param_map, remainder);
|
self.collect_stmt(interner, param_map, remainder);
|
||||||
}
|
}
|
||||||
|
|
||||||
Expect { remainder, .. } => {
|
Expect { remainder, .. } => {
|
||||||
self.collect_stmt(param_map, remainder);
|
self.collect_stmt(interner, param_map, remainder);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpectFx { remainder, .. } => {
|
ExpectFx { remainder, .. } => {
|
||||||
self.collect_stmt(param_map, remainder);
|
self.collect_stmt(interner, param_map, remainder);
|
||||||
}
|
}
|
||||||
|
|
||||||
Refcounting(_, _) => unreachable!("these have not been introduced yet"),
|
Refcounting(_, _) => unreachable!("these have not been introduced yet"),
|
||||||
|
@ -891,6 +932,7 @@ impl<'a> BorrowInfState<'a> {
|
||||||
|
|
||||||
fn collect_proc(
|
fn collect_proc(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
interner: &STLayoutInterner<'a>,
|
||||||
param_map: &mut ParamMap<'a>,
|
param_map: &mut ParamMap<'a>,
|
||||||
proc: &Proc<'a>,
|
proc: &Proc<'a>,
|
||||||
param_offset: ParamOffset,
|
param_offset: ParamOffset,
|
||||||
|
@ -912,7 +954,7 @@ impl<'a> BorrowInfState<'a> {
|
||||||
owned_entry.extend(params.iter().map(|p| p.symbol));
|
owned_entry.extend(params.iter().map(|p| p.symbol));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.collect_stmt(param_map, &proc.body);
|
self.collect_stmt(interner, param_map, &proc.body);
|
||||||
self.update_param_map_declaration(param_map, param_offset, proc.args.len());
|
self.update_param_map_declaration(param_map, param_offset, proc.args.len());
|
||||||
|
|
||||||
self.param_set = old;
|
self.param_set = old;
|
||||||
|
|
|
@ -605,7 +605,7 @@ impl<'a, 'i> Context<'a, 'i> {
|
||||||
// get the borrow signature
|
// get the borrow signature
|
||||||
let ps = self
|
let ps = self
|
||||||
.param_map
|
.param_map
|
||||||
.get_symbol(name.name(), top_level)
|
.get_symbol(self.layout_interner, name.name(), top_level)
|
||||||
.expect("function is defined");
|
.expect("function is defined");
|
||||||
|
|
||||||
let v = Expr::Call(crate::ir::Call {
|
let v = Expr::Call(crate::ir::Call {
|
||||||
|
@ -653,10 +653,11 @@ impl<'a, 'i> Context<'a, 'i> {
|
||||||
niche: passed_function.name.niche(),
|
niche: passed_function.name.niche(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let function_ps = match self
|
let function_ps = match self.param_map.get_symbol(
|
||||||
.param_map
|
self.layout_interner,
|
||||||
.get_symbol(passed_function.name.name(), function_layout)
|
passed_function.name.name(),
|
||||||
{
|
function_layout,
|
||||||
|
) {
|
||||||
Some(function_ps) => function_ps,
|
Some(function_ps) => function_ps,
|
||||||
None => unreachable!(),
|
None => unreachable!(),
|
||||||
};
|
};
|
||||||
|
@ -1510,19 +1511,28 @@ pub fn visit_procs<'a, 'i>(
|
||||||
};
|
};
|
||||||
|
|
||||||
for (key, proc) in procs.iter_mut() {
|
for (key, proc) in procs.iter_mut() {
|
||||||
visit_proc(arena, &mut codegen, param_map, &ctx, proc, key.1);
|
visit_proc(
|
||||||
|
arena,
|
||||||
|
layout_interner,
|
||||||
|
&mut codegen,
|
||||||
|
param_map,
|
||||||
|
&ctx,
|
||||||
|
proc,
|
||||||
|
key.1,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_proc<'a, 'i>(
|
fn visit_proc<'a, 'i>(
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
|
interner: &STLayoutInterner<'a>,
|
||||||
codegen: &mut CodegenTools<'i>,
|
codegen: &mut CodegenTools<'i>,
|
||||||
param_map: &'a ParamMap<'a>,
|
param_map: &'a ParamMap<'a>,
|
||||||
ctx: &Context<'a, 'i>,
|
ctx: &Context<'a, 'i>,
|
||||||
proc: &mut Proc<'a>,
|
proc: &mut Proc<'a>,
|
||||||
layout: ProcLayout<'a>,
|
layout: ProcLayout<'a>,
|
||||||
) {
|
) {
|
||||||
let params = match param_map.get_symbol(proc.name.name(), layout) {
|
let params = match param_map.get_symbol(interner, proc.name.name(), layout) {
|
||||||
Some(slice) => slice,
|
Some(slice) => slice,
|
||||||
None => Vec::from_iter_in(
|
None => Vec::from_iter_in(
|
||||||
proc.args.iter().cloned().map(|(layout, symbol)| Param {
|
proc.args.iter().cloned().map(|(layout, symbol)| Param {
|
||||||
|
|
|
@ -4038,6 +4038,33 @@ impl<'a> ProcLayout<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn dbg_deep<'r, I: LayoutInterner<'a>>(&self, interner: &'r I) -> DbgProcLayout<'a, 'r, I> {
|
||||||
|
DbgProcLayout {
|
||||||
|
layout: *self,
|
||||||
|
interner,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DbgProcLayout<'a, 'r, I: LayoutInterner<'a>> {
|
||||||
|
layout: ProcLayout<'a>,
|
||||||
|
interner: &'r I,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'r, I: LayoutInterner<'a>> std::fmt::Debug for DbgProcLayout<'a, 'r, I> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let ProcLayout {
|
||||||
|
arguments,
|
||||||
|
result,
|
||||||
|
niche,
|
||||||
|
} = self.layout;
|
||||||
|
f.debug_struct("ProcLayout")
|
||||||
|
.field("arguments", &self.interner.dbg_deep_iter(arguments))
|
||||||
|
.field("result", &self.interner.dbg_deep(result))
|
||||||
|
.field("niche", &niche.dbg_deep(self.interner))
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn specialize_naked_symbol<'a>(
|
fn specialize_naked_symbol<'a>(
|
||||||
|
|
|
@ -1313,6 +1313,14 @@ impl<'a> Niche<'a> {
|
||||||
]),
|
]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn dbg_deep<'r, I: LayoutInterner<'a>>(
|
||||||
|
&'r self,
|
||||||
|
interner: &'r I,
|
||||||
|
) -> crate::layout::intern::dbg::DbgFields<'a, 'r, I> {
|
||||||
|
let NichePriv::Captures(caps) = &self.0;
|
||||||
|
interner.dbg_deep_iter(caps)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||||
|
|
|
@ -365,6 +365,10 @@ pub trait LayoutInterner<'a>: Sized {
|
||||||
fn dbg_deep<'r>(&'r self, layout: InLayout<'a>) -> dbg::Dbg<'a, 'r, Self> {
|
fn dbg_deep<'r>(&'r self, layout: InLayout<'a>) -> dbg::Dbg<'a, 'r, Self> {
|
||||||
dbg::Dbg(self, layout)
|
dbg::Dbg(self, layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn dbg_deep_iter<'r>(&'r self, layouts: &'a [InLayout<'a>]) -> dbg::DbgFields<'a, 'r, Self> {
|
||||||
|
dbg::DbgFields(self, layouts)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An interned layout.
|
/// An interned layout.
|
||||||
|
@ -1274,7 +1278,7 @@ mod equiv {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod dbg {
|
pub mod dbg {
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
|
|
||||||
use crate::layout::{Builtin, LambdaSet, Layout, UnionLayout};
|
use crate::layout::{Builtin, LambdaSet, Layout, UnionLayout};
|
||||||
|
@ -1311,7 +1315,7 @@ mod dbg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DbgFields<'a, 'r, I: LayoutInterner<'a>>(&'r I, &'a [InLayout<'a>]);
|
pub struct DbgFields<'a, 'r, I: LayoutInterner<'a>>(pub &'r I, pub &'a [InLayout<'a>]);
|
||||||
|
|
||||||
impl<'a, 'r, I: LayoutInterner<'a>> std::fmt::Debug for DbgFields<'a, 'r, I> {
|
impl<'a, 'r, I: LayoutInterner<'a>> std::fmt::Debug for DbgFields<'a, 'r, I> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::ast::CommentOrNewline;
|
use crate::ast::CommentOrNewline;
|
||||||
use crate::ast::Spaceable;
|
use crate::ast::Spaceable;
|
||||||
|
use crate::parser::Progress;
|
||||||
use crate::parser::SpaceProblem;
|
use crate::parser::SpaceProblem;
|
||||||
use crate::parser::{self, and, backtrackable, BadInputError, Parser, Progress::*};
|
use crate::parser::{self, and, backtrackable, BadInputError, Parser, Progress::*};
|
||||||
use crate::state::State;
|
use crate::state::State;
|
||||||
|
@ -7,6 +8,7 @@ use bumpalo::collections::vec::Vec;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use roc_region::all::Loc;
|
use roc_region::all::Loc;
|
||||||
use roc_region::all::Position;
|
use roc_region::all::Position;
|
||||||
|
use roc_region::all::Region;
|
||||||
|
|
||||||
pub fn space0_around_ee<'a, P, S, E>(
|
pub fn space0_around_ee<'a, P, S, E>(
|
||||||
parser: P,
|
parser: P,
|
||||||
|
@ -386,9 +388,42 @@ pub fn spaces<'a, E>() -> impl Parser<'a, &'a [CommentOrNewline<'a>], E>
|
||||||
where
|
where
|
||||||
E: 'a + SpaceProblem,
|
E: 'a + SpaceProblem,
|
||||||
{
|
{
|
||||||
move |arena, mut state: State<'a>, _min_indent: u32| {
|
move |arena, state: State<'a>, _min_indent: u32| {
|
||||||
let mut newlines = Vec::new_in(arena);
|
let mut newlines = Vec::new_in(arena);
|
||||||
|
|
||||||
|
match consume_spaces(state, |_, space, _| newlines.push(space)) {
|
||||||
|
Ok((progress, state)) => Ok((progress, newlines.into_bump_slice(), state)),
|
||||||
|
Err((progress, err)) => Err((progress, err)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn loc_spaces<'a, E>() -> impl Parser<'a, &'a [Loc<CommentOrNewline<'a>>], E>
|
||||||
|
where
|
||||||
|
E: 'a + SpaceProblem,
|
||||||
|
{
|
||||||
|
move |arena, state: State<'a>, _min_indent: u32| {
|
||||||
|
let mut newlines = Vec::new_in(arena);
|
||||||
|
|
||||||
|
match consume_spaces(state, |start, space, end| {
|
||||||
|
newlines.push(Loc::at(Region::between(start, end), space))
|
||||||
|
}) {
|
||||||
|
Ok((progress, state)) => Ok((progress, newlines.into_bump_slice(), state)),
|
||||||
|
Err((progress, err)) => Err((progress, err)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn consume_spaces<'a, E, F>(
|
||||||
|
mut state: State<'a>,
|
||||||
|
mut on_space: F,
|
||||||
|
) -> Result<(Progress, State<'a>), (Progress, E)>
|
||||||
|
where
|
||||||
|
E: 'a + SpaceProblem,
|
||||||
|
F: FnMut(Position, CommentOrNewline<'a>, Position),
|
||||||
|
{
|
||||||
let mut progress = NoProgress;
|
let mut progress = NoProgress;
|
||||||
|
let mut found_newline = false;
|
||||||
loop {
|
loop {
|
||||||
let whitespace = fast_eat_whitespace(state.bytes());
|
let whitespace = fast_eat_whitespace(state.bytes());
|
||||||
if whitespace > 0 {
|
if whitespace > 0 {
|
||||||
|
@ -396,6 +431,8 @@ where
|
||||||
progress = MadeProgress;
|
progress = MadeProgress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let start = state.pos();
|
||||||
|
|
||||||
match state.bytes().first() {
|
match state.bytes().first() {
|
||||||
Some(b'#') => {
|
Some(b'#') => {
|
||||||
state.advance_mut(1);
|
state.advance_mut(1);
|
||||||
|
@ -424,8 +461,9 @@ where
|
||||||
} else {
|
} else {
|
||||||
CommentOrNewline::LineComment(text)
|
CommentOrNewline::LineComment(text)
|
||||||
};
|
};
|
||||||
newlines.push(comment);
|
|
||||||
state.advance_mut(len);
|
state.advance_mut(len);
|
||||||
|
on_space(start, comment, state.pos());
|
||||||
|
found_newline = true;
|
||||||
|
|
||||||
if begins_with_crlf(state.bytes()) {
|
if begins_with_crlf(state.bytes()) {
|
||||||
state.advance_mut(1);
|
state.advance_mut(1);
|
||||||
|
@ -438,23 +476,22 @@ where
|
||||||
}
|
}
|
||||||
Some(b'\r') => {
|
Some(b'\r') => {
|
||||||
if state.bytes().get(1) == Some(&b'\n') {
|
if state.bytes().get(1) == Some(&b'\n') {
|
||||||
newlines.push(CommentOrNewline::Newline);
|
|
||||||
state.advance_mut(1);
|
state.advance_mut(1);
|
||||||
state = state.advance_newline();
|
state = state.advance_newline();
|
||||||
|
on_space(start, CommentOrNewline::Newline, state.pos());
|
||||||
|
found_newline = true;
|
||||||
progress = MadeProgress;
|
progress = MadeProgress;
|
||||||
} else {
|
} else {
|
||||||
return Err((
|
return Err((
|
||||||
progress,
|
progress,
|
||||||
E::space_problem(
|
E::space_problem(BadInputError::HasMisplacedCarriageReturn, state.pos()),
|
||||||
BadInputError::HasMisplacedCarriageReturn,
|
|
||||||
state.pos(),
|
|
||||||
),
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(b'\n') => {
|
Some(b'\n') => {
|
||||||
newlines.push(CommentOrNewline::Newline);
|
|
||||||
state = state.advance_newline();
|
state = state.advance_newline();
|
||||||
|
on_space(start, CommentOrNewline::Newline, state.pos());
|
||||||
|
found_newline = true;
|
||||||
progress = MadeProgress;
|
progress = MadeProgress;
|
||||||
}
|
}
|
||||||
Some(b'\t') => {
|
Some(b'\t') => {
|
||||||
|
@ -470,7 +507,7 @@ where
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if !newlines.is_empty() {
|
if found_newline {
|
||||||
state = state.mark_current_indent();
|
state = state.mark_current_indent();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -478,6 +515,5 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((progress, newlines.into_bump_slice(), state))
|
Ok((progress, state))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
565
crates/compiler/parse/src/highlight.rs
Normal file
565
crates/compiler/parse/src/highlight.rs
Normal file
|
@ -0,0 +1,565 @@
|
||||||
|
use encode_unicode::CharExt;
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
use bumpalo::Bump;
|
||||||
|
use roc_region::all::{Loc, Region};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
ast::CommentOrNewline,
|
||||||
|
blankspace::loc_spaces,
|
||||||
|
keyword::KEYWORDS,
|
||||||
|
number_literal::positive_number_literal,
|
||||||
|
parser::{EExpr, ParseResult, Parser},
|
||||||
|
state::State,
|
||||||
|
string_literal::{parse_str_like_literal, StrLikeLiteral},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub enum Token {
|
||||||
|
LineComment,
|
||||||
|
DocComment,
|
||||||
|
Error,
|
||||||
|
SingleQuote,
|
||||||
|
String,
|
||||||
|
UnicodeEscape,
|
||||||
|
EscapedChar,
|
||||||
|
Interpolated,
|
||||||
|
Keyword,
|
||||||
|
UpperIdent,
|
||||||
|
LowerIdent,
|
||||||
|
Number,
|
||||||
|
Other,
|
||||||
|
Minus,
|
||||||
|
Plus,
|
||||||
|
Colon,
|
||||||
|
Bar,
|
||||||
|
Equals,
|
||||||
|
GreaterThan,
|
||||||
|
LessThan,
|
||||||
|
Comma,
|
||||||
|
Backslash,
|
||||||
|
Brace,
|
||||||
|
Bracket,
|
||||||
|
Paren,
|
||||||
|
Arrow,
|
||||||
|
Pipe,
|
||||||
|
Backpass,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn highlight(text: &str) -> Vec<Loc<Token>> {
|
||||||
|
let mut tokens = Vec::new();
|
||||||
|
let state = State::new(text.as_bytes());
|
||||||
|
|
||||||
|
let arena = Bump::new();
|
||||||
|
|
||||||
|
let header_keywords = HEADER_KEYWORDS.iter().copied().collect::<HashSet<_>>();
|
||||||
|
let body_keywords = KEYWORDS.iter().copied().collect::<HashSet<_>>();
|
||||||
|
|
||||||
|
if let Ok((_prog, _, new_state)) = crate::module::header().parse(&arena, state.clone(), 0) {
|
||||||
|
let inner_state =
|
||||||
|
State::new(text[..state.bytes().len() - new_state.bytes().len()].as_bytes());
|
||||||
|
highlight_inner(&arena, inner_state, &mut tokens, &header_keywords);
|
||||||
|
highlight_inner(&arena, new_state, &mut tokens, &body_keywords);
|
||||||
|
} else {
|
||||||
|
highlight_inner(&arena, state, &mut tokens, &body_keywords);
|
||||||
|
}
|
||||||
|
|
||||||
|
tokens = combine_tokens(tokens);
|
||||||
|
|
||||||
|
tokens
|
||||||
|
}
|
||||||
|
|
||||||
|
fn combine_tokens(locations: Vec<Loc<Token>>) -> Vec<Loc<Token>> {
|
||||||
|
let mut tokens: Vec<Loc<Token>> = Vec::new();
|
||||||
|
let mut previous_location: Option<Loc<Token>> = None;
|
||||||
|
|
||||||
|
for location in locations {
|
||||||
|
match location.value {
|
||||||
|
// Catch tokens which may combine for a different meaning
|
||||||
|
Token::LessThan => match previous_location {
|
||||||
|
Some(prev) => {
|
||||||
|
tokens.push(prev);
|
||||||
|
tokens.push(location);
|
||||||
|
previous_location = None;
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
previous_location = Some(location);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Token::Bar => match previous_location {
|
||||||
|
Some(prev) => {
|
||||||
|
tokens.push(prev);
|
||||||
|
tokens.push(location);
|
||||||
|
previous_location = None;
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
previous_location = Some(location);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Combination tokens
|
||||||
|
Token::GreaterThan => {
|
||||||
|
match previous_location {
|
||||||
|
Some(prev) => {
|
||||||
|
match prev.value {
|
||||||
|
Token::Minus => {
|
||||||
|
// arrow operator "->"
|
||||||
|
tokens.push(Loc::at(
|
||||||
|
Region::between(prev.region.start(), location.region.end()),
|
||||||
|
Token::Arrow,
|
||||||
|
));
|
||||||
|
previous_location = None;
|
||||||
|
}
|
||||||
|
Token::Bar => {
|
||||||
|
// pipe operator "|>"
|
||||||
|
tokens.push(Loc::at(
|
||||||
|
Region::between(prev.region.start(), location.region.end()),
|
||||||
|
Token::Pipe,
|
||||||
|
));
|
||||||
|
previous_location = None;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
tokens.push(prev);
|
||||||
|
tokens.push(location);
|
||||||
|
previous_location = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
tokens.push(location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Token::Minus => {
|
||||||
|
match previous_location {
|
||||||
|
Some(prev) => {
|
||||||
|
match prev.value {
|
||||||
|
Token::LessThan => {
|
||||||
|
// backpass operator "<-"
|
||||||
|
tokens.push(Loc::at(
|
||||||
|
Region::between(prev.region.start(), location.region.end()),
|
||||||
|
Token::Backpass,
|
||||||
|
));
|
||||||
|
previous_location = None;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
tokens.push(prev);
|
||||||
|
tokens.push(location);
|
||||||
|
previous_location = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
previous_location = Some(location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
tokens.push(location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tokens
|
||||||
|
}
|
||||||
|
|
||||||
|
fn highlight_inner<'a>(
|
||||||
|
arena: &'a Bump,
|
||||||
|
mut state: State<'a>,
|
||||||
|
tokens: &mut Vec<Loc<Token>>,
|
||||||
|
keywords: &HashSet<&str>,
|
||||||
|
) {
|
||||||
|
loop {
|
||||||
|
let start = state.pos();
|
||||||
|
if let Ok((b, _width)) = char::from_utf8_slice_start(state.bytes()) {
|
||||||
|
match b {
|
||||||
|
' ' | '\n' | '\t' | '\r' | '#' => {
|
||||||
|
let res: ParseResult<'a, _, EExpr<'a>> =
|
||||||
|
loc_spaces().parse(arena, state.clone(), 0);
|
||||||
|
if let Ok((_, spaces, new_state)) = res {
|
||||||
|
state = new_state;
|
||||||
|
for space in spaces {
|
||||||
|
let token = match space.value {
|
||||||
|
CommentOrNewline::Newline => {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
CommentOrNewline::LineComment(_) => Token::LineComment,
|
||||||
|
CommentOrNewline::DocComment(_) => Token::DocComment,
|
||||||
|
};
|
||||||
|
tokens.push(Loc::at(space.region, token));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fast_forward_to(&mut state, tokens, start, |c| c == b'\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'"' | '\'' => {
|
||||||
|
if let Ok((_, item, new_state)) =
|
||||||
|
parse_str_like_literal().parse(arena, state.clone(), 0)
|
||||||
|
{
|
||||||
|
state = new_state;
|
||||||
|
match item {
|
||||||
|
StrLikeLiteral::SingleQuote(_) => {
|
||||||
|
tokens.push(Loc::at(
|
||||||
|
Region::between(start, state.pos()),
|
||||||
|
Token::SingleQuote,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
StrLikeLiteral::Str(_) => {
|
||||||
|
tokens.push(Loc::at(
|
||||||
|
Region::between(start, state.pos()),
|
||||||
|
Token::String,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fast_forward_to(&mut state, tokens, start, |c| c == b'\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c if c.is_alphabetic() => {
|
||||||
|
let buffer = state.bytes();
|
||||||
|
let mut chomped = 0;
|
||||||
|
|
||||||
|
let is_upper = c.is_uppercase();
|
||||||
|
|
||||||
|
while let Ok((ch, width)) = char::from_utf8_slice_start(&buffer[chomped..]) {
|
||||||
|
if ch.is_alphabetic() || ch.is_ascii_digit() {
|
||||||
|
chomped += width;
|
||||||
|
} else {
|
||||||
|
// we're done
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let ident = std::str::from_utf8(&buffer[..chomped]).unwrap();
|
||||||
|
state.advance_mut(chomped);
|
||||||
|
|
||||||
|
if keywords.contains(ident) {
|
||||||
|
tokens.push(Loc::at(Region::between(start, state.pos()), Token::Keyword));
|
||||||
|
} else {
|
||||||
|
tokens.push(Loc::at(
|
||||||
|
Region::between(start, state.pos()),
|
||||||
|
if is_upper {
|
||||||
|
Token::UpperIdent
|
||||||
|
} else {
|
||||||
|
Token::LowerIdent
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'0'..='9' => {
|
||||||
|
if let Ok((_, _item, new_state)) =
|
||||||
|
positive_number_literal().parse(arena, state.clone(), 0)
|
||||||
|
{
|
||||||
|
state = new_state;
|
||||||
|
tokens.push(Loc::at(Region::between(start, state.pos()), Token::Number));
|
||||||
|
} else {
|
||||||
|
fast_forward_to(&mut state, tokens, start, |b| !b.is_ascii_digit());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
':' => {
|
||||||
|
state.advance_mut(1);
|
||||||
|
tokens.push(Loc::at(Region::between(start, state.pos()), Token::Colon));
|
||||||
|
}
|
||||||
|
'|' => {
|
||||||
|
state.advance_mut(1);
|
||||||
|
tokens.push(Loc::at(Region::between(start, state.pos()), Token::Bar));
|
||||||
|
}
|
||||||
|
'-' => {
|
||||||
|
state.advance_mut(1);
|
||||||
|
tokens.push(Loc::at(Region::between(start, state.pos()), Token::Minus));
|
||||||
|
}
|
||||||
|
'+' => {
|
||||||
|
state.advance_mut(1);
|
||||||
|
tokens.push(Loc::at(Region::between(start, state.pos()), Token::Plus));
|
||||||
|
}
|
||||||
|
'=' => {
|
||||||
|
state.advance_mut(1);
|
||||||
|
tokens.push(Loc::at(Region::between(start, state.pos()), Token::Equals));
|
||||||
|
}
|
||||||
|
'>' => {
|
||||||
|
state.advance_mut(1);
|
||||||
|
tokens.push(Loc::at(
|
||||||
|
Region::between(start, state.pos()),
|
||||||
|
Token::GreaterThan,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
'<' => {
|
||||||
|
state.advance_mut(1);
|
||||||
|
tokens.push(Loc::at(
|
||||||
|
Region::between(start, state.pos()),
|
||||||
|
Token::LessThan,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
',' => {
|
||||||
|
state.advance_mut(1);
|
||||||
|
tokens.push(Loc::at(Region::between(start, state.pos()), Token::Comma));
|
||||||
|
}
|
||||||
|
'\\' => {
|
||||||
|
state.advance_mut(1);
|
||||||
|
tokens.push(Loc::at(
|
||||||
|
Region::between(start, state.pos()),
|
||||||
|
Token::Backslash,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
'{' | '}' => {
|
||||||
|
state.advance_mut(1);
|
||||||
|
tokens.push(Loc::at(Region::between(start, state.pos()), Token::Brace));
|
||||||
|
}
|
||||||
|
'[' | ']' => {
|
||||||
|
state.advance_mut(1);
|
||||||
|
tokens.push(Loc::at(Region::between(start, state.pos()), Token::Bracket));
|
||||||
|
}
|
||||||
|
'(' | ')' => {
|
||||||
|
state.advance_mut(1);
|
||||||
|
tokens.push(Loc::at(Region::between(start, state.pos()), Token::Paren));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
state.advance_mut(1);
|
||||||
|
tokens.push(Loc::at(Region::between(start, state.pos()), Token::Other));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fast_forward_to(
|
||||||
|
state: &mut State,
|
||||||
|
tokens: &mut Vec<Loc<Token>>,
|
||||||
|
start: roc_region::all::Position,
|
||||||
|
end: impl Fn(u8) -> bool,
|
||||||
|
) {
|
||||||
|
while let Some(b) = state.bytes().first() {
|
||||||
|
if end(*b) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
state.advance_mut(1);
|
||||||
|
}
|
||||||
|
tokens.push(Loc::at(Region::between(start, state.pos()), Token::Error));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const HEADER_KEYWORDS: [&str; 14] = [
|
||||||
|
"interface",
|
||||||
|
"app",
|
||||||
|
"package",
|
||||||
|
"platform",
|
||||||
|
"hosted",
|
||||||
|
"exposes",
|
||||||
|
"imports",
|
||||||
|
"with",
|
||||||
|
"generates",
|
||||||
|
"package",
|
||||||
|
"packages",
|
||||||
|
"requires",
|
||||||
|
"provides",
|
||||||
|
"to",
|
||||||
|
];
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use roc_region::all::Position;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_highlight_comments() {
|
||||||
|
let text = "# a\n#b\n#c";
|
||||||
|
let tokens = highlight(text);
|
||||||
|
assert_eq!(
|
||||||
|
tokens,
|
||||||
|
vec![
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(0), Position::new(3)),
|
||||||
|
Token::LineComment
|
||||||
|
),
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(4), Position::new(6)),
|
||||||
|
Token::LineComment
|
||||||
|
),
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(7), Position::new(9)),
|
||||||
|
Token::LineComment
|
||||||
|
),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_highlight_doc_comments() {
|
||||||
|
let text = "## a\n##b\n##c";
|
||||||
|
let tokens = highlight(text);
|
||||||
|
assert_eq!(
|
||||||
|
tokens,
|
||||||
|
vec![
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(0), Position::new(4)),
|
||||||
|
Token::DocComment
|
||||||
|
),
|
||||||
|
// the next two are line comments because there's not a space at the beginning
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(5), Position::new(8)),
|
||||||
|
Token::LineComment
|
||||||
|
),
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(9), Position::new(12)),
|
||||||
|
Token::LineComment
|
||||||
|
),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_highlight_strings() {
|
||||||
|
let text = r#""a""#;
|
||||||
|
let tokens = highlight(text);
|
||||||
|
assert_eq!(
|
||||||
|
tokens,
|
||||||
|
vec![Loc::at(
|
||||||
|
Region::between(Position::new(0), Position::new(3)),
|
||||||
|
Token::String
|
||||||
|
)]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_highlight_single_quotes() {
|
||||||
|
let text = r#"'a'"#;
|
||||||
|
let tokens = highlight(text);
|
||||||
|
assert_eq!(
|
||||||
|
tokens,
|
||||||
|
vec![Loc::at(
|
||||||
|
Region::between(Position::new(0), Position::new(3)),
|
||||||
|
Token::SingleQuote
|
||||||
|
)]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_highlight_header() {
|
||||||
|
let text = r#"app "test-app" provides [] to "./blah""#;
|
||||||
|
let tokens = highlight(text);
|
||||||
|
assert_eq!(
|
||||||
|
tokens,
|
||||||
|
vec![
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(0), Position::new(3)),
|
||||||
|
Token::Keyword
|
||||||
|
),
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(4), Position::new(14)),
|
||||||
|
Token::String
|
||||||
|
),
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(15), Position::new(23)),
|
||||||
|
Token::Keyword
|
||||||
|
),
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(24), Position::new(25)),
|
||||||
|
Token::Bracket
|
||||||
|
),
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(25), Position::new(26)),
|
||||||
|
Token::Bracket
|
||||||
|
),
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(27), Position::new(29)),
|
||||||
|
Token::Keyword
|
||||||
|
),
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(30), Position::new(38)),
|
||||||
|
Token::String
|
||||||
|
),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_highlight_numbers() {
|
||||||
|
let text = "123.0 123 123. 123.0e10 123e10 123e-10 0x123";
|
||||||
|
let tokens = highlight(text);
|
||||||
|
assert_eq!(
|
||||||
|
tokens,
|
||||||
|
vec![
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(0), Position::new(5)),
|
||||||
|
Token::Number
|
||||||
|
),
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(6), Position::new(9)),
|
||||||
|
Token::Number
|
||||||
|
),
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(10), Position::new(14)),
|
||||||
|
Token::Number
|
||||||
|
),
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(15), Position::new(23)),
|
||||||
|
Token::Number
|
||||||
|
),
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(24), Position::new(30)),
|
||||||
|
Token::Number
|
||||||
|
),
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(31), Position::new(38)),
|
||||||
|
Token::Number
|
||||||
|
),
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(39), Position::new(44)),
|
||||||
|
Token::Number
|
||||||
|
),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_combine_tokens() {
|
||||||
|
let input: Vec<Loc<Token>> = vec![
|
||||||
|
// arrow operator "->"
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(0), Position::new(5)),
|
||||||
|
Token::Minus,
|
||||||
|
),
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(6), Position::new(7)),
|
||||||
|
Token::GreaterThan,
|
||||||
|
),
|
||||||
|
// pipe operator "|>"
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(8), Position::new(9)),
|
||||||
|
Token::Bar,
|
||||||
|
),
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(10), Position::new(11)),
|
||||||
|
Token::GreaterThan,
|
||||||
|
),
|
||||||
|
// backpass operator "<-"
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(12), Position::new(13)),
|
||||||
|
Token::LessThan,
|
||||||
|
),
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(14), Position::new(15)),
|
||||||
|
Token::Minus,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
let actual = combine_tokens(input);
|
||||||
|
let expected = vec![
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(0), Position::new(7)),
|
||||||
|
Token::Arrow,
|
||||||
|
),
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(8), Position::new(11)),
|
||||||
|
Token::Pipe,
|
||||||
|
),
|
||||||
|
Loc::at(
|
||||||
|
Region::between(Position::new(12), Position::new(15)),
|
||||||
|
Token::Backpass,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
assert_eq!(actual, expected);
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ pub mod ast;
|
||||||
pub mod blankspace;
|
pub mod blankspace;
|
||||||
pub mod expr;
|
pub mod expr;
|
||||||
pub mod header;
|
pub mod header;
|
||||||
|
pub mod highlight;
|
||||||
pub mod ident;
|
pub mod ident;
|
||||||
pub mod keyword;
|
pub mod keyword;
|
||||||
pub mod module;
|
pub mod module;
|
||||||
|
|
|
@ -129,6 +129,10 @@ impl Position {
|
||||||
offset: self.offset - count as u32,
|
offset: self.offset - count as u32,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn byte_offset(&self) -> usize {
|
||||||
|
self.offset as usize
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for Position {
|
impl Debug for Position {
|
||||||
|
@ -322,6 +326,10 @@ impl<T> Loc<T> {
|
||||||
value: transform(self.value),
|
value: transform(self.value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn byte_range(&self) -> std::ops::Range<usize> {
|
||||||
|
self.region.start.byte_offset()..self.region.end.byte_offset()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> fmt::Debug for Loc<T>
|
impl<T> fmt::Debug for Loc<T>
|
||||||
|
|
|
@ -787,6 +787,59 @@ fn encode_derived_record_with_many_types() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(all(any(feature = "gen-llvm", feature = "gen-wasm")))]
|
||||||
|
fn encode_derived_generic_record_with_different_field_types() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
app "test"
|
||||||
|
imports [Encode, Json]
|
||||||
|
provides [main] to "./platform"
|
||||||
|
|
||||||
|
Q a b := {a: a, b: b} has [Encoding]
|
||||||
|
|
||||||
|
q = @Q {a: 10u32, b: "fieldb"}
|
||||||
|
|
||||||
|
main =
|
||||||
|
result = Str.fromUtf8 (Encode.toBytes q Json.toUtf8)
|
||||||
|
when result is
|
||||||
|
Ok s -> s
|
||||||
|
_ -> "<bad>"
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
RocStr::from(r#"{"a":10,"b":"fieldb"}"#),
|
||||||
|
RocStr
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(all(any(feature = "gen-llvm", feature = "gen-wasm")))]
|
||||||
|
fn encode_derived_generic_tag_with_different_field_types() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
app "test"
|
||||||
|
imports [Encode, Json]
|
||||||
|
provides [main] to "./platform"
|
||||||
|
|
||||||
|
Q a b := [A a, B b] has [Encoding]
|
||||||
|
|
||||||
|
q : Q Str U32
|
||||||
|
q = @Q (B 67)
|
||||||
|
|
||||||
|
main =
|
||||||
|
result = Str.fromUtf8 (Encode.toBytes q Json.toUtf8)
|
||||||
|
when result is
|
||||||
|
Ok s -> s
|
||||||
|
_ -> "<bad>"
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
RocStr::from(r#"{"B":[67]}"#),
|
||||||
|
RocStr
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||||
fn decode_use_stdlib() {
|
fn decode_use_stdlib() {
|
||||||
|
|
|
@ -1859,13 +1859,11 @@ fn first_int_list() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when List.first [12, 9, 6, 3] is
|
List.first [12, 9, 6, 3]
|
||||||
Ok val -> val
|
|
||||||
Err _ -> -1
|
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
12,
|
RocResult::ok(12),
|
||||||
i64
|
RocResult<i64, ()>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1889,45 +1887,42 @@ fn first_wildcard_empty_list() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when List.first [] is
|
List.last [] |> Result.map (\_ -> 0i64)
|
||||||
Ok _ -> 5
|
|
||||||
Err _ -> -1
|
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
-1,
|
RocResult::err(()),
|
||||||
i64
|
RocResult<i64, ()>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
fn first_empty_list() {
|
fn first_empty_list() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when List.first [] is
|
list : List I64
|
||||||
Ok val -> val
|
list = []
|
||||||
Err _ -> -1
|
|
||||||
|
List.first list
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
-1,
|
RocResult::err(()),
|
||||||
i64
|
RocResult<i64, ()>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
fn last_int_list() {
|
fn last_int_list() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when List.last [12, 9, 6, 3] is
|
List.last [12, 9, 6, 3]
|
||||||
Ok val -> val
|
|
||||||
Err _ -> -1
|
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
3,
|
RocResult::ok(3),
|
||||||
i64
|
RocResult<i64, ()>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1937,13 +1932,11 @@ fn last_wildcard_empty_list() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when List.last [] is
|
List.last [] |> Result.map (\_ -> 0i64)
|
||||||
Ok _ -> 5
|
|
||||||
Err _ -> -1
|
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
-1,
|
RocResult::err(()),
|
||||||
i64
|
RocResult<i64, ()>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1953,13 +1946,14 @@ fn last_empty_list() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when List.last [] is
|
list : List I64
|
||||||
Ok val -> val
|
list = []
|
||||||
Err _ -> -1
|
|
||||||
|
List.last list
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
-1,
|
RocResult::err(()),
|
||||||
i64
|
RocResult<i64, ()>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1969,29 +1963,32 @@ fn get_empty_list() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when List.get [] 0 is
|
list : List I64
|
||||||
Ok val -> val
|
list = []
|
||||||
Err _ -> -1
|
|
||||||
|
List.get list 0
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
-1,
|
RocResult::err(()),
|
||||||
i64
|
RocResult<i64, ()>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||||
fn get_wildcard_empty_list() {
|
fn get_wildcard_empty_list() {
|
||||||
|
// NOTE: by default, the return type is `Result [] [NotFound]`, which is actually represented
|
||||||
|
// as just `[NotFound]`. Casting that to `RocResult<(), ()>` is invalid! But accepting any `()`
|
||||||
|
// would make the test pointless. Therefore, we must explicitly change the type on the roc side
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when List.get [] 0 is
|
List.get [] 0
|
||||||
Ok _ -> 5
|
|> Result.map (\_ -> {})
|
||||||
Err _ -> -1
|
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
-1,
|
RocResult::err(()),
|
||||||
i64
|
RocResult<(), ()>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2010,39 +2007,35 @@ fn get_str_list_ok() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
fn get_int_list_ok() {
|
fn get_int_list_ok() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when List.get [12, 9, 6] 1 is
|
List.get [12, 9, 6] 1
|
||||||
Ok val -> val
|
|
||||||
Err _ -> -1
|
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
9,
|
RocResult::ok(9),
|
||||||
i64
|
RocResult<i64, ()>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
fn get_int_list_oob() {
|
fn get_int_list_oob() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when List.get [12, 9, 6] 1000 is
|
List.get [12, 9, 6] 1000
|
||||||
Ok val -> val
|
|
||||||
Err _ -> -1
|
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
-1,
|
RocResult::err(()),
|
||||||
i64
|
RocResult<i64, ()>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
fn replace_unique_int_list() {
|
fn replace_unique_int_list() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -2057,7 +2050,7 @@ fn replace_unique_int_list() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
fn replace_unique_int_list_out_of_bounds() {
|
fn replace_unique_int_list_out_of_bounds() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -2072,7 +2065,7 @@ fn replace_unique_int_list_out_of_bounds() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
fn replace_unique_int_list_get_old_value() {
|
fn replace_unique_int_list_get_old_value() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -2087,7 +2080,7 @@ fn replace_unique_int_list_get_old_value() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
fn replace_unique_get_large_value() {
|
fn replace_unique_get_large_value() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -2138,13 +2131,11 @@ fn get_set_unique_int_list_i64() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when List.get (List.set [12, 9, 7, 3] 1 42) 1 is
|
List.get (List.set [12, 9, 7, 3] 1 42) 1
|
||||||
Ok val -> val
|
|
||||||
Err _ -> -1
|
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
42,
|
RocResult::ok(42),
|
||||||
i64
|
RocResult<i64, ()>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2154,13 +2145,11 @@ fn get_set_unique_int_list_i8() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when List.get (List.set [12, 9, 7, 3] 1 42i8) 1 is
|
List.get (List.set [12, 9, 7, 3] 1 42i8) 1
|
||||||
Ok val -> val
|
|
||||||
Err _ -> -1i8
|
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
42,
|
RocResult::ok(42),
|
||||||
i8
|
RocResult<i8, ()>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2175,7 +2164,7 @@ fn set_unique_int_list() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
fn set_unique_list_oob() {
|
fn set_unique_list_oob() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
"List.set [3, 17, 4.1] 1337 9.25",
|
"List.set [3, 17, 4.1] 1337 9.25",
|
||||||
|
@ -2240,20 +2229,18 @@ fn set_shared_list_oob() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
fn get_unique_int_list() {
|
fn get_unique_int_list() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
unique = [2, 4]
|
unique = [2, 4]
|
||||||
|
|
||||||
when List.get unique 1 is
|
List.get unique 1
|
||||||
Ok num -> num
|
|
||||||
Err _ -> -1
|
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
4,
|
RocResult::ok(4),
|
||||||
i64
|
RocResult<i64, ()>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2275,7 +2262,7 @@ fn gen_wrap_len() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
fn gen_wrap_first() {
|
fn gen_wrap_first() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -2292,7 +2279,7 @@ fn gen_wrap_first() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
fn gen_duplicate() {
|
fn gen_duplicate() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -2605,7 +2592,7 @@ fn list_literal_increment_decrement() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
fn list_pass_to_function() {
|
fn list_pass_to_function() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -2625,7 +2612,7 @@ fn list_pass_to_function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
fn list_pass_to_set() {
|
fn list_pass_to_set() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -2713,24 +2700,22 @@ fn list_min() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when List.min [] is
|
List.min []
|
||||||
Ok val -> val
|
|> Result.map (\_ -> {})
|
||||||
Err _ -> -1
|
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
-1,
|
RocResult::err(()),
|
||||||
i64
|
RocResult<(), ()>
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when List.min [3, 1, 2] is
|
List.min [3, 1, 2]
|
||||||
Ok val -> val
|
|
||||||
Err _ -> -1
|
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
1,
|
RocResult::ok(1),
|
||||||
i64
|
RocResult<i64, ()>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2740,24 +2725,22 @@ fn list_max() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when List.max [] is
|
List.max []
|
||||||
Ok val -> val
|
|> Result.map (\_ -> {})
|
||||||
Err _ -> -1
|
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
-1,
|
RocResult::err(()),
|
||||||
i64
|
RocResult<(), ()>
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when List.max [3, 1, 2] is
|
List.max [3, 1, 2]
|
||||||
Ok val -> val
|
|
||||||
Err _ -> -1
|
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
3,
|
RocResult::ok(3),
|
||||||
i64
|
RocResult<i64, ()>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ fn nat_alias() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
fn i128_signed_int_alias() {
|
fn i128_signed_int_alias() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -115,7 +115,7 @@ fn i8_signed_int_alias() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||||
fn i128_hex_int_alias() {
|
fn i128_hex_int_alias() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -196,7 +196,7 @@ fn i8_hex_int_alias() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||||
fn u128_signed_int_alias() {
|
fn u128_signed_int_alias() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -277,7 +277,7 @@ fn u8_signed_int_alias() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||||
fn u128_hex_int_alias() {
|
fn u128_hex_int_alias() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -418,7 +418,7 @@ fn character_literal_new_line() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||||
fn dec_float_alias() {
|
fn dec_float_alias() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -451,7 +451,7 @@ fn f64_float_alias() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||||
fn f32_float_alias() {
|
fn f32_float_alias() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -468,112 +468,51 @@ fn f32_float_alias() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||||
fn f64_sqrt() {
|
fn f64_sqrt_100() {
|
||||||
assert_evals_to!(
|
assert_evals_to!("Num.sqrt 100", 10.0, f64);
|
||||||
indoc!(
|
}
|
||||||
r#"
|
|
||||||
when Num.sqrtChecked 100 is
|
#[test]
|
||||||
Ok val -> val
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||||
Err _ -> -1
|
fn f64_sqrt_checked_0() {
|
||||||
"#
|
assert_evals_to!("Num.sqrt 0", 0.0, f64);
|
||||||
),
|
|
||||||
10.0,
|
|
||||||
f64
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||||
fn f64_log() {
|
fn f64_sqrt_checked_positive() {
|
||||||
assert_evals_to!(
|
assert_evals_to!("Num.sqrtChecked 100", RocResult::ok(10.0), RocResult<f64, ()>);
|
||||||
indoc!(
|
|
||||||
r#"
|
|
||||||
Num.log 7.38905609893
|
|
||||||
"#
|
|
||||||
),
|
|
||||||
1.999999999999912,
|
|
||||||
f64
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
|
||||||
fn f64_log_checked_one() {
|
|
||||||
assert_evals_to!(
|
|
||||||
indoc!(
|
|
||||||
r#"
|
|
||||||
when Num.logChecked 1 is
|
|
||||||
Ok val -> val
|
|
||||||
Err _ -> -1
|
|
||||||
"#
|
|
||||||
),
|
|
||||||
0.0,
|
|
||||||
f64
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
|
||||||
fn f64_sqrt_zero() {
|
|
||||||
assert_evals_to!(
|
|
||||||
indoc!(
|
|
||||||
r#"
|
|
||||||
when Num.sqrtChecked 0 is
|
|
||||||
Ok val -> val
|
|
||||||
Err _ -> -1
|
|
||||||
"#
|
|
||||||
),
|
|
||||||
0.0,
|
|
||||||
f64
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||||
fn f64_sqrt_checked_negative() {
|
fn f64_sqrt_checked_negative() {
|
||||||
assert_evals_to!(
|
assert_evals_to!("Num.sqrtChecked -1f64", RocResult::err(()), RocResult<f64, ()>);
|
||||||
indoc!(
|
}
|
||||||
r#"
|
|
||||||
when Num.sqrtChecked -1 is
|
#[test]
|
||||||
Err _ -> 42
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||||
Ok val -> val
|
fn f64_log() {
|
||||||
"#
|
assert_evals_to!("Num.log 7.38905609893", 1.999999999999912, f64);
|
||||||
),
|
}
|
||||||
42.0,
|
|
||||||
f64
|
#[test]
|
||||||
);
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||||
|
fn f64_log_checked_one() {
|
||||||
|
assert_evals_to!("Num.logChecked 1", RocResult::ok(0.0), RocResult<f64, ()>);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||||
fn f64_log_checked_zero() {
|
fn f64_log_checked_zero() {
|
||||||
assert_evals_to!(
|
assert_evals_to!("Num.logChecked 0", RocResult::err(()), RocResult<f64, ()>);
|
||||||
indoc!(
|
|
||||||
r#"
|
|
||||||
when Num.logChecked 0 is
|
|
||||||
Err _ -> 42
|
|
||||||
Ok val -> val
|
|
||||||
"#
|
|
||||||
),
|
|
||||||
42.0,
|
|
||||||
f64
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||||
fn f64_log_negative() {
|
fn f64_log_negative() {
|
||||||
assert_evals_to!(
|
assert_evals_to!("Num.log -1", true, f64, |f: f64| f.is_nan());
|
||||||
indoc!(
|
|
||||||
r#"
|
|
||||||
Num.log -1
|
|
||||||
"#
|
|
||||||
),
|
|
||||||
true,
|
|
||||||
f64,
|
|
||||||
|f: f64| f.is_nan()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -890,16 +829,20 @@ fn gen_int_neq() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
fn gen_int_less_than() {
|
fn int_less_than() {
|
||||||
assert_evals_to!(
|
assert_evals_to!("4 < 5", true, bool);
|
||||||
indoc!(
|
}
|
||||||
r#"
|
|
||||||
4 < 5
|
#[test]
|
||||||
"#
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
),
|
fn float_less_than() {
|
||||||
true,
|
assert_evals_to!("4.0 < 5.0", true, bool);
|
||||||
bool
|
}
|
||||||
);
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
|
fn float_greater_than() {
|
||||||
|
assert_evals_to!("5.0 > 4.0", true, bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -3307,10 +3307,46 @@ fn box_str() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
fn box_and_unbox_num() {
|
fn box_and_unbox_u64() {
|
||||||
assert_evals_to!("Box.unbox (Box.box (123u64))", 123, u64)
|
assert_evals_to!("Box.unbox (Box.box (123u64))", 123, u64)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
|
fn box_and_unbox_u32() {
|
||||||
|
assert_evals_to!("Box.unbox (Box.box (123u32))", 123, u32)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
|
fn box_and_unbox_u16() {
|
||||||
|
assert_evals_to!("Box.unbox (Box.box (123u16))", 123, u16)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
|
fn box_and_unbox_u8() {
|
||||||
|
assert_evals_to!("Box.unbox (Box.box (123u8))", 123, u8)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
|
fn box_and_unbox_bool() {
|
||||||
|
assert_evals_to!("Box.unbox (Box.box (Bool.true))", true, bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
|
fn box_and_unbox_f64() {
|
||||||
|
assert_evals_to!("Box.unbox (Box.box (123.0f64))", 123.0, f64)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
|
fn box_and_unbox_f32() {
|
||||||
|
assert_evals_to!("Box.unbox (Box.box (123.0f32))", 123.0, f32)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||||
fn box_and_unbox_record() {
|
fn box_and_unbox_record() {
|
||||||
|
|
|
@ -360,7 +360,7 @@ fn i64_record1_literal() {
|
||||||
// );
|
// );
|
||||||
// }
|
// }
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
fn bool_literal() {
|
fn bool_literal() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -1111,3 +1111,22 @@ fn toplevel_accessor_fn_thunk() {
|
||||||
u8
|
u8
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||||
|
fn pass_record_of_u8s() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
app "test" provides [main] to "./platform"
|
||||||
|
|
||||||
|
ra = \_ -> 1u8
|
||||||
|
|
||||||
|
main =
|
||||||
|
ra { a: 1u8, b: 0u8 }
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
true,
|
||||||
|
bool
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -227,7 +227,7 @@ fn is_err() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
fn roc_result_ok() {
|
fn roc_result_ok_i64() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
|
@ -242,6 +242,26 @@ fn roc_result_ok() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||||
|
fn roc_result_ok_f64() {
|
||||||
|
// NOTE: the dev backend does not currently use float registers when returning a more
|
||||||
|
// complex type, but the rust side does expect it to. Hence this test fails with gen-dev
|
||||||
|
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
result : Result F64 {}
|
||||||
|
result = Ok 42.0
|
||||||
|
|
||||||
|
result
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
RocResult::ok(42.0),
|
||||||
|
RocResult<f64, ()>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
fn roc_result_err() {
|
fn roc_result_err() {
|
||||||
|
|
|
@ -16,7 +16,7 @@ use indoc::indoc;
|
||||||
use roc_std::{RocList, RocResult, RocStr};
|
use roc_std::{RocList, RocResult, RocStr};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_split_empty_delimiter() {
|
fn str_split_empty_delimiter() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -46,7 +46,7 @@ fn str_split_empty_delimiter() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_split_bigger_delimiter_small_str() {
|
fn str_split_bigger_delimiter_small_str() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -110,7 +110,7 @@ fn str_split_small_str_bigger_delimiter() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_split_big_str_small_delimiter() {
|
fn str_split_big_str_small_delimiter() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -154,7 +154,7 @@ fn str_split_small_str_small_delimiter() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_split_bigger_delimiter_big_strs() {
|
fn str_split_bigger_delimiter_big_strs() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -198,7 +198,7 @@ fn str_split_minimal_example() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_split_small_str_big_delimiter() {
|
fn str_split_small_str_big_delimiter() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -227,7 +227,7 @@ fn str_split_small_str_big_delimiter() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_split_small_str_20_char_delimiter() {
|
fn str_split_small_str_20_char_delimiter() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -243,7 +243,7 @@ fn str_split_small_str_20_char_delimiter() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_concat_big_to_big() {
|
fn str_concat_big_to_big() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -402,7 +402,7 @@ fn small_str_concat_empty_second_arg() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn small_str_concat_small_to_big() {
|
fn small_str_concat_small_to_big() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
r#"Str.concat "abc" " this is longer than 15 chars""#,
|
r#"Str.concat "abc" " this is longer than 15 chars""#,
|
||||||
|
@ -530,7 +530,7 @@ fn str_count_graphemes_three_js() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_count_graphemes_big_str() {
|
fn str_count_graphemes_big_str() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
r#"Str.countGraphemes "6🤔å🤔e¥🤔çppkd🙃1jdal🦯asdfa∆ltråø˚waia8918.,🏅jjc""#,
|
r#"Str.countGraphemes "6🤔å🤔e¥🤔çppkd🙃1jdal🦯asdfa∆ltråø˚waia8918.,🏅jjc""#,
|
||||||
|
@ -540,7 +540,7 @@ fn str_count_graphemes_big_str() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_starts_with_same_big_str() {
|
fn str_starts_with_same_big_str() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
r#"Str.startsWith "123456789123456789" "123456789123456789""#,
|
r#"Str.startsWith "123456789123456789" "123456789123456789""#,
|
||||||
|
@ -550,7 +550,7 @@ fn str_starts_with_same_big_str() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_starts_with_different_big_str() {
|
fn str_starts_with_different_big_str() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
r#"Str.startsWith "12345678912345678910" "123456789123456789""#,
|
r#"Str.startsWith "12345678912345678910" "123456789123456789""#,
|
||||||
|
@ -560,24 +560,24 @@ fn str_starts_with_different_big_str() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_starts_with_same_small_str() {
|
fn str_starts_with_same_small_str() {
|
||||||
assert_evals_to!(r#"Str.startsWith "1234" "1234""#, true, bool);
|
assert_evals_to!(r#"Str.startsWith "1234" "1234""#, true, bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_starts_with_different_small_str() {
|
fn str_starts_with_different_small_str() {
|
||||||
assert_evals_to!(r#"Str.startsWith "1234" "12""#, true, bool);
|
assert_evals_to!(r#"Str.startsWith "1234" "12""#, true, bool);
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_starts_with_false_small_str() {
|
fn str_starts_with_false_small_str() {
|
||||||
assert_evals_to!(r#"Str.startsWith "1234" "23""#, false, bool);
|
assert_evals_to!(r#"Str.startsWith "1234" "23""#, false, bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_from_utf8_pass_single_ascii() {
|
fn str_from_utf8_pass_single_ascii() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -593,7 +593,7 @@ fn str_from_utf8_pass_single_ascii() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_from_utf8_pass_many_ascii() {
|
fn str_from_utf8_pass_many_ascii() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -609,7 +609,7 @@ fn str_from_utf8_pass_many_ascii() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_from_utf8_pass_single_unicode() {
|
fn str_from_utf8_pass_single_unicode() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -625,7 +625,7 @@ fn str_from_utf8_pass_single_unicode() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_from_utf8_pass_many_unicode() {
|
fn str_from_utf8_pass_many_unicode() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -641,7 +641,7 @@ fn str_from_utf8_pass_many_unicode() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_from_utf8_pass_single_grapheme() {
|
fn str_from_utf8_pass_single_grapheme() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -657,7 +657,7 @@ fn str_from_utf8_pass_single_grapheme() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_from_utf8_pass_many_grapheme() {
|
fn str_from_utf8_pass_many_grapheme() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -673,7 +673,7 @@ fn str_from_utf8_pass_many_grapheme() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_from_utf8_pass_all() {
|
fn str_from_utf8_pass_all() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -689,7 +689,7 @@ fn str_from_utf8_pass_all() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_from_utf8_fail_invalid_start_byte() {
|
fn str_from_utf8_fail_invalid_start_byte() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -709,7 +709,7 @@ fn str_from_utf8_fail_invalid_start_byte() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_from_utf8_fail_unexpected_end_of_sequence() {
|
fn str_from_utf8_fail_unexpected_end_of_sequence() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -729,7 +729,7 @@ fn str_from_utf8_fail_unexpected_end_of_sequence() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_from_utf8_fail_expected_continuation() {
|
fn str_from_utf8_fail_expected_continuation() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -749,7 +749,7 @@ fn str_from_utf8_fail_expected_continuation() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_from_utf8_fail_overlong_encoding() {
|
fn str_from_utf8_fail_overlong_encoding() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -769,7 +769,7 @@ fn str_from_utf8_fail_overlong_encoding() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_from_utf8_fail_codepoint_too_large() {
|
fn str_from_utf8_fail_codepoint_too_large() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -789,7 +789,7 @@ fn str_from_utf8_fail_codepoint_too_large() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_from_utf8_fail_surrogate_half() {
|
fn str_from_utf8_fail_surrogate_half() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -809,7 +809,7 @@ fn str_from_utf8_fail_surrogate_half() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_equality() {
|
fn str_equality() {
|
||||||
assert_evals_to!(r#""a" == "a""#, true, bool);
|
assert_evals_to!(r#""a" == "a""#, true, bool);
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
|
@ -865,7 +865,7 @@ fn nested_recursive_literal() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_join_comma_small() {
|
fn str_join_comma_small() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
r#"Str.joinWith ["1", "2"] ", " "#,
|
r#"Str.joinWith ["1", "2"] ", " "#,
|
||||||
|
@ -875,7 +875,7 @@ fn str_join_comma_small() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_join_comma_big() {
|
fn str_join_comma_big() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
r#"Str.joinWith ["10000000", "2000000", "30000000"] ", " "#,
|
r#"Str.joinWith ["10000000", "2000000", "30000000"] ", " "#,
|
||||||
|
@ -885,13 +885,13 @@ fn str_join_comma_big() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_join_comma_single() {
|
fn str_join_comma_single() {
|
||||||
assert_evals_to!(r#"Str.joinWith ["1"] ", " "#, RocStr::from("1"), RocStr);
|
assert_evals_to!(r#"Str.joinWith ["1"] ", " "#, RocStr::from("1"), RocStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_to_utf8() {
|
fn str_to_utf8() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
r#"Str.toUtf8 "hello""#,
|
r#"Str.toUtf8 "hello""#,
|
||||||
|
@ -909,7 +909,7 @@ fn str_to_utf8() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_from_utf8_range() {
|
fn str_from_utf8_range() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -926,7 +926,7 @@ fn str_from_utf8_range() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_from_utf8_range_slice() {
|
fn str_from_utf8_range_slice() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -943,7 +943,7 @@ fn str_from_utf8_range_slice() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_from_utf8_range_slice_not_end() {
|
fn str_from_utf8_range_slice_not_end() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -960,7 +960,7 @@ fn str_from_utf8_range_slice_not_end() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_from_utf8_range_order_does_not_matter() {
|
fn str_from_utf8_range_order_does_not_matter() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -977,7 +977,7 @@ fn str_from_utf8_range_order_does_not_matter() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_from_utf8_range_out_of_bounds_start_value() {
|
fn str_from_utf8_range_out_of_bounds_start_value() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -995,7 +995,7 @@ fn str_from_utf8_range_out_of_bounds_start_value() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_from_utf8_range_count_too_high() {
|
fn str_from_utf8_range_count_too_high() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -1013,7 +1013,7 @@ fn str_from_utf8_range_count_too_high() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_from_utf8_range_count_too_high_for_start() {
|
fn str_from_utf8_range_count_too_high_for_start() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -1031,7 +1031,7 @@ fn str_from_utf8_range_count_too_high_for_start() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_repeat_small_stays_small() {
|
fn str_repeat_small_stays_small() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(r#"Str.repeat "Roc" 3"#),
|
indoc!(r#"Str.repeat "Roc" 3"#),
|
||||||
|
@ -1041,7 +1041,7 @@ fn str_repeat_small_stays_small() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_repeat_small_becomes_big() {
|
fn str_repeat_small_becomes_big() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(r#"Str.repeat "less than 23 characters" 2"#),
|
indoc!(r#"Str.repeat "less than 23 characters" 2"#),
|
||||||
|
@ -1051,7 +1051,7 @@ fn str_repeat_small_becomes_big() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_repeat_big() {
|
fn str_repeat_big() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(r#"Str.repeat "more than 23 characters now" 2"#),
|
indoc!(r#"Str.repeat "more than 23 characters now" 2"#),
|
||||||
|
@ -1061,27 +1061,26 @@ fn str_repeat_big() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_repeat_empty_string() {
|
fn str_repeat_empty_string() {
|
||||||
let a = indoc!(r#"Str.repeat "" 3"#);
|
let a = indoc!(r#"Str.repeat "" 3"#);
|
||||||
let b = RocStr::from("");
|
assert_evals_to!(a, RocStr::from(""), RocStr);
|
||||||
assert_evals_to!(a, b, RocStr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_repeat_zero_times() {
|
fn str_repeat_zero_times() {
|
||||||
assert_evals_to!(indoc!(r#"Str.repeat "Roc" 0"#), RocStr::from(""), RocStr);
|
assert_evals_to!(indoc!(r#"Str.repeat "Roc" 0"#), RocStr::from(""), RocStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_trim_empty_string() {
|
fn str_trim_empty_string() {
|
||||||
assert_evals_to!(indoc!(r#"Str.trim """#), RocStr::from(""), RocStr);
|
assert_evals_to!(indoc!(r#"Str.trim """#), RocStr::from(""), RocStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_trim_null_byte() {
|
fn str_trim_null_byte() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(r#"Str.trim (Str.reserve "\u(0000)" 40)"#),
|
indoc!(r#"Str.trim (Str.reserve "\u(0000)" 40)"#),
|
||||||
|
@ -1091,13 +1090,13 @@ fn str_trim_null_byte() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_trim_small_blank_string() {
|
fn str_trim_small_blank_string() {
|
||||||
assert_evals_to!(indoc!(r#"Str.trim " ""#), RocStr::from(""), RocStr);
|
assert_evals_to!(indoc!(r#"Str.trim " ""#), RocStr::from(""), RocStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_trim_small_to_small() {
|
fn str_trim_small_to_small() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(r#"Str.trim " hello world ""#),
|
indoc!(r#"Str.trim " hello world ""#),
|
||||||
|
@ -1107,7 +1106,7 @@ fn str_trim_small_to_small() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_trim_large_to_large_unique() {
|
fn str_trim_large_to_large_unique() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(r#"Str.trim (Str.concat " " "hello world from a large string ")"#),
|
indoc!(r#"Str.trim (Str.concat " " "hello world from a large string ")"#),
|
||||||
|
@ -1117,7 +1116,7 @@ fn str_trim_large_to_large_unique() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_trim_large_to_small_unique() {
|
fn str_trim_large_to_small_unique() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(r#"Str.trim (Str.concat " " "hello world ")"#),
|
indoc!(r#"Str.trim (Str.concat " " "hello world ")"#),
|
||||||
|
@ -1184,13 +1183,13 @@ fn str_trim_small_to_small_shared() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_trim_left_small_blank_string() {
|
fn str_trim_left_small_blank_string() {
|
||||||
assert_evals_to!(indoc!(r#"Str.trimLeft " ""#), RocStr::from(""), RocStr);
|
assert_evals_to!(indoc!(r#"Str.trimLeft " ""#), RocStr::from(""), RocStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_trim_left_small_to_small() {
|
fn str_trim_left_small_to_small() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(r#"Str.trimLeft " hello world ""#),
|
indoc!(r#"Str.trimLeft " hello world ""#),
|
||||||
|
@ -1200,7 +1199,7 @@ fn str_trim_left_small_to_small() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_trim_left_large_to_large_unique() {
|
fn str_trim_left_large_to_large_unique() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(r#"Str.trimLeft (Str.concat " " "hello world from a large string ")"#),
|
indoc!(r#"Str.trimLeft (Str.concat " " "hello world from a large string ")"#),
|
||||||
|
@ -1210,7 +1209,7 @@ fn str_trim_left_large_to_large_unique() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_trim_left_large_to_small_unique() {
|
fn str_trim_left_large_to_small_unique() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(r#"Str.trimLeft (Str.concat " " "hello world ")"#),
|
indoc!(r#"Str.trimLeft (Str.concat " " "hello world ")"#),
|
||||||
|
@ -1277,13 +1276,13 @@ fn str_trim_left_small_to_small_shared() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_trim_right_small_blank_string() {
|
fn str_trim_right_small_blank_string() {
|
||||||
assert_evals_to!(indoc!(r#"Str.trimRight " ""#), RocStr::from(""), RocStr);
|
assert_evals_to!(indoc!(r#"Str.trimRight " ""#), RocStr::from(""), RocStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_trim_right_small_to_small() {
|
fn str_trim_right_small_to_small() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(r#"Str.trimRight " hello world ""#),
|
indoc!(r#"Str.trimRight " hello world ""#),
|
||||||
|
@ -1293,7 +1292,7 @@ fn str_trim_right_small_to_small() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_trim_right_large_to_large_unique() {
|
fn str_trim_right_large_to_large_unique() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(r#"Str.trimRight (Str.concat " hello world from a large string" " ")"#),
|
indoc!(r#"Str.trimRight (Str.concat " hello world from a large string" " ")"#),
|
||||||
|
@ -1303,7 +1302,7 @@ fn str_trim_right_large_to_large_unique() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_trim_right_large_to_small_unique() {
|
fn str_trim_right_large_to_small_unique() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(r#"Str.trimRight (Str.concat " hello world" " ")"#),
|
indoc!(r#"Str.trimRight (Str.concat " hello world" " ")"#),
|
||||||
|
@ -1370,9 +1369,17 @@ fn str_trim_right_small_to_small_shared() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_to_nat() {
|
fn str_to_nat() {
|
||||||
assert_evals_to!(r#"Str.toNat "1" |> Result.withDefault 0"#, 1, usize);
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
Str.toNat "1"
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
RocResult::ok(1),
|
||||||
|
RocResult<usize, ()>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1381,14 +1388,11 @@ fn str_to_i128() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when Str.toI128 "1" is
|
Str.toI128 "1"
|
||||||
Ok n -> n
|
|
||||||
Err _ -> 0
|
|
||||||
|
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
1,
|
RocResult::ok(1),
|
||||||
i128
|
RocResult<i128, ()>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1398,41 +1402,39 @@ fn str_to_u128() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when Str.toU128 "1" is
|
Str.toU128 "1"
|
||||||
Ok n -> n
|
|
||||||
Err _ -> 0
|
|
||||||
|
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
1,
|
RocResult::ok(1),
|
||||||
u128
|
RocResult<u128, ()>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_to_i64() {
|
fn str_to_i64() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when Str.toI64 "1" is
|
Str.toI64 "1"
|
||||||
Ok n -> n
|
|
||||||
Err _ -> 0
|
|
||||||
|
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
1,
|
RocResult::ok(1),
|
||||||
i64
|
RocResult<i64, ()>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_to_u64() {
|
fn str_to_u64() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
r#"Str.toU64 "1""#,
|
indoc!(
|
||||||
RocResult::ok(1u64),
|
r#"
|
||||||
RocResult<u64, u8>
|
Str.toU64 "1"
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
RocResult::ok(1),
|
||||||
|
RocResult<u64, ()>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1442,14 +1444,11 @@ fn str_to_i32() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when Str.toI32 "1" is
|
Str.toI32 "1"
|
||||||
Ok n -> n
|
|
||||||
Err _ -> 0
|
|
||||||
|
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
1,
|
RocResult::ok(1),
|
||||||
i32
|
RocResult<i32, ()>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1457,9 +1456,13 @@ fn str_to_i32() {
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm"))]
|
||||||
fn str_to_u32() {
|
fn str_to_u32() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
r#"Str.toU32 "1""#,
|
indoc!(
|
||||||
RocResult::ok(1u32),
|
r#"
|
||||||
RocResult<u32, u8>
|
Str.toU32 "1"
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
RocResult::ok(1),
|
||||||
|
RocResult<u32, ()>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1469,14 +1472,11 @@ fn str_to_i16() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when Str.toI16 "1" is
|
Str.toI16 "1"
|
||||||
Ok n -> n
|
|
||||||
Err _ -> 0
|
|
||||||
|
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
1,
|
RocResult::ok(1),
|
||||||
i16
|
RocResult<i16, ()>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1486,14 +1486,11 @@ fn str_to_u16() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when Str.toU16 "1" is
|
Str.toU16 "1"
|
||||||
Ok n -> n
|
|
||||||
Err _ -> 0
|
|
||||||
|
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
1,
|
RocResult::ok(1),
|
||||||
u16
|
RocResult<u16, ()>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1503,14 +1500,11 @@ fn str_to_i8() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when Str.toI8 "1" is
|
Str.toI8 "1"
|
||||||
Ok n -> n
|
|
||||||
Err _ -> 0
|
|
||||||
|
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
1,
|
RocResult::ok(1),
|
||||||
i8
|
RocResult<i8, ()>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1520,14 +1514,11 @@ fn str_to_u8() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when Str.toU8 "1" is
|
Str.toU8 "1"
|
||||||
Ok n -> n
|
|
||||||
Err _ -> 0
|
|
||||||
|
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
1,
|
RocResult::ok(1),
|
||||||
u8
|
RocResult<u8, ()>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1585,7 +1576,7 @@ fn str_to_dec() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn issue_2811() {
|
fn issue_2811() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -1601,7 +1592,7 @@ fn issue_2811() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn to_scalar_1_byte() {
|
fn to_scalar_1_byte() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -1625,7 +1616,7 @@ fn to_scalar_1_byte() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn to_scalar_2_byte() {
|
fn to_scalar_2_byte() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -1649,7 +1640,7 @@ fn to_scalar_2_byte() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn to_scalar_3_byte() {
|
fn to_scalar_3_byte() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -1673,7 +1664,7 @@ fn to_scalar_3_byte() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn to_scalar_4_byte() {
|
fn to_scalar_4_byte() {
|
||||||
// from https://design215.com/toolbox/utf8-4byte-characters.php
|
// from https://design215.com/toolbox/utf8-4byte-characters.php
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
|
@ -1698,7 +1689,7 @@ fn to_scalar_4_byte() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_split_first_one_char() {
|
fn str_split_first_one_char() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -1714,7 +1705,7 @@ fn str_split_first_one_char() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_split_first_multiple_chars() {
|
fn str_split_first_multiple_chars() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -1728,7 +1719,7 @@ fn str_split_first_multiple_chars() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_split_first_entire_input() {
|
fn str_split_first_entire_input() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -1742,7 +1733,7 @@ fn str_split_first_entire_input() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_split_first_not_found() {
|
fn str_split_first_not_found() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -1756,7 +1747,7 @@ fn str_split_first_not_found() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_split_last_one_char() {
|
fn str_split_last_one_char() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -1770,7 +1761,7 @@ fn str_split_last_one_char() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_split_last_multiple_chars() {
|
fn str_split_last_multiple_chars() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -1784,7 +1775,7 @@ fn str_split_last_multiple_chars() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_split_last_entire_input() {
|
fn str_split_last_entire_input() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -1798,12 +1789,12 @@ fn str_split_last_entire_input() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_split_last_not_found() {
|
fn str_split_last_not_found() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
Str.splitFirst "foo" "bar"
|
Str.splitLast "foo" "bar"
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
RocResult::err(()),
|
RocResult::err(()),
|
||||||
|
@ -1812,7 +1803,7 @@ fn str_split_last_not_found() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_split_overlapping_substring_1() {
|
fn str_split_overlapping_substring_1() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
r#"Str.split "aaa" "aa""#,
|
r#"Str.split "aaa" "aa""#,
|
||||||
|
@ -1822,7 +1813,7 @@ fn str_split_overlapping_substring_1() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_split_overlapping_substring_2() {
|
fn str_split_overlapping_substring_2() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
r#"Str.split "aaaa" "aa""#,
|
r#"Str.split "aaaa" "aa""#,
|
||||||
|
@ -1832,7 +1823,7 @@ fn str_split_overlapping_substring_2() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_walk_utf8_with_index() {
|
fn str_walk_utf8_with_index() {
|
||||||
#[cfg(not(feature = "gen-llvm-wasm"))]
|
#[cfg(not(feature = "gen-llvm-wasm"))]
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
|
@ -1872,7 +1863,7 @@ fn str_append_scalar() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||||
fn str_walk_scalars() {
|
fn str_walk_scalars() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -1951,7 +1942,7 @@ fn when_on_strings() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
fn with_capacity() {
|
fn with_capacity() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -1965,7 +1956,7 @@ fn with_capacity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
fn with_capacity_concat() {
|
fn with_capacity_concat() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -1979,7 +1970,7 @@ fn with_capacity_concat() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
fn str_with_prefix() {
|
fn str_with_prefix() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -2003,7 +1994,7 @@ fn str_with_prefix() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
fn destructure_pattern_assigned_from_thunk_opaque() {
|
fn destructure_pattern_assigned_from_thunk_opaque() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -2025,7 +2016,7 @@ fn destructure_pattern_assigned_from_thunk_opaque() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||||
fn destructure_pattern_assigned_from_thunk_tag() {
|
fn destructure_pattern_assigned_from_thunk_tag() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
|
|
@ -3,7 +3,7 @@ procedure Bool.11 (#Attr.2, #Attr.3):
|
||||||
ret Bool.24;
|
ret Bool.24;
|
||||||
|
|
||||||
procedure List.26 (List.152, List.153, List.154):
|
procedure List.26 (List.152, List.153, List.154):
|
||||||
let List.493 : [C U64, C U64] = CallByName List.90 List.152 List.153 List.154;
|
let List.493 : [C U64, C U64] = CallByName List.91 List.152 List.153 List.154;
|
||||||
let List.496 : U8 = 1i64;
|
let List.496 : U8 = 1i64;
|
||||||
let List.497 : U8 = GetTagId List.493;
|
let List.497 : U8 = GetTagId List.493;
|
||||||
let List.498 : Int1 = lowlevel Eq List.496 List.497;
|
let List.498 : Int1 = lowlevel Eq List.496 List.497;
|
||||||
|
@ -53,13 +53,7 @@ procedure List.72 (#Attr.2, #Attr.3, #Attr.4):
|
||||||
let List.484 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4;
|
let List.484 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4;
|
||||||
ret List.484;
|
ret List.484;
|
||||||
|
|
||||||
procedure List.90 (List.426, List.427, List.428):
|
procedure List.80 (List.528, List.529, List.530, List.531, List.532):
|
||||||
let List.500 : U64 = 0i64;
|
|
||||||
let List.501 : U64 = CallByName List.6 List.426;
|
|
||||||
let List.499 : [C U64, C U64] = CallByName List.91 List.426 List.427 List.428 List.500 List.501;
|
|
||||||
ret List.499;
|
|
||||||
|
|
||||||
procedure List.91 (List.528, List.529, List.530, List.531, List.532):
|
|
||||||
joinpoint List.502 List.429 List.430 List.431 List.432 List.433:
|
joinpoint List.502 List.429 List.430 List.431 List.432 List.433:
|
||||||
let List.504 : Int1 = CallByName Num.22 List.432 List.433;
|
let List.504 : Int1 = CallByName Num.22 List.432 List.433;
|
||||||
if List.504 then
|
if List.504 then
|
||||||
|
@ -83,6 +77,12 @@ procedure List.91 (List.528, List.529, List.530, List.531, List.532):
|
||||||
in
|
in
|
||||||
jump List.502 List.528 List.529 List.530 List.531 List.532;
|
jump List.502 List.528 List.529 List.530 List.531 List.532;
|
||||||
|
|
||||||
|
procedure List.91 (List.426, List.427, List.428):
|
||||||
|
let List.500 : U64 = 0i64;
|
||||||
|
let List.501 : U64 = CallByName List.6 List.426;
|
||||||
|
let List.499 : [C U64, C U64] = CallByName List.80 List.426 List.427 List.428 List.500 List.501;
|
||||||
|
ret List.499;
|
||||||
|
|
||||||
procedure Num.19 (#Attr.2, #Attr.3):
|
procedure Num.19 (#Attr.2, #Attr.3):
|
||||||
let Num.258 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
let Num.258 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||||
ret Num.258;
|
ret Num.258;
|
||||||
|
|
|
@ -21,12 +21,12 @@ procedure Dict.4 (Dict.497):
|
||||||
|
|
||||||
procedure List.11 (List.114, List.115):
|
procedure List.11 (List.114, List.115):
|
||||||
let List.479 : List I8 = CallByName List.68 List.115;
|
let List.479 : List I8 = CallByName List.68 List.115;
|
||||||
let List.478 : List I8 = CallByName List.80 List.114 List.115 List.479;
|
let List.478 : List I8 = CallByName List.81 List.114 List.115 List.479;
|
||||||
ret List.478;
|
ret List.478;
|
||||||
|
|
||||||
procedure List.11 (List.114, List.115):
|
procedure List.11 (List.114, List.115):
|
||||||
let List.491 : List U64 = CallByName List.68 List.115;
|
let List.491 : List U64 = CallByName List.68 List.115;
|
||||||
let List.490 : List U64 = CallByName List.80 List.114 List.115 List.491;
|
let List.490 : List U64 = CallByName List.81 List.114 List.115 List.491;
|
||||||
ret List.490;
|
ret List.490;
|
||||||
|
|
||||||
procedure List.68 (#Attr.2):
|
procedure List.68 (#Attr.2):
|
||||||
|
@ -45,7 +45,7 @@ procedure List.71 (#Attr.2, #Attr.3):
|
||||||
let List.498 : List U64 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3;
|
let List.498 : List U64 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3;
|
||||||
ret List.498;
|
ret List.498;
|
||||||
|
|
||||||
procedure List.80 (List.502, List.503, List.504):
|
procedure List.81 (List.502, List.503, List.504):
|
||||||
joinpoint List.480 List.116 List.117 List.118:
|
joinpoint List.480 List.116 List.117 List.118:
|
||||||
let List.488 : U64 = 0i64;
|
let List.488 : U64 = 0i64;
|
||||||
let List.482 : Int1 = CallByName Num.24 List.117 List.488;
|
let List.482 : Int1 = CallByName Num.24 List.117 List.488;
|
||||||
|
@ -59,7 +59,7 @@ procedure List.80 (List.502, List.503, List.504):
|
||||||
in
|
in
|
||||||
jump List.480 List.502 List.503 List.504;
|
jump List.480 List.502 List.503 List.504;
|
||||||
|
|
||||||
procedure List.80 (List.510, List.511, List.512):
|
procedure List.81 (List.510, List.511, List.512):
|
||||||
joinpoint List.492 List.116 List.117 List.118:
|
joinpoint List.492 List.116 List.117 List.118:
|
||||||
let List.500 : U64 = 0i64;
|
let List.500 : U64 = 0i64;
|
||||||
let List.494 : Int1 = CallByName Num.24 List.117 List.500;
|
let List.494 : Int1 = CallByName Num.24 List.117 List.500;
|
||||||
|
|
|
@ -213,11 +213,11 @@ procedure List.138 (List.139, List.140, List.137):
|
||||||
ret List.592;
|
ret List.592;
|
||||||
|
|
||||||
procedure List.18 (List.135, List.136, List.137):
|
procedure List.18 (List.135, List.136, List.137):
|
||||||
let List.500 : {List U8, U64} = CallByName List.90 List.135 List.136 List.137;
|
let List.500 : {List U8, U64} = CallByName List.91 List.135 List.136 List.137;
|
||||||
ret List.500;
|
ret List.500;
|
||||||
|
|
||||||
procedure List.18 (List.135, List.136, List.137):
|
procedure List.18 (List.135, List.136, List.137):
|
||||||
let List.573 : {List U8, U64} = CallByName List.90 List.135 List.136 List.137;
|
let List.573 : {List U8, U64} = CallByName List.91 List.135 List.136 List.137;
|
||||||
ret List.573;
|
ret List.573;
|
||||||
|
|
||||||
procedure List.4 (List.106, List.107):
|
procedure List.4 (List.106, List.107):
|
||||||
|
@ -258,19 +258,7 @@ procedure List.8 (#Attr.2, #Attr.3):
|
||||||
let List.594 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3;
|
let List.594 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3;
|
||||||
ret List.594;
|
ret List.594;
|
||||||
|
|
||||||
procedure List.90 (List.426, List.427, List.428):
|
procedure List.80 (List.531, List.532, List.533, List.534, List.535):
|
||||||
let List.504 : U64 = 0i64;
|
|
||||||
let List.505 : U64 = CallByName List.6 List.426;
|
|
||||||
let List.503 : {List U8, U64} = CallByName List.91 List.426 List.427 List.428 List.504 List.505;
|
|
||||||
ret List.503;
|
|
||||||
|
|
||||||
procedure List.90 (List.426, List.427, List.428):
|
|
||||||
let List.577 : U64 = 0i64;
|
|
||||||
let List.578 : U64 = CallByName List.6 List.426;
|
|
||||||
let List.576 : {List U8, U64} = CallByName List.91 List.426 List.427 List.428 List.577 List.578;
|
|
||||||
ret List.576;
|
|
||||||
|
|
||||||
procedure List.91 (List.531, List.532, List.533, List.534, List.535):
|
|
||||||
joinpoint List.506 List.429 List.430 List.431 List.432 List.433:
|
joinpoint List.506 List.429 List.430 List.431 List.432 List.433:
|
||||||
let List.508 : Int1 = CallByName Num.22 List.432 List.433;
|
let List.508 : Int1 = CallByName Num.22 List.432 List.433;
|
||||||
if List.508 then
|
if List.508 then
|
||||||
|
@ -284,7 +272,7 @@ procedure List.91 (List.531, List.532, List.533, List.534, List.535):
|
||||||
in
|
in
|
||||||
jump List.506 List.531 List.532 List.533 List.534 List.535;
|
jump List.506 List.531 List.532 List.533 List.534 List.535;
|
||||||
|
|
||||||
procedure List.91 (List.605, List.606, List.607, List.608, List.609):
|
procedure List.80 (List.605, List.606, List.607, List.608, List.609):
|
||||||
joinpoint List.579 List.429 List.430 List.431 List.432 List.433:
|
joinpoint List.579 List.429 List.430 List.431 List.432 List.433:
|
||||||
let List.581 : Int1 = CallByName Num.22 List.432 List.433;
|
let List.581 : Int1 = CallByName Num.22 List.432 List.433;
|
||||||
if List.581 then
|
if List.581 then
|
||||||
|
@ -298,6 +286,18 @@ procedure List.91 (List.605, List.606, List.607, List.608, List.609):
|
||||||
in
|
in
|
||||||
jump List.579 List.605 List.606 List.607 List.608 List.609;
|
jump List.579 List.605 List.606 List.607 List.608 List.609;
|
||||||
|
|
||||||
|
procedure List.91 (List.426, List.427, List.428):
|
||||||
|
let List.504 : U64 = 0i64;
|
||||||
|
let List.505 : U64 = CallByName List.6 List.426;
|
||||||
|
let List.503 : {List U8, U64} = CallByName List.80 List.426 List.427 List.428 List.504 List.505;
|
||||||
|
ret List.503;
|
||||||
|
|
||||||
|
procedure List.91 (List.426, List.427, List.428):
|
||||||
|
let List.577 : U64 = 0i64;
|
||||||
|
let List.578 : U64 = CallByName List.6 List.426;
|
||||||
|
let List.576 : {List U8, U64} = CallByName List.80 List.426 List.427 List.428 List.577 List.578;
|
||||||
|
ret List.576;
|
||||||
|
|
||||||
procedure Num.125 (#Attr.2):
|
procedure Num.125 (#Attr.2):
|
||||||
let Num.282 : U8 = lowlevel NumIntCast #Attr.2;
|
let Num.282 : U8 = lowlevel NumIntCast #Attr.2;
|
||||||
ret Num.282;
|
ret Num.282;
|
||||||
|
|
|
@ -122,7 +122,7 @@ procedure List.138 (List.139, List.140, List.137):
|
||||||
ret List.525;
|
ret List.525;
|
||||||
|
|
||||||
procedure List.18 (List.135, List.136, List.137):
|
procedure List.18 (List.135, List.136, List.137):
|
||||||
let List.506 : {List U8, U64} = CallByName List.90 List.135 List.136 List.137;
|
let List.506 : {List U8, U64} = CallByName List.91 List.135 List.136 List.137;
|
||||||
ret List.506;
|
ret List.506;
|
||||||
|
|
||||||
procedure List.4 (List.106, List.107):
|
procedure List.4 (List.106, List.107):
|
||||||
|
@ -155,13 +155,7 @@ procedure List.8 (#Attr.2, #Attr.3):
|
||||||
let List.527 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3;
|
let List.527 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3;
|
||||||
ret List.527;
|
ret List.527;
|
||||||
|
|
||||||
procedure List.90 (List.426, List.427, List.428):
|
procedure List.80 (List.538, List.539, List.540, List.541, List.542):
|
||||||
let List.510 : U64 = 0i64;
|
|
||||||
let List.511 : U64 = CallByName List.6 List.426;
|
|
||||||
let List.509 : {List U8, U64} = CallByName List.91 List.426 List.427 List.428 List.510 List.511;
|
|
||||||
ret List.509;
|
|
||||||
|
|
||||||
procedure List.91 (List.538, List.539, List.540, List.541, List.542):
|
|
||||||
joinpoint List.512 List.429 List.430 List.431 List.432 List.433:
|
joinpoint List.512 List.429 List.430 List.431 List.432 List.433:
|
||||||
let List.514 : Int1 = CallByName Num.22 List.432 List.433;
|
let List.514 : Int1 = CallByName Num.22 List.432 List.433;
|
||||||
if List.514 then
|
if List.514 then
|
||||||
|
@ -175,6 +169,12 @@ procedure List.91 (List.538, List.539, List.540, List.541, List.542):
|
||||||
in
|
in
|
||||||
jump List.512 List.538 List.539 List.540 List.541 List.542;
|
jump List.512 List.538 List.539 List.540 List.541 List.542;
|
||||||
|
|
||||||
|
procedure List.91 (List.426, List.427, List.428):
|
||||||
|
let List.510 : U64 = 0i64;
|
||||||
|
let List.511 : U64 = CallByName List.6 List.426;
|
||||||
|
let List.509 : {List U8, U64} = CallByName List.80 List.426 List.427 List.428 List.510 List.511;
|
||||||
|
ret List.509;
|
||||||
|
|
||||||
procedure Num.125 (#Attr.2):
|
procedure Num.125 (#Attr.2):
|
||||||
let Num.263 : U8 = lowlevel NumIntCast #Attr.2;
|
let Num.263 : U8 = lowlevel NumIntCast #Attr.2;
|
||||||
ret Num.263;
|
ret Num.263;
|
||||||
|
|
|
@ -130,7 +130,7 @@ procedure List.138 (List.139, List.140, List.137):
|
||||||
ret List.525;
|
ret List.525;
|
||||||
|
|
||||||
procedure List.18 (List.135, List.136, List.137):
|
procedure List.18 (List.135, List.136, List.137):
|
||||||
let List.506 : {List U8, U64} = CallByName List.90 List.135 List.136 List.137;
|
let List.506 : {List U8, U64} = CallByName List.91 List.135 List.136 List.137;
|
||||||
ret List.506;
|
ret List.506;
|
||||||
|
|
||||||
procedure List.4 (List.106, List.107):
|
procedure List.4 (List.106, List.107):
|
||||||
|
@ -163,13 +163,7 @@ procedure List.8 (#Attr.2, #Attr.3):
|
||||||
let List.527 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3;
|
let List.527 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3;
|
||||||
ret List.527;
|
ret List.527;
|
||||||
|
|
||||||
procedure List.90 (List.426, List.427, List.428):
|
procedure List.80 (List.538, List.539, List.540, List.541, List.542):
|
||||||
let List.510 : U64 = 0i64;
|
|
||||||
let List.511 : U64 = CallByName List.6 List.426;
|
|
||||||
let List.509 : {List U8, U64} = CallByName List.91 List.426 List.427 List.428 List.510 List.511;
|
|
||||||
ret List.509;
|
|
||||||
|
|
||||||
procedure List.91 (List.538, List.539, List.540, List.541, List.542):
|
|
||||||
joinpoint List.512 List.429 List.430 List.431 List.432 List.433:
|
joinpoint List.512 List.429 List.430 List.431 List.432 List.433:
|
||||||
let List.514 : Int1 = CallByName Num.22 List.432 List.433;
|
let List.514 : Int1 = CallByName Num.22 List.432 List.433;
|
||||||
if List.514 then
|
if List.514 then
|
||||||
|
@ -183,6 +177,12 @@ procedure List.91 (List.538, List.539, List.540, List.541, List.542):
|
||||||
in
|
in
|
||||||
jump List.512 List.538 List.539 List.540 List.541 List.542;
|
jump List.512 List.538 List.539 List.540 List.541 List.542;
|
||||||
|
|
||||||
|
procedure List.91 (List.426, List.427, List.428):
|
||||||
|
let List.510 : U64 = 0i64;
|
||||||
|
let List.511 : U64 = CallByName List.6 List.426;
|
||||||
|
let List.509 : {List U8, U64} = CallByName List.80 List.426 List.427 List.428 List.510 List.511;
|
||||||
|
ret List.509;
|
||||||
|
|
||||||
procedure Num.125 (#Attr.2):
|
procedure Num.125 (#Attr.2):
|
||||||
let Num.263 : U8 = lowlevel NumIntCast #Attr.2;
|
let Num.263 : U8 = lowlevel NumIntCast #Attr.2;
|
||||||
ret Num.263;
|
ret Num.263;
|
||||||
|
|
|
@ -131,7 +131,7 @@ procedure List.138 (List.139, List.140, List.137):
|
||||||
ret List.531;
|
ret List.531;
|
||||||
|
|
||||||
procedure List.18 (List.135, List.136, List.137):
|
procedure List.18 (List.135, List.136, List.137):
|
||||||
let List.512 : {List U8, U64} = CallByName List.90 List.135 List.136 List.137;
|
let List.512 : {List U8, U64} = CallByName List.91 List.135 List.136 List.137;
|
||||||
ret List.512;
|
ret List.512;
|
||||||
|
|
||||||
procedure List.4 (List.106, List.107):
|
procedure List.4 (List.106, List.107):
|
||||||
|
@ -164,13 +164,7 @@ procedure List.8 (#Attr.2, #Attr.3):
|
||||||
let List.534 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3;
|
let List.534 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3;
|
||||||
ret List.534;
|
ret List.534;
|
||||||
|
|
||||||
procedure List.90 (List.426, List.427, List.428):
|
procedure List.80 (List.544, List.545, List.546, List.547, List.548):
|
||||||
let List.516 : U64 = 0i64;
|
|
||||||
let List.517 : U64 = CallByName List.6 List.426;
|
|
||||||
let List.515 : {List U8, U64} = CallByName List.91 List.426 List.427 List.428 List.516 List.517;
|
|
||||||
ret List.515;
|
|
||||||
|
|
||||||
procedure List.91 (List.544, List.545, List.546, List.547, List.548):
|
|
||||||
joinpoint List.518 List.429 List.430 List.431 List.432 List.433:
|
joinpoint List.518 List.429 List.430 List.431 List.432 List.433:
|
||||||
let List.520 : Int1 = CallByName Num.22 List.432 List.433;
|
let List.520 : Int1 = CallByName Num.22 List.432 List.433;
|
||||||
if List.520 then
|
if List.520 then
|
||||||
|
@ -184,6 +178,12 @@ procedure List.91 (List.544, List.545, List.546, List.547, List.548):
|
||||||
in
|
in
|
||||||
jump List.518 List.544 List.545 List.546 List.547 List.548;
|
jump List.518 List.544 List.545 List.546 List.547 List.548;
|
||||||
|
|
||||||
|
procedure List.91 (List.426, List.427, List.428):
|
||||||
|
let List.516 : U64 = 0i64;
|
||||||
|
let List.517 : U64 = CallByName List.6 List.426;
|
||||||
|
let List.515 : {List U8, U64} = CallByName List.80 List.426 List.427 List.428 List.516 List.517;
|
||||||
|
ret List.515;
|
||||||
|
|
||||||
procedure Num.125 (#Attr.2):
|
procedure Num.125 (#Attr.2):
|
||||||
let Num.265 : U8 = lowlevel NumIntCast #Attr.2;
|
let Num.265 : U8 = lowlevel NumIntCast #Attr.2;
|
||||||
ret Num.265;
|
ret Num.265;
|
||||||
|
|
|
@ -137,7 +137,7 @@ procedure List.138 (List.139, List.140, List.137):
|
||||||
ret List.531;
|
ret List.531;
|
||||||
|
|
||||||
procedure List.18 (List.135, List.136, List.137):
|
procedure List.18 (List.135, List.136, List.137):
|
||||||
let List.512 : {List U8, U64} = CallByName List.90 List.135 List.136 List.137;
|
let List.512 : {List U8, U64} = CallByName List.91 List.135 List.136 List.137;
|
||||||
ret List.512;
|
ret List.512;
|
||||||
|
|
||||||
procedure List.4 (List.106, List.107):
|
procedure List.4 (List.106, List.107):
|
||||||
|
@ -170,13 +170,7 @@ procedure List.8 (#Attr.2, #Attr.3):
|
||||||
let List.534 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3;
|
let List.534 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3;
|
||||||
ret List.534;
|
ret List.534;
|
||||||
|
|
||||||
procedure List.90 (List.426, List.427, List.428):
|
procedure List.80 (List.544, List.545, List.546, List.547, List.548):
|
||||||
let List.516 : U64 = 0i64;
|
|
||||||
let List.517 : U64 = CallByName List.6 List.426;
|
|
||||||
let List.515 : {List U8, U64} = CallByName List.91 List.426 List.427 List.428 List.516 List.517;
|
|
||||||
ret List.515;
|
|
||||||
|
|
||||||
procedure List.91 (List.544, List.545, List.546, List.547, List.548):
|
|
||||||
joinpoint List.518 List.429 List.430 List.431 List.432 List.433:
|
joinpoint List.518 List.429 List.430 List.431 List.432 List.433:
|
||||||
let List.520 : Int1 = CallByName Num.22 List.432 List.433;
|
let List.520 : Int1 = CallByName Num.22 List.432 List.433;
|
||||||
if List.520 then
|
if List.520 then
|
||||||
|
@ -190,6 +184,12 @@ procedure List.91 (List.544, List.545, List.546, List.547, List.548):
|
||||||
in
|
in
|
||||||
jump List.518 List.544 List.545 List.546 List.547 List.548;
|
jump List.518 List.544 List.545 List.546 List.547 List.548;
|
||||||
|
|
||||||
|
procedure List.91 (List.426, List.427, List.428):
|
||||||
|
let List.516 : U64 = 0i64;
|
||||||
|
let List.517 : U64 = CallByName List.6 List.426;
|
||||||
|
let List.515 : {List U8, U64} = CallByName List.80 List.426 List.427 List.428 List.516 List.517;
|
||||||
|
ret List.515;
|
||||||
|
|
||||||
procedure Num.125 (#Attr.2):
|
procedure Num.125 (#Attr.2):
|
||||||
let Num.265 : U8 = lowlevel NumIntCast #Attr.2;
|
let Num.265 : U8 = lowlevel NumIntCast #Attr.2;
|
||||||
ret Num.265;
|
ret Num.265;
|
||||||
|
|
|
@ -0,0 +1,235 @@
|
||||||
|
procedure Bool.2 ():
|
||||||
|
let Bool.23 : Int1 = true;
|
||||||
|
ret Bool.23;
|
||||||
|
|
||||||
|
procedure Encode.22 (Encode.93):
|
||||||
|
ret Encode.93;
|
||||||
|
|
||||||
|
procedure Encode.22 (Encode.93):
|
||||||
|
ret Encode.93;
|
||||||
|
|
||||||
|
procedure Encode.22 (Encode.93):
|
||||||
|
ret Encode.93;
|
||||||
|
|
||||||
|
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
|
||||||
|
let Encode.106 : List U8 = CallByName Test.5 Encode.94 Encode.96 Encode.102;
|
||||||
|
ret Encode.106;
|
||||||
|
|
||||||
|
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
|
||||||
|
let Encode.113 : List U8 = CallByName Json.126 Encode.94 Encode.96 Encode.102;
|
||||||
|
ret Encode.113;
|
||||||
|
|
||||||
|
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
|
||||||
|
let Encode.118 : List U8 = CallByName Json.96 Encode.94 Encode.96 Encode.102;
|
||||||
|
ret Encode.118;
|
||||||
|
|
||||||
|
procedure Encode.25 (Encode.100, Encode.101):
|
||||||
|
let Encode.104 : List U8 = Array [];
|
||||||
|
let Encode.105 : {Str, Str} = CallByName Test.2 Encode.100;
|
||||||
|
let Encode.103 : List U8 = CallByName Encode.23 Encode.104 Encode.105 Encode.101;
|
||||||
|
ret Encode.103;
|
||||||
|
|
||||||
|
procedure Json.1 ():
|
||||||
|
let Json.396 : {} = Struct {};
|
||||||
|
ret Json.396;
|
||||||
|
|
||||||
|
procedure Json.126 (Json.127, Json.399, #Attr.12):
|
||||||
|
let Json.125 : List Str = StructAtIndex 1 #Attr.12;
|
||||||
|
inc Json.125;
|
||||||
|
let Json.124 : Str = StructAtIndex 0 #Attr.12;
|
||||||
|
inc Json.124;
|
||||||
|
dec #Attr.12;
|
||||||
|
let Json.437 : I64 = 123i64;
|
||||||
|
let Json.436 : U8 = CallByName Num.125 Json.437;
|
||||||
|
let Json.433 : List U8 = CallByName List.4 Json.127 Json.436;
|
||||||
|
let Json.435 : I64 = 34i64;
|
||||||
|
let Json.434 : U8 = CallByName Num.125 Json.435;
|
||||||
|
let Json.431 : List U8 = CallByName List.4 Json.433 Json.434;
|
||||||
|
let Json.432 : List U8 = CallByName Str.12 Json.124;
|
||||||
|
let Json.428 : List U8 = CallByName List.8 Json.431 Json.432;
|
||||||
|
let Json.430 : I64 = 34i64;
|
||||||
|
let Json.429 : U8 = CallByName Num.125 Json.430;
|
||||||
|
let Json.425 : List U8 = CallByName List.4 Json.428 Json.429;
|
||||||
|
let Json.427 : I64 = 58i64;
|
||||||
|
let Json.426 : U8 = CallByName Num.125 Json.427;
|
||||||
|
let Json.422 : List U8 = CallByName List.4 Json.425 Json.426;
|
||||||
|
let Json.424 : I64 = 91i64;
|
||||||
|
let Json.423 : U8 = CallByName Num.125 Json.424;
|
||||||
|
let Json.129 : List U8 = CallByName List.4 Json.422 Json.423;
|
||||||
|
let Json.421 : U64 = CallByName List.6 Json.125;
|
||||||
|
let Json.409 : {List U8, U64} = Struct {Json.129, Json.421};
|
||||||
|
let Json.410 : {} = Struct {};
|
||||||
|
let Json.408 : {List U8, U64} = CallByName List.18 Json.125 Json.409 Json.410;
|
||||||
|
dec Json.125;
|
||||||
|
let Json.131 : List U8 = StructAtIndex 0 Json.408;
|
||||||
|
inc Json.131;
|
||||||
|
dec Json.408;
|
||||||
|
let Json.407 : I64 = 93i64;
|
||||||
|
let Json.406 : U8 = CallByName Num.125 Json.407;
|
||||||
|
let Json.403 : List U8 = CallByName List.4 Json.131 Json.406;
|
||||||
|
let Json.405 : I64 = 125i64;
|
||||||
|
let Json.404 : U8 = CallByName Num.125 Json.405;
|
||||||
|
let Json.402 : List U8 = CallByName List.4 Json.403 Json.404;
|
||||||
|
ret Json.402;
|
||||||
|
|
||||||
|
procedure Json.128 (Json.401, Json.134):
|
||||||
|
let Json.132 : List U8 = StructAtIndex 0 Json.401;
|
||||||
|
inc Json.132;
|
||||||
|
let Json.133 : U64 = StructAtIndex 1 Json.401;
|
||||||
|
dec Json.401;
|
||||||
|
let Json.420 : {} = Struct {};
|
||||||
|
let Json.135 : List U8 = CallByName Encode.23 Json.132 Json.134 Json.420;
|
||||||
|
joinpoint Json.415 Json.136:
|
||||||
|
let Json.413 : U64 = 1i64;
|
||||||
|
let Json.412 : U64 = CallByName Num.20 Json.133 Json.413;
|
||||||
|
let Json.411 : {List U8, U64} = Struct {Json.136, Json.412};
|
||||||
|
ret Json.411;
|
||||||
|
in
|
||||||
|
let Json.419 : U64 = 1i64;
|
||||||
|
let Json.416 : Int1 = CallByName Num.24 Json.133 Json.419;
|
||||||
|
if Json.416 then
|
||||||
|
let Json.418 : I64 = 44i64;
|
||||||
|
let Json.417 : U8 = CallByName Num.125 Json.418;
|
||||||
|
let Json.414 : List U8 = CallByName List.4 Json.135 Json.417;
|
||||||
|
jump Json.415 Json.414;
|
||||||
|
else
|
||||||
|
jump Json.415 Json.135;
|
||||||
|
|
||||||
|
procedure Json.18 (Json.95):
|
||||||
|
let Json.453 : Str = CallByName Encode.22 Json.95;
|
||||||
|
ret Json.453;
|
||||||
|
|
||||||
|
procedure Json.21 (Json.124, Json.125):
|
||||||
|
let Json.439 : {Str, List Str} = Struct {Json.124, Json.125};
|
||||||
|
let Json.438 : {Str, List Str} = CallByName Encode.22 Json.439;
|
||||||
|
ret Json.438;
|
||||||
|
|
||||||
|
procedure Json.96 (Json.97, Json.443, Json.95):
|
||||||
|
let Json.452 : I64 = 34i64;
|
||||||
|
let Json.451 : U8 = CallByName Num.125 Json.452;
|
||||||
|
let Json.449 : List U8 = CallByName List.4 Json.97 Json.451;
|
||||||
|
let Json.450 : List U8 = CallByName Str.12 Json.95;
|
||||||
|
let Json.446 : List U8 = CallByName List.8 Json.449 Json.450;
|
||||||
|
let Json.448 : I64 = 34i64;
|
||||||
|
let Json.447 : U8 = CallByName Num.125 Json.448;
|
||||||
|
let Json.445 : List U8 = CallByName List.4 Json.446 Json.447;
|
||||||
|
ret Json.445;
|
||||||
|
|
||||||
|
procedure List.138 (List.139, List.140, List.137):
|
||||||
|
let List.529 : {List U8, U64} = CallByName Json.128 List.139 List.140;
|
||||||
|
ret List.529;
|
||||||
|
|
||||||
|
procedure List.18 (List.135, List.136, List.137):
|
||||||
|
let List.510 : {List U8, U64} = CallByName List.91 List.135 List.136 List.137;
|
||||||
|
ret List.510;
|
||||||
|
|
||||||
|
procedure List.4 (List.106, List.107):
|
||||||
|
let List.509 : U64 = 1i64;
|
||||||
|
let List.508 : List U8 = CallByName List.70 List.106 List.509;
|
||||||
|
let List.507 : List U8 = CallByName List.71 List.508 List.107;
|
||||||
|
ret List.507;
|
||||||
|
|
||||||
|
procedure List.6 (#Attr.2):
|
||||||
|
let List.530 : U64 = lowlevel ListLen #Attr.2;
|
||||||
|
ret List.530;
|
||||||
|
|
||||||
|
procedure List.66 (#Attr.2, #Attr.3):
|
||||||
|
let List.526 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
|
||||||
|
ret List.526;
|
||||||
|
|
||||||
|
procedure List.70 (#Attr.2, #Attr.3):
|
||||||
|
let List.482 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3;
|
||||||
|
ret List.482;
|
||||||
|
|
||||||
|
procedure List.71 (#Attr.2, #Attr.3):
|
||||||
|
let List.480 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3;
|
||||||
|
ret List.480;
|
||||||
|
|
||||||
|
procedure List.8 (#Attr.2, #Attr.3):
|
||||||
|
let List.532 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3;
|
||||||
|
ret List.532;
|
||||||
|
|
||||||
|
procedure List.80 (List.542, List.543, List.544, List.545, List.546):
|
||||||
|
joinpoint List.516 List.429 List.430 List.431 List.432 List.433:
|
||||||
|
let List.518 : Int1 = CallByName Num.22 List.432 List.433;
|
||||||
|
if List.518 then
|
||||||
|
let List.525 : Str = CallByName List.66 List.429 List.432;
|
||||||
|
let List.519 : {List U8, U64} = CallByName List.138 List.430 List.525 List.431;
|
||||||
|
let List.522 : U64 = 1i64;
|
||||||
|
let List.521 : U64 = CallByName Num.19 List.432 List.522;
|
||||||
|
jump List.516 List.429 List.519 List.431 List.521 List.433;
|
||||||
|
else
|
||||||
|
ret List.430;
|
||||||
|
in
|
||||||
|
jump List.516 List.542 List.543 List.544 List.545 List.546;
|
||||||
|
|
||||||
|
procedure List.91 (List.426, List.427, List.428):
|
||||||
|
let List.514 : U64 = 0i64;
|
||||||
|
let List.515 : U64 = CallByName List.6 List.426;
|
||||||
|
let List.513 : {List U8, U64} = CallByName List.80 List.426 List.427 List.428 List.514 List.515;
|
||||||
|
ret List.513;
|
||||||
|
|
||||||
|
procedure Num.125 (#Attr.2):
|
||||||
|
let Num.265 : U8 = lowlevel NumIntCast #Attr.2;
|
||||||
|
ret Num.265;
|
||||||
|
|
||||||
|
procedure Num.19 (#Attr.2, #Attr.3):
|
||||||
|
let Num.268 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||||
|
ret Num.268;
|
||||||
|
|
||||||
|
procedure Num.20 (#Attr.2, #Attr.3):
|
||||||
|
let Num.266 : U64 = lowlevel NumSub #Attr.2 #Attr.3;
|
||||||
|
ret Num.266;
|
||||||
|
|
||||||
|
procedure Num.22 (#Attr.2, #Attr.3):
|
||||||
|
let Num.269 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||||
|
ret Num.269;
|
||||||
|
|
||||||
|
procedure Num.24 (#Attr.2, #Attr.3):
|
||||||
|
let Num.267 : Int1 = lowlevel NumGt #Attr.2 #Attr.3;
|
||||||
|
ret Num.267;
|
||||||
|
|
||||||
|
procedure Str.12 (#Attr.2):
|
||||||
|
let Str.266 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||||
|
ret Str.266;
|
||||||
|
|
||||||
|
procedure Test.2 (Test.10):
|
||||||
|
let Test.15 : {Str, Str} = CallByName Encode.22 Test.10;
|
||||||
|
ret Test.15;
|
||||||
|
|
||||||
|
procedure Test.3 ():
|
||||||
|
let Test.9 : Str = "";
|
||||||
|
inc Test.9;
|
||||||
|
let Test.14 : {Str, Str} = Struct {Test.9, Test.9};
|
||||||
|
ret Test.14;
|
||||||
|
|
||||||
|
procedure Test.5 (Test.6, Test.7, Test.4):
|
||||||
|
joinpoint Test.20 Test.8:
|
||||||
|
let Test.18 : List U8 = CallByName Encode.23 Test.6 Test.8 Test.7;
|
||||||
|
ret Test.18;
|
||||||
|
in
|
||||||
|
let Test.25 : Int1 = CallByName Bool.2;
|
||||||
|
if Test.25 then
|
||||||
|
let Test.26 : Str = "A";
|
||||||
|
let Test.29 : Str = StructAtIndex 0 Test.4;
|
||||||
|
inc Test.29;
|
||||||
|
dec Test.4;
|
||||||
|
let Test.28 : Str = CallByName Json.18 Test.29;
|
||||||
|
let Test.27 : List Str = Array [Test.28];
|
||||||
|
let Test.19 : {Str, List Str} = CallByName Json.21 Test.26 Test.27;
|
||||||
|
jump Test.20 Test.19;
|
||||||
|
else
|
||||||
|
let Test.21 : Str = "B";
|
||||||
|
let Test.24 : Str = StructAtIndex 1 Test.4;
|
||||||
|
inc Test.24;
|
||||||
|
dec Test.4;
|
||||||
|
let Test.23 : Str = CallByName Json.18 Test.24;
|
||||||
|
let Test.22 : List Str = Array [Test.23];
|
||||||
|
let Test.19 : {Str, List Str} = CallByName Json.21 Test.21 Test.22;
|
||||||
|
jump Test.20 Test.19;
|
||||||
|
|
||||||
|
procedure Test.0 ():
|
||||||
|
let Test.12 : {Str, Str} = CallByName Test.3;
|
||||||
|
let Test.13 : {} = CallByName Json.1;
|
||||||
|
let Test.11 : List U8 = CallByName Encode.25 Test.12 Test.13;
|
||||||
|
ret Test.11;
|
|
@ -0,0 +1,82 @@
|
||||||
|
procedure Bool.2 ():
|
||||||
|
let Bool.23 : Int1 = true;
|
||||||
|
ret Bool.23;
|
||||||
|
|
||||||
|
procedure Test.12 (Test.52):
|
||||||
|
let Test.75 : Int1 = false;
|
||||||
|
ret Test.75;
|
||||||
|
|
||||||
|
procedure Test.13 (Test.51):
|
||||||
|
let Test.83 : Int1 = true;
|
||||||
|
ret Test.83;
|
||||||
|
|
||||||
|
procedure Test.14 (Test.50):
|
||||||
|
ret Test.50;
|
||||||
|
|
||||||
|
procedure Test.15 (Test.49):
|
||||||
|
let Test.74 : {} = Struct {};
|
||||||
|
let Test.73 : Int1 = CallByName Test.12 Test.74;
|
||||||
|
ret Test.73;
|
||||||
|
|
||||||
|
procedure Test.16 (Test.48):
|
||||||
|
let Test.82 : {} = Struct {};
|
||||||
|
let Test.81 : Int1 = CallByName Test.13 Test.82;
|
||||||
|
ret Test.81;
|
||||||
|
|
||||||
|
procedure Test.17 (Test.47):
|
||||||
|
ret Test.47;
|
||||||
|
|
||||||
|
procedure Test.35 (Test.36, Test.76):
|
||||||
|
inc Test.36;
|
||||||
|
ret Test.36;
|
||||||
|
|
||||||
|
procedure Test.37 (Test.38, Test.84):
|
||||||
|
inc Test.38;
|
||||||
|
ret Test.38;
|
||||||
|
|
||||||
|
procedure Test.40 (Test.41, Test.65, Test.39):
|
||||||
|
let Test.68 : {} = Struct {};
|
||||||
|
joinpoint Test.69 Test.67:
|
||||||
|
ret Test.67;
|
||||||
|
in
|
||||||
|
switch Test.39:
|
||||||
|
case 0:
|
||||||
|
let Test.70 : List U8 = CallByName Test.35 Test.41 Test.68;
|
||||||
|
jump Test.69 Test.70;
|
||||||
|
|
||||||
|
default:
|
||||||
|
let Test.71 : List U8 = CallByName Test.37 Test.41 Test.68;
|
||||||
|
jump Test.69 Test.71;
|
||||||
|
|
||||||
|
|
||||||
|
procedure Test.43 (Test.44, Test.42):
|
||||||
|
joinpoint Test.62 Test.60:
|
||||||
|
let Test.59 : List U8 = Array [];
|
||||||
|
let Test.58 : List U8 = CallByName Test.40 Test.59 Test.44 Test.60;
|
||||||
|
dec Test.59;
|
||||||
|
ret Test.58;
|
||||||
|
in
|
||||||
|
let Test.78 : Int1 = CallByName Bool.2;
|
||||||
|
if Test.78 then
|
||||||
|
let Test.80 : Str = StructAtIndex 0 Test.42;
|
||||||
|
inc Test.80;
|
||||||
|
dec Test.42;
|
||||||
|
let Test.79 : Int1 = CallByName Test.16 Test.80;
|
||||||
|
dec Test.80;
|
||||||
|
let Test.61 : Int1 = CallByName Test.14 Test.79;
|
||||||
|
jump Test.62 Test.61;
|
||||||
|
else
|
||||||
|
let Test.72 : U8 = StructAtIndex 1 Test.42;
|
||||||
|
dec Test.42;
|
||||||
|
let Test.63 : Int1 = CallByName Test.15 Test.72;
|
||||||
|
let Test.61 : Int1 = CallByName Test.14 Test.63;
|
||||||
|
jump Test.62 Test.61;
|
||||||
|
|
||||||
|
procedure Test.0 ():
|
||||||
|
let Test.86 : Str = "";
|
||||||
|
let Test.87 : U8 = 7i64;
|
||||||
|
let Test.55 : {Str, U8} = Struct {Test.86, Test.87};
|
||||||
|
let Test.46 : {Str, U8} = CallByName Test.17 Test.55;
|
||||||
|
let Test.54 : {} = Struct {};
|
||||||
|
let Test.53 : List U8 = CallByName Test.43 Test.54 Test.46;
|
||||||
|
ret Test.53;
|
|
@ -0,0 +1,374 @@
|
||||||
|
procedure #Derived.0 (#Derived.1):
|
||||||
|
let #Derived_gen.10 : [C {}, C {}] = TagId(0) #Derived.1;
|
||||||
|
let #Derived_gen.9 : [C {}, C {}] = CallByName Encode.22 #Derived_gen.10;
|
||||||
|
ret #Derived_gen.9;
|
||||||
|
|
||||||
|
procedure #Derived.2 (#Derived.3, #Derived.4, #Attr.12):
|
||||||
|
let #Derived.1 : {} = UnionAtIndex (Id 0) (Index 0) #Attr.12;
|
||||||
|
joinpoint #Derived_gen.14 #Derived_gen.13:
|
||||||
|
let #Derived_gen.12 : List U8 = CallByName Encode.23 #Derived.3 #Derived_gen.13 #Derived.4;
|
||||||
|
ret #Derived_gen.12;
|
||||||
|
in
|
||||||
|
let #Derived_gen.16 : Str = "A";
|
||||||
|
let #Derived_gen.17 : List [] = Array [];
|
||||||
|
let #Derived_gen.15 : {Str, List []} = CallByName Json.21 #Derived_gen.16 #Derived_gen.17;
|
||||||
|
jump #Derived_gen.14 #Derived_gen.15;
|
||||||
|
|
||||||
|
procedure #Derived.5 (#Derived.6):
|
||||||
|
let #Derived_gen.1 : [C {}, C {}] = TagId(1) #Derived.6;
|
||||||
|
let #Derived_gen.0 : [C {}, C {}] = CallByName Encode.22 #Derived_gen.1;
|
||||||
|
ret #Derived_gen.0;
|
||||||
|
|
||||||
|
procedure #Derived.7 (#Derived.8, #Derived.9, #Attr.12):
|
||||||
|
let #Derived.6 : {} = UnionAtIndex (Id 1) (Index 0) #Attr.12;
|
||||||
|
joinpoint #Derived_gen.5 #Derived_gen.4:
|
||||||
|
let #Derived_gen.3 : List U8 = CallByName Encode.23 #Derived.8 #Derived_gen.4 #Derived.9;
|
||||||
|
ret #Derived_gen.3;
|
||||||
|
in
|
||||||
|
let #Derived_gen.7 : Str = "B";
|
||||||
|
let #Derived_gen.8 : List [] = Array [];
|
||||||
|
let #Derived_gen.6 : {Str, List []} = CallByName Json.21 #Derived_gen.7 #Derived_gen.8;
|
||||||
|
jump #Derived_gen.5 #Derived_gen.6;
|
||||||
|
|
||||||
|
procedure Bool.2 ():
|
||||||
|
let Bool.23 : Int1 = true;
|
||||||
|
ret Bool.23;
|
||||||
|
|
||||||
|
procedure Encode.22 (Encode.93):
|
||||||
|
ret Encode.93;
|
||||||
|
|
||||||
|
procedure Encode.22 (Encode.93):
|
||||||
|
ret Encode.93;
|
||||||
|
|
||||||
|
procedure Encode.22 (Encode.93):
|
||||||
|
ret Encode.93;
|
||||||
|
|
||||||
|
procedure Encode.22 (Encode.93):
|
||||||
|
ret Encode.93;
|
||||||
|
|
||||||
|
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
|
||||||
|
let Encode.106 : List U8 = CallByName Test.5 Encode.94 Encode.96 Encode.102;
|
||||||
|
ret Encode.106;
|
||||||
|
|
||||||
|
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
|
||||||
|
let Encode.113 : List U8 = CallByName Json.126 Encode.94 Encode.96 Encode.102;
|
||||||
|
ret Encode.113;
|
||||||
|
|
||||||
|
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
|
||||||
|
let Encode.117 : U8 = GetTagId Encode.102;
|
||||||
|
joinpoint Encode.118 Encode.116:
|
||||||
|
ret Encode.116;
|
||||||
|
in
|
||||||
|
switch Encode.117:
|
||||||
|
case 0:
|
||||||
|
let Encode.119 : List U8 = CallByName #Derived.2 Encode.94 Encode.96 Encode.102;
|
||||||
|
jump Encode.118 Encode.119;
|
||||||
|
|
||||||
|
default:
|
||||||
|
let Encode.120 : List U8 = CallByName #Derived.7 Encode.94 Encode.96 Encode.102;
|
||||||
|
jump Encode.118 Encode.120;
|
||||||
|
|
||||||
|
|
||||||
|
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
|
||||||
|
let Encode.132 : List U8 = CallByName Json.126 Encode.94 Encode.96 Encode.102;
|
||||||
|
ret Encode.132;
|
||||||
|
|
||||||
|
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
|
||||||
|
let Encode.136 : Str = "a Lambda Set is empty. Most likely there is a type error in your program.";
|
||||||
|
Crash Encode.136
|
||||||
|
|
||||||
|
procedure Encode.25 (Encode.100, Encode.101):
|
||||||
|
let Encode.104 : List U8 = Array [];
|
||||||
|
let Encode.105 : {{}, {}} = CallByName Test.2 Encode.100;
|
||||||
|
let Encode.103 : List U8 = CallByName Encode.23 Encode.104 Encode.105 Encode.101;
|
||||||
|
ret Encode.103;
|
||||||
|
|
||||||
|
procedure Json.1 ():
|
||||||
|
let Json.396 : {} = Struct {};
|
||||||
|
ret Json.396;
|
||||||
|
|
||||||
|
procedure Json.126 (Json.127, Json.399, #Attr.12):
|
||||||
|
let Json.125 : List [C {}, C {}] = StructAtIndex 1 #Attr.12;
|
||||||
|
inc Json.125;
|
||||||
|
let Json.124 : Str = StructAtIndex 0 #Attr.12;
|
||||||
|
inc Json.124;
|
||||||
|
dec #Attr.12;
|
||||||
|
let Json.437 : I64 = 123i64;
|
||||||
|
let Json.436 : U8 = CallByName Num.125 Json.437;
|
||||||
|
let Json.433 : List U8 = CallByName List.4 Json.127 Json.436;
|
||||||
|
let Json.435 : I64 = 34i64;
|
||||||
|
let Json.434 : U8 = CallByName Num.125 Json.435;
|
||||||
|
let Json.431 : List U8 = CallByName List.4 Json.433 Json.434;
|
||||||
|
let Json.432 : List U8 = CallByName Str.12 Json.124;
|
||||||
|
let Json.428 : List U8 = CallByName List.8 Json.431 Json.432;
|
||||||
|
let Json.430 : I64 = 34i64;
|
||||||
|
let Json.429 : U8 = CallByName Num.125 Json.430;
|
||||||
|
let Json.425 : List U8 = CallByName List.4 Json.428 Json.429;
|
||||||
|
let Json.427 : I64 = 58i64;
|
||||||
|
let Json.426 : U8 = CallByName Num.125 Json.427;
|
||||||
|
let Json.422 : List U8 = CallByName List.4 Json.425 Json.426;
|
||||||
|
let Json.424 : I64 = 91i64;
|
||||||
|
let Json.423 : U8 = CallByName Num.125 Json.424;
|
||||||
|
let Json.129 : List U8 = CallByName List.4 Json.422 Json.423;
|
||||||
|
let Json.421 : U64 = CallByName List.6 Json.125;
|
||||||
|
let Json.409 : {List U8, U64} = Struct {Json.129, Json.421};
|
||||||
|
let Json.410 : {} = Struct {};
|
||||||
|
let Json.408 : {List U8, U64} = CallByName List.18 Json.125 Json.409 Json.410;
|
||||||
|
dec Json.125;
|
||||||
|
let Json.131 : List U8 = StructAtIndex 0 Json.408;
|
||||||
|
inc Json.131;
|
||||||
|
dec Json.408;
|
||||||
|
let Json.407 : I64 = 93i64;
|
||||||
|
let Json.406 : U8 = CallByName Num.125 Json.407;
|
||||||
|
let Json.403 : List U8 = CallByName List.4 Json.131 Json.406;
|
||||||
|
let Json.405 : I64 = 125i64;
|
||||||
|
let Json.404 : U8 = CallByName Num.125 Json.405;
|
||||||
|
let Json.402 : List U8 = CallByName List.4 Json.403 Json.404;
|
||||||
|
ret Json.402;
|
||||||
|
|
||||||
|
procedure Json.126 (Json.127, Json.399, #Attr.12):
|
||||||
|
let Json.125 : List [] = StructAtIndex 1 #Attr.12;
|
||||||
|
inc Json.125;
|
||||||
|
let Json.124 : Str = StructAtIndex 0 #Attr.12;
|
||||||
|
inc Json.124;
|
||||||
|
dec #Attr.12;
|
||||||
|
let Json.487 : I64 = 123i64;
|
||||||
|
let Json.486 : U8 = CallByName Num.125 Json.487;
|
||||||
|
let Json.483 : List U8 = CallByName List.4 Json.127 Json.486;
|
||||||
|
let Json.485 : I64 = 34i64;
|
||||||
|
let Json.484 : U8 = CallByName Num.125 Json.485;
|
||||||
|
let Json.481 : List U8 = CallByName List.4 Json.483 Json.484;
|
||||||
|
let Json.482 : List U8 = CallByName Str.12 Json.124;
|
||||||
|
let Json.478 : List U8 = CallByName List.8 Json.481 Json.482;
|
||||||
|
let Json.480 : I64 = 34i64;
|
||||||
|
let Json.479 : U8 = CallByName Num.125 Json.480;
|
||||||
|
let Json.475 : List U8 = CallByName List.4 Json.478 Json.479;
|
||||||
|
let Json.477 : I64 = 58i64;
|
||||||
|
let Json.476 : U8 = CallByName Num.125 Json.477;
|
||||||
|
let Json.472 : List U8 = CallByName List.4 Json.475 Json.476;
|
||||||
|
let Json.474 : I64 = 91i64;
|
||||||
|
let Json.473 : U8 = CallByName Num.125 Json.474;
|
||||||
|
let Json.129 : List U8 = CallByName List.4 Json.472 Json.473;
|
||||||
|
let Json.471 : U64 = CallByName List.6 Json.125;
|
||||||
|
let Json.459 : {List U8, U64} = Struct {Json.129, Json.471};
|
||||||
|
let Json.460 : {} = Struct {};
|
||||||
|
let Json.458 : {List U8, U64} = CallByName List.18 Json.125 Json.459 Json.460;
|
||||||
|
dec Json.125;
|
||||||
|
let Json.131 : List U8 = StructAtIndex 0 Json.458;
|
||||||
|
inc Json.131;
|
||||||
|
dec Json.458;
|
||||||
|
let Json.457 : I64 = 93i64;
|
||||||
|
let Json.456 : U8 = CallByName Num.125 Json.457;
|
||||||
|
let Json.453 : List U8 = CallByName List.4 Json.131 Json.456;
|
||||||
|
let Json.455 : I64 = 125i64;
|
||||||
|
let Json.454 : U8 = CallByName Num.125 Json.455;
|
||||||
|
let Json.452 : List U8 = CallByName List.4 Json.453 Json.454;
|
||||||
|
ret Json.452;
|
||||||
|
|
||||||
|
procedure Json.128 (Json.401, Json.134):
|
||||||
|
let Json.132 : List U8 = StructAtIndex 0 Json.401;
|
||||||
|
inc Json.132;
|
||||||
|
let Json.133 : U64 = StructAtIndex 1 Json.401;
|
||||||
|
dec Json.401;
|
||||||
|
let Json.420 : {} = Struct {};
|
||||||
|
let Json.135 : List U8 = CallByName Encode.23 Json.132 Json.134 Json.420;
|
||||||
|
joinpoint Json.415 Json.136:
|
||||||
|
let Json.413 : U64 = 1i64;
|
||||||
|
let Json.412 : U64 = CallByName Num.20 Json.133 Json.413;
|
||||||
|
let Json.411 : {List U8, U64} = Struct {Json.136, Json.412};
|
||||||
|
ret Json.411;
|
||||||
|
in
|
||||||
|
let Json.419 : U64 = 1i64;
|
||||||
|
let Json.416 : Int1 = CallByName Num.24 Json.133 Json.419;
|
||||||
|
if Json.416 then
|
||||||
|
let Json.418 : I64 = 44i64;
|
||||||
|
let Json.417 : U8 = CallByName Num.125 Json.418;
|
||||||
|
let Json.414 : List U8 = CallByName List.4 Json.135 Json.417;
|
||||||
|
jump Json.415 Json.414;
|
||||||
|
else
|
||||||
|
jump Json.415 Json.135;
|
||||||
|
|
||||||
|
procedure Json.128 (Json.401, Json.134):
|
||||||
|
let Json.132 : List U8 = StructAtIndex 0 Json.401;
|
||||||
|
inc Json.132;
|
||||||
|
let Json.133 : U64 = StructAtIndex 1 Json.401;
|
||||||
|
dec Json.401;
|
||||||
|
let Json.470 : {} = Struct {};
|
||||||
|
let Json.135 : List U8 = CallByName Encode.23 Json.132 Json.134 Json.470;
|
||||||
|
dec Json.132;
|
||||||
|
joinpoint Json.465 Json.136:
|
||||||
|
let Json.463 : U64 = 1i64;
|
||||||
|
let Json.462 : U64 = CallByName Num.20 Json.133 Json.463;
|
||||||
|
let Json.461 : {List U8, U64} = Struct {Json.136, Json.462};
|
||||||
|
ret Json.461;
|
||||||
|
in
|
||||||
|
let Json.469 : U64 = 1i64;
|
||||||
|
let Json.466 : Int1 = CallByName Num.24 Json.133 Json.469;
|
||||||
|
if Json.466 then
|
||||||
|
let Json.468 : I64 = 44i64;
|
||||||
|
let Json.467 : U8 = CallByName Num.125 Json.468;
|
||||||
|
let Json.464 : List U8 = CallByName List.4 Json.135 Json.467;
|
||||||
|
jump Json.465 Json.464;
|
||||||
|
else
|
||||||
|
jump Json.465 Json.135;
|
||||||
|
|
||||||
|
procedure Json.21 (Json.124, Json.125):
|
||||||
|
let Json.439 : {Str, List [C {}, C {}]} = Struct {Json.124, Json.125};
|
||||||
|
let Json.438 : {Str, List [C {}, C {}]} = CallByName Encode.22 Json.439;
|
||||||
|
ret Json.438;
|
||||||
|
|
||||||
|
procedure Json.21 (Json.124, Json.125):
|
||||||
|
let Json.489 : {Str, List []} = Struct {Json.124, Json.125};
|
||||||
|
let Json.488 : {Str, List []} = CallByName Encode.22 Json.489;
|
||||||
|
ret Json.488;
|
||||||
|
|
||||||
|
procedure List.138 (List.139, List.140, List.137):
|
||||||
|
let List.523 : {List U8, U64} = CallByName Json.128 List.139 List.140;
|
||||||
|
ret List.523;
|
||||||
|
|
||||||
|
procedure List.138 (List.139, List.140, List.137):
|
||||||
|
let List.596 : {List U8, U64} = CallByName Json.128 List.139 List.140;
|
||||||
|
ret List.596;
|
||||||
|
|
||||||
|
procedure List.18 (List.135, List.136, List.137):
|
||||||
|
let List.504 : {List U8, U64} = CallByName List.91 List.135 List.136 List.137;
|
||||||
|
ret List.504;
|
||||||
|
|
||||||
|
procedure List.18 (List.135, List.136, List.137):
|
||||||
|
let List.577 : {List U8, U64} = CallByName List.91 List.135 List.136 List.137;
|
||||||
|
ret List.577;
|
||||||
|
|
||||||
|
procedure List.4 (List.106, List.107):
|
||||||
|
let List.576 : U64 = 1i64;
|
||||||
|
let List.575 : List U8 = CallByName List.70 List.106 List.576;
|
||||||
|
let List.574 : List U8 = CallByName List.71 List.575 List.107;
|
||||||
|
ret List.574;
|
||||||
|
|
||||||
|
procedure List.6 (#Attr.2):
|
||||||
|
let List.524 : U64 = lowlevel ListLen #Attr.2;
|
||||||
|
ret List.524;
|
||||||
|
|
||||||
|
procedure List.6 (#Attr.2):
|
||||||
|
let List.597 : U64 = lowlevel ListLen #Attr.2;
|
||||||
|
ret List.597;
|
||||||
|
|
||||||
|
procedure List.66 (#Attr.2, #Attr.3):
|
||||||
|
let List.520 : [C {}, C {}] = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
|
||||||
|
ret List.520;
|
||||||
|
|
||||||
|
procedure List.66 (#Attr.2, #Attr.3):
|
||||||
|
let List.593 : [] = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
|
||||||
|
ret List.593;
|
||||||
|
|
||||||
|
procedure List.70 (#Attr.2, #Attr.3):
|
||||||
|
let List.555 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3;
|
||||||
|
ret List.555;
|
||||||
|
|
||||||
|
procedure List.71 (#Attr.2, #Attr.3):
|
||||||
|
let List.553 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3;
|
||||||
|
ret List.553;
|
||||||
|
|
||||||
|
procedure List.8 (#Attr.2, #Attr.3):
|
||||||
|
let List.598 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3;
|
||||||
|
ret List.598;
|
||||||
|
|
||||||
|
procedure List.80 (List.535, List.536, List.537, List.538, List.539):
|
||||||
|
joinpoint List.510 List.429 List.430 List.431 List.432 List.433:
|
||||||
|
let List.512 : Int1 = CallByName Num.22 List.432 List.433;
|
||||||
|
if List.512 then
|
||||||
|
let List.519 : [C {}, C {}] = CallByName List.66 List.429 List.432;
|
||||||
|
let List.513 : {List U8, U64} = CallByName List.138 List.430 List.519 List.431;
|
||||||
|
let List.516 : U64 = 1i64;
|
||||||
|
let List.515 : U64 = CallByName Num.19 List.432 List.516;
|
||||||
|
jump List.510 List.429 List.513 List.431 List.515 List.433;
|
||||||
|
else
|
||||||
|
ret List.430;
|
||||||
|
in
|
||||||
|
jump List.510 List.535 List.536 List.537 List.538 List.539;
|
||||||
|
|
||||||
|
procedure List.80 (List.608, List.609, List.610, List.611, List.612):
|
||||||
|
joinpoint List.583 List.429 List.430 List.431 List.432 List.433:
|
||||||
|
let List.585 : Int1 = CallByName Num.22 List.432 List.433;
|
||||||
|
if List.585 then
|
||||||
|
let List.592 : [] = CallByName List.66 List.429 List.432;
|
||||||
|
let List.586 : {List U8, U64} = CallByName List.138 List.430 List.592 List.431;
|
||||||
|
let List.589 : U64 = 1i64;
|
||||||
|
let List.588 : U64 = CallByName Num.19 List.432 List.589;
|
||||||
|
jump List.583 List.429 List.586 List.431 List.588 List.433;
|
||||||
|
else
|
||||||
|
ret List.430;
|
||||||
|
in
|
||||||
|
jump List.583 List.608 List.609 List.610 List.611 List.612;
|
||||||
|
|
||||||
|
procedure List.91 (List.426, List.427, List.428):
|
||||||
|
let List.508 : U64 = 0i64;
|
||||||
|
let List.509 : U64 = CallByName List.6 List.426;
|
||||||
|
let List.507 : {List U8, U64} = CallByName List.80 List.426 List.427 List.428 List.508 List.509;
|
||||||
|
ret List.507;
|
||||||
|
|
||||||
|
procedure List.91 (List.426, List.427, List.428):
|
||||||
|
let List.581 : U64 = 0i64;
|
||||||
|
let List.582 : U64 = CallByName List.6 List.426;
|
||||||
|
let List.580 : {List U8, U64} = CallByName List.80 List.426 List.427 List.428 List.581 List.582;
|
||||||
|
ret List.580;
|
||||||
|
|
||||||
|
procedure Num.125 (#Attr.2):
|
||||||
|
let Num.284 : U8 = lowlevel NumIntCast #Attr.2;
|
||||||
|
ret Num.284;
|
||||||
|
|
||||||
|
procedure Num.19 (#Attr.2, #Attr.3):
|
||||||
|
let Num.287 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||||
|
ret Num.287;
|
||||||
|
|
||||||
|
procedure Num.20 (#Attr.2, #Attr.3):
|
||||||
|
let Num.285 : U64 = lowlevel NumSub #Attr.2 #Attr.3;
|
||||||
|
ret Num.285;
|
||||||
|
|
||||||
|
procedure Num.22 (#Attr.2, #Attr.3):
|
||||||
|
let Num.288 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||||
|
ret Num.288;
|
||||||
|
|
||||||
|
procedure Num.24 (#Attr.2, #Attr.3):
|
||||||
|
let Num.286 : Int1 = lowlevel NumGt #Attr.2 #Attr.3;
|
||||||
|
ret Num.286;
|
||||||
|
|
||||||
|
procedure Str.12 (#Attr.2):
|
||||||
|
let Str.267 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||||
|
ret Str.267;
|
||||||
|
|
||||||
|
procedure Test.2 (Test.11):
|
||||||
|
let Test.18 : {{}, {}} = CallByName Encode.22 Test.11;
|
||||||
|
ret Test.18;
|
||||||
|
|
||||||
|
procedure Test.3 ():
|
||||||
|
let Test.16 : {} = Struct {};
|
||||||
|
let Test.17 : {} = Struct {};
|
||||||
|
let Test.15 : {{}, {}} = Struct {Test.16, Test.17};
|
||||||
|
ret Test.15;
|
||||||
|
|
||||||
|
procedure Test.5 (Test.6, Test.7, Test.4):
|
||||||
|
joinpoint Test.23 Test.8:
|
||||||
|
let Test.21 : List U8 = CallByName Encode.23 Test.6 Test.8 Test.7;
|
||||||
|
ret Test.21;
|
||||||
|
in
|
||||||
|
let Test.28 : Int1 = CallByName Bool.2;
|
||||||
|
if Test.28 then
|
||||||
|
let Test.29 : Str = "A";
|
||||||
|
let Test.32 : {} = StructAtIndex 0 Test.4;
|
||||||
|
let Test.31 : [C {}, C {}] = CallByName #Derived.0 Test.32;
|
||||||
|
let Test.30 : List [C {}, C {}] = Array [Test.31];
|
||||||
|
let Test.22 : {Str, List [C {}, C {}]} = CallByName Json.21 Test.29 Test.30;
|
||||||
|
jump Test.23 Test.22;
|
||||||
|
else
|
||||||
|
let Test.24 : Str = "B";
|
||||||
|
let Test.27 : {} = StructAtIndex 1 Test.4;
|
||||||
|
let Test.26 : [C {}, C {}] = CallByName #Derived.5 Test.27;
|
||||||
|
let Test.25 : List [C {}, C {}] = Array [Test.26];
|
||||||
|
let Test.22 : {Str, List [C {}, C {}]} = CallByName Json.21 Test.24 Test.25;
|
||||||
|
jump Test.23 Test.22;
|
||||||
|
|
||||||
|
procedure Test.0 ():
|
||||||
|
let Test.13 : {{}, {}} = CallByName Test.3;
|
||||||
|
let Test.14 : {} = CallByName Json.1;
|
||||||
|
let Test.12 : List U8 = CallByName Encode.25 Test.13 Test.14;
|
||||||
|
ret Test.12;
|
|
@ -3,7 +3,7 @@ procedure Bool.11 (#Attr.2, #Attr.3):
|
||||||
ret Bool.24;
|
ret Bool.24;
|
||||||
|
|
||||||
procedure List.26 (List.152, List.153, List.154):
|
procedure List.26 (List.152, List.153, List.154):
|
||||||
let List.493 : [C U64, C U64] = CallByName List.90 List.152 List.153 List.154;
|
let List.493 : [C U64, C U64] = CallByName List.91 List.152 List.153 List.154;
|
||||||
let List.496 : U8 = 1i64;
|
let List.496 : U8 = 1i64;
|
||||||
let List.497 : U8 = GetTagId List.493;
|
let List.497 : U8 = GetTagId List.493;
|
||||||
let List.498 : Int1 = lowlevel Eq List.496 List.497;
|
let List.498 : Int1 = lowlevel Eq List.496 List.497;
|
||||||
|
@ -53,13 +53,7 @@ procedure List.72 (#Attr.2, #Attr.3, #Attr.4):
|
||||||
let List.484 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4;
|
let List.484 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4;
|
||||||
ret List.484;
|
ret List.484;
|
||||||
|
|
||||||
procedure List.90 (List.426, List.427, List.428):
|
procedure List.80 (List.528, List.529, List.530, List.531, List.532):
|
||||||
let List.500 : U64 = 0i64;
|
|
||||||
let List.501 : U64 = CallByName List.6 List.426;
|
|
||||||
let List.499 : [C U64, C U64] = CallByName List.91 List.426 List.427 List.428 List.500 List.501;
|
|
||||||
ret List.499;
|
|
||||||
|
|
||||||
procedure List.91 (List.528, List.529, List.530, List.531, List.532):
|
|
||||||
joinpoint List.502 List.429 List.430 List.431 List.432 List.433:
|
joinpoint List.502 List.429 List.430 List.431 List.432 List.433:
|
||||||
let List.504 : Int1 = CallByName Num.22 List.432 List.433;
|
let List.504 : Int1 = CallByName Num.22 List.432 List.433;
|
||||||
if List.504 then
|
if List.504 then
|
||||||
|
@ -83,6 +77,12 @@ procedure List.91 (List.528, List.529, List.530, List.531, List.532):
|
||||||
in
|
in
|
||||||
jump List.502 List.528 List.529 List.530 List.531 List.532;
|
jump List.502 List.528 List.529 List.530 List.531 List.532;
|
||||||
|
|
||||||
|
procedure List.91 (List.426, List.427, List.428):
|
||||||
|
let List.500 : U64 = 0i64;
|
||||||
|
let List.501 : U64 = CallByName List.6 List.426;
|
||||||
|
let List.499 : [C U64, C U64] = CallByName List.80 List.426 List.427 List.428 List.500 List.501;
|
||||||
|
ret List.499;
|
||||||
|
|
||||||
procedure Num.19 (#Attr.2, #Attr.3):
|
procedure Num.19 (#Attr.2, #Attr.3):
|
||||||
let Num.258 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
let Num.258 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||||
ret Num.258;
|
ret Num.258;
|
||||||
|
|
|
@ -2571,3 +2571,155 @@ fn recursive_lambda_set_has_nested_non_recursive_lambda_sets_issue_5026() {
|
||||||
"#
|
"#
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[mono_test]
|
||||||
|
fn unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unification() {
|
||||||
|
// This is a regression test for the ambient lambda set specialization algorithm.
|
||||||
|
//
|
||||||
|
// In the program below, monomorphization of `toEncoderQ` with the `Q` in `main` induces the
|
||||||
|
// resolution of `t.a` and `t.b`, and the unification of their pending unspecialization lambda
|
||||||
|
// sets, when `t.a` and `t.b` have been resolved to concrete types, but before the
|
||||||
|
// specialization procedure steps in to resolve the lambda sets concretely. That's because
|
||||||
|
// monomorphization unifies the general type of `toEncoderQ` with the concrete type, forcing
|
||||||
|
// concretization of `t`, but the specialization procedure runs only after the unification is
|
||||||
|
// complete.
|
||||||
|
//
|
||||||
|
// In this case, it's imperative that the unspecialized lambda sets of `toEncoder t.a` and
|
||||||
|
// `toEncoder t.b` wind up in the same lambda set, that is in
|
||||||
|
//
|
||||||
|
// tag : @MEncoder (Bytes, Linear -[[] + @MU8:toEncoder:1 + @MStr:toEncoder+1] -> Bytes)
|
||||||
|
// -[lTag]->
|
||||||
|
// @MEncoder (Bytes, Linear -[[Linear:lTag:3 { @MEncoder (Bytes, Linear -[[] + @MU8:toEncoder:1 + @MStr:toEncoder:1] -> Bytes) }]] -> Bytes)
|
||||||
|
//
|
||||||
|
// rather than forcing the lambda set inside to `tag` to become disjoint, as e.g.
|
||||||
|
//
|
||||||
|
// tag : @MEncoder (Bytes, Linear -[[] + @MU8:toEncoder:1 + @MStr:toEncoder+1] -> Bytes)
|
||||||
|
// -[lTag]->
|
||||||
|
// @MEncoder (Bytes, Linear -[[
|
||||||
|
// Linear:lTag:3 { @MEncoder (Bytes, Linear -[[] + @MU8:toEncoder:1] -> Bytes) },
|
||||||
|
// Linear:lTag:3 { @MEncoder (Bytes, Linear -[[] + @MStr:toEncoder:1] -> Bytes) },
|
||||||
|
// ]] -> Bytes)
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
app "test" provides [main] to "./platform"
|
||||||
|
|
||||||
|
MEncoder fmt := List U8, fmt -> List U8 | fmt has Format
|
||||||
|
|
||||||
|
MEncoding has
|
||||||
|
toEncoder : val -> MEncoder fmt | val has MEncoding, fmt has Format
|
||||||
|
|
||||||
|
Format has
|
||||||
|
u8 : {} -> MEncoder fmt | fmt has Format
|
||||||
|
str : {} -> MEncoder fmt | fmt has Format
|
||||||
|
tag : MEncoder fmt -> MEncoder fmt | fmt has Format
|
||||||
|
|
||||||
|
Linear := {} has [Format {u8: lU8, str: lStr, tag: lTag}]
|
||||||
|
|
||||||
|
MU8 := U8 has [MEncoding {toEncoder: toEncoderU8}]
|
||||||
|
MStr := Str has [MEncoding {toEncoder: toEncoderStr}]
|
||||||
|
|
||||||
|
Q a b := { a: a, b: b }
|
||||||
|
|
||||||
|
lU8 = \{} -> @MEncoder (\lst, @Linear {} -> lst)
|
||||||
|
lStr = \{} -> @MEncoder (\lst, @Linear {} -> lst)
|
||||||
|
|
||||||
|
lTag = \@MEncoder doFormat -> @MEncoder (\lst, @Linear {} ->
|
||||||
|
doFormat lst (@Linear {})
|
||||||
|
)
|
||||||
|
|
||||||
|
toEncoderU8 = \@MU8 _ -> u8 {}
|
||||||
|
|
||||||
|
toEncoderStr = \@MStr _ -> str {}
|
||||||
|
|
||||||
|
toEncoderQ =
|
||||||
|
\@Q t -> \fmt ->
|
||||||
|
@MEncoder doit = if Bool.true
|
||||||
|
then tag (toEncoder t.a)
|
||||||
|
else tag (toEncoder t.b)
|
||||||
|
|
||||||
|
doit [] fmt
|
||||||
|
|
||||||
|
main =
|
||||||
|
fmt = toEncoderQ (@Q {a : @MStr "", b: @MU8 7})
|
||||||
|
fmt (@Linear {})
|
||||||
|
"#
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[mono_test]
|
||||||
|
fn unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unification_of_unifiable()
|
||||||
|
{
|
||||||
|
// This is a regression test for the ambient lambda set specialization algorithm.
|
||||||
|
//
|
||||||
|
// The principle of the test is equivalent to that of `unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unification`.
|
||||||
|
//
|
||||||
|
// However, this test requires a larger reproduction because it is negative behavior is only
|
||||||
|
// visible in the presence of builtin ability usage (in this case, `Encoding` and
|
||||||
|
// `EncoderFormatting`).
|
||||||
|
//
|
||||||
|
// In this test, the payload types `[A]*` and `[B]*` of the encoded type `Q` are unifiable in
|
||||||
|
// their unspecialized lambda set representations under `toEncoderQ`; however, they must not
|
||||||
|
// be, because they in fact represent to different specializations of needed encoders. In
|
||||||
|
// particular, the lambda set `[[] + [A]:toEncoder:1 + [B]:toEncoder:1]` must be preserved,
|
||||||
|
// rather than collapsing to `[[] + [A, B]:toEncoder:1]`.
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
app "test" imports [Json] provides [main] to "./platform"
|
||||||
|
|
||||||
|
Q a b := { a: a, b: b } has [Encoding {toEncoder: toEncoderQ}]
|
||||||
|
|
||||||
|
toEncoderQ =
|
||||||
|
\@Q t -> Encode.custom \bytes, fmt ->
|
||||||
|
f = if Bool.true
|
||||||
|
then Encode.tag "A" [Encode.toEncoder t.a]
|
||||||
|
else Encode.tag "B" [Encode.toEncoder t.b]
|
||||||
|
|
||||||
|
Encode.appendWith bytes f fmt
|
||||||
|
|
||||||
|
accessor = @Q {a : A, b: B}
|
||||||
|
|
||||||
|
main =
|
||||||
|
Encode.toBytes accessor Json.toUtf8
|
||||||
|
"#
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[mono_test]
|
||||||
|
fn unspecialized_lambda_set_unification_does_not_duplicate_identical_concrete_types() {
|
||||||
|
// This is a regression test for the ambient lambda set specialization algorithm.
|
||||||
|
//
|
||||||
|
// The principle of the test is equivalent to that of `unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unification`.
|
||||||
|
//
|
||||||
|
// However, this test requires a larger reproduction because it is negative behavior is only
|
||||||
|
// visible in the presence of builtin ability usage (in this case, `Encoding` and
|
||||||
|
// `EncoderFormatting`).
|
||||||
|
//
|
||||||
|
// In this test, the payload types `Str` and `Str` of the encoded type `Q` are unifiable in
|
||||||
|
// their unspecialized lambda set representations under `toEncoderQ`, and moreoever they are
|
||||||
|
// equivalent specializations, since they both come from the same root variable `x`. In as
|
||||||
|
// such, the lambda set `[[] + Str:toEncoder:1]` should be produced during compaction, rather
|
||||||
|
// than staying as the expanded `[[] + Str:toEncoder:1 + Str:toEncoder:1]` after the types of
|
||||||
|
// `t.a` and `t.b` are filled in.
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
app "test" imports [Json] provides [main] to "./platform"
|
||||||
|
|
||||||
|
Q a b := { a: a, b: b } has [Encoding {toEncoder: toEncoderQ}]
|
||||||
|
|
||||||
|
toEncoderQ =
|
||||||
|
\@Q t -> Encode.custom \bytes, fmt ->
|
||||||
|
f = if Bool.true
|
||||||
|
then Encode.tag "A" [Encode.toEncoder t.a]
|
||||||
|
else Encode.tag "B" [Encode.toEncoder t.b]
|
||||||
|
|
||||||
|
Encode.appendWith bytes f fmt
|
||||||
|
|
||||||
|
accessor =
|
||||||
|
x = ""
|
||||||
|
@Q {a : x, b: x}
|
||||||
|
|
||||||
|
main =
|
||||||
|
Encode.toBytes accessor Json.toUtf8
|
||||||
|
"#
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -568,6 +568,15 @@ mod test_snapshots {
|
||||||
Err(err) => Err(format!("{:?}", err)),
|
Err(err) => Err(format!("{:?}", err)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if expect == TestExpectation::Pass {
|
||||||
|
let tokens = roc_parse::highlight::highlight(&source);
|
||||||
|
for token in tokens {
|
||||||
|
if token.value == roc_parse::highlight::Token::Error {
|
||||||
|
panic!("Found an error highlight token in the input: {:?}", token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let actual_result =
|
let actual_result =
|
||||||
if expect == TestExpectation::Pass || expect == TestExpectation::Malformed {
|
if expect == TestExpectation::Pass || expect == TestExpectation::Malformed {
|
||||||
result.expect("The source code for this test did not successfully parse!")
|
result.expect("The source code for this test did not successfully parse!")
|
||||||
|
|
|
@ -1568,8 +1568,10 @@ fn unspecialized_lambda_set_sorter(subs: &Subs, uls1: Uls, uls2: Uls) -> std::cm
|
||||||
}
|
}
|
||||||
(FlexAbleVar(..), _) => Greater,
|
(FlexAbleVar(..), _) => Greater,
|
||||||
(_, FlexAbleVar(..)) => Less,
|
(_, FlexAbleVar(..)) => Less,
|
||||||
// For everything else, the order is irrelevant
|
// For everything else, sort by the root key
|
||||||
(_, _) => Less,
|
(_, _) => subs
|
||||||
|
.get_root_key_without_compacting(var1)
|
||||||
|
.cmp(&subs.get_root_key_without_compacting(var2)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ord => ord,
|
ord => ord,
|
||||||
|
@ -1731,6 +1733,8 @@ fn unify_unspecialized_lambdas<M: MetaCollector>(
|
||||||
let kept = uls_left.next().unwrap();
|
let kept = uls_left.next().unwrap();
|
||||||
merged_uls.push(*kept);
|
merged_uls.push(*kept);
|
||||||
} else {
|
} else {
|
||||||
|
// CASE: disjoint_flex_specializations
|
||||||
|
//
|
||||||
// ... a1 ...
|
// ... a1 ...
|
||||||
// ... b1 ...
|
// ... b1 ...
|
||||||
// => ... a1, b1 ...
|
// => ... a1, b1 ...
|
||||||
|
@ -1800,20 +1804,47 @@ fn unify_unspecialized_lambdas<M: MetaCollector>(
|
||||||
let _dropped = uls_left.next().unwrap();
|
let _dropped = uls_left.next().unwrap();
|
||||||
}
|
}
|
||||||
(_, _) => {
|
(_, _) => {
|
||||||
// ... {foo: _} ...
|
if env.subs.equivalent_without_compacting(var_l, var_r) {
|
||||||
// ... {foo: _} ...
|
// ... a1 ...
|
||||||
// => ... {foo: _} ...
|
// ... b1=a1 ...
|
||||||
|
// => ... a1 ...
|
||||||
//
|
//
|
||||||
// Unify them, then advance one.
|
// Keep the one on the left, drop the one on the right. Then progress
|
||||||
// (the choice is arbitrary, so we choose the left)
|
// both, because the next variable on the left must be disjoint from
|
||||||
|
// the current on the right (resp. next variable on the right vs.
|
||||||
|
// current left) - if they aren't, then the invariant was broken.
|
||||||
|
//
|
||||||
|
// Then progress both, because the invariant tells us they must be
|
||||||
|
// disjoint, and if there were any concrete variables, they would have
|
||||||
|
// appeared earlier.
|
||||||
|
let _dropped = uls_right.next().unwrap();
|
||||||
|
let kept = uls_left.next().unwrap();
|
||||||
|
merged_uls.push(*kept);
|
||||||
|
|
||||||
let outcome = unify_pool(env, pool, var_l, var_r, mode);
|
debug_assert!(uls_right
|
||||||
if !outcome.mismatches.is_empty() {
|
.peek()
|
||||||
return Err(outcome);
|
.map(|r| env.subs.equivalent_without_compacting(var_l, r.0))
|
||||||
|
.unwrap_or(true));
|
||||||
|
debug_assert!(uls_left
|
||||||
|
.peek()
|
||||||
|
.map(|l| env.subs.equivalent_without_compacting(l.0, var_r))
|
||||||
|
.unwrap_or(true));
|
||||||
|
} else {
|
||||||
|
// Even if these two variables unify, since they are not equivalent,
|
||||||
|
// they correspond to different specializations! As such we must not
|
||||||
|
// merge them.
|
||||||
|
//
|
||||||
|
// Instead, keep both, but do so by adding and advancing the side with
|
||||||
|
// the lower root. See CASE disjoint_flex_specializations for
|
||||||
|
// reasoning.
|
||||||
|
if env.subs.get_root_key(var_l) < env.subs.get_root_key(var_r) {
|
||||||
|
let kept = uls_left.next().unwrap();
|
||||||
|
merged_uls.push(*kept);
|
||||||
|
} else {
|
||||||
|
let kept = uls_right.next().unwrap();
|
||||||
|
merged_uls.push(*kept);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
whole_outcome.union(outcome);
|
|
||||||
|
|
||||||
let _dropped = uls_left.next().unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@ normal = ["confy"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
with_sound = ["rodio"]
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
roc_ast = { path = "../ast" }
|
roc_ast = { path = "../ast" }
|
||||||
|
@ -57,7 +56,6 @@ confy = { git = 'https://github.com/rust-cli/confy', features = [
|
||||||
], default-features = false }
|
], default-features = false }
|
||||||
serde = { version = "1.0.144", features = ["derive"] }
|
serde = { version = "1.0.144", features = ["derive"] }
|
||||||
nonempty = "0.8.0"
|
nonempty = "0.8.0"
|
||||||
rodio = { version = "0.15.0", optional = true } # to play sounds
|
|
||||||
threadpool = "1.8.1"
|
threadpool = "1.8.1"
|
||||||
|
|
||||||
fs_extra.workspace = true
|
fs_extra.workspace = true
|
||||||
|
|
|
@ -8,7 +8,5 @@ mod mvc;
|
||||||
mod render_ast;
|
mod render_ast;
|
||||||
mod render_debug;
|
mod render_debug;
|
||||||
mod resources;
|
mod resources;
|
||||||
#[cfg(feature = "with_sound")]
|
|
||||||
mod sound;
|
|
||||||
mod theme;
|
mod theme;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
|
@ -21,8 +21,6 @@ use crate::editor::mvc::string_update::start_new_string;
|
||||||
use crate::editor::mvc::string_update::update_small_string;
|
use crate::editor::mvc::string_update::update_small_string;
|
||||||
use crate::editor::mvc::string_update::update_string;
|
use crate::editor::mvc::string_update::update_string;
|
||||||
use crate::editor::mvc::tld_value_update::{start_new_tld_value, update_tld_val_name};
|
use crate::editor::mvc::tld_value_update::{start_new_tld_value, update_tld_val_name};
|
||||||
#[cfg(feature = "with_sound")]
|
|
||||||
use crate::editor::sound::play_sound;
|
|
||||||
use crate::ui::text::caret_w_select::CaretWSelect;
|
use crate::ui::text::caret_w_select::CaretWSelect;
|
||||||
use crate::ui::text::lines::MoveCaretFun;
|
use crate::ui::text::lines::MoveCaretFun;
|
||||||
use crate::ui::text::selection::validate_raw_sel;
|
use crate::ui::text::selection::validate_raw_sel;
|
||||||
|
@ -546,12 +544,6 @@ impl<'a> EdModel<'a> {
|
||||||
self.show_debug_view = !self.show_debug_view;
|
self.show_debug_view = !self.show_debug_view;
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
F12 => {
|
|
||||||
#[cfg(feature = "with_sound")]
|
|
||||||
_sound_thread_pool.execute(move || {
|
|
||||||
play_sound("./editor/src/editor/resources/sounds/bell_sound.mp3");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
use rodio::{Decoder, OutputStream, Sink};
|
|
||||||
use std::fs::File;
|
|
||||||
use std::io::BufReader;
|
|
||||||
|
|
||||||
pub(crate) fn play_sound(sound_path_str: &str) {
|
|
||||||
let out_stream_res = OutputStream::try_default();
|
|
||||||
|
|
||||||
match out_stream_res {
|
|
||||||
Ok((_, out_stream_handle)) => match Sink::try_new(&out_stream_handle) {
|
|
||||||
Ok(sink) => match File::open(sound_path_str) {
|
|
||||||
Ok(file) => {
|
|
||||||
let reader = BufReader::new(file);
|
|
||||||
|
|
||||||
match Decoder::new(reader) {
|
|
||||||
Ok(decoder) => {
|
|
||||||
sink.append(decoder);
|
|
||||||
sink.sleep_until_end();
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
println!("Failed to create Decoder from BufReader from sound file at {}. Error message: {:?}", sound_path_str, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
println!(
|
|
||||||
"Failed to open sound file at {}. Error message: {}",
|
|
||||||
sound_path_str, e
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
println!(
|
|
||||||
"Failed to create Sink to play sound. Error message: {:?}",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
println!(
|
|
||||||
"Failed to create OutputStream to play sound. Error message: {:?}",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -65,7 +65,6 @@ rustPlatform.buildRustPackage {
|
||||||
cargo
|
cargo
|
||||||
makeWrapper # necessary for postBuild wrapProgram
|
makeWrapper # necessary for postBuild wrapProgram
|
||||||
] ++ lib.optionals pkgs.stdenv.isLinux [
|
] ++ lib.optionals pkgs.stdenv.isLinux [
|
||||||
alsa-lib
|
|
||||||
valgrind
|
valgrind
|
||||||
vulkan-headers
|
vulkan-headers
|
||||||
vulkan-loader
|
vulkan-loader
|
||||||
|
|
|
@ -39,7 +39,6 @@ confy = { git = 'https://github.com/rust-cli/confy', features = [
|
||||||
serde = { version = "1.0.130", features = ["derive"] }
|
serde = { version = "1.0.130", features = ["derive"] }
|
||||||
nonempty = "0.7.0"
|
nonempty = "0.7.0"
|
||||||
fs_extra = "1.2.0"
|
fs_extra = "1.2.0"
|
||||||
rodio = { version = "0.14.0", optional = true } # to play sounds
|
|
||||||
threadpool = "1.8.1"
|
threadpool = "1.8.1"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
|
@ -50,7 +49,6 @@ normal = ["confy"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
with_sound = ["rodio"]
|
|
||||||
|
|
||||||
[dependencies.bytemuck]
|
[dependencies.bytemuck]
|
||||||
version = "1.7.2"
|
version = "1.7.2"
|
||||||
|
|
|
@ -40,7 +40,6 @@ confy = { git = 'https://github.com/rust-cli/confy', features = [
|
||||||
serde = { version = "1.0.130", features = ["derive"] }
|
serde = { version = "1.0.130", features = ["derive"] }
|
||||||
nonempty = "0.7.0"
|
nonempty = "0.7.0"
|
||||||
fs_extra = "1.2.0"
|
fs_extra = "1.2.0"
|
||||||
rodio = { version = "0.14.0", optional = true } # to play sounds
|
|
||||||
threadpool = "1.8.1"
|
threadpool = "1.8.1"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
|
@ -51,7 +50,6 @@ normal = ["confy"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
with_sound = ["rodio"]
|
|
||||||
|
|
||||||
[dependencies.bytemuck]
|
[dependencies.bytemuck]
|
||||||
version = "1.7.2"
|
version = "1.7.2"
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
app "parse-movies-csv"
|
|
||||||
packages { pf: "platform/main.roc" }
|
|
||||||
imports [Parser.Core.{ Parser, map, keep }, Parser.Str.{ RawStr }, Parser.CSV.{ CSV, record, field, string, nat }]
|
|
||||||
provides [main] to pf
|
|
||||||
|
|
||||||
input : Str
|
|
||||||
input = "Airplane!,1980,\"Robert Hays,Julie Hagerty\"\r\nCaddyshack,1980,\"Chevy Chase,Rodney Dangerfield,Ted Knight,Michael O'Keefe,Bill Murray\""
|
|
||||||
|
|
||||||
main : Str
|
|
||||||
main =
|
|
||||||
when Parser.CSV.parseStr movieInfoParser input is
|
|
||||||
Ok movies ->
|
|
||||||
moviesString =
|
|
||||||
movies
|
|
||||||
|> List.map movieInfoExplanation
|
|
||||||
|> Str.joinWith ("\n")
|
|
||||||
nMovies = List.len movies |> Num.toStr
|
|
||||||
|
|
||||||
"\(nMovies) movies were found:\n\n\(moviesString)\n\nParse success!\n"
|
|
||||||
|
|
||||||
Err problem ->
|
|
||||||
when problem is
|
|
||||||
ParsingFailure failure ->
|
|
||||||
"Parsing failure: \(failure)\n"
|
|
||||||
|
|
||||||
ParsingIncomplete leftover ->
|
|
||||||
leftoverStr = leftover |> List.map Parser.Str.strFromRaw |> List.map (\val -> "\"\(val)\"") |> Str.joinWith ", "
|
|
||||||
|
|
||||||
"Parsing incomplete. Following leftover fields while parsing a record: \(leftoverStr)\n"
|
|
||||||
|
|
||||||
SyntaxError error ->
|
|
||||||
"Parsing failure. Syntax error in the CSV: \(error)"
|
|
||||||
|
|
||||||
MovieInfo := { title : Str, releaseYear : Nat, actors : List Str }
|
|
||||||
|
|
||||||
movieInfoParser =
|
|
||||||
record (\title -> \releaseYear -> \actors -> @MovieInfo { title, releaseYear, actors })
|
|
||||||
|> keep (field string)
|
|
||||||
|> keep (field nat)
|
|
||||||
|> keep (field actorsParser)
|
|
||||||
|
|
||||||
actorsParser =
|
|
||||||
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.split elements (List.len elements - 1)
|
|
||||||
|
|
||||||
last
|
|
||||||
|> List.prepend (inits |> Str.joinWith ", ")
|
|
||||||
|> Str.joinWith " and "
|
|
|
@ -1,125 +0,0 @@
|
||||||
const std = @import("std");
|
|
||||||
const builtin = @import("builtin");
|
|
||||||
const str = @import("str");
|
|
||||||
const RocStr = str.RocStr;
|
|
||||||
const testing = std.testing;
|
|
||||||
const expectEqual = testing.expectEqual;
|
|
||||||
const expect = testing.expect;
|
|
||||||
|
|
||||||
extern fn roc__mainForHost_1_exposed_generic(*RocStr) void;
|
|
||||||
|
|
||||||
pub fn main() u8 {
|
|
||||||
const stdout = std.io.getStdOut().writer();
|
|
||||||
|
|
||||||
// actually call roc to populate the callresult
|
|
||||||
var callresult = RocStr.empty();
|
|
||||||
roc__mainForHost_1_exposed_generic(&callresult);
|
|
||||||
|
|
||||||
// stdout the result
|
|
||||||
stdout.print("{s}", .{callresult.asSlice()}) catch unreachable;
|
|
||||||
|
|
||||||
callresult.deinit();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
comptime {
|
|
||||||
// This is a workaround for https://github.com/ziglang/zig/issues/8218
|
|
||||||
// which is only necessary on macOS.
|
|
||||||
//
|
|
||||||
// Once that issue is fixed, we can undo the changes in
|
|
||||||
// 177cf12e0555147faa4d436e52fc15175c2c4ff0 and go back to passing
|
|
||||||
// -fcompiler-rt in link.rs instead of doing this. Note that this
|
|
||||||
// workaround is present in many host.zig files, so make sure to undo
|
|
||||||
// it everywhere!
|
|
||||||
if (builtin.os.tag == .macos) {
|
|
||||||
_ = @import("compiler_rt");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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(@alignCast(Align, @ptrCast([*]u8, 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(@alignCast(Align, @ptrCast([*]u8, c_ptr)));
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn roc_panic(c_ptr: *anyopaque, tag_id: u32) callconv(.C) void {
|
|
||||||
_ = tag_id;
|
|
||||||
|
|
||||||
const stderr = std.io.getStdErr().writer();
|
|
||||||
const msg = @ptrCast([*:0]const u8, c_ptr);
|
|
||||||
stderr.print("Application crashed with message\n\n {s}\n\nShutting down\n", .{msg}) catch unreachable;
|
|
||||||
std.process.exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn roc_memcpy(dst: [*]u8, src: [*]u8, size: usize) callconv(.C) void {
|
|
||||||
return memcpy(dst, src, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
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_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 });
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
platform "hello-world"
|
|
||||||
requires {} { main : Str }
|
|
||||||
exposes []
|
|
||||||
packages {}
|
|
||||||
imports []
|
|
||||||
provides [mainForHost]
|
|
||||||
|
|
||||||
mainForHost : Str
|
|
||||||
mainForHost = main
|
|
|
@ -9,7 +9,7 @@ To run, `cd` into this directory and run this in your terminal:
|
||||||
|
|
||||||
If `roc` is on your PATH:
|
If `roc` is on your PATH:
|
||||||
```bash
|
```bash
|
||||||
roc run static-site.roc input/ output/
|
roc run static-site.roc -- input/ output/
|
||||||
```
|
```
|
||||||
|
|
||||||
If not, and you're building Roc from source:
|
If not, and you're building Roc from source:
|
||||||
|
|
|
@ -44,24 +44,92 @@ ingeniis in pugna quadripedis glandes superos. Tanta quam, illo es prole est
|
||||||
telis **unus verba** quisquis iuvenci annis. Nec velox sed sacra gaudia vacuos,
|
telis **unus verba** quisquis iuvenci annis. Nec velox sed sacra gaudia vacuos,
|
||||||
Herculei undae calcata inmeriti quercus ignes parabant iam.
|
Herculei undae calcata inmeriti quercus ignes parabant iam.
|
||||||
|
|
||||||
digitize(undoDhcp(card_record, cad_flash_dot));
|
### Example Table
|
||||||
supercomputer(2 - load_type, yobibyteTraceroute - installHibernate, 1);
|
|
||||||
burnPci.pop_wrap.usbEmulation(hostESmm, processor_impression(4, lanNntp),
|
| Tables | Are | Cool |
|
||||||
-5);
|
| :------------ | :-----------: | ----: |
|
||||||
map_camera -= 73;
|
| col 3 is | right-aligned | $1600 |
|
||||||
if (53) {
|
| col 2 is | centered | $12 |
|
||||||
dacRootkitDrive(publicActivex.bmpNumWhite.wins_pci_firmware(scroll_cell,
|
| zebra stripes | are neat | $1 |
|
||||||
4, tShortcut));
|
|
||||||
horse_algorithm_eide -= 51;
|
### Example Code Blocks
|
||||||
flatbed_blob(flat);
|
|
||||||
} else {
|
```sh
|
||||||
surge.pci -= open_flash_dv(4, 4, usbStation);
|
# This isn't fenced roc code so its not formatted
|
||||||
led.memory_fsb.matrixBinaryUrl(umlEngineOsd.agp_thick_thin.t(58));
|
# Use a fence like ```roc to format code blocks
|
||||||
kindle_cookie(formulaLedVpn, digital_meme);
|
```
|
||||||
|
|
||||||
|
```roc
|
||||||
|
## This is a documentation comment
|
||||||
|
|
||||||
|
# This is a comment
|
||||||
|
app "static-site"
|
||||||
|
packages { pf: "platform/main.roc" }
|
||||||
|
imports [
|
||||||
|
pf.Html.{ html, head, body, div, text, a, ul, li, link, meta },
|
||||||
|
pf.Html.Attributes.{ httpEquiv, content, href, rel, lang, class, title },
|
||||||
|
]
|
||||||
|
provides [transformFileContent] to pf
|
||||||
|
|
||||||
|
NavLink : {
|
||||||
|
# this is another comment
|
||||||
|
url : Str,
|
||||||
|
title : Str,
|
||||||
|
text : Str,
|
||||||
}
|
}
|
||||||
|
|
||||||
Foret inpendere, haec ipse ossa, dolentes das Caystro miscuit iunctoque
|
navLinks : List NavLink
|
||||||
spoliantis illae, ex! Bello istis nunc Aegides? Animo caelestia melior,
|
navLinks = [
|
||||||
furoribus optat maior invecta quid harenis [est](http://example.org) sollemnia modo
|
{ url: "apple.html", title: "Exempli Gratia Pagina Pomi", text: "Apple" },
|
||||||
Phineu. Suarum pectora. Relinquam in labore Medusae sororem Herculis [simillima
|
{ url: "banana.html", title: "Exempli Gratia Pagina Musa", text: "Banana" },
|
||||||
corpora](http://example.org) plus regi ignibus, totum domus!
|
{ url: "cherry.html", title: "Exempli Pagina Cerasus", text: "Cherry" },
|
||||||
|
]
|
||||||
|
|
||||||
|
transformFileContent : Str, Str -> Str
|
||||||
|
transformFileContent = \currentUrl, htmlContent ->
|
||||||
|
List.findFirst navLinks (\{ url } -> url == currentUrl)
|
||||||
|
|> Result.map (\currentNavLink -> view currentNavLink htmlContent)
|
||||||
|
|> Result.map Html.render
|
||||||
|
|> Result.withDefault ""
|
||||||
|
|
||||||
|
view : NavLink, Str -> Html.Node
|
||||||
|
view = \currentNavLink, htmlContent ->
|
||||||
|
html [lang "en"] [
|
||||||
|
head [] [
|
||||||
|
meta [httpEquiv "content-type", content "text/html; charset=utf-8"] [],
|
||||||
|
Html.title [] [text currentNavLink.title],
|
||||||
|
link [rel "stylesheet", href "style.css"] [],
|
||||||
|
],
|
||||||
|
body [] [
|
||||||
|
div [class "main"] [
|
||||||
|
div [class "navbar"] [
|
||||||
|
viewNavbar currentNavLink,
|
||||||
|
],
|
||||||
|
div [class "article"] [
|
||||||
|
# For now `text` is not escaped so we can use it to insert HTML
|
||||||
|
# We'll probably want something more explicit in the long term though!
|
||||||
|
text htmlContent,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]
|
||||||
|
|
||||||
|
viewNavbar : NavLink -> Html.Node
|
||||||
|
viewNavbar = \currentNavLink ->
|
||||||
|
ul
|
||||||
|
[]
|
||||||
|
(List.map navLinks \nl -> viewNavLink (nl == currentNavLink) nl)
|
||||||
|
|
||||||
|
viewNavLink : Bool, NavLink -> Html.Node
|
||||||
|
viewNavLink = \isCurrent, navlink ->
|
||||||
|
if isCurrent then
|
||||||
|
li [class "nav-link nav-link--current"] [
|
||||||
|
text navlink.text,
|
||||||
|
]
|
||||||
|
else
|
||||||
|
li [class "nav-link"] [
|
||||||
|
a
|
||||||
|
[href navlink.url, title navlink.title]
|
||||||
|
[text navlink.text],
|
||||||
|
]
|
||||||
|
```
|
|
@ -39,7 +39,102 @@
|
||||||
color: #444;
|
color: #444;
|
||||||
}
|
}
|
||||||
.article pre {
|
.article pre {
|
||||||
background-color: #222;
|
background-color: rgb(241, 241, 241);
|
||||||
color: yellow;
|
color: rgb(27, 27, 27);
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
samp .ann {
|
||||||
|
/* type annotation - purple in the repl */
|
||||||
|
color: #f384fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
samp .autovar .comment {
|
||||||
|
/* automatic variable names in the repl, e.g. # val1 */
|
||||||
|
color: #338545;
|
||||||
|
}
|
||||||
|
|
||||||
|
samp .kw {
|
||||||
|
/* language keywords, e.g. `if`*/
|
||||||
|
color: #004cc2;
|
||||||
|
}
|
||||||
|
|
||||||
|
samp .arrow {
|
||||||
|
/* operators, e.g. `+` */
|
||||||
|
color: #0600c2;
|
||||||
|
}
|
||||||
|
|
||||||
|
samp .pipe {
|
||||||
|
/* operators, e.g. `+` */
|
||||||
|
color: #0600c2;
|
||||||
|
}
|
||||||
|
|
||||||
|
samp .op {
|
||||||
|
/* operators, e.g. `+` */
|
||||||
|
color: #0600c2;
|
||||||
|
}
|
||||||
|
|
||||||
|
samp .assign {
|
||||||
|
color: #48fd00;
|
||||||
|
}
|
||||||
|
|
||||||
|
samp .paren {
|
||||||
|
color: #ff0000;
|
||||||
|
}
|
||||||
|
|
||||||
|
samp .comma {
|
||||||
|
color: #ff00fb;
|
||||||
|
}
|
||||||
|
|
||||||
|
samp .colon {
|
||||||
|
color: #9b0098;
|
||||||
|
}
|
||||||
|
|
||||||
|
samp .number {
|
||||||
|
/* number literals */
|
||||||
|
color: #9669ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
samp .str {
|
||||||
|
/* string literals */
|
||||||
|
color: #1dbf00;
|
||||||
|
}
|
||||||
|
|
||||||
|
samp .str-esc, samp .str-interp {
|
||||||
|
/* escapes inside string literals, e.g. \t */
|
||||||
|
color: #3474db;
|
||||||
|
}
|
||||||
|
|
||||||
|
samp .dim {
|
||||||
|
opacity: 0.55;
|
||||||
|
}
|
||||||
|
|
||||||
|
samp .comment {
|
||||||
|
color: #005a13;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
table {
|
||||||
|
table-layout: fixed;
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
border: 3px solid rgb(161, 64, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody tr:nth-child(even) {
|
||||||
|
background-color: #c6f4ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
background-color: #ffabab;
|
||||||
|
}
|
||||||
|
|
||||||
|
th,
|
||||||
|
td {
|
||||||
|
|
||||||
|
padding: 2px;
|
||||||
|
}
|
374
examples/static-site-gen/platform/Cargo.lock
generated
374
examples/static-site-gen/platform/Cargo.lock
generated
|
@ -2,27 +2,194 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "addr2line"
|
||||||
|
version = "0.19.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
|
||||||
|
dependencies = [
|
||||||
|
"gimli",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ahash"
|
||||||
|
version = "0.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
"once_cell",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayvec"
|
name = "arrayvec"
|
||||||
version = "0.7.2"
|
version = "0.7.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
|
checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "backtrace"
|
||||||
|
version = "0.3.67"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
|
||||||
|
dependencies = [
|
||||||
|
"addr2line",
|
||||||
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"miniz_oxide",
|
||||||
|
"object",
|
||||||
|
"rustc-demangle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitmaps"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2"
|
||||||
|
dependencies = [
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitvec"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
|
||||||
|
dependencies = [
|
||||||
|
"funty",
|
||||||
|
"radium",
|
||||||
|
"tap",
|
||||||
|
"wyz",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bumpalo"
|
||||||
|
version = "3.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.0.79"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "doc-comment"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "encode_unicode"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fnv"
|
||||||
|
version = "1.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "funty"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gimli"
|
||||||
|
version = "0.27.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||||
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
|
"bumpalo",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "host"
|
name = "host"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"pulldown-cmark",
|
"pulldown-cmark",
|
||||||
|
"roc_parse",
|
||||||
|
"roc_region",
|
||||||
"roc_std",
|
"roc_std",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "im"
|
||||||
|
version = "15.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9"
|
||||||
|
dependencies = [
|
||||||
|
"bitmaps",
|
||||||
|
"rand_core",
|
||||||
|
"rand_xoshiro",
|
||||||
|
"sized-chunks",
|
||||||
|
"typenum",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "im-rc"
|
||||||
|
version = "15.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe"
|
||||||
|
dependencies = [
|
||||||
|
"bitmaps",
|
||||||
|
"rand_core",
|
||||||
|
"rand_xoshiro",
|
||||||
|
"sized-chunks",
|
||||||
|
"typenum",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.132"
|
version = "0.2.132"
|
||||||
|
@ -35,6 +202,39 @@ version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.6.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
|
||||||
|
dependencies = [
|
||||||
|
"adler",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "object"
|
||||||
|
version = "0.30.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.17.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.51"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pulldown-cmark"
|
name = "pulldown-cmark"
|
||||||
version = "0.9.2"
|
version = "0.9.2"
|
||||||
|
@ -46,6 +246,88 @@ dependencies = [
|
||||||
"unicase",
|
"unicase",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "radium"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_xoshiro"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "roc_collections"
|
||||||
|
version = "0.0.1"
|
||||||
|
dependencies = [
|
||||||
|
"bitvec",
|
||||||
|
"bumpalo",
|
||||||
|
"fnv",
|
||||||
|
"hashbrown",
|
||||||
|
"im",
|
||||||
|
"im-rc",
|
||||||
|
"wyhash",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "roc_error_macros"
|
||||||
|
version = "0.0.1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "roc_ident"
|
||||||
|
version = "0.0.1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "roc_module"
|
||||||
|
version = "0.0.1"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"roc_collections",
|
||||||
|
"roc_error_macros",
|
||||||
|
"roc_ident",
|
||||||
|
"roc_region",
|
||||||
|
"snafu",
|
||||||
|
"static_assertions",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "roc_parse"
|
||||||
|
version = "0.0.1"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"encode_unicode",
|
||||||
|
"roc_collections",
|
||||||
|
"roc_module",
|
||||||
|
"roc_region",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "roc_region"
|
||||||
|
version = "0.0.1"
|
||||||
|
dependencies = [
|
||||||
|
"static_assertions",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "roc_std"
|
name = "roc_std"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
|
@ -54,12 +336,74 @@ dependencies = [
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-demangle"
|
||||||
|
version = "0.1.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sized-chunks"
|
||||||
|
version = "0.6.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e"
|
||||||
|
dependencies = [
|
||||||
|
"bitmaps",
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "snafu"
|
||||||
|
version = "0.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cb0656e7e3ffb70f6c39b3c2a86332bb74aa3c679da781642590f3c1118c5045"
|
||||||
|
dependencies = [
|
||||||
|
"backtrace",
|
||||||
|
"doc-comment",
|
||||||
|
"snafu-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "snafu-derive"
|
||||||
|
version = "0.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "475b3bbe5245c26f2d8a6f62d67c1f30eb9fffeccee721c45d162c3ebbdf81b2"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "static_assertions"
|
name = "static_assertions"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.107"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tap"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typenum"
|
||||||
|
version = "1.16.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicase"
|
name = "unicase"
|
||||||
version = "2.6.0"
|
version = "2.6.0"
|
||||||
|
@ -69,8 +413,38 @@ dependencies = [
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wyhash"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf6e163c25e3fac820b4b453185ea2dea3b6a3e0a721d4d23d75bd33734c295"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wyz"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
|
||||||
|
dependencies = [
|
||||||
|
"tap",
|
||||||
|
]
|
||||||
|
|
|
@ -18,7 +18,11 @@ path = "src/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
roc_std = { path = "../../../crates/roc_std" }
|
roc_std = { path = "../../../crates/roc_std" }
|
||||||
|
roc_region = { path = "../../../crates/compiler/region" }
|
||||||
|
roc_parse = { path = "../../../crates/compiler/parse" }
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
|
html-escape = "0.2"
|
||||||
|
|
||||||
# Default features include building a binary that we don't need
|
# Default features include building a binary that we don't need
|
||||||
pulldown-cmark = { version = "0.9.2", default-features = false }
|
pulldown-cmark = { version = "0.9.2", default-features = false }
|
||||||
|
|
||||||
|
|
77
examples/static-site-gen/platform/src/highlight.rs
Normal file
77
examples/static-site-gen/platform/src/highlight.rs
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
use roc_parse::highlight::Token;
|
||||||
|
use roc_region::all::Loc;
|
||||||
|
|
||||||
|
pub fn highlight_roc_code(code: &str) -> String {
|
||||||
|
let locations: Vec<Loc<Token>> = roc_parse::highlight::highlight(code);
|
||||||
|
let mut buf: Vec<String> = Vec::new();
|
||||||
|
let mut offset = 0;
|
||||||
|
|
||||||
|
for location in locations {
|
||||||
|
let current_text = &code[offset..location.byte_range().end];
|
||||||
|
|
||||||
|
match location.value {
|
||||||
|
Token::LineComment | Token::DocComment => {
|
||||||
|
buf = push_html_span(buf, current_text, "comment");
|
||||||
|
}
|
||||||
|
Token::SingleQuote
|
||||||
|
| Token::String
|
||||||
|
| Token::UnicodeEscape
|
||||||
|
| Token::EscapedChar
|
||||||
|
| Token::Interpolated => {
|
||||||
|
buf = push_html_span(buf, current_text, "str");
|
||||||
|
}
|
||||||
|
Token::Keyword => {
|
||||||
|
buf = push_html_span(buf, current_text, "kw");
|
||||||
|
}
|
||||||
|
Token::Number => {
|
||||||
|
buf = push_html_span(buf, current_text, "number");
|
||||||
|
}
|
||||||
|
Token::Pipe => {
|
||||||
|
buf = push_html_span(buf, current_text, "pipe");
|
||||||
|
}
|
||||||
|
Token::Arrow => {
|
||||||
|
buf = push_html_span(buf, current_text, "arrow");
|
||||||
|
}
|
||||||
|
Token::Backpass => {
|
||||||
|
buf = push_html_span(buf, current_text, "arrow");
|
||||||
|
}
|
||||||
|
Token::Comma => {
|
||||||
|
buf = push_html_span(buf, current_text, "comma");
|
||||||
|
}
|
||||||
|
Token::Colon | Token::Backslash => {
|
||||||
|
buf = push_html_span(buf, current_text, "colon");
|
||||||
|
}
|
||||||
|
Token::GreaterThan | Token::Minus | Token::LessThan | Token::Plus | Token::Equals => {
|
||||||
|
buf = push_html_span(buf, current_text, "op");
|
||||||
|
}
|
||||||
|
Token::Brace | Token::Bracket | Token::Paren => {
|
||||||
|
buf = push_html_span(buf, current_text, "paren");
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
buf = push_html(buf, current_text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = location.byte_range().end;
|
||||||
|
}
|
||||||
|
|
||||||
|
format!("<pre><samp>{}</samp></pre>", buf.join(""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_html_span(mut buf: Vec<String>, curr: &str, class: &str) -> Vec<String> {
|
||||||
|
// html escape strings from source code
|
||||||
|
let escaped = html_escape::encode_text(curr);
|
||||||
|
|
||||||
|
buf.push(format!("<span class=\"{}\">{}</span>", class, escaped));
|
||||||
|
|
||||||
|
buf
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_html(mut buf: Vec<String>, curr: &str) -> Vec<String> {
|
||||||
|
// html escape strings from source code
|
||||||
|
let escaped = html_escape::encode_text(curr);
|
||||||
|
|
||||||
|
buf.push(format!("{}", escaped));
|
||||||
|
|
||||||
|
buf
|
||||||
|
}
|
|
@ -8,6 +8,8 @@ use std::fs;
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
mod highlight;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#[link_name = "roc__transformFileContentForHost_1_exposed"]
|
#[link_name = "roc__transformFileContentForHost_1_exposed"]
|
||||||
fn roc_transformFileContentForHost(relPath: &RocStr, content: &RocStr) -> RocStr;
|
fn roc_transformFileContentForHost(relPath: &RocStr, content: &RocStr) -> RocStr;
|
||||||
|
@ -202,7 +204,54 @@ fn process_file(input_dir: &Path, output_dir: &Path, input_file: &Path) -> Resul
|
||||||
options.remove(Options::ENABLE_SMART_PUNCTUATION);
|
options.remove(Options::ENABLE_SMART_PUNCTUATION);
|
||||||
|
|
||||||
let parser = Parser::new_ext(&content_md, options);
|
let parser = Parser::new_ext(&content_md, options);
|
||||||
html::push_html(&mut content_html, parser);
|
|
||||||
|
// We'll build a new vector of events since we can only consume the parser once
|
||||||
|
let mut parser_with_highlighting = Vec::new();
|
||||||
|
// As we go along, we'll want to highlight code in bundles, not lines
|
||||||
|
let mut to_highlight = String::new();
|
||||||
|
// And track a little bit of state
|
||||||
|
let mut in_code_block = false;
|
||||||
|
let mut is_roc_code = false;
|
||||||
|
|
||||||
|
for event in parser {
|
||||||
|
match event {
|
||||||
|
pulldown_cmark::Event::Start(pulldown_cmark::Tag::CodeBlock(cbk)) => {
|
||||||
|
in_code_block = true;
|
||||||
|
is_roc_code = is_roc_code_block(&cbk);
|
||||||
|
}
|
||||||
|
pulldown_cmark::Event::End(pulldown_cmark::Tag::CodeBlock(_)) => {
|
||||||
|
if in_code_block {
|
||||||
|
// Format the whole multi-line code block as HTML all at once
|
||||||
|
let highlighted_html: String;
|
||||||
|
if is_roc_code {
|
||||||
|
highlighted_html = crate::highlight::highlight_roc_code(&to_highlight)
|
||||||
|
} else {
|
||||||
|
highlighted_html = format!("<pre><samp>{}</pre></samp>", &to_highlight)
|
||||||
|
}
|
||||||
|
|
||||||
|
// And put it into the vector
|
||||||
|
parser_with_highlighting.push(pulldown_cmark::Event::Html(
|
||||||
|
pulldown_cmark::CowStr::from(highlighted_html),
|
||||||
|
));
|
||||||
|
to_highlight = String::new();
|
||||||
|
in_code_block = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pulldown_cmark::Event::Text(t) => {
|
||||||
|
if in_code_block {
|
||||||
|
// If we're in a code block, build up the string of text
|
||||||
|
to_highlight.push_str(&t);
|
||||||
|
} else {
|
||||||
|
parser_with_highlighting.push(pulldown_cmark::Event::Text(t))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
e => {
|
||||||
|
parser_with_highlighting.push(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
html::push_html(&mut content_html, parser_with_highlighting.into_iter());
|
||||||
|
|
||||||
let roc_relpath = RocStr::from(output_relpath.to_str().unwrap());
|
let roc_relpath = RocStr::from(output_relpath.to_str().unwrap());
|
||||||
let roc_content_html = RocStr::from(content_html.as_str());
|
let roc_content_html = RocStr::from(content_html.as_str());
|
||||||
|
@ -240,3 +289,16 @@ pub fn strip_windows_prefix(path_buf: PathBuf) -> std::path::PathBuf {
|
||||||
|
|
||||||
std::path::Path::new(path_str.trim_start_matches(r"\\?\")).to_path_buf()
|
std::path::Path::new(path_str.trim_start_matches(r"\\?\")).to_path_buf()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_roc_code_block(cbk: &pulldown_cmark::CodeBlockKind) -> bool {
|
||||||
|
match cbk {
|
||||||
|
pulldown_cmark::CodeBlockKind::Indented => false,
|
||||||
|
pulldown_cmark::CodeBlockKind::Fenced(cow_str) => {
|
||||||
|
if cow_str.contains("roc") {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -44,7 +44,6 @@
|
||||||
xorg.libXrandr
|
xorg.libXrandr
|
||||||
xorg.libXi
|
xorg.libXi
|
||||||
xorg.libxcb
|
xorg.libxcb
|
||||||
alsa-lib
|
|
||||||
];
|
];
|
||||||
|
|
||||||
darwinInputs = with pkgs;
|
darwinInputs = with pkgs;
|
||||||
|
|
|
@ -629,7 +629,7 @@ We can also give `List.map` a named function, instead of an anonymous one:
|
||||||
|
|
||||||
<samp>List.map <span class="brace">[</span><span class="number">1</span><span class="comma">,</span> <span class="number">2</span><span class="comma">,</span> <span class="number">3</span><span class="brace">]</span> Num.isOdd</samp>
|
<samp>List.map <span class="brace">[</span><span class="number">1</span><span class="comma">,</span> <span class="number">2</span><span class="comma">,</span> <span class="number">3</span><span class="brace">]</span> Num.isOdd</samp>
|
||||||
|
|
||||||
This `Num.isOdd` function returns `Bool.true` if it's given an odd number, and `Bool.false` otherwise. So `Num.isOdd 5` returns true and `Num.isOdd 2` returns false.
|
This `Num.isOdd` function returns `Bool.true` if it's given an odd number, and `Bool.false` otherwise. So `Num.isOdd 5` returns `Bool.true` and `Num.isOdd 2` returns `Bool.false`.
|
||||||
|
|
||||||
As such, calling `List.map [1, 2, 3] Num.isOdd` returns a new list of `[Bool.true, Bool.false, Bool.true]`.
|
As such, calling `List.map [1, 2, 3] Num.isOdd` returns a new list of `[Bool.true, Bool.false, Bool.true]`.
|
||||||
|
|
||||||
|
@ -694,7 +694,7 @@ These two versions compile to the same thing. As a convenience, Roc lets you spe
|
||||||
|
|
||||||
### [`List.any` and `List.all`](#list-any-and-list-all) {#list-any-and-list-all}
|
### [`List.any` and `List.all`](#list-any-and-list-all) {#list-any-and-list-all}
|
||||||
|
|
||||||
There are several functions that work like `List.map`, they walk through each element of a list and do something with it. Another is `List.any`, which returns `Bool.true` if calling the given function on any element in the list returns `true`:
|
There are several functions that work like `List.map`, they walk through each element of a list and do something with it. Another is `List.any`, which returns `Bool.true` if calling the given function on any element in the list returns `Bool.true`:
|
||||||
|
|
||||||
<pre><samp>List.any [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>] Num.isOdd
|
<pre><samp>List.any [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>] Num.isOdd
|
||||||
<span class="comment"># returns `Bool.true` because 1 and 3 are odd</span>
|
<span class="comment"># returns `Bool.true` because 1 and 3 are odd</span>
|
||||||
|
@ -704,7 +704,7 @@ There are several functions that work like `List.map`, they walk through each el
|
||||||
<span class="comment"># returns `Bool.false` because none of these is negative</span>
|
<span class="comment"># returns `Bool.false` because none of these is negative</span>
|
||||||
</samp></pre>
|
</samp></pre>
|
||||||
|
|
||||||
There's also `List.all` which only returns `true` if all the elements in the list pass the test:
|
There's also `List.all` which only returns `Bool.true` if all the elements in the list pass the test:
|
||||||
|
|
||||||
<pre><samp>List.all [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>] Num.isOdd
|
<pre><samp>List.all [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>] Num.isOdd
|
||||||
<span class="comment"># returns `Bool.<span class="hljs-literal">false</span>` because 2 is not odd</span>
|
<span class="comment"># returns `Bool.<span class="hljs-literal">false</span>` because 2 is not odd</span>
|
||||||
|
@ -722,7 +722,7 @@ You can also drop elements from a list. One way is `List.dropAt` - for example:
|
||||||
<span class="comment"># drops the element at offset 1 ("Lee") and returns ["Sam", "Ari"]</span>
|
<span class="comment"># drops the element at offset 1 ("Lee") and returns ["Sam", "Ari"]</span>
|
||||||
</samp></pre>
|
</samp></pre>
|
||||||
|
|
||||||
Another way is to use `List.keepIf`, which passes each of the list's elements to the given function, and then keeps them only if that function returns `true`.
|
Another way is to use `List.keepIf`, which passes each of the list's elements to the given function, and then keeps them only if that function returns `Bool.true`.
|
||||||
|
|
||||||
<pre><samp>List.keepIf [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>] Num.isEven
|
<pre><samp>List.keepIf [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>] Num.isEven
|
||||||
<span class="comment"># returns [2, 4]</span>
|
<span class="comment"># returns [2, 4]</span>
|
||||||
|
@ -1279,7 +1279,7 @@ You can write automated tests for your Roc code like so:
|
||||||
<span class="kw">expect</span> pluralize <span class="str">"cactus"</span> <span class="str">"cacti"</span> <span class="number">2</span> <span class="op">==</span> <span class="str">"2 cacti"</span>
|
<span class="kw">expect</span> pluralize <span class="str">"cactus"</span> <span class="str">"cacti"</span> <span class="number">2</span> <span class="op">==</span> <span class="str">"2 cacti"</span>
|
||||||
</samp></pre>
|
</samp></pre>
|
||||||
|
|
||||||
If you put this in a file named `main.roc` and run `roc test`, Roc will execute the two `expect` expressions (that is, the two `pluralize` calls) and report any that returned `false`.
|
If you put this in a file named `main.roc` and run `roc test`, Roc will execute the two `expect` expressions (that is, the two `pluralize` calls) and report any that returned `Bool.false`.
|
||||||
|
|
||||||
If a test fails, it will not show the actual value that differs from the expected value. To show the actual value, you can write the expect like this:
|
If a test fails, it will not show the actual value that differs from the expected value. To show the actual value, you can write the expect like this:
|
||||||
|
|
||||||
|
|
|
@ -323,6 +323,10 @@ p, aside, li, footer {
|
||||||
font-size: inherit;
|
font-size: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
#tutorial-toc-toggle-label,
|
#tutorial-toc-toggle-label,
|
||||||
#close-tutorial-toc {
|
#close-tutorial-toc {
|
||||||
display: block;
|
display: block;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue