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
|
||||
|
||||
- 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.
|
||||
|
||||
- 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
|
||||
|
||||
- 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.
|
||||
|
||||
- name: get commit SHA
|
||||
|
|
346
Cargo.lock
generated
346
Cargo.lock
generated
|
@ -68,28 +68,6 @@ dependencies = [
|
|||
"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]]
|
||||
name = "approx"
|
||||
version = "0.4.0"
|
||||
|
@ -198,25 +176,6 @@ dependencies = [
|
|||
"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]]
|
||||
name = "bit-set"
|
||||
version = "0.5.2"
|
||||
|
@ -415,24 +374,6 @@ name = "cc"
|
|||
version = "1.0.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "cfg-if"
|
||||
|
@ -462,17 +403,6 @@ dependencies = [
|
|||
"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]]
|
||||
name = "clap"
|
||||
version = "2.34.0"
|
||||
|
@ -523,12 +453,6 @@ dependencies = [
|
|||
"os_str_bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "claxon"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688"
|
||||
|
||||
[[package]]
|
||||
name = "cli_utils"
|
||||
version = "0.0.1"
|
||||
|
@ -620,16 +544,6 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "combine"
|
||||
version = "4.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a604e93b79d1808327a6fca85a6f2d69de66461e7620f5a4cbf5fb4d1d7c948"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "confy"
|
||||
version = "0.5.0"
|
||||
|
@ -792,50 +706,6 @@ dependencies = [
|
|||
"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]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.2"
|
||||
|
@ -1471,12 +1341,6 @@ version = "0.26.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4"
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||
|
||||
[[package]]
|
||||
name = "glow"
|
||||
version = "0.11.2"
|
||||
|
@ -1632,12 +1496,6 @@ version = "0.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
|
||||
|
||||
[[package]]
|
||||
name = "hound"
|
||||
version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a164bb2ceaeff4f42542bdb847c41517c78a60f5649671b2a07312b6e117549"
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "0.2.8"
|
||||
|
@ -1876,35 +1734,12 @@ version = "1.0.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "jni-sys"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.60"
|
||||
|
@ -1946,23 +1781,6 @@ version = "1.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "libc"
|
||||
version = "0.2.135"
|
||||
|
@ -2032,15 +1850,6 @@ dependencies = [
|
|||
"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]]
|
||||
name = "mach_object"
|
||||
version = "0.1.17"
|
||||
|
@ -2155,26 +1964,6 @@ version = "0.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.5.3"
|
||||
|
@ -2232,20 +2021,7 @@ checksum = "96d868f654c72e75f8687572699cdabe755f03effbb62542768e995d5b8d699d"
|
|||
dependencies = [
|
||||
"bitflags",
|
||||
"jni-sys",
|
||||
"ndk-sys 0.2.2",
|
||||
"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",
|
||||
"ndk-sys",
|
||||
"num_enum",
|
||||
"thiserror",
|
||||
]
|
||||
|
@ -2265,25 +2041,10 @@ dependencies = [
|
|||
"lazy_static",
|
||||
"libc",
|
||||
"log",
|
||||
"ndk 0.5.0",
|
||||
"ndk",
|
||||
"ndk-context",
|
||||
"ndk-macro",
|
||||
"ndk-sys 0.2.2",
|
||||
]
|
||||
|
||||
[[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",
|
||||
"ndk-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2305,15 +2066,6 @@ version = "0.2.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "nibble_vec"
|
||||
version = "0.1.0"
|
||||
|
@ -2386,17 +2138,6 @@ dependencies = [
|
|||
"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]]
|
||||
name = "num-traits"
|
||||
version = "0.2.15"
|
||||
|
@ -2498,38 +2239,6 @@ dependencies = [
|
|||
"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]]
|
||||
name = "once_cell"
|
||||
version = "1.17.0"
|
||||
|
@ -2685,12 +2394,6 @@ dependencies = [
|
|||
"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]]
|
||||
name = "peg"
|
||||
version = "0.8.1"
|
||||
|
@ -3570,7 +3273,6 @@ dependencies = [
|
|||
"roc_types",
|
||||
"roc_unify",
|
||||
"roc_utils",
|
||||
"rodio",
|
||||
"serde",
|
||||
"snafu",
|
||||
"tempfile",
|
||||
|
@ -4187,19 +3889,6 @@ dependencies = [
|
|||
"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]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.21"
|
||||
|
@ -4501,12 +4190,6 @@ dependencies = [
|
|||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook"
|
||||
version = "0.3.14"
|
||||
|
@ -4554,17 +4237,6 @@ version = "0.4.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "slotmap"
|
||||
version = "1.0.6"
|
||||
|
@ -4682,12 +4354,6 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "stdweb"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e"
|
||||
|
||||
[[package]]
|
||||
name = "str-buf"
|
||||
version = "1.0.6"
|
||||
|
@ -5792,9 +5458,9 @@ dependencies = [
|
|||
"libc",
|
||||
"log",
|
||||
"mio",
|
||||
"ndk 0.5.0",
|
||||
"ndk-glue 0.5.2",
|
||||
"ndk-sys 0.2.2",
|
||||
"ndk",
|
||||
"ndk-glue",
|
||||
"ndk-sys",
|
||||
"objc",
|
||||
"parking_lot 0.11.2",
|
||||
"percent-encoding",
|
||||
|
|
|
@ -748,6 +748,7 @@ sqrtChecked = \x ->
|
|||
else
|
||||
Ok (Num.sqrt x)
|
||||
|
||||
## Natural logarithm
|
||||
log : Frac a -> Frac a
|
||||
|
||||
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!(),
|
||||
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!(),
|
||||
Expect { .. } => 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.
|
||||
- [Alternative Online Assembler](http://shell-storm.org/online/Online-Assembler-and-Disassembler/) -
|
||||
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.
|
||||
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) -
|
||||
|
|
|
@ -2,10 +2,13 @@ use crate::generic64::{storage::StorageManager, Assembler, CallConv, RegTrait};
|
|||
use crate::Relocation;
|
||||
use bumpalo::collections::Vec;
|
||||
use packed_struct::prelude::*;
|
||||
use roc_builtins::bitcode::FloatWidth;
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::layout::{InLayout, STLayoutInterner};
|
||||
|
||||
use super::CompareOperation;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
|
||||
#[allow(dead_code)]
|
||||
pub enum AArch64GeneralReg {
|
||||
|
@ -609,9 +612,31 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> for AArch64Assembler {
|
|||
}
|
||||
}
|
||||
#[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) {
|
||||
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)]
|
||||
fn mov_base32_reg64(buf: &mut Vec<'_, u8>, offset: i32, src: AArch64GeneralReg) {
|
||||
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)]
|
||||
fn mov_reg64_mem64_offset32(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
|
@ -640,6 +678,41 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> for AArch64Assembler {
|
|||
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)]
|
||||
fn mov_mem64_offset32_reg64(
|
||||
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)]
|
||||
fn movsx_reg64_base32(buf: &mut Vec<'_, u8>, dst: AArch64GeneralReg, offset: i32, size: u8) {
|
||||
debug_assert!(size <= 8);
|
||||
|
@ -788,6 +891,18 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> for AArch64Assembler {
|
|||
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)]
|
||||
fn igt_reg64_reg64_reg64(
|
||||
_buf: &mut Vec<'_, u8>,
|
||||
|
@ -938,6 +1053,14 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> for AArch64Assembler {
|
|||
{
|
||||
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 {}
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
|||
single_register_floats, single_register_int_builtins, single_register_integers, Backend, Env,
|
||||
Relocation,
|
||||
};
|
||||
use bumpalo::collections::Vec;
|
||||
use bumpalo::collections::{CollectIn, Vec};
|
||||
use roc_builtins::bitcode::{self, FloatWidth, IntWidth};
|
||||
use roc_collections::all::MutMap;
|
||||
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.
|
||||
/// 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.
|
||||
|
@ -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.
|
||||
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(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
dst: GeneralReg,
|
||||
src: GeneralReg,
|
||||
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(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
dst: GeneralReg,
|
||||
offset: i32,
|
||||
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`
|
||||
/// 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_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 mul_freg32_freg32_freg32(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
|
@ -361,6 +416,15 @@ pub trait Assembler<GeneralReg: RegTrait, FloatReg: RegTrait>: Sized + Copy {
|
|||
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(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
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>) {
|
||||
use Builtin::Int;
|
||||
|
||||
|
@ -1112,6 +1200,16 @@ impl<
|
|||
.load_to_general_reg(&mut self.buf, src2);
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
@ -1128,42 +1226,27 @@ impl<
|
|||
.load_to_general_reg(&mut self.buf, src2);
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
||||
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>) {
|
||||
match *arg_layout {
|
||||
Layout::BOOL => {
|
||||
|
@ -1209,6 +1292,20 @@ impl<
|
|||
.load_to_general_reg(&mut self.buf, src2);
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
@ -1241,6 +1338,20 @@ impl<
|
|||
.load_to_general_reg(&mut self.buf, src2);
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
@ -1321,6 +1432,26 @@ impl<
|
|||
.load_to_general_reg(&mut self.buf, src2);
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
@ -1343,6 +1474,26 @@ impl<
|
|||
.load_to_general_reg(&mut self.buf, src2);
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
@ -1567,43 +1718,14 @@ impl<
|
|||
ASM::add_reg64_reg64_reg64(buf, tmp, tmp, list_ptr);
|
||||
let element_ptr = tmp;
|
||||
|
||||
match *ret_layout {
|
||||
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(
|
||||
Self::ptr_read(
|
||||
buf,
|
||||
storage_manager,
|
||||
*dst,
|
||||
self.layout_interner,
|
||||
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(
|
||||
&mut self,
|
||||
sym: &Symbol,
|
||||
element_layout: &InLayout<'a>,
|
||||
elements: &'a [ListLiteralElement<'a>],
|
||||
element_in_layout: &InLayout<'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)
|
||||
let data_bytes_symbol = Symbol::DEV_TMP;
|
||||
|
@ -1904,54 +2027,34 @@ impl<
|
|||
.load_to_general_reg(&mut self.buf, &Symbol::DEV_TMP3);
|
||||
|
||||
// Copy everything into output array.
|
||||
let mut elem_offset = 0;
|
||||
let mut element_offset = 0;
|
||||
for elem in elements {
|
||||
// TODO: this could be a lot faster when loading large lists
|
||||
// if we move matching on the element layout to outside this loop.
|
||||
// It also greatly bloats the code here.
|
||||
// Refactor this and switch to one external match.
|
||||
// We also could make loadining indivitual literals much faster
|
||||
let elem_sym = match elem {
|
||||
ListLiteralElement::Symbol(sym) => sym,
|
||||
let element_symbol = match elem {
|
||||
ListLiteralElement::Symbol(sym) => *sym,
|
||||
ListLiteralElement::Literal(lit) => {
|
||||
self.load_literal(&Symbol::DEV_TMP, element_layout, lit);
|
||||
&Symbol::DEV_TMP
|
||||
self.load_literal(&Symbol::DEV_TMP, element_in_layout, lit);
|
||||
Symbol::DEV_TMP
|
||||
}
|
||||
};
|
||||
// TODO: Expand to all types.
|
||||
match self.layout_interner.get(*element_layout) {
|
||||
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(
|
||||
|
||||
Self::ptr_write(
|
||||
&mut self.buf,
|
||||
|_storage_manager, buf, tmp_reg| {
|
||||
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,
|
||||
&mut self.storage_manager,
|
||||
ptr_reg,
|
||||
elem_offset + i,
|
||||
tmp_reg,
|
||||
element_offset,
|
||||
element_width,
|
||||
element_layout,
|
||||
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);
|
||||
|
||||
element_offset += element_width as i32;
|
||||
if element_symbol == Symbol::DEV_TMP {
|
||||
self.free_symbol(&element_symbol);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2049,38 +2152,15 @@ impl<
|
|||
let element_width = self.layout_interner.stack_size(element_layout) as u64;
|
||||
let element_offset = 0;
|
||||
|
||||
// TODO: Expand to all types.
|
||||
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(
|
||||
Self::ptr_write(
|
||||
&mut self.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,
|
||||
&mut self.storage_manager,
|
||||
ptr_reg,
|
||||
element_offset + i,
|
||||
tmp_reg,
|
||||
element_offset,
|
||||
element_width,
|
||||
self.layout_interner.get(element_layout),
|
||||
value,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
x => todo!("copying data to list with layout, {:?}", x),
|
||||
}
|
||||
|
||||
if value == Symbol::DEV_TMP {
|
||||
self.free_symbol(&value);
|
||||
|
@ -2098,26 +2178,15 @@ impl<
|
|||
.storage_manager
|
||||
.load_to_general_reg(&mut self.buf, &ptr);
|
||||
|
||||
let ret_stack_size = self.layout_interner.stack_size(element_layout);
|
||||
|
||||
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(
|
||||
Self::ptr_read(
|
||||
&mut self.buf,
|
||||
|storage_manager, buf, tmp_reg| {
|
||||
Self::unbox_str_or_list(buf, storage_manager, dst, ptr_reg, tmp_reg);
|
||||
},
|
||||
&mut self.storage_manager,
|
||||
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>) {
|
||||
self.storage_manager.load_union_tag_id(
|
||||
|
@ -2165,6 +2234,33 @@ impl<
|
|||
let val = *x;
|
||||
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)) => {
|
||||
let reg = self.storage_manager.claim_general_reg(&mut self.buf, sym);
|
||||
let val = [*x as u8; 16];
|
||||
|
@ -2180,7 +2276,27 @@ impl<
|
|||
let val = *x as f32;
|
||||
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.
|
||||
self.storage_manager.with_tmp_general_reg(
|
||||
&mut self.buf,
|
||||
|
@ -2207,6 +2323,17 @@ impl<
|
|||
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),
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -2494,6 +2633,115 @@ impl<
|
|||
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.
|
||||
fn update_jmp_imm32_offset(
|
||||
&mut self,
|
||||
|
|
|
@ -9,7 +9,6 @@ use roc_collections::all::{MutMap, MutSet};
|
|||
use roc_error_macros::internal_error;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::{
|
||||
borrow::Ownership,
|
||||
ir::{JoinPointId, Param},
|
||||
layout::{
|
||||
Builtin, InLayout, Layout, LayoutInterner, STLayoutInterner, TagIdIntType, UnionLayout,
|
||||
|
@ -315,7 +314,7 @@ impl<
|
|||
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 {
|
||||
reg: None,
|
||||
|
@ -350,8 +349,10 @@ impl<
|
|||
self.free_reference(sym);
|
||||
reg
|
||||
}
|
||||
Stack(Complex { .. }) => {
|
||||
internal_error!("Cannot load large values into general registers: {}", sym)
|
||||
Stack(Complex { size, .. }) => {
|
||||
internal_error!(
|
||||
"Cannot load large values (size {size}) into general registers: {sym:?}",
|
||||
)
|
||||
}
|
||||
NoData => {
|
||||
internal_error!("Cannot load no data into general registers: {}", sym)
|
||||
|
@ -448,7 +449,7 @@ impl<
|
|||
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 {
|
||||
reg: None,
|
||||
|
@ -458,19 +459,25 @@ impl<
|
|||
ASM::mov_reg64_base32(buf, reg, *base_offset);
|
||||
}
|
||||
Stack(ReferencedPrimitive {
|
||||
base_offset, size, ..
|
||||
}) if base_offset % 8 == 0 && *size == 8 => {
|
||||
// The primitive is aligned and the data is exactly 8 bytes, treat it like regular stack.
|
||||
ASM::mov_reg64_base32(buf, reg, *base_offset);
|
||||
base_offset,
|
||||
size,
|
||||
sign_extend,
|
||||
}) => {
|
||||
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 { .. }) => {
|
||||
internal_error!("Cannot load large values into general registers: {}", sym)
|
||||
Stack(Complex { size, .. }) => {
|
||||
internal_error!(
|
||||
"Cannot load large values (size {size}) into general registers: {sym:?}",
|
||||
)
|
||||
}
|
||||
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.symbol_storage_map.insert(
|
||||
*sym,
|
||||
Stack(if is_primitive(layout) {
|
||||
Stack(if is_primitive(layout_interner, layout) {
|
||||
ReferencedPrimitive {
|
||||
base_offset: data_offset,
|
||||
size,
|
||||
|
@ -739,16 +746,74 @@ impl<
|
|||
layout: &InLayout<'a>,
|
||||
) {
|
||||
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);
|
||||
let reg = self.load_to_general_reg(buf, sym);
|
||||
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);
|
||||
let reg = self.load_to_float_reg(buf, sym);
|
||||
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 => {}
|
||||
// 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.
|
||||
|
@ -756,20 +821,64 @@ impl<
|
|||
// Later, it will be reloaded and stored in refcounted as needed.
|
||||
_ if layout_interner.stack_size(*layout) > 8 => {
|
||||
let (from_offset, size) = self.stack_offset_and_size(sym);
|
||||
debug_assert!(from_offset % 8 == 0);
|
||||
debug_assert!(size % 8 == 0);
|
||||
debug_assert_eq!(from_offset % 8, 0);
|
||||
debug_assert_eq!(size % 8, 0);
|
||||
debug_assert_eq!(size, layout_interner.stack_size(*layout));
|
||||
self.with_tmp_general_reg(buf, |_storage_manager, buf, reg| {
|
||||
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);
|
||||
}
|
||||
});
|
||||
self.copy_to_stack_offset(buf, size, from_offset, to_offset)
|
||||
}
|
||||
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)]
|
||||
/// Ensures that a register is free. If it is not free, data will be moved to make it free.
|
||||
pub fn ensure_reg_free(
|
||||
|
@ -1008,15 +1117,10 @@ impl<
|
|||
param_storage.reserve(params.len());
|
||||
for Param {
|
||||
symbol,
|
||||
ownership,
|
||||
ownership: _,
|
||||
layout,
|
||||
} 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.
|
||||
// Put everything on the stack for simplicity.
|
||||
match *layout {
|
||||
|
@ -1331,6 +1435,15 @@ impl<
|
|||
}
|
||||
}
|
||||
|
||||
fn is_primitive(layout: InLayout<'_>) -> bool {
|
||||
matches!(layout, single_register_layouts!())
|
||||
fn is_primitive(layout_interner: &mut STLayoutInterner<'_>, layout: InLayout<'_>) -> bool {
|
||||
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 => {
|
||||
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(
|
||||
sym,
|
||||
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)
|
||||
}
|
||||
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 => {
|
||||
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)
|
||||
|
@ -572,6 +596,20 @@ trait Backend<'a> {
|
|||
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 => {
|
||||
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)
|
||||
|
@ -623,32 +661,6 @@ trait Backend<'a> {
|
|||
);
|
||||
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 => {
|
||||
debug_assert_eq!(1, args.len(), "Not: expected to have exactly one argument");
|
||||
debug_assert_eq!(
|
||||
|
@ -739,6 +751,30 @@ trait Backend<'a> {
|
|||
);
|
||||
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(
|
||||
sym,
|
||||
bitcode::NUM_ROUND_F64[IntWidth::I64].to_string(),
|
||||
|
@ -819,6 +855,13 @@ trait Backend<'a> {
|
|||
arg_layouts,
|
||||
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(
|
||||
sym,
|
||||
bitcode::STR_SPLIT.to_string(),
|
||||
|
@ -840,6 +883,13 @@ trait Backend<'a> {
|
|||
arg_layouts,
|
||||
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(
|
||||
sym,
|
||||
bitcode::STR_ENDS_WITH.to_string(),
|
||||
|
@ -854,6 +904,122 @@ trait Backend<'a> {
|
|||
arg_layouts,
|
||||
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 => {
|
||||
debug_assert_eq!(
|
||||
1,
|
||||
|
@ -920,13 +1086,6 @@ trait Backend<'a> {
|
|||
self.load_literal_symbols(args);
|
||||
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 => {
|
||||
let bool_layout = Layout::BOOL;
|
||||
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.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>,
|
||||
);
|
||||
|
||||
/// 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.
|
||||
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.
|
||||
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.
|
||||
fn build_not(&mut self, dst: &Symbol, src: &Symbol, arg_layout: &InLayout<'a>);
|
||||
|
||||
|
@ -1105,6 +1285,9 @@ trait Backend<'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.
|
||||
fn build_list_len(&mut self, dst: &Symbol, list: &Symbol);
|
||||
|
||||
|
|
|
@ -1319,6 +1319,7 @@ define_builtins! {
|
|||
53 STR_WITH_CAPACITY: "withCapacity"
|
||||
54 STR_WITH_PREFIX: "withPrefix"
|
||||
55 STR_GRAPHEMES: "graphemes"
|
||||
56 STR_IS_VALID_SCALAR: "isValidScalar"
|
||||
}
|
||||
6 LIST: "List" => {
|
||||
0 LIST_LIST: "List" exposed_apply_type=true // the List.List type alias
|
||||
|
@ -1401,6 +1402,7 @@ define_builtins! {
|
|||
77 LIST_COUNT_IF: "countIf"
|
||||
78 LIST_WALK_FROM: "walkFrom"
|
||||
79 LIST_WALK_FROM_UNTIL: "walkFromUntil"
|
||||
80 LIST_ITER_HELP: "iterHelp"
|
||||
}
|
||||
7 RESULT: "Result" => {
|
||||
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.
|
||||
let is_host_exposed = host_exposed_procs.contains(&key.0);
|
||||
|
||||
let param_offset = param_map.get_param_offset(key.0, key.1);
|
||||
env.collect_proc(&mut param_map, proc, param_offset, is_host_exposed);
|
||||
let param_offset = param_map.get_param_offset(interner, key.0, key.1);
|
||||
env.collect_proc(
|
||||
interner,
|
||||
&mut param_map,
|
||||
proc,
|
||||
param_offset,
|
||||
is_host_exposed,
|
||||
);
|
||||
}
|
||||
|
||||
if !env.modified {
|
||||
|
@ -167,6 +173,7 @@ impl<'a> DeclarationToIndex<'a> {
|
|||
|
||||
fn get_param_offset(
|
||||
&self,
|
||||
interner: &STLayoutInterner<'a>,
|
||||
needle_symbol: Symbol,
|
||||
needle_layout: ProcLayout<'a>,
|
||||
) -> ParamOffset {
|
||||
|
@ -181,12 +188,14 @@ impl<'a> DeclarationToIndex<'a> {
|
|||
.elements
|
||||
.iter()
|
||||
.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<_>>();
|
||||
unreachable!(
|
||||
"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> {
|
||||
pub fn get_param_offset(&self, symbol: Symbol, layout: ProcLayout<'a>) -> ParamOffset {
|
||||
self.declaration_to_index.get_param_offset(symbol, layout)
|
||||
pub fn get_param_offset(
|
||||
&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.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())
|
||||
}
|
||||
|
@ -292,7 +312,7 @@ impl<'a> ParamMap<'a> {
|
|||
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)
|
||||
.iter()
|
||||
|
@ -312,7 +332,7 @@ impl<'a> ParamMap<'a> {
|
|||
proc: &Proc<'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)
|
||||
.iter()
|
||||
|
@ -534,7 +554,13 @@ impl<'a> BorrowInfState<'a> {
|
|||
///
|
||||
/// and determines whether z and which of the symbols used in e
|
||||
/// 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::*;
|
||||
|
||||
let crate::ir::Call {
|
||||
|
@ -553,7 +579,7 @@ impl<'a> BorrowInfState<'a> {
|
|||
|
||||
// get the borrow signature of the applied function
|
||||
let ps = param_map
|
||||
.get_symbol(name.name(), top_level)
|
||||
.get_symbol(interner, name.name(), top_level)
|
||||
.expect("function is defined");
|
||||
|
||||
// the return value will be owned
|
||||
|
@ -595,8 +621,11 @@ impl<'a> BorrowInfState<'a> {
|
|||
niche: passed_function.name.niche(),
|
||||
};
|
||||
|
||||
let function_ps =
|
||||
match param_map.get_symbol(passed_function.name.name(), closure_layout) {
|
||||
let function_ps = match param_map.get_symbol(
|
||||
interner,
|
||||
passed_function.name.name(),
|
||||
closure_layout,
|
||||
) {
|
||||
Some(function_ps) => function_ps,
|
||||
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::*;
|
||||
|
||||
match e {
|
||||
|
@ -724,7 +759,7 @@ impl<'a> BorrowInfState<'a> {
|
|||
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(_) => {}
|
||||
|
||||
|
@ -757,6 +792,7 @@ impl<'a> BorrowInfState<'a> {
|
|||
#[allow(clippy::many_single_char_names)]
|
||||
fn preserve_tail_call(
|
||||
&mut self,
|
||||
interner: &STLayoutInterner<'a>,
|
||||
param_map: &mut ParamMap<'a>,
|
||||
x: Symbol,
|
||||
v: &Expr<'a>,
|
||||
|
@ -782,7 +818,7 @@ impl<'a> BorrowInfState<'a> {
|
|||
if self.current_proc == g.name() && x == *z {
|
||||
// anonymous functions (for which the ps may not be known)
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
@ -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::*;
|
||||
|
||||
match stmt {
|
||||
|
@ -813,11 +854,11 @@ impl<'a> BorrowInfState<'a> {
|
|||
} => {
|
||||
let old = self.param_set.clone();
|
||||
self.update_param_set(ys);
|
||||
self.collect_stmt(param_map, v);
|
||||
self.collect_stmt(interner, param_map, v);
|
||||
self.param_set = old;
|
||||
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) => {
|
||||
|
@ -830,17 +871,17 @@ impl<'a> BorrowInfState<'a> {
|
|||
stack.push((*symbol, expr));
|
||||
}
|
||||
|
||||
self.collect_stmt(param_map, b);
|
||||
self.collect_stmt(interner, param_map, b);
|
||||
|
||||
let mut it = stack.into_iter().rev();
|
||||
|
||||
// collect the final expr, and see if we need to preserve a tail call
|
||||
let (x, v) = it.next().unwrap();
|
||||
self.collect_expr(param_map, x, v);
|
||||
self.preserve_tail_call(param_map, x, v, b);
|
||||
self.collect_expr(interner, param_map, x, v);
|
||||
self.preserve_tail_call(interner, param_map, x, v, b);
|
||||
|
||||
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() {
|
||||
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, .. } => {
|
||||
self.collect_stmt(param_map, remainder);
|
||||
self.collect_stmt(interner, param_map, remainder);
|
||||
}
|
||||
|
||||
Expect { remainder, .. } => {
|
||||
self.collect_stmt(param_map, remainder);
|
||||
self.collect_stmt(interner, param_map, remainder);
|
||||
}
|
||||
|
||||
ExpectFx { remainder, .. } => {
|
||||
self.collect_stmt(param_map, remainder);
|
||||
self.collect_stmt(interner, param_map, remainder);
|
||||
}
|
||||
|
||||
Refcounting(_, _) => unreachable!("these have not been introduced yet"),
|
||||
|
@ -891,6 +932,7 @@ impl<'a> BorrowInfState<'a> {
|
|||
|
||||
fn collect_proc(
|
||||
&mut self,
|
||||
interner: &STLayoutInterner<'a>,
|
||||
param_map: &mut ParamMap<'a>,
|
||||
proc: &Proc<'a>,
|
||||
param_offset: ParamOffset,
|
||||
|
@ -912,7 +954,7 @@ impl<'a> BorrowInfState<'a> {
|
|||
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.param_set = old;
|
||||
|
|
|
@ -605,7 +605,7 @@ impl<'a, 'i> Context<'a, 'i> {
|
|||
// get the borrow signature
|
||||
let ps = self
|
||||
.param_map
|
||||
.get_symbol(name.name(), top_level)
|
||||
.get_symbol(self.layout_interner, name.name(), top_level)
|
||||
.expect("function is defined");
|
||||
|
||||
let v = Expr::Call(crate::ir::Call {
|
||||
|
@ -653,10 +653,11 @@ impl<'a, 'i> Context<'a, 'i> {
|
|||
niche: passed_function.name.niche(),
|
||||
};
|
||||
|
||||
let function_ps = match self
|
||||
.param_map
|
||||
.get_symbol(passed_function.name.name(), function_layout)
|
||||
{
|
||||
let function_ps = match self.param_map.get_symbol(
|
||||
self.layout_interner,
|
||||
passed_function.name.name(),
|
||||
function_layout,
|
||||
) {
|
||||
Some(function_ps) => function_ps,
|
||||
None => unreachable!(),
|
||||
};
|
||||
|
@ -1510,19 +1511,28 @@ pub fn visit_procs<'a, 'i>(
|
|||
};
|
||||
|
||||
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>(
|
||||
arena: &'a Bump,
|
||||
interner: &STLayoutInterner<'a>,
|
||||
codegen: &mut CodegenTools<'i>,
|
||||
param_map: &'a ParamMap<'a>,
|
||||
ctx: &Context<'a, 'i>,
|
||||
proc: &mut Proc<'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,
|
||||
None => Vec::from_iter_in(
|
||||
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>(
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -365,6 +365,10 @@ pub trait LayoutInterner<'a>: Sized {
|
|||
fn dbg_deep<'r>(&'r self, layout: InLayout<'a>) -> dbg::Dbg<'a, 'r, Self> {
|
||||
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.
|
||||
|
@ -1274,7 +1278,7 @@ mod equiv {
|
|||
}
|
||||
}
|
||||
|
||||
mod dbg {
|
||||
pub mod dbg {
|
||||
use roc_module::symbol::Symbol;
|
||||
|
||||
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> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::ast::CommentOrNewline;
|
||||
use crate::ast::Spaceable;
|
||||
use crate::parser::Progress;
|
||||
use crate::parser::SpaceProblem;
|
||||
use crate::parser::{self, and, backtrackable, BadInputError, Parser, Progress::*};
|
||||
use crate::state::State;
|
||||
|
@ -7,6 +8,7 @@ use bumpalo::collections::vec::Vec;
|
|||
use bumpalo::Bump;
|
||||
use roc_region::all::Loc;
|
||||
use roc_region::all::Position;
|
||||
use roc_region::all::Region;
|
||||
|
||||
pub fn space0_around_ee<'a, P, S, E>(
|
||||
parser: P,
|
||||
|
@ -386,9 +388,42 @@ pub fn spaces<'a, E>() -> impl Parser<'a, &'a [CommentOrNewline<'a>], E>
|
|||
where
|
||||
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);
|
||||
|
||||
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 found_newline = false;
|
||||
loop {
|
||||
let whitespace = fast_eat_whitespace(state.bytes());
|
||||
if whitespace > 0 {
|
||||
|
@ -396,6 +431,8 @@ where
|
|||
progress = MadeProgress;
|
||||
}
|
||||
|
||||
let start = state.pos();
|
||||
|
||||
match state.bytes().first() {
|
||||
Some(b'#') => {
|
||||
state.advance_mut(1);
|
||||
|
@ -424,8 +461,9 @@ where
|
|||
} else {
|
||||
CommentOrNewline::LineComment(text)
|
||||
};
|
||||
newlines.push(comment);
|
||||
state.advance_mut(len);
|
||||
on_space(start, comment, state.pos());
|
||||
found_newline = true;
|
||||
|
||||
if begins_with_crlf(state.bytes()) {
|
||||
state.advance_mut(1);
|
||||
|
@ -438,23 +476,22 @@ where
|
|||
}
|
||||
Some(b'\r') => {
|
||||
if state.bytes().get(1) == Some(&b'\n') {
|
||||
newlines.push(CommentOrNewline::Newline);
|
||||
state.advance_mut(1);
|
||||
state = state.advance_newline();
|
||||
on_space(start, CommentOrNewline::Newline, state.pos());
|
||||
found_newline = true;
|
||||
progress = MadeProgress;
|
||||
} else {
|
||||
return Err((
|
||||
progress,
|
||||
E::space_problem(
|
||||
BadInputError::HasMisplacedCarriageReturn,
|
||||
state.pos(),
|
||||
),
|
||||
E::space_problem(BadInputError::HasMisplacedCarriageReturn, state.pos()),
|
||||
));
|
||||
}
|
||||
}
|
||||
Some(b'\n') => {
|
||||
newlines.push(CommentOrNewline::Newline);
|
||||
state = state.advance_newline();
|
||||
on_space(start, CommentOrNewline::Newline, state.pos());
|
||||
found_newline = true;
|
||||
progress = MadeProgress;
|
||||
}
|
||||
Some(b'\t') => {
|
||||
|
@ -470,7 +507,7 @@ where
|
|||
));
|
||||
}
|
||||
_ => {
|
||||
if !newlines.is_empty() {
|
||||
if found_newline {
|
||||
state = state.mark_current_indent();
|
||||
}
|
||||
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 expr;
|
||||
pub mod header;
|
||||
pub mod highlight;
|
||||
pub mod ident;
|
||||
pub mod keyword;
|
||||
pub mod module;
|
||||
|
|
|
@ -129,6 +129,10 @@ impl Position {
|
|||
offset: self.offset - count as u32,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn byte_offset(&self) -> usize {
|
||||
self.offset as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Position {
|
||||
|
@ -322,6 +326,10 @@ impl<T> Loc<T> {
|
|||
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>
|
||||
|
|
|
@ -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]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn decode_use_stdlib() {
|
||||
|
|
|
@ -1859,13 +1859,11 @@ fn first_int_list() {
|
|||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.first [12, 9, 6, 3] is
|
||||
Ok val -> val
|
||||
Err _ -> -1
|
||||
List.first [12, 9, 6, 3]
|
||||
"#
|
||||
),
|
||||
12,
|
||||
i64
|
||||
RocResult::ok(12),
|
||||
RocResult<i64, ()>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1889,45 +1887,42 @@ fn first_wildcard_empty_list() {
|
|||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.first [] is
|
||||
Ok _ -> 5
|
||||
Err _ -> -1
|
||||
List.last [] |> Result.map (\_ -> 0i64)
|
||||
"#
|
||||
),
|
||||
-1,
|
||||
i64
|
||||
RocResult::err(()),
|
||||
RocResult<i64, ()>
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn first_empty_list() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.first [] is
|
||||
Ok val -> val
|
||||
Err _ -> -1
|
||||
list : List I64
|
||||
list = []
|
||||
|
||||
List.first list
|
||||
"#
|
||||
),
|
||||
-1,
|
||||
i64
|
||||
RocResult::err(()),
|
||||
RocResult<i64, ()>
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn last_int_list() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.last [12, 9, 6, 3] is
|
||||
Ok val -> val
|
||||
Err _ -> -1
|
||||
List.last [12, 9, 6, 3]
|
||||
"#
|
||||
),
|
||||
3,
|
||||
i64
|
||||
RocResult::ok(3),
|
||||
RocResult<i64, ()>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1937,13 +1932,11 @@ fn last_wildcard_empty_list() {
|
|||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.last [] is
|
||||
Ok _ -> 5
|
||||
Err _ -> -1
|
||||
List.last [] |> Result.map (\_ -> 0i64)
|
||||
"#
|
||||
),
|
||||
-1,
|
||||
i64
|
||||
RocResult::err(()),
|
||||
RocResult<i64, ()>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1953,13 +1946,14 @@ fn last_empty_list() {
|
|||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.last [] is
|
||||
Ok val -> val
|
||||
Err _ -> -1
|
||||
list : List I64
|
||||
list = []
|
||||
|
||||
List.last list
|
||||
"#
|
||||
),
|
||||
-1,
|
||||
i64
|
||||
RocResult::err(()),
|
||||
RocResult<i64, ()>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1969,29 +1963,32 @@ fn get_empty_list() {
|
|||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.get [] 0 is
|
||||
Ok val -> val
|
||||
Err _ -> -1
|
||||
list : List I64
|
||||
list = []
|
||||
|
||||
List.get list 0
|
||||
"#
|
||||
),
|
||||
-1,
|
||||
i64
|
||||
RocResult::err(()),
|
||||
RocResult<i64, ()>
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
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!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.get [] 0 is
|
||||
Ok _ -> 5
|
||||
Err _ -> -1
|
||||
List.get [] 0
|
||||
|> Result.map (\_ -> {})
|
||||
"#
|
||||
),
|
||||
-1,
|
||||
i64
|
||||
RocResult::err(()),
|
||||
RocResult<(), ()>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2010,39 +2007,35 @@ fn get_str_list_ok() {
|
|||
}
|
||||
|
||||
#[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() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.get [12, 9, 6] 1 is
|
||||
Ok val -> val
|
||||
Err _ -> -1
|
||||
List.get [12, 9, 6] 1
|
||||
"#
|
||||
),
|
||||
9,
|
||||
i64
|
||||
RocResult::ok(9),
|
||||
RocResult<i64, ()>
|
||||
);
|
||||
}
|
||||
|
||||
#[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() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.get [12, 9, 6] 1000 is
|
||||
Ok val -> val
|
||||
Err _ -> -1
|
||||
List.get [12, 9, 6] 1000
|
||||
"#
|
||||
),
|
||||
-1,
|
||||
i64
|
||||
RocResult::err(()),
|
||||
RocResult<i64, ()>
|
||||
);
|
||||
}
|
||||
|
||||
#[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() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -2057,7 +2050,7 @@ fn replace_unique_int_list() {
|
|||
}
|
||||
|
||||
#[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() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -2072,7 +2065,7 @@ fn replace_unique_int_list_out_of_bounds() {
|
|||
}
|
||||
|
||||
#[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() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -2087,7 +2080,7 @@ fn replace_unique_int_list_get_old_value() {
|
|||
}
|
||||
|
||||
#[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() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -2138,13 +2131,11 @@ fn get_set_unique_int_list_i64() {
|
|||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.get (List.set [12, 9, 7, 3] 1 42) 1 is
|
||||
Ok val -> val
|
||||
Err _ -> -1
|
||||
List.get (List.set [12, 9, 7, 3] 1 42) 1
|
||||
"#
|
||||
),
|
||||
42,
|
||||
i64
|
||||
RocResult::ok(42),
|
||||
RocResult<i64, ()>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2154,13 +2145,11 @@ fn get_set_unique_int_list_i8() {
|
|||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.get (List.set [12, 9, 7, 3] 1 42i8) 1 is
|
||||
Ok val -> val
|
||||
Err _ -> -1i8
|
||||
List.get (List.set [12, 9, 7, 3] 1 42i8) 1
|
||||
"#
|
||||
),
|
||||
42,
|
||||
i8
|
||||
RocResult::ok(42),
|
||||
RocResult<i8, ()>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2175,7 +2164,7 @@ fn set_unique_int_list() {
|
|||
}
|
||||
|
||||
#[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() {
|
||||
assert_evals_to!(
|
||||
"List.set [3, 17, 4.1] 1337 9.25",
|
||||
|
@ -2240,20 +2229,18 @@ fn set_shared_list_oob() {
|
|||
}
|
||||
|
||||
#[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() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
unique = [2, 4]
|
||||
|
||||
when List.get unique 1 is
|
||||
Ok num -> num
|
||||
Err _ -> -1
|
||||
List.get unique 1
|
||||
"#
|
||||
),
|
||||
4,
|
||||
i64
|
||||
RocResult::ok(4),
|
||||
RocResult<i64, ()>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2275,7 +2262,7 @@ fn gen_wrap_len() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn gen_wrap_first() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -2292,7 +2279,7 @@ fn gen_wrap_first() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn gen_duplicate() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -2605,7 +2592,7 @@ fn list_literal_increment_decrement() {
|
|||
}
|
||||
|
||||
#[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() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -2625,7 +2612,7 @@ fn list_pass_to_function() {
|
|||
}
|
||||
|
||||
#[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() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -2713,24 +2700,22 @@ fn list_min() {
|
|||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.min [] is
|
||||
Ok val -> val
|
||||
Err _ -> -1
|
||||
List.min []
|
||||
|> Result.map (\_ -> {})
|
||||
"#
|
||||
),
|
||||
-1,
|
||||
i64
|
||||
RocResult::err(()),
|
||||
RocResult<(), ()>
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.min [3, 1, 2] is
|
||||
Ok val -> val
|
||||
Err _ -> -1
|
||||
List.min [3, 1, 2]
|
||||
"#
|
||||
),
|
||||
1,
|
||||
i64
|
||||
RocResult::ok(1),
|
||||
RocResult<i64, ()>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2740,24 +2725,22 @@ fn list_max() {
|
|||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.max [] is
|
||||
Ok val -> val
|
||||
Err _ -> -1
|
||||
List.max []
|
||||
|> Result.map (\_ -> {})
|
||||
"#
|
||||
),
|
||||
-1,
|
||||
i64
|
||||
RocResult::err(()),
|
||||
RocResult<(), ()>
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.max [3, 1, 2] is
|
||||
Ok val -> val
|
||||
Err _ -> -1
|
||||
List.max [3, 1, 2]
|
||||
"#
|
||||
),
|
||||
3,
|
||||
i64
|
||||
RocResult::ok(3),
|
||||
RocResult<i64, ()>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ fn nat_alias() {
|
|||
}
|
||||
|
||||
#[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() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -115,7 +115,7 @@ fn i8_signed_int_alias() {
|
|||
}
|
||||
|
||||
#[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() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -196,7 +196,7 @@ fn i8_hex_int_alias() {
|
|||
}
|
||||
|
||||
#[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() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -277,7 +277,7 @@ fn u8_signed_int_alias() {
|
|||
}
|
||||
|
||||
#[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() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -418,7 +418,7 @@ fn character_literal_new_line() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn dec_float_alias() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -451,7 +451,7 @@ fn f64_float_alias() {
|
|||
);
|
||||
}
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn f32_float_alias() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -468,112 +468,51 @@ fn f32_float_alias() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn f64_sqrt() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when Num.sqrtChecked 100 is
|
||||
Ok val -> val
|
||||
Err _ -> -1
|
||||
"#
|
||||
),
|
||||
10.0,
|
||||
f64
|
||||
);
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn f64_sqrt_100() {
|
||||
assert_evals_to!("Num.sqrt 100", 10.0, f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn f64_sqrt_checked_0() {
|
||||
assert_evals_to!("Num.sqrt 0", 0.0, f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn f64_log() {
|
||||
assert_evals_to!(
|
||||
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
|
||||
);
|
||||
fn f64_sqrt_checked_positive() {
|
||||
assert_evals_to!("Num.sqrtChecked 100", RocResult::ok(10.0), RocResult<f64, ()>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn f64_sqrt_checked_negative() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when Num.sqrtChecked -1 is
|
||||
Err _ -> 42
|
||||
Ok val -> val
|
||||
"#
|
||||
),
|
||||
42.0,
|
||||
f64
|
||||
);
|
||||
assert_evals_to!("Num.sqrtChecked -1f64", RocResult::err(()), RocResult<f64, ()>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn f64_log() {
|
||||
assert_evals_to!("Num.log 7.38905609893", 1.999999999999912, 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]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn f64_log_checked_zero() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when Num.logChecked 0 is
|
||||
Err _ -> 42
|
||||
Ok val -> val
|
||||
"#
|
||||
),
|
||||
42.0,
|
||||
f64
|
||||
);
|
||||
assert_evals_to!("Num.logChecked 0", RocResult::err(()), RocResult<f64, ()>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn f64_log_negative() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
Num.log -1
|
||||
"#
|
||||
),
|
||||
true,
|
||||
f64,
|
||||
|f: f64| f.is_nan()
|
||||
);
|
||||
assert_evals_to!("Num.log -1", true, f64, |f: f64| f.is_nan());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -890,16 +829,20 @@ fn gen_int_neq() {
|
|||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn gen_int_less_than() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
4 < 5
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
fn int_less_than() {
|
||||
assert_evals_to!("4 < 5", true, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn float_less_than() {
|
||||
assert_evals_to!("4.0 < 5.0", true, 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]
|
||||
|
|
|
@ -3307,10 +3307,46 @@ fn box_str() {
|
|||
|
||||
#[test]
|
||||
#[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)
|
||||
}
|
||||
|
||||
#[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]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn box_and_unbox_record() {
|
||||
|
|
|
@ -360,7 +360,7 @@ fn i64_record1_literal() {
|
|||
// );
|
||||
// }
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn bool_literal() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1111,3 +1111,22 @@ fn toplevel_accessor_fn_thunk() {
|
|||
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]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn roc_result_ok() {
|
||||
fn roc_result_ok_i64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
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]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn roc_result_err() {
|
||||
|
|
|
@ -16,7 +16,7 @@ use indoc::indoc;
|
|||
use roc_std::{RocList, RocResult, RocStr};
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_split_empty_delimiter() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -46,7 +46,7 @@ fn str_split_empty_delimiter() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_split_bigger_delimiter_small_str() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -110,7 +110,7 @@ fn str_split_small_str_bigger_delimiter() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_split_big_str_small_delimiter() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -154,7 +154,7 @@ fn str_split_small_str_small_delimiter() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_split_bigger_delimiter_big_strs() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -198,7 +198,7 @@ fn str_split_minimal_example() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_split_small_str_big_delimiter() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -227,7 +227,7 @@ fn str_split_small_str_big_delimiter() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_split_small_str_20_char_delimiter() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -243,7 +243,7 @@ fn str_split_small_str_20_char_delimiter() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_concat_big_to_big() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -402,7 +402,7 @@ fn small_str_concat_empty_second_arg() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn small_str_concat_small_to_big() {
|
||||
assert_evals_to!(
|
||||
r#"Str.concat "abc" " this is longer than 15 chars""#,
|
||||
|
@ -530,7 +530,7 @@ fn str_count_graphemes_three_js() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_count_graphemes_big_str() {
|
||||
assert_evals_to!(
|
||||
r#"Str.countGraphemes "6🤔å🤔e¥🤔çppkd🙃1jdal🦯asdfa∆ltråø˚waia8918.,🏅jjc""#,
|
||||
|
@ -540,7 +540,7 @@ fn str_count_graphemes_big_str() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_starts_with_same_big_str() {
|
||||
assert_evals_to!(
|
||||
r#"Str.startsWith "123456789123456789" "123456789123456789""#,
|
||||
|
@ -550,7 +550,7 @@ fn str_starts_with_same_big_str() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_starts_with_different_big_str() {
|
||||
assert_evals_to!(
|
||||
r#"Str.startsWith "12345678912345678910" "123456789123456789""#,
|
||||
|
@ -560,24 +560,24 @@ fn str_starts_with_different_big_str() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_starts_with_same_small_str() {
|
||||
assert_evals_to!(r#"Str.startsWith "1234" "1234""#, true, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_starts_with_different_small_str() {
|
||||
assert_evals_to!(r#"Str.startsWith "1234" "12""#, true, bool);
|
||||
}
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_starts_with_false_small_str() {
|
||||
assert_evals_to!(r#"Str.startsWith "1234" "23""#, false, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_from_utf8_pass_single_ascii() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -593,7 +593,7 @@ fn str_from_utf8_pass_single_ascii() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_from_utf8_pass_many_ascii() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -609,7 +609,7 @@ fn str_from_utf8_pass_many_ascii() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_from_utf8_pass_single_unicode() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -625,7 +625,7 @@ fn str_from_utf8_pass_single_unicode() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_from_utf8_pass_many_unicode() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -641,7 +641,7 @@ fn str_from_utf8_pass_many_unicode() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_from_utf8_pass_single_grapheme() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -657,7 +657,7 @@ fn str_from_utf8_pass_single_grapheme() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_from_utf8_pass_many_grapheme() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -673,7 +673,7 @@ fn str_from_utf8_pass_many_grapheme() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_from_utf8_pass_all() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -689,7 +689,7 @@ fn str_from_utf8_pass_all() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_from_utf8_fail_invalid_start_byte() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -709,7 +709,7 @@ fn str_from_utf8_fail_invalid_start_byte() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_from_utf8_fail_unexpected_end_of_sequence() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -729,7 +729,7 @@ fn str_from_utf8_fail_unexpected_end_of_sequence() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_from_utf8_fail_expected_continuation() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -749,7 +749,7 @@ fn str_from_utf8_fail_expected_continuation() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_from_utf8_fail_overlong_encoding() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -769,7 +769,7 @@ fn str_from_utf8_fail_overlong_encoding() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_from_utf8_fail_codepoint_too_large() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -789,7 +789,7 @@ fn str_from_utf8_fail_codepoint_too_large() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_from_utf8_fail_surrogate_half() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -809,7 +809,7 @@ fn str_from_utf8_fail_surrogate_half() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_equality() {
|
||||
assert_evals_to!(r#""a" == "a""#, true, bool);
|
||||
assert_evals_to!(
|
||||
|
@ -865,7 +865,7 @@ fn nested_recursive_literal() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_join_comma_small() {
|
||||
assert_evals_to!(
|
||||
r#"Str.joinWith ["1", "2"] ", " "#,
|
||||
|
@ -875,7 +875,7 @@ fn str_join_comma_small() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_join_comma_big() {
|
||||
assert_evals_to!(
|
||||
r#"Str.joinWith ["10000000", "2000000", "30000000"] ", " "#,
|
||||
|
@ -885,13 +885,13 @@ fn str_join_comma_big() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_join_comma_single() {
|
||||
assert_evals_to!(r#"Str.joinWith ["1"] ", " "#, RocStr::from("1"), RocStr);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_to_utf8() {
|
||||
assert_evals_to!(
|
||||
r#"Str.toUtf8 "hello""#,
|
||||
|
@ -909,7 +909,7 @@ fn str_to_utf8() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_from_utf8_range() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -926,7 +926,7 @@ fn str_from_utf8_range() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_from_utf8_range_slice() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -943,7 +943,7 @@ fn str_from_utf8_range_slice() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_from_utf8_range_slice_not_end() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -960,7 +960,7 @@ fn str_from_utf8_range_slice_not_end() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_from_utf8_range_order_does_not_matter() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -977,7 +977,7 @@ fn str_from_utf8_range_order_does_not_matter() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_from_utf8_range_out_of_bounds_start_value() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -995,7 +995,7 @@ fn str_from_utf8_range_out_of_bounds_start_value() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_from_utf8_range_count_too_high() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1013,7 +1013,7 @@ fn str_from_utf8_range_count_too_high() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_from_utf8_range_count_too_high_for_start() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1031,7 +1031,7 @@ fn str_from_utf8_range_count_too_high_for_start() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_repeat_small_stays_small() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.repeat "Roc" 3"#),
|
||||
|
@ -1041,7 +1041,7 @@ fn str_repeat_small_stays_small() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_repeat_small_becomes_big() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.repeat "less than 23 characters" 2"#),
|
||||
|
@ -1051,7 +1051,7 @@ fn str_repeat_small_becomes_big() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_repeat_big() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.repeat "more than 23 characters now" 2"#),
|
||||
|
@ -1061,27 +1061,26 @@ fn str_repeat_big() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_repeat_empty_string() {
|
||||
let a = indoc!(r#"Str.repeat "" 3"#);
|
||||
let b = RocStr::from("");
|
||||
assert_evals_to!(a, b, RocStr);
|
||||
assert_evals_to!(a, RocStr::from(""), RocStr);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_repeat_zero_times() {
|
||||
assert_evals_to!(indoc!(r#"Str.repeat "Roc" 0"#), RocStr::from(""), RocStr);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_trim_empty_string() {
|
||||
assert_evals_to!(indoc!(r#"Str.trim """#), RocStr::from(""), RocStr);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_trim_null_byte() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.trim (Str.reserve "\u(0000)" 40)"#),
|
||||
|
@ -1091,13 +1090,13 @@ fn str_trim_null_byte() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_trim_small_blank_string() {
|
||||
assert_evals_to!(indoc!(r#"Str.trim " ""#), RocStr::from(""), RocStr);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_trim_small_to_small() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.trim " hello world ""#),
|
||||
|
@ -1107,7 +1106,7 @@ fn str_trim_small_to_small() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_trim_large_to_large_unique() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.trim (Str.concat " " "hello world from a large string ")"#),
|
||||
|
@ -1117,7 +1116,7 @@ fn str_trim_large_to_large_unique() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_trim_large_to_small_unique() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.trim (Str.concat " " "hello world ")"#),
|
||||
|
@ -1184,13 +1183,13 @@ fn str_trim_small_to_small_shared() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_trim_left_small_blank_string() {
|
||||
assert_evals_to!(indoc!(r#"Str.trimLeft " ""#), RocStr::from(""), RocStr);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_trim_left_small_to_small() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.trimLeft " hello world ""#),
|
||||
|
@ -1200,7 +1199,7 @@ fn str_trim_left_small_to_small() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_trim_left_large_to_large_unique() {
|
||||
assert_evals_to!(
|
||||
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]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_trim_left_large_to_small_unique() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.trimLeft (Str.concat " " "hello world ")"#),
|
||||
|
@ -1277,13 +1276,13 @@ fn str_trim_left_small_to_small_shared() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_trim_right_small_blank_string() {
|
||||
assert_evals_to!(indoc!(r#"Str.trimRight " ""#), RocStr::from(""), RocStr);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_trim_right_small_to_small() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.trimRight " hello world ""#),
|
||||
|
@ -1293,7 +1292,7 @@ fn str_trim_right_small_to_small() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_trim_right_large_to_large_unique() {
|
||||
assert_evals_to!(
|
||||
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]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_trim_right_large_to_small_unique() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.trimRight (Str.concat " hello world" " ")"#),
|
||||
|
@ -1370,9 +1369,17 @@ fn str_trim_right_small_to_small_shared() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
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]
|
||||
|
@ -1381,14 +1388,11 @@ fn str_to_i128() {
|
|||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when Str.toI128 "1" is
|
||||
Ok n -> n
|
||||
Err _ -> 0
|
||||
|
||||
Str.toI128 "1"
|
||||
"#
|
||||
),
|
||||
1,
|
||||
i128
|
||||
RocResult::ok(1),
|
||||
RocResult<i128, ()>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1398,41 +1402,39 @@ fn str_to_u128() {
|
|||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when Str.toU128 "1" is
|
||||
Ok n -> n
|
||||
Err _ -> 0
|
||||
|
||||
Str.toU128 "1"
|
||||
"#
|
||||
),
|
||||
1,
|
||||
u128
|
||||
RocResult::ok(1),
|
||||
RocResult<u128, ()>
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_to_i64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when Str.toI64 "1" is
|
||||
Ok n -> n
|
||||
Err _ -> 0
|
||||
|
||||
Str.toI64 "1"
|
||||
"#
|
||||
),
|
||||
1,
|
||||
i64
|
||||
RocResult::ok(1),
|
||||
RocResult<i64, ()>
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_to_u64() {
|
||||
assert_evals_to!(
|
||||
r#"Str.toU64 "1""#,
|
||||
RocResult::ok(1u64),
|
||||
RocResult<u64, u8>
|
||||
indoc!(
|
||||
r#"
|
||||
Str.toU64 "1"
|
||||
"#
|
||||
),
|
||||
RocResult::ok(1),
|
||||
RocResult<u64, ()>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1442,14 +1444,11 @@ fn str_to_i32() {
|
|||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when Str.toI32 "1" is
|
||||
Ok n -> n
|
||||
Err _ -> 0
|
||||
|
||||
Str.toI32 "1"
|
||||
"#
|
||||
),
|
||||
1,
|
||||
i32
|
||||
RocResult::ok(1),
|
||||
RocResult<i32, ()>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1457,9 +1456,13 @@ fn str_to_i32() {
|
|||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_to_u32() {
|
||||
assert_evals_to!(
|
||||
r#"Str.toU32 "1""#,
|
||||
RocResult::ok(1u32),
|
||||
RocResult<u32, u8>
|
||||
indoc!(
|
||||
r#"
|
||||
Str.toU32 "1"
|
||||
"#
|
||||
),
|
||||
RocResult::ok(1),
|
||||
RocResult<u32, ()>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1469,14 +1472,11 @@ fn str_to_i16() {
|
|||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when Str.toI16 "1" is
|
||||
Ok n -> n
|
||||
Err _ -> 0
|
||||
|
||||
Str.toI16 "1"
|
||||
"#
|
||||
),
|
||||
1,
|
||||
i16
|
||||
RocResult::ok(1),
|
||||
RocResult<i16, ()>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1486,14 +1486,11 @@ fn str_to_u16() {
|
|||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when Str.toU16 "1" is
|
||||
Ok n -> n
|
||||
Err _ -> 0
|
||||
|
||||
Str.toU16 "1"
|
||||
"#
|
||||
),
|
||||
1,
|
||||
u16
|
||||
RocResult::ok(1),
|
||||
RocResult<u16, ()>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1503,14 +1500,11 @@ fn str_to_i8() {
|
|||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when Str.toI8 "1" is
|
||||
Ok n -> n
|
||||
Err _ -> 0
|
||||
|
||||
Str.toI8 "1"
|
||||
"#
|
||||
),
|
||||
1,
|
||||
i8
|
||||
RocResult::ok(1),
|
||||
RocResult<i8, ()>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1520,14 +1514,11 @@ fn str_to_u8() {
|
|||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when Str.toU8 "1" is
|
||||
Ok n -> n
|
||||
Err _ -> 0
|
||||
|
||||
Str.toU8 "1"
|
||||
"#
|
||||
),
|
||||
1,
|
||||
u8
|
||||
RocResult::ok(1),
|
||||
RocResult<u8, ()>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1585,7 +1576,7 @@ fn str_to_dec() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn issue_2811() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1601,7 +1592,7 @@ fn issue_2811() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn to_scalar_1_byte() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1625,7 +1616,7 @@ fn to_scalar_1_byte() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn to_scalar_2_byte() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1649,7 +1640,7 @@ fn to_scalar_2_byte() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn to_scalar_3_byte() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1673,7 +1664,7 @@ fn to_scalar_3_byte() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn to_scalar_4_byte() {
|
||||
// from https://design215.com/toolbox/utf8-4byte-characters.php
|
||||
assert_evals_to!(
|
||||
|
@ -1698,7 +1689,7 @@ fn to_scalar_4_byte() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_split_first_one_char() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1714,7 +1705,7 @@ fn str_split_first_one_char() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_split_first_multiple_chars() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1728,7 +1719,7 @@ fn str_split_first_multiple_chars() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_split_first_entire_input() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1742,7 +1733,7 @@ fn str_split_first_entire_input() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_split_first_not_found() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1756,7 +1747,7 @@ fn str_split_first_not_found() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_split_last_one_char() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1770,7 +1761,7 @@ fn str_split_last_one_char() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_split_last_multiple_chars() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1784,7 +1775,7 @@ fn str_split_last_multiple_chars() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_split_last_entire_input() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1798,12 +1789,12 @@ fn str_split_last_entire_input() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_split_last_not_found() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
Str.splitFirst "foo" "bar"
|
||||
Str.splitLast "foo" "bar"
|
||||
"#
|
||||
),
|
||||
RocResult::err(()),
|
||||
|
@ -1812,7 +1803,7 @@ fn str_split_last_not_found() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_split_overlapping_substring_1() {
|
||||
assert_evals_to!(
|
||||
r#"Str.split "aaa" "aa""#,
|
||||
|
@ -1822,7 +1813,7 @@ fn str_split_overlapping_substring_1() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_split_overlapping_substring_2() {
|
||||
assert_evals_to!(
|
||||
r#"Str.split "aaaa" "aa""#,
|
||||
|
@ -1832,7 +1823,7 @@ fn str_split_overlapping_substring_2() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_walk_utf8_with_index() {
|
||||
#[cfg(not(feature = "gen-llvm-wasm"))]
|
||||
assert_evals_to!(
|
||||
|
@ -1872,7 +1863,7 @@ fn str_append_scalar() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_walk_scalars() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1951,7 +1942,7 @@ fn when_on_strings() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn with_capacity() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1965,7 +1956,7 @@ fn with_capacity() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn with_capacity_concat() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1979,7 +1970,7 @@ fn with_capacity_concat() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn str_with_prefix() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -2003,7 +1994,7 @@ fn str_with_prefix() {
|
|||
}
|
||||
|
||||
#[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() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -2025,7 +2016,7 @@ fn destructure_pattern_assigned_from_thunk_opaque() {
|
|||
}
|
||||
|
||||
#[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() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
|
|
@ -3,7 +3,7 @@ procedure Bool.11 (#Attr.2, #Attr.3):
|
|||
ret Bool.24;
|
||||
|
||||
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.497 : U8 = GetTagId List.493;
|
||||
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;
|
||||
ret List.484;
|
||||
|
||||
procedure List.90 (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.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):
|
||||
procedure List.80 (List.528, List.529, List.530, List.531, List.532):
|
||||
joinpoint List.502 List.429 List.430 List.431 List.432 List.433:
|
||||
let List.504 : Int1 = CallByName Num.22 List.432 List.433;
|
||||
if List.504 then
|
||||
|
@ -83,6 +77,12 @@ procedure List.91 (List.528, List.529, List.530, List.531, List.532):
|
|||
in
|
||||
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):
|
||||
let Num.258 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.258;
|
||||
|
|
|
@ -21,12 +21,12 @@ procedure Dict.4 (Dict.497):
|
|||
|
||||
procedure List.11 (List.114, 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;
|
||||
|
||||
procedure List.11 (List.114, 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;
|
||||
|
||||
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;
|
||||
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:
|
||||
let List.488 : U64 = 0i64;
|
||||
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
|
||||
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:
|
||||
let List.500 : U64 = 0i64;
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
ret List.594;
|
||||
|
||||
procedure List.90 (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.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):
|
||||
procedure List.80 (List.531, List.532, List.533, List.534, List.535):
|
||||
joinpoint List.506 List.429 List.430 List.431 List.432 List.433:
|
||||
let List.508 : Int1 = CallByName Num.22 List.432 List.433;
|
||||
if List.508 then
|
||||
|
@ -284,7 +272,7 @@ procedure List.91 (List.531, List.532, List.533, List.534, List.535):
|
|||
in
|
||||
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:
|
||||
let List.581 : Int1 = CallByName Num.22 List.432 List.433;
|
||||
if List.581 then
|
||||
|
@ -298,6 +286,18 @@ procedure List.91 (List.605, List.606, List.607, List.608, List.609):
|
|||
in
|
||||
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):
|
||||
let Num.282 : U8 = lowlevel NumIntCast #Attr.2;
|
||||
ret Num.282;
|
||||
|
|
|
@ -122,7 +122,7 @@ procedure List.138 (List.139, List.140, List.137):
|
|||
ret List.525;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
ret List.527;
|
||||
|
||||
procedure List.90 (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.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):
|
||||
procedure List.80 (List.538, List.539, List.540, List.541, List.542):
|
||||
joinpoint List.512 List.429 List.430 List.431 List.432 List.433:
|
||||
let List.514 : Int1 = CallByName Num.22 List.432 List.433;
|
||||
if List.514 then
|
||||
|
@ -175,6 +169,12 @@ procedure List.91 (List.538, List.539, List.540, List.541, List.542):
|
|||
in
|
||||
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):
|
||||
let Num.263 : U8 = lowlevel NumIntCast #Attr.2;
|
||||
ret Num.263;
|
||||
|
|
|
@ -130,7 +130,7 @@ procedure List.138 (List.139, List.140, List.137):
|
|||
ret List.525;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
ret List.527;
|
||||
|
||||
procedure List.90 (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.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):
|
||||
procedure List.80 (List.538, List.539, List.540, List.541, List.542):
|
||||
joinpoint List.512 List.429 List.430 List.431 List.432 List.433:
|
||||
let List.514 : Int1 = CallByName Num.22 List.432 List.433;
|
||||
if List.514 then
|
||||
|
@ -183,6 +177,12 @@ procedure List.91 (List.538, List.539, List.540, List.541, List.542):
|
|||
in
|
||||
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):
|
||||
let Num.263 : U8 = lowlevel NumIntCast #Attr.2;
|
||||
ret Num.263;
|
||||
|
|
|
@ -131,7 +131,7 @@ procedure List.138 (List.139, List.140, List.137):
|
|||
ret List.531;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
ret List.534;
|
||||
|
||||
procedure List.90 (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.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):
|
||||
procedure List.80 (List.544, List.545, List.546, List.547, List.548):
|
||||
joinpoint List.518 List.429 List.430 List.431 List.432 List.433:
|
||||
let List.520 : Int1 = CallByName Num.22 List.432 List.433;
|
||||
if List.520 then
|
||||
|
@ -184,6 +178,12 @@ procedure List.91 (List.544, List.545, List.546, List.547, List.548):
|
|||
in
|
||||
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):
|
||||
let Num.265 : U8 = lowlevel NumIntCast #Attr.2;
|
||||
ret Num.265;
|
||||
|
|
|
@ -137,7 +137,7 @@ procedure List.138 (List.139, List.140, List.137):
|
|||
ret List.531;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
ret List.534;
|
||||
|
||||
procedure List.90 (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.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):
|
||||
procedure List.80 (List.544, List.545, List.546, List.547, List.548):
|
||||
joinpoint List.518 List.429 List.430 List.431 List.432 List.433:
|
||||
let List.520 : Int1 = CallByName Num.22 List.432 List.433;
|
||||
if List.520 then
|
||||
|
@ -190,6 +184,12 @@ procedure List.91 (List.544, List.545, List.546, List.547, List.548):
|
|||
in
|
||||
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):
|
||||
let Num.265 : U8 = lowlevel NumIntCast #Attr.2;
|
||||
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;
|
||||
|
||||
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.497 : U8 = GetTagId List.493;
|
||||
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;
|
||||
ret List.484;
|
||||
|
||||
procedure List.90 (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.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):
|
||||
procedure List.80 (List.528, List.529, List.530, List.531, List.532):
|
||||
joinpoint List.502 List.429 List.430 List.431 List.432 List.433:
|
||||
let List.504 : Int1 = CallByName Num.22 List.432 List.433;
|
||||
if List.504 then
|
||||
|
@ -83,6 +77,12 @@ procedure List.91 (List.528, List.529, List.530, List.531, List.532):
|
|||
in
|
||||
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):
|
||||
let Num.258 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
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)),
|
||||
};
|
||||
|
||||
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 =
|
||||
if expect == TestExpectation::Pass || expect == TestExpectation::Malformed {
|
||||
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(..)) => Less,
|
||||
// For everything else, the order is irrelevant
|
||||
(_, _) => Less,
|
||||
// For everything else, sort by the root key
|
||||
(_, _) => subs
|
||||
.get_root_key_without_compacting(var1)
|
||||
.cmp(&subs.get_root_key_without_compacting(var2)),
|
||||
}
|
||||
}
|
||||
ord => ord,
|
||||
|
@ -1731,6 +1733,8 @@ fn unify_unspecialized_lambdas<M: MetaCollector>(
|
|||
let kept = uls_left.next().unwrap();
|
||||
merged_uls.push(*kept);
|
||||
} else {
|
||||
// CASE: disjoint_flex_specializations
|
||||
//
|
||||
// ... a1 ...
|
||||
// ... b1 ...
|
||||
// => ... a1, b1 ...
|
||||
|
@ -1800,20 +1804,47 @@ fn unify_unspecialized_lambdas<M: MetaCollector>(
|
|||
let _dropped = uls_left.next().unwrap();
|
||||
}
|
||||
(_, _) => {
|
||||
// ... {foo: _} ...
|
||||
// ... {foo: _} ...
|
||||
// => ... {foo: _} ...
|
||||
if env.subs.equivalent_without_compacting(var_l, var_r) {
|
||||
// ... a1 ...
|
||||
// ... b1=a1 ...
|
||||
// => ... a1 ...
|
||||
//
|
||||
// Unify them, then advance one.
|
||||
// (the choice is arbitrary, so we choose the left)
|
||||
// Keep the one on the left, drop the one on the right. Then progress
|
||||
// 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);
|
||||
if !outcome.mismatches.is_empty() {
|
||||
return Err(outcome);
|
||||
debug_assert!(uls_right
|
||||
.peek()
|
||||
.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]
|
||||
default = []
|
||||
with_sound = ["rodio"]
|
||||
|
||||
[dependencies]
|
||||
roc_ast = { path = "../ast" }
|
||||
|
@ -57,7 +56,6 @@ confy = { git = 'https://github.com/rust-cli/confy', features = [
|
|||
], default-features = false }
|
||||
serde = { version = "1.0.144", features = ["derive"] }
|
||||
nonempty = "0.8.0"
|
||||
rodio = { version = "0.15.0", optional = true } # to play sounds
|
||||
threadpool = "1.8.1"
|
||||
|
||||
fs_extra.workspace = true
|
||||
|
|
|
@ -8,7 +8,5 @@ mod mvc;
|
|||
mod render_ast;
|
||||
mod render_debug;
|
||||
mod resources;
|
||||
#[cfg(feature = "with_sound")]
|
||||
mod sound;
|
||||
mod theme;
|
||||
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_string;
|
||||
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::lines::MoveCaretFun;
|
||||
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.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
|
||||
makeWrapper # necessary for postBuild wrapProgram
|
||||
] ++ lib.optionals pkgs.stdenv.isLinux [
|
||||
alsa-lib
|
||||
valgrind
|
||||
vulkan-headers
|
||||
vulkan-loader
|
||||
|
|
|
@ -39,7 +39,6 @@ confy = { git = 'https://github.com/rust-cli/confy', features = [
|
|||
serde = { version = "1.0.130", features = ["derive"] }
|
||||
nonempty = "0.7.0"
|
||||
fs_extra = "1.2.0"
|
||||
rodio = { version = "0.14.0", optional = true } # to play sounds
|
||||
threadpool = "1.8.1"
|
||||
|
||||
[package.metadata.cargo-udeps.ignore]
|
||||
|
@ -50,7 +49,6 @@ normal = ["confy"]
|
|||
|
||||
[features]
|
||||
default = []
|
||||
with_sound = ["rodio"]
|
||||
|
||||
[dependencies.bytemuck]
|
||||
version = "1.7.2"
|
||||
|
|
|
@ -40,7 +40,6 @@ confy = { git = 'https://github.com/rust-cli/confy', features = [
|
|||
serde = { version = "1.0.130", features = ["derive"] }
|
||||
nonempty = "0.7.0"
|
||||
fs_extra = "1.2.0"
|
||||
rodio = { version = "0.14.0", optional = true } # to play sounds
|
||||
threadpool = "1.8.1"
|
||||
|
||||
[package.metadata.cargo-udeps.ignore]
|
||||
|
@ -51,7 +50,6 @@ normal = ["confy"]
|
|||
|
||||
[features]
|
||||
default = []
|
||||
with_sound = ["rodio"]
|
||||
|
||||
[dependencies.bytemuck]
|
||||
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:
|
||||
```bash
|
||||
roc run static-site.roc input/ output/
|
||||
roc run static-site.roc -- input/ output/
|
||||
```
|
||||
|
||||
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,
|
||||
Herculei undae calcata inmeriti quercus ignes parabant iam.
|
||||
|
||||
digitize(undoDhcp(card_record, cad_flash_dot));
|
||||
supercomputer(2 - load_type, yobibyteTraceroute - installHibernate, 1);
|
||||
burnPci.pop_wrap.usbEmulation(hostESmm, processor_impression(4, lanNntp),
|
||||
-5);
|
||||
map_camera -= 73;
|
||||
if (53) {
|
||||
dacRootkitDrive(publicActivex.bmpNumWhite.wins_pci_firmware(scroll_cell,
|
||||
4, tShortcut));
|
||||
horse_algorithm_eide -= 51;
|
||||
flatbed_blob(flat);
|
||||
} else {
|
||||
surge.pci -= open_flash_dv(4, 4, usbStation);
|
||||
led.memory_fsb.matrixBinaryUrl(umlEngineOsd.agp_thick_thin.t(58));
|
||||
kindle_cookie(formulaLedVpn, digital_meme);
|
||||
}
|
||||
### Example Table
|
||||
|
||||
Foret inpendere, haec ipse ossa, dolentes das Caystro miscuit iunctoque
|
||||
spoliantis illae, ex! Bello istis nunc Aegides? Animo caelestia melior,
|
||||
furoribus optat maior invecta quid harenis [est](http://example.org) sollemnia modo
|
||||
Phineu. Suarum pectora. Relinquam in labore Medusae sororem Herculis [simillima
|
||||
corpora](http://example.org) plus regi ignibus, totum domus!
|
||||
| Tables | Are | Cool |
|
||||
| :------------ | :-----------: | ----: |
|
||||
| col 3 is | right-aligned | $1600 |
|
||||
| col 2 is | centered | $12 |
|
||||
| zebra stripes | are neat | $1 |
|
||||
|
||||
### Example Code Blocks
|
||||
|
||||
```sh
|
||||
# This isn't fenced roc code so its not formatted
|
||||
# Use a fence like ```roc to format code blocks
|
||||
```
|
||||
|
||||
```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,
|
||||
}
|
||||
|
||||
navLinks : List NavLink
|
||||
navLinks = [
|
||||
{ url: "apple.html", title: "Exempli Gratia Pagina Pomi", text: "Apple" },
|
||||
{ url: "banana.html", title: "Exempli Gratia Pagina Musa", text: "Banana" },
|
||||
{ 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;
|
||||
}
|
||||
.article pre {
|
||||
background-color: #222;
|
||||
color: yellow;
|
||||
background-color: rgb(241, 241, 241);
|
||||
color: rgb(27, 27, 27);
|
||||
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.
|
||||
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]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "host"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"pulldown-cmark",
|
||||
"roc_parse",
|
||||
"roc_region",
|
||||
"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]]
|
||||
name = "libc"
|
||||
version = "0.2.132"
|
||||
|
@ -35,6 +202,39 @@ version = "2.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "pulldown-cmark"
|
||||
version = "0.9.2"
|
||||
|
@ -46,6 +246,88 @@ dependencies = [
|
|||
"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]]
|
||||
name = "roc_std"
|
||||
version = "0.0.1"
|
||||
|
@ -54,12 +336,74 @@ dependencies = [
|
|||
"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]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "unicase"
|
||||
version = "2.6.0"
|
||||
|
@ -69,8 +413,38 @@ dependencies = [
|
|||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]
|
||||
roc_std = { path = "../../../crates/roc_std" }
|
||||
roc_region = { path = "../../../crates/compiler/region" }
|
||||
roc_parse = { path = "../../../crates/compiler/parse" }
|
||||
libc = "0.2"
|
||||
html-escape = "0.2"
|
||||
|
||||
# Default features include building a binary that we don't need
|
||||
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::path::{Path, PathBuf};
|
||||
|
||||
mod highlight;
|
||||
|
||||
extern "C" {
|
||||
#[link_name = "roc__transformFileContentForHost_1_exposed"]
|
||||
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);
|
||||
|
||||
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_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()
|
||||
}
|
||||
|
||||
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.libXi
|
||||
xorg.libxcb
|
||||
alsa-lib
|
||||
];
|
||||
|
||||
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>
|
||||
|
||||
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]`.
|
||||
|
||||
|
@ -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}
|
||||
|
||||
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
|
||||
<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>
|
||||
</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
|
||||
<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>
|
||||
</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
|
||||
<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>
|
||||
</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:
|
||||
|
||||
|
|
|
@ -323,6 +323,10 @@ p, aside, li, footer {
|
|||
font-size: inherit;
|
||||
}
|
||||
|
||||
code {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
#tutorial-toc-toggle-label,
|
||||
#close-tutorial-toc {
|
||||
display: block;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue