mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 00:24:34 +00:00
Merge branch 'main' of github.com:roc-lang/roc into fix_benchmarks
This commit is contained in:
commit
6a6345eb01
130 changed files with 7235 additions and 9783 deletions
4
.github/workflows/basic_cli_test_arm64.yml
vendored
4
.github/workflows/basic_cli_test_arm64.yml
vendored
|
@ -53,6 +53,10 @@ jobs:
|
||||||
latestTag=$(git describe --tags $(git rev-list --tags --max-count=1))
|
latestTag=$(git describe --tags $(git rev-list --tags --max-count=1))
|
||||||
git checkout $latestTag
|
git checkout $latestTag
|
||||||
|
|
||||||
|
# temp issue with new string interpolation syntax
|
||||||
|
# TODO undo when 0.7.2 or 0.8.0 is released
|
||||||
|
- run: sed -i 's/\$//g' basic-cli/examples/tcp-client.roc
|
||||||
|
|
||||||
- name: Run all tests with latest roc nightly and latest basic-cli release
|
- name: Run all tests with latest roc nightly and latest basic-cli release
|
||||||
run: |
|
run: |
|
||||||
sed -i 's/x86_64/arm64/g' ./ci/test_latest_release.sh
|
sed -i 's/x86_64/arm64/g' ./ci/test_latest_release.sh
|
||||||
|
|
30
.gitignore
vendored
30
.gitignore
vendored
|
@ -1,3 +1,27 @@
|
||||||
|
### Do not modify these first three ignore rules. Needed to ignore files with no extension ###
|
||||||
|
# Ignore all files including binary files that have no extension
|
||||||
|
*
|
||||||
|
# Unignore all files with extensions
|
||||||
|
!*.*
|
||||||
|
# Unignore all directories
|
||||||
|
!*/
|
||||||
|
|
||||||
|
# Specifically keep these files with no extension
|
||||||
|
!Earthfile
|
||||||
|
!AUTHORS
|
||||||
|
!LICENSE*
|
||||||
|
!LEGAL*
|
||||||
|
!Dockerfile
|
||||||
|
# .reuse/dep5 see https://reuse.software/
|
||||||
|
!dep5
|
||||||
|
# NotARocFile is used for formatter test
|
||||||
|
!NotARocFile
|
||||||
|
# also includes keeping one exe benchmark file
|
||||||
|
!dynhost_benchmarks*
|
||||||
|
|
||||||
|
### Add specific file extensions and directories below ###
|
||||||
|
|
||||||
|
# Ignore the following directories and file extensions
|
||||||
target
|
target
|
||||||
generated-docs
|
generated-docs
|
||||||
zig-cache
|
zig-cache
|
||||||
|
@ -63,10 +87,12 @@ result
|
||||||
|
|
||||||
# Only keep Cargo.lock dependencies for the main compiler.
|
# Only keep Cargo.lock dependencies for the main compiler.
|
||||||
# Examples and test only crates should be fine to be unlocked.
|
# Examples and test only crates should be fine to be unlocked.
|
||||||
# This remove unneccessary lock file versioning.
|
# This remove unnecessary lock file versioning.
|
||||||
# It also ensures the compiler can always pull in 1 version of things and doesn't get restricted by sub lockfiles.
|
# It also ensures the compiler can always pull in 1 version of things and doesn't get restricted by sub lockfiles.
|
||||||
/**/Cargo.lock
|
/**/Cargo.lock
|
||||||
!/Cargo.lock
|
!/Cargo.lock
|
||||||
|
!/examples/static-site-gen/platform/Cargo.lock
|
||||||
|
# static-site-gen exception is because of https://github.com/tkaitchuck/aHash/issues/195
|
||||||
|
|
||||||
# snapshot tests temp file
|
# snapshot tests temp file
|
||||||
*.pending-snap
|
*.pending-snap
|
||||||
|
@ -82,3 +108,5 @@ www/dist
|
||||||
www/content/examples
|
www/content/examples
|
||||||
www/examples-main.zip
|
www/examples-main.zip
|
||||||
www/examples-main
|
www/examples-main
|
||||||
|
|
||||||
|
examples/static-site-gen/**/*.html
|
136
Cargo.lock
generated
136
Cargo.lock
generated
|
@ -19,13 +19,14 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ahash"
|
name = "ahash"
|
||||||
version = "0.8.3"
|
version = "0.8.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
|
checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"version_check",
|
"version_check",
|
||||||
|
"zerocopy",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -61,6 +62,12 @@ dependencies = [
|
||||||
"alloc-no-stdlib",
|
"alloc-no-stdlib",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "allocator-api2"
|
||||||
|
version = "0.2.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "android-tzdata"
|
name = "android-tzdata"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
@ -124,13 +131,6 @@ dependencies = [
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "arena-pool"
|
|
||||||
version = "0.0.1"
|
|
||||||
dependencies = [
|
|
||||||
"roc_error_macros",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayref"
|
name = "arrayref"
|
||||||
version = "0.3.7"
|
version = "0.3.7"
|
||||||
|
@ -209,7 +209,7 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"miniz_oxide",
|
"miniz_oxide",
|
||||||
"object 0.32.1",
|
"object",
|
||||||
"rustc-demangle",
|
"rustc-demangle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -707,7 +707,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
|
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"hashbrown 0.14.1",
|
"hashbrown 0.14.3",
|
||||||
"lock_api",
|
"lock_api",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"parking_lot_core",
|
"parking_lot_core",
|
||||||
|
@ -722,6 +722,17 @@ dependencies = [
|
||||||
"powerfmt",
|
"powerfmt",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "derive_more"
|
||||||
|
version = "0.99.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "diff"
|
name = "diff"
|
||||||
version = "0.1.13"
|
version = "0.1.13"
|
||||||
|
@ -827,6 +838,12 @@ dependencies = [
|
||||||
"regex",
|
"regex",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "equivalent"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "errno"
|
name = "errno"
|
||||||
version = "0.3.5"
|
version = "0.3.5"
|
||||||
|
@ -1041,7 +1058,7 @@ dependencies = [
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http",
|
"http",
|
||||||
"indexmap",
|
"indexmap 1.9.3",
|
||||||
"slab",
|
"slab",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
|
@ -1062,20 +1079,14 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.13.2"
|
version = "0.14.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
|
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash",
|
"ahash",
|
||||||
"bumpalo",
|
"allocator-api2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hashbrown"
|
|
||||||
version = "0.14.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
|
@ -1258,6 +1269,16 @@ dependencies = [
|
||||||
"hashbrown 0.12.3",
|
"hashbrown 0.12.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
|
||||||
|
dependencies = [
|
||||||
|
"equivalent",
|
||||||
|
"hashbrown 0.14.3",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indoc"
|
name = "indoc"
|
||||||
version = "1.0.9"
|
version = "1.0.9"
|
||||||
|
@ -1636,24 +1657,16 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "object"
|
name = "object"
|
||||||
version = "0.30.4"
|
version = "0.32.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385"
|
checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
"flate2",
|
"flate2",
|
||||||
"hashbrown 0.13.2",
|
"hashbrown 0.14.3",
|
||||||
"indexmap",
|
"indexmap 2.1.0",
|
||||||
"memchr",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "object"
|
|
||||||
version = "0.32.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
|
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
"memchr",
|
||||||
|
"ruzstd",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2152,9 +2165,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reqwest"
|
name = "reqwest"
|
||||||
version = "0.11.22"
|
version = "0.11.23"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b"
|
checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.21.4",
|
"base64 0.21.4",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
@ -2396,7 +2409,7 @@ dependencies = [
|
||||||
"bitvec",
|
"bitvec",
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"fnv",
|
"fnv",
|
||||||
"hashbrown 0.13.2",
|
"hashbrown 0.14.3",
|
||||||
"im",
|
"im",
|
||||||
"im-rc",
|
"im-rc",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
|
@ -2526,7 +2539,7 @@ version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"capstone",
|
"capstone",
|
||||||
"object 0.30.4",
|
"object",
|
||||||
"packed_struct",
|
"packed_struct",
|
||||||
"roc_builtins",
|
"roc_builtins",
|
||||||
"roc_can",
|
"roc_can",
|
||||||
|
@ -2591,7 +2604,7 @@ dependencies = [
|
||||||
"cli_utils",
|
"cli_utils",
|
||||||
"dircpy",
|
"dircpy",
|
||||||
"fnv",
|
"fnv",
|
||||||
"indexmap",
|
"indexmap 2.1.0",
|
||||||
"indoc",
|
"indoc",
|
||||||
"libc",
|
"libc",
|
||||||
"libloading",
|
"libloading",
|
||||||
|
@ -2682,7 +2695,7 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"mach_object",
|
"mach_object",
|
||||||
"memmap2",
|
"memmap2",
|
||||||
"object 0.30.4",
|
"object",
|
||||||
"roc_collections",
|
"roc_collections",
|
||||||
"roc_error_macros",
|
"roc_error_macros",
|
||||||
"roc_load",
|
"roc_load",
|
||||||
|
@ -2785,7 +2798,7 @@ dependencies = [
|
||||||
"arrayvec 0.7.4",
|
"arrayvec 0.7.4",
|
||||||
"bitvec",
|
"bitvec",
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"hashbrown 0.13.2",
|
"hashbrown 0.14.3",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"roc_builtins",
|
"roc_builtins",
|
||||||
"roc_can",
|
"roc_can",
|
||||||
|
@ -3282,6 +3295,17 @@ dependencies = [
|
||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ruzstd"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "58c4eb8a81997cf040a091d1f7e1938aeab6749d3a0dfa73af43cdc32393483d"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"derive_more",
|
||||||
|
"twox-hash",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.15"
|
version = "1.0.15"
|
||||||
|
@ -4135,6 +4159,16 @@ version = "0.2.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
|
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "twox-hash"
|
||||||
|
version = "1.6.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"static_assertions",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typed-arena"
|
name = "typed-arena"
|
||||||
version = "2.0.2"
|
version = "2.0.2"
|
||||||
|
@ -4683,3 +4717,23 @@ name = "yansi"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
|
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.7.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.7.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.38",
|
||||||
|
]
|
||||||
|
|
|
@ -101,11 +101,11 @@ fnv = "1.0.7"
|
||||||
fs_extra = "1.3.0"
|
fs_extra = "1.3.0"
|
||||||
futures = "0.3.26"
|
futures = "0.3.26"
|
||||||
glyph_brush = "0.7.7"
|
glyph_brush = "0.7.7"
|
||||||
hashbrown = { version = "0.13.2", features = ["bumpalo"] }
|
hashbrown = { version = "0.14.3" }
|
||||||
iced-x86 = { version = "1.18.0", default-features = false, features = ["std", "decoder", "op_code_info", "instr_info"] }
|
iced-x86 = { version = "1.18.0", default-features = false, features = ["std", "decoder", "op_code_info", "instr_info"] }
|
||||||
im = "15.1.0"
|
im = "15.1.0"
|
||||||
im-rc = "15.1.0"
|
im-rc = "15.1.0"
|
||||||
indexmap = "1.9.2"
|
indexmap = "2.1.0"
|
||||||
indoc = "1.0.9"
|
indoc = "1.0.9"
|
||||||
insta = "1.28.0"
|
insta = "1.28.0"
|
||||||
js-sys = "0.3.61"
|
js-sys = "0.3.61"
|
||||||
|
@ -120,7 +120,7 @@ maplit = "1.0.2"
|
||||||
memmap2 = "0.5.10"
|
memmap2 = "0.5.10"
|
||||||
mimalloc = { version = "0.1.34", default-features = false }
|
mimalloc = { version = "0.1.34", default-features = false }
|
||||||
nonempty = "0.8.1"
|
nonempty = "0.8.1"
|
||||||
object = { version = "0.30.3", features = ["read", "write"] }
|
object = { version = "0.32.2", features = ["read", "write"] }
|
||||||
packed_struct = "0.10.1"
|
packed_struct = "0.10.1"
|
||||||
page_size = "0.5.0"
|
page_size = "0.5.0"
|
||||||
palette = "0.6.1"
|
palette = "0.6.1"
|
||||||
|
@ -139,7 +139,7 @@ quote = "1.0.23"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
regex = "1.7.1"
|
regex = "1.7.1"
|
||||||
remove_dir_all = "0.8.1"
|
remove_dir_all = "0.8.1"
|
||||||
reqwest = { version = "0.11.20", default-features = false, features = ["blocking", "rustls-tls"] } # default-features=false removes libopenssl as a dependency on Linux, which might not be available!
|
reqwest = { version = "0.11.23", default-features = false, features = ["blocking", "rustls-tls"] } # default-features=false removes libopenssl as a dependency on Linux, which might not be available!
|
||||||
rlimit = "0.9.1"
|
rlimit = "0.9.1"
|
||||||
rustyline = { git = "https://github.com/roc-lang/rustyline", rev = "e74333c" }
|
rustyline = { git = "https://github.com/roc-lang/rustyline", rev = "e74333c" }
|
||||||
rustyline-derive = { git = "https://github.com/roc-lang/rustyline", rev = "e74333c" }
|
rustyline-derive = { git = "https://github.com/roc-lang/rustyline", rev = "e74333c" }
|
||||||
|
|
|
@ -465,7 +465,6 @@ pub fn test(matches: &ArgMatches, triple: Triple) -> io::Result<i32> {
|
||||||
|
|
||||||
let arena = &arena;
|
let arena = &arena;
|
||||||
let target = &triple;
|
let target = &triple;
|
||||||
let opt_level = opt_level;
|
|
||||||
let target_info = TargetInfo::from(target);
|
let target_info = TargetInfo::from(target);
|
||||||
// TODO may need to determine this dynamically based on dev builds.
|
// TODO may need to determine this dynamically based on dev builds.
|
||||||
let function_kind = FunctionKind::LambdaSet;
|
let function_kind = FunctionKind::LambdaSet;
|
||||||
|
|
|
@ -145,7 +145,7 @@ fn main() -> io::Result<()> {
|
||||||
let triple = target.to_triple();
|
let triple = target.to_triple();
|
||||||
let function_kind = FunctionKind::LambdaSet;
|
let function_kind = FunctionKind::LambdaSet;
|
||||||
let (platform_path, stub_lib, stub_dll_symbols) = roc_linker::generate_stub_lib(
|
let (platform_path, stub_lib, stub_dll_symbols) = roc_linker::generate_stub_lib(
|
||||||
&input_path,
|
input_path,
|
||||||
RocCacheDir::Persistent(cache::roc_cache_dir().as_path()),
|
RocCacheDir::Persistent(cache::roc_cache_dir().as_path()),
|
||||||
&triple,
|
&triple,
|
||||||
function_kind,
|
function_kind,
|
||||||
|
|
11
crates/cli/tests/fixtures/.gitignore
vendored
11
crates/cli/tests/fixtures/.gitignore
vendored
|
@ -1,11 +0,0 @@
|
||||||
app
|
|
||||||
*.o
|
|
||||||
*.dSYM
|
|
||||||
dynhost
|
|
||||||
libapp.so
|
|
||||||
metadata
|
|
||||||
preprocessedhost
|
|
||||||
packages-test
|
|
||||||
|
|
||||||
multi-dep-str/multi-dep-str
|
|
||||||
multi-dep-thunk/multi-dep-thunk
|
|
|
@ -1 +0,0 @@
|
||||||
Main
|
|
|
@ -1 +0,0 @@
|
||||||
Main
|
|
17
crates/cli_testing_examples/.gitignore
vendored
17
crates/cli_testing_examples/.gitignore
vendored
|
@ -1,17 +0,0 @@
|
||||||
*.dSYM
|
|
||||||
libhost.a
|
|
||||||
libapp.so
|
|
||||||
dynhost
|
|
||||||
preprocessedhost
|
|
||||||
metadata
|
|
||||||
|
|
||||||
expects/expects
|
|
||||||
benchmarks/rbtree-ck
|
|
||||||
benchmarks/rbtree-insert
|
|
||||||
benchmarks/test-astar
|
|
||||||
benchmarks/test-base64
|
|
||||||
benchmarks/NQueens
|
|
||||||
benchmarks/cFold
|
|
||||||
benchmarks/nQueens
|
|
||||||
benchmarks/quicksortApp
|
|
||||||
benchmarks/rBTreeCk
|
|
|
@ -1,2 +0,0 @@
|
||||||
fibonacci
|
|
||||||
quicksort
|
|
|
@ -1,12 +0,0 @@
|
||||||
cfold
|
|
||||||
closure
|
|
||||||
deriv
|
|
||||||
issue2279
|
|
||||||
nqueens
|
|
||||||
quicksortapp
|
|
||||||
RBTreeCk
|
|
||||||
RBTreeDel
|
|
||||||
RBTreeInsert
|
|
||||||
TestAStar
|
|
||||||
TestBase64
|
|
||||||
*.wasm
|
|
|
@ -1,12 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "arena-pool"
|
|
||||||
description = "An implementation of an arena allocator designed for the compiler's workloads."
|
|
||||||
|
|
||||||
authors.workspace = true
|
|
||||||
edition.workspace = true
|
|
||||||
license.workspace = true
|
|
||||||
repository.workspace = true
|
|
||||||
version.workspace = true
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
roc_error_macros = { path = "../../error_macros" }
|
|
|
@ -1,2 +0,0 @@
|
||||||
//! An implementation of an [arena allocator](https://mgravell.github.io/Pipelines.Sockets.Unofficial/docs/arenas.html) designed for the compiler's workloads.
|
|
||||||
pub mod pool;
|
|
|
@ -1,397 +0,0 @@
|
||||||
use roc_error_macros::internal_error;
|
|
||||||
use std::marker::PhantomPinned;
|
|
||||||
use std::ptr::{copy_nonoverlapping, NonNull};
|
|
||||||
|
|
||||||
pub struct ArenaRef<T> {
|
|
||||||
ptr: NonNull<T>,
|
|
||||||
_pin: PhantomPinned,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> ArenaRef<T> {
|
|
||||||
pub fn get<'a, A: AsArena<T>>(&'a self, arena: &A) -> &'a T {
|
|
||||||
arena.verify_ownership(self.ptr);
|
|
||||||
|
|
||||||
// SAFETY: we know this pointer is safe to follow because it will only
|
|
||||||
// get deallocated once the pool where it was created gets deallocated
|
|
||||||
// (along with all of the Arenas it detached), and we just verified that
|
|
||||||
// this ArenaRef's ID matches a pool which has not yet been deallocated.
|
|
||||||
unsafe { self.ptr.as_ref() }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_mut<'a, A: AsArena<T>>(&'a mut self, arena: &A) -> &'a mut T {
|
|
||||||
arena.verify_ownership(self.ptr);
|
|
||||||
|
|
||||||
// SAFETY: we know this pointer is safe to follow because it will only
|
|
||||||
// get deallocated once the pool where it was created gets deallocated
|
|
||||||
// (along with all of the Arenas it detached), and we just verified that
|
|
||||||
// this ArenaRef's ID matches a pool which has not yet been deallocated.
|
|
||||||
unsafe { self.ptr.as_mut() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Like a Vec, except the capacity you give it initially is its maximum
|
|
||||||
/// capacity forever. If you ever exceed it, it'll panic!
|
|
||||||
pub struct ArenaVec<T> {
|
|
||||||
buffer_ptr: NonNull<T>,
|
|
||||||
len: usize,
|
|
||||||
capacity: usize,
|
|
||||||
_pin: PhantomPinned,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> ArenaVec<T> {
|
|
||||||
pub fn new_in(arena: &mut Arena<T>) -> Self {
|
|
||||||
// We can't start with a NonNull::dangling pointer because when we go
|
|
||||||
// to push elements into this, they'll try to verify the dangling
|
|
||||||
// pointer resides in the arena it was given, which will likely panic.
|
|
||||||
//
|
|
||||||
// Instead, we'll take a pointer inside the array but never use it
|
|
||||||
// other than for verification, because our capacity is 0.
|
|
||||||
Self::with_capacity_in(0, arena)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_capacity_in(capacity: usize, arena: &mut Arena<T>) -> Self {
|
|
||||||
let ptr = arena.alloc_vec(capacity);
|
|
||||||
|
|
||||||
Self {
|
|
||||||
buffer_ptr: unsafe { NonNull::new_unchecked(ptr) },
|
|
||||||
capacity,
|
|
||||||
len: 0,
|
|
||||||
_pin: PhantomPinned,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push(&mut self, val: T, arena: &mut Arena<T>) {
|
|
||||||
// Verify that this is the arena where we originally got our buffer,
|
|
||||||
// and is therefore safe to read and to write to. (If we have sufficient
|
|
||||||
// capacity, we'll write to it, and otherwise we'll read from it when
|
|
||||||
// copying our buffer over to the new reserved block.)
|
|
||||||
arena.verify_ownership(self.buffer_ptr);
|
|
||||||
|
|
||||||
if self.len <= self.capacity {
|
|
||||||
// We're all set!
|
|
||||||
//
|
|
||||||
// This empty branch is just here for branch prediction,
|
|
||||||
// since this should be the most common case in practice.
|
|
||||||
} else {
|
|
||||||
// Double our capacity and reserve a new block.
|
|
||||||
self.capacity *= 2;
|
|
||||||
|
|
||||||
let ptr = arena.alloc_vec(self.capacity);
|
|
||||||
|
|
||||||
// SAFETY: the existing buffer must have at least self.len elements,
|
|
||||||
// as must the new one, so copying that many between them is safe.
|
|
||||||
unsafe {
|
|
||||||
// Copy all elements from the current buffer into the new one
|
|
||||||
copy_nonoverlapping(self.buffer_ptr.as_ptr(), ptr, self.len);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.buffer_ptr = unsafe { NonNull::new_unchecked(ptr) };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store the element in the appropriate memory address.
|
|
||||||
let elem_ptr = unsafe { &mut *self.buffer_ptr.as_ptr().add(self.len) };
|
|
||||||
|
|
||||||
*elem_ptr = val;
|
|
||||||
|
|
||||||
self.len += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get<'a>(&'a self, index: usize, arena: &Arena<T>) -> Option<&'a T> {
|
|
||||||
arena.verify_ownership(self.buffer_ptr);
|
|
||||||
|
|
||||||
if index < self.len {
|
|
||||||
// SAFETY: we know this pointer is safe to follow because we've
|
|
||||||
// done a bounds check, and because we know it will only get
|
|
||||||
// deallocated once the pool where it was created gets deallocated
|
|
||||||
// (along with all of the Arenas it detached), and we just verified that
|
|
||||||
// this ArenaRef's ID matches a pool which has not yet been deallocated.
|
|
||||||
Some(unsafe { &*self.buffer_ptr.as_ptr().add(index) })
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_mut<'a>(&'a mut self, index: usize, arena: &Arena<T>) -> Option<&'a mut T> {
|
|
||||||
arena.verify_ownership(self.buffer_ptr);
|
|
||||||
|
|
||||||
if index < self.len {
|
|
||||||
// SAFETY: we know this pointer is safe to follow because we've
|
|
||||||
// done a bounds check, and because we know it will only get
|
|
||||||
// deallocated once the pool where it was created gets deallocated
|
|
||||||
// (along with all of the Arenas it detached), and we just verified that
|
|
||||||
// this ArenaRef's ID matches a pool which has not yet been deallocated.
|
|
||||||
Some(unsafe { &mut *self.buffer_ptr.as_ptr().add(index) })
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq, Eq)]
|
|
||||||
pub struct ArenaPool<T> {
|
|
||||||
first_chunk: Vec<T>,
|
|
||||||
extra_chunks: Vec<Vec<T>>,
|
|
||||||
num_leased: usize,
|
|
||||||
default_chunk_capacity: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> ArenaPool<T> {
|
|
||||||
const DEFAULT_CHUNK_SIZE: usize = 1024;
|
|
||||||
|
|
||||||
/// Be careful! Both of these arguments are of type usize.
|
|
||||||
///
|
|
||||||
/// The first is the number of elements that will be in each arena.
|
|
||||||
/// The second is the number of arenas.
|
|
||||||
///
|
|
||||||
/// This returns a new Pool, and also an iterator of Arenas. These Arenas can
|
|
||||||
/// be given to different threads, where they can be used to allocate
|
|
||||||
/// ArenaRef and ArenaVec values which can then be dereferenced by the Arena
|
|
||||||
/// that created them, or by this pool once those Arenas have been
|
|
||||||
/// reabsorbed back into it.
|
|
||||||
///
|
|
||||||
/// (A word of warning: if you try to use this pool to dereference ArenaRec
|
|
||||||
/// and ArenaVec values which were allocated by arenas that have *not* yet
|
|
||||||
/// been reabsorbed, it may work some of the time and panic other times,
|
|
||||||
/// depending on whether the arena needed to allocate extra chunks beyond
|
|
||||||
/// its initial chunk. tl;dr - doing that may panic, so don't try it!)
|
|
||||||
///
|
|
||||||
/// Before this pool gets dropped, you must call reabsorb() on every
|
|
||||||
/// arena that has been leased - otherwise, you'll get a panic when this
|
|
||||||
/// gets dropped! The memory safety of the system depends on all arenas
|
|
||||||
/// having been reabsorbed before the pool gets deallocated, which is why
|
|
||||||
/// the pool's Drop implementation enforces it.
|
|
||||||
pub fn new(num_arenas: usize, elems_per_arena: usize) -> (ArenaPool<T>, ArenaIter<T>) {
|
|
||||||
Self::with_chunk_size(num_arenas, elems_per_arena, Self::DEFAULT_CHUNK_SIZE)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Like `new`, except you can also specify the chunk size that each
|
|
||||||
/// arena will use to allocate its extra chunks if it runs out of space
|
|
||||||
/// in its main buffer.
|
|
||||||
///
|
|
||||||
/// Things will run fastest if that main buffer never runs out, though!
|
|
||||||
pub fn with_chunk_size(
|
|
||||||
num_arenas: usize,
|
|
||||||
elems_per_arena: usize,
|
|
||||||
chunk_size: usize,
|
|
||||||
) -> (ArenaPool<T>, ArenaIter<T>) {
|
|
||||||
let mut first_chunk = Vec::with_capacity(elems_per_arena * num_arenas);
|
|
||||||
let iter = ArenaIter {
|
|
||||||
ptr: first_chunk.as_mut_ptr(),
|
|
||||||
quantity_remaining: num_arenas,
|
|
||||||
first_chunk_capacity: elems_per_arena,
|
|
||||||
};
|
|
||||||
let pool = Self {
|
|
||||||
first_chunk,
|
|
||||||
extra_chunks: Vec::new(),
|
|
||||||
num_leased: num_arenas,
|
|
||||||
default_chunk_capacity: chunk_size,
|
|
||||||
};
|
|
||||||
|
|
||||||
(pool, iter)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return an arena to the pool. (This would have been called "return" but
|
|
||||||
/// that's a reserved keyword.)
|
|
||||||
pub fn reabsorb(&mut self, arena: Arena<T>) {
|
|
||||||
// Ensure we're reabsorbing an arena that was
|
|
||||||
// actually leased by this pool in the first place!
|
|
||||||
verify_ownership(
|
|
||||||
self.first_chunk.as_ptr(),
|
|
||||||
self.first_chunk.capacity(),
|
|
||||||
&self.extra_chunks,
|
|
||||||
arena.first_chunk_ptr,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add the arena's extra chunks to our own, so their memory remains live
|
|
||||||
// after the arena gets dropped. This is important, because at this
|
|
||||||
// point their pointers can still potentially be dereferenced!
|
|
||||||
self.extra_chunks.extend(arena.extra_chunks);
|
|
||||||
|
|
||||||
self.num_leased -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Drop for ArenaPool<T> {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
// When an ArenaPool gets dropped, it must not have any leased
|
|
||||||
// arenas remaining. If it does, there will be outstanding IDs which
|
|
||||||
// could be used with those non-reabsorbed Arenas to read freed memory!
|
|
||||||
// This would be a use-after-free; we panic rather than permit that.
|
|
||||||
assert_eq!(self.num_leased, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ArenaIter<T> {
|
|
||||||
ptr: *mut T,
|
|
||||||
quantity_remaining: usize,
|
|
||||||
first_chunk_capacity: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implement `Iterator` for `Fibonacci`.
|
|
||||||
// The `Iterator` trait only requires a method to be defined for the `next` element.
|
|
||||||
impl<T> Iterator for ArenaIter<T> {
|
|
||||||
type Item = Arena<T>;
|
|
||||||
|
|
||||||
// Here, we define the sequence using `.curr` and `.next`.
|
|
||||||
// The return type is `Option<T>`:
|
|
||||||
// * When the `Iterator` is finished, `None` is returned.
|
|
||||||
// * Otherwise, the next value is wrapped in `Some` and returned.
|
|
||||||
fn next(&mut self) -> Option<Arena<T>> {
|
|
||||||
if self.quantity_remaining != 0 {
|
|
||||||
let first_chunk_ptr = self.ptr;
|
|
||||||
|
|
||||||
self.ptr = unsafe { self.ptr.add(self.first_chunk_capacity) };
|
|
||||||
self.quantity_remaining -= 1;
|
|
||||||
|
|
||||||
Some(Arena {
|
|
||||||
first_chunk_ptr,
|
|
||||||
first_chunk_len: 0,
|
|
||||||
first_chunk_cap: self.first_chunk_capacity,
|
|
||||||
extra_chunks: Vec::new(),
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq, Eq)]
|
|
||||||
pub struct Arena<T> {
|
|
||||||
first_chunk_ptr: *mut T,
|
|
||||||
first_chunk_len: usize,
|
|
||||||
first_chunk_cap: usize,
|
|
||||||
extra_chunks: Vec<Vec<T>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Arena<T> {
|
|
||||||
pub fn alloc(&mut self, val: T) -> ArenaRef<T> {
|
|
||||||
let ptr: *mut T = if self.first_chunk_len < self.first_chunk_cap {
|
|
||||||
// We have enough room in the first chunk for 1 allocation.
|
|
||||||
self.first_chunk_len += 1;
|
|
||||||
|
|
||||||
// Return a pointer to the next available slot.
|
|
||||||
unsafe { self.first_chunk_ptr.add(self.first_chunk_len) }
|
|
||||||
} else {
|
|
||||||
// We ran out of space in the first chunk, so we turn to extra chunks.
|
|
||||||
// First, ensure that we have an extra chunk with enough space in it.
|
|
||||||
match self.extra_chunks.last() {
|
|
||||||
Some(chunk) => {
|
|
||||||
if chunk.len() >= chunk.capacity() {
|
|
||||||
// We've run out of space in our last chunk. Create a new one!
|
|
||||||
self.extra_chunks
|
|
||||||
.push(Vec::with_capacity(self.first_chunk_cap));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
// We've never had extra chunks until now. Create the first one!
|
|
||||||
self.extra_chunks
|
|
||||||
.push(Vec::with_capacity(self.first_chunk_cap));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let chunk = self.extra_chunks.last_mut().unwrap();
|
|
||||||
let index = chunk.len();
|
|
||||||
|
|
||||||
chunk.push(val);
|
|
||||||
|
|
||||||
// Get a pointer to a memory address within our particular chunk.
|
|
||||||
&mut chunk[index]
|
|
||||||
};
|
|
||||||
|
|
||||||
ArenaRef {
|
|
||||||
ptr: unsafe { NonNull::new_unchecked(ptr) },
|
|
||||||
_pin: PhantomPinned,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn alloc_vec(&mut self, num_elems: usize) -> *mut T {
|
|
||||||
if self.first_chunk_len + num_elems <= self.first_chunk_cap {
|
|
||||||
// We have enough room in the first chunk for this vec.
|
|
||||||
self.first_chunk_len += num_elems;
|
|
||||||
|
|
||||||
// Return a pointer to the next available element.
|
|
||||||
unsafe { self.first_chunk_ptr.add(self.first_chunk_len) }
|
|
||||||
} else {
|
|
||||||
let new_chunk_cap = self.first_chunk_cap.max(num_elems);
|
|
||||||
|
|
||||||
// We ran out of space in the first chunk, so we turn to extra chunks.
|
|
||||||
// First, ensure that we have an extra chunk with enough space in it.
|
|
||||||
match self.extra_chunks.last() {
|
|
||||||
Some(chunk) => {
|
|
||||||
if chunk.len() + num_elems >= chunk.capacity() {
|
|
||||||
// We don't have enough space in our last chunk.
|
|
||||||
// Create a new one!
|
|
||||||
self.extra_chunks.push(Vec::with_capacity(new_chunk_cap));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
// We've never had extra chunks until now. Create the first one!
|
|
||||||
self.extra_chunks.push(Vec::with_capacity(new_chunk_cap));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let chunk = self.extra_chunks.last_mut().unwrap();
|
|
||||||
let index = chunk.len();
|
|
||||||
|
|
||||||
// Get a pointer to a memory address within our particular chunk.
|
|
||||||
&mut chunk[index]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait AsArena<T> {
|
|
||||||
fn verify_ownership(&self, ptr: NonNull<T>);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> AsArena<T> for ArenaPool<T> {
|
|
||||||
fn verify_ownership(&self, ptr: NonNull<T>) {
|
|
||||||
verify_ownership(
|
|
||||||
self.first_chunk.as_ptr(),
|
|
||||||
self.first_chunk.capacity(),
|
|
||||||
&self.extra_chunks,
|
|
||||||
ptr.as_ptr(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> AsArena<T> for Arena<T> {
|
|
||||||
fn verify_ownership(&self, ptr: NonNull<T>) {
|
|
||||||
verify_ownership(
|
|
||||||
self.first_chunk_ptr,
|
|
||||||
self.first_chunk_cap,
|
|
||||||
&self.extra_chunks,
|
|
||||||
ptr.as_ptr(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn verify_ownership<T>(
|
|
||||||
first_chunk_ptr: *const T,
|
|
||||||
first_chunk_cap: usize,
|
|
||||||
extra_chunks: &[Vec<T>],
|
|
||||||
ptr: *const T,
|
|
||||||
) {
|
|
||||||
let addr = ptr as usize;
|
|
||||||
let start_addr = first_chunk_ptr as usize;
|
|
||||||
let end_addr = start_addr + first_chunk_cap;
|
|
||||||
|
|
||||||
if start_addr <= addr && addr < end_addr {
|
|
||||||
// This is within our first chunk's address space, so it's verified!
|
|
||||||
} else {
|
|
||||||
// This wasn't within our first chunk's address space, so we need
|
|
||||||
// to see if we can find it in one of our extra_chunks.
|
|
||||||
for chunk in extra_chunks {
|
|
||||||
let start_addr = chunk.as_ptr() as usize;
|
|
||||||
let end_addr = start_addr + chunk.capacity();
|
|
||||||
|
|
||||||
if start_addr <= addr && addr < end_addr {
|
|
||||||
// Found it! No need to loop anymore; verification passed.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The address wasn't within any of our chunks' bounds.
|
|
||||||
// Panic to avoid use-after-free errors!
|
|
||||||
internal_error!("Pointer ownership verification failed.");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
// #[macro_use]
|
|
||||||
// extern crate pretty_assertions;
|
|
||||||
|
|
||||||
extern crate arena_pool;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test_arena_pool {
|
|
||||||
use arena_pool::pool::{ArenaIter, ArenaPool};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn empty_pool() {
|
|
||||||
// Neither of these does anything, but they
|
|
||||||
// at least shouldn't panic or anything.
|
|
||||||
let _: (ArenaPool<()>, ArenaIter<()>) = ArenaPool::new(0, 0);
|
|
||||||
let _: (ArenaPool<()>, ArenaIter<()>) = ArenaPool::with_chunk_size(0, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -802,7 +802,7 @@ fn build_loaded_file<'a>(
|
||||||
platform_main_roc.with_file_name(roc_linker::preprocessed_host_filename(target).unwrap())
|
platform_main_roc.with_file_name(roc_linker::preprocessed_host_filename(target).unwrap())
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut output_exe_path = match out_path {
|
let output_exe_path = match out_path {
|
||||||
Some(path) => {
|
Some(path) => {
|
||||||
// true iff the path ends with a directory separator,
|
// true iff the path ends with a directory separator,
|
||||||
// e.g. '/' on UNIX, '/' or '\\' on Windows
|
// e.g. '/' on UNIX, '/' or '\\' on Windows
|
||||||
|
@ -830,12 +830,22 @@ fn build_loaded_file<'a>(
|
||||||
if ends_with_sep {
|
if ends_with_sep {
|
||||||
let filename = app_module_path.file_name().unwrap_or_default();
|
let filename = app_module_path.file_name().unwrap_or_default();
|
||||||
|
|
||||||
with_executable_extension(&path.join(filename), operating_system)
|
with_output_extension(
|
||||||
|
&path.join(filename),
|
||||||
|
operating_system,
|
||||||
|
linking_strategy,
|
||||||
|
link_type,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
path.to_path_buf()
|
path.to_path_buf()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => with_executable_extension(&app_module_path, operating_system),
|
None => with_output_extension(
|
||||||
|
&app_module_path,
|
||||||
|
operating_system,
|
||||||
|
linking_strategy,
|
||||||
|
link_type,
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
// We don't need to spawn a rebuild thread when using a prebuilt host.
|
// We don't need to spawn a rebuild thread when using a prebuilt host.
|
||||||
|
@ -994,7 +1004,6 @@ fn build_loaded_file<'a>(
|
||||||
}
|
}
|
||||||
(LinkingStrategy::Additive, _) | (LinkingStrategy::Legacy, LinkType::None) => {
|
(LinkingStrategy::Additive, _) | (LinkingStrategy::Legacy, LinkType::None) => {
|
||||||
// Just copy the object file to the output folder.
|
// Just copy the object file to the output folder.
|
||||||
output_exe_path.set_extension(operating_system.object_file_ext());
|
|
||||||
std::fs::write(&output_exe_path, &*roc_app_bytes).unwrap();
|
std::fs::write(&output_exe_path, &*roc_app_bytes).unwrap();
|
||||||
}
|
}
|
||||||
(LinkingStrategy::Legacy, _) => {
|
(LinkingStrategy::Legacy, _) => {
|
||||||
|
@ -1324,6 +1333,17 @@ pub fn build_str_test<'a>(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_executable_extension(path: &Path, os: OperatingSystem) -> PathBuf {
|
fn with_output_extension(
|
||||||
path.with_extension(os.executable_file_ext().unwrap_or_default())
|
path: &Path,
|
||||||
|
os: OperatingSystem,
|
||||||
|
linking_strategy: LinkingStrategy,
|
||||||
|
link_type: LinkType,
|
||||||
|
) -> PathBuf {
|
||||||
|
match (linking_strategy, link_type) {
|
||||||
|
(LinkingStrategy::Additive, _) | (LinkingStrategy::Legacy, LinkType::None) => {
|
||||||
|
// Additive linking and no linking both output the object file type.
|
||||||
|
path.with_extension(os.object_file_ext())
|
||||||
|
}
|
||||||
|
_ => path.with_extension(os.executable_file_ext().unwrap_or_default()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
1
crates/compiler/builtins/.gitignore
vendored
1
crates/compiler/builtins/.gitignore
vendored
|
@ -1 +0,0 @@
|
||||||
builtins.ll
|
|
5
crates/compiler/builtins/bitcode/.gitignore
vendored
5
crates/compiler/builtins/bitcode/.gitignore
vendored
|
@ -1,5 +0,0 @@
|
||||||
zig-out
|
|
||||||
zig-cache
|
|
||||||
src/zig-cache
|
|
||||||
benchmark/zig-cache
|
|
||||||
dec
|
|
|
@ -264,6 +264,9 @@ comptime {
|
||||||
if (builtin.target.cpu.arch == .aarch64) {
|
if (builtin.target.cpu.arch == .aarch64) {
|
||||||
@export(__roc_force_setjmp, .{ .name = "__roc_force_setjmp", .linkage = .Weak });
|
@export(__roc_force_setjmp, .{ .name = "__roc_force_setjmp", .linkage = .Weak });
|
||||||
@export(__roc_force_longjmp, .{ .name = "__roc_force_longjmp", .linkage = .Weak });
|
@export(__roc_force_longjmp, .{ .name = "__roc_force_longjmp", .linkage = .Weak });
|
||||||
|
} else if (builtin.os.tag == .windows) {
|
||||||
|
@export(__roc_force_setjmp_windows, .{ .name = "__roc_force_setjmp", .linkage = .Weak });
|
||||||
|
@export(__roc_force_longjmp_windows, .{ .name = "__roc_force_longjmp", .linkage = .Weak });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,14 +282,103 @@ pub extern fn _longjmp([*c]c_int, c_int) noreturn;
|
||||||
pub extern fn sigsetjmp([*c]c_int, c_int) c_int;
|
pub extern fn sigsetjmp([*c]c_int, c_int) c_int;
|
||||||
pub extern fn siglongjmp([*c]c_int, c_int) noreturn;
|
pub extern fn siglongjmp([*c]c_int, c_int) noreturn;
|
||||||
pub extern fn longjmperror() void;
|
pub extern fn longjmperror() void;
|
||||||
|
|
||||||
// Zig won't expose the externs (and hence link correctly) unless we force them to be used.
|
// Zig won't expose the externs (and hence link correctly) unless we force them to be used.
|
||||||
fn __roc_force_setjmp(it: [*c]c_int) callconv(.C) c_int {
|
fn __roc_force_setjmp(it: [*c]c_int) callconv(.C) c_int {
|
||||||
return setjmp(it);
|
return setjmp(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __roc_force_longjmp(a0: [*c]c_int, a1: c_int) callconv(.C) noreturn {
|
fn __roc_force_longjmp(a0: [*c]c_int, a1: c_int) callconv(.C) noreturn {
|
||||||
longjmp(a0, a1);
|
longjmp(a0, a1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub extern fn windows_setjmp([*c]c_int) c_int;
|
||||||
|
pub extern fn windows_longjmp([*c]c_int, c_int) noreturn;
|
||||||
|
|
||||||
|
fn __roc_force_setjmp_windows(it: [*c]c_int) callconv(.C) c_int {
|
||||||
|
return windows_setjmp(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __roc_force_longjmp_windows(a0: [*c]c_int, a1: c_int) callconv(.C) noreturn {
|
||||||
|
windows_longjmp(a0, a1);
|
||||||
|
}
|
||||||
|
|
||||||
|
comptime {
|
||||||
|
if (builtin.os.tag == .windows) {
|
||||||
|
asm (
|
||||||
|
\\.global windows_longjmp;
|
||||||
|
\\windows_longjmp:
|
||||||
|
\\ movq 0x00(%rcx), %rdx
|
||||||
|
\\ movq 0x08(%rcx), %rbx
|
||||||
|
\\ # note 0x10 is not used yet!
|
||||||
|
\\ movq 0x18(%rcx), %rbp
|
||||||
|
\\ movq 0x20(%rcx), %rsi
|
||||||
|
\\ movq 0x28(%rcx), %rdi
|
||||||
|
\\ movq 0x30(%rcx), %r12
|
||||||
|
\\ movq 0x38(%rcx), %r13
|
||||||
|
\\ movq 0x40(%rcx), %r14
|
||||||
|
\\ movq 0x48(%rcx), %r15
|
||||||
|
\\
|
||||||
|
\\ # restore stack pointer
|
||||||
|
\\ movq 0x10(%rcx), %rsp
|
||||||
|
\\
|
||||||
|
\\ # load jmp address
|
||||||
|
\\ movq 0x50(%rcx), %r8
|
||||||
|
\\
|
||||||
|
\\ # set up return value
|
||||||
|
\\ movq %rbx, %rax
|
||||||
|
\\
|
||||||
|
\\ movdqu 0x60(%rcx), %xmm6
|
||||||
|
\\ movdqu 0x70(%rcx), %xmm7
|
||||||
|
\\ movdqu 0x80(%rcx), %xmm8
|
||||||
|
\\ movdqu 0x90(%rcx), %xmm9
|
||||||
|
\\ movdqu 0xa0(%rcx), %xmm10
|
||||||
|
\\ movdqu 0xb0(%rcx), %xmm11
|
||||||
|
\\ movdqu 0xc0(%rcx), %xmm12
|
||||||
|
\\ movdqu 0xd0(%rcx), %xmm13
|
||||||
|
\\ movdqu 0xe0(%rcx), %xmm14
|
||||||
|
\\ movdqu 0xf0(%rcx), %xmm15
|
||||||
|
\\
|
||||||
|
\\ jmp *%r8
|
||||||
|
\\
|
||||||
|
\\.global windows_setjmp;
|
||||||
|
\\windows_setjmp:
|
||||||
|
\\ movq %rdx, 0x00(%rcx)
|
||||||
|
\\ movq %rbx, 0x08(%rcx)
|
||||||
|
\\ # note 0x10 is not used yet!
|
||||||
|
\\ movq %rbp, 0x18(%rcx)
|
||||||
|
\\ movq %rsi, 0x20(%rcx)
|
||||||
|
\\ movq %rdi, 0x28(%rcx)
|
||||||
|
\\ movq %r12, 0x30(%rcx)
|
||||||
|
\\ movq %r13, 0x38(%rcx)
|
||||||
|
\\ movq %r14, 0x40(%rcx)
|
||||||
|
\\ movq %r15, 0x48(%rcx)
|
||||||
|
\\
|
||||||
|
\\ # the stack location right after the windows_setjmp call
|
||||||
|
\\ leaq 0x08(%rsp), %r8
|
||||||
|
\\ movq %r8, 0x10(%rcx)
|
||||||
|
\\
|
||||||
|
\\ movq (%rsp), %r8
|
||||||
|
\\ movq %r8, 0x50(%rcx)
|
||||||
|
\\
|
||||||
|
\\ movdqu %xmm6, 0x60(%rcx)
|
||||||
|
\\ movdqu %xmm7, 0x70(%rcx)
|
||||||
|
\\ movdqu %xmm8, 0x80(%rcx)
|
||||||
|
\\ movdqu %xmm9, 0x90(%rcx)
|
||||||
|
\\ movdqu %xmm10, 0xa0(%rcx)
|
||||||
|
\\ movdqu %xmm11, 0xb0(%rcx)
|
||||||
|
\\ movdqu %xmm12, 0xc0(%rcx)
|
||||||
|
\\ movdqu %xmm13, 0xd0(%rcx)
|
||||||
|
\\ movdqu %xmm14, 0xe0(%rcx)
|
||||||
|
\\ movdqu %xmm15, 0xf0(%rcx)
|
||||||
|
\\
|
||||||
|
\\ xorl %eax, %eax
|
||||||
|
\\ ret
|
||||||
|
\\
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Export helpers - Must be run inside a comptime
|
// Export helpers - Must be run inside a comptime
|
||||||
fn exportBuiltinFn(comptime func: anytype, comptime func_name: []const u8) void {
|
fn exportBuiltinFn(comptime func: anytype, comptime func_name: []const u8) void {
|
||||||
@export(func, .{ .name = "roc_builtins." ++ func_name, .linkage = .Strong });
|
@export(func, .{ .name = "roc_builtins." ++ func_name, .linkage = .Strong });
|
||||||
|
|
|
@ -445,6 +445,9 @@ pub const NOTIFY_PARENT_EXPECT: &str = "roc_builtins.utils.notify_parent_expect"
|
||||||
pub const UTILS_LONGJMP: &str = "longjmp";
|
pub const UTILS_LONGJMP: &str = "longjmp";
|
||||||
pub const UTILS_SETJMP: &str = "setjmp";
|
pub const UTILS_SETJMP: &str = "setjmp";
|
||||||
|
|
||||||
|
pub const UTILS_WINDOWS_SETJMP: &str = "windows_setjmp";
|
||||||
|
pub const UTILS_WINDOWS_LONGJMP: &str = "windows_longjmp";
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct IntToIntrinsicName {
|
pub struct IntToIntrinsicName {
|
||||||
pub options: [IntrinsicName; 10],
|
pub options: [IntrinsicName; 10],
|
||||||
|
|
|
@ -1112,7 +1112,7 @@ fn deep_copy_type_vars<C: CopyEnv>(
|
||||||
}
|
}
|
||||||
for uls_index in unspecialized {
|
for uls_index in unspecialized {
|
||||||
let Uls(var, _, _) = env.source()[uls_index];
|
let Uls(var, _, _) = env.source()[uls_index];
|
||||||
descend_var!(var);
|
let _ignored = descend_var!(var);
|
||||||
}
|
}
|
||||||
let new_ambient_function = descend_var!(ambient_function);
|
let new_ambient_function = descend_var!(ambient_function);
|
||||||
|
|
||||||
|
|
|
@ -74,14 +74,25 @@ fn print_declarations_help<'a>(
|
||||||
f.intersperse(defs, f.hardline().append(f.hardline()))
|
f.intersperse(defs, f.hardline().append(f.hardline()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn always_true() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! maybe_paren {
|
macro_rules! maybe_paren {
|
||||||
($paren_if_above:expr, $my_prec:expr, $doc:expr) => {
|
($paren_if_above:expr, $my_prec:expr, $doc:expr) => {
|
||||||
maybe_paren!($paren_if_above, $my_prec, || true, $doc)
|
maybe_paren!($paren_if_above, $my_prec, always_true, $doc)
|
||||||
};
|
};
|
||||||
($paren_if_above:expr, $my_prec:expr, $extra_cond:expr, $doc:expr) => {
|
($paren_if_above:expr, $my_prec:expr, $extra_cond:expr, $doc:expr) => {
|
||||||
if $my_prec > $paren_if_above && $extra_cond() {
|
'blk: {
|
||||||
$doc.parens().group()
|
if $my_prec > $paren_if_above {
|
||||||
} else {
|
#[allow(clippy::redundant_closure_call)]
|
||||||
|
let extra_cond = $extra_cond();
|
||||||
|
|
||||||
|
if extra_cond {
|
||||||
|
break 'blk $doc.parens().group();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$doc
|
$doc
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -2423,7 +2423,9 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
|
||||||
| ast::StrSegment::Plaintext(_) => true,
|
| ast::StrSegment::Plaintext(_) => true,
|
||||||
// Disallow nested interpolation. Alternatively, we could allow it but require
|
// Disallow nested interpolation. Alternatively, we could allow it but require
|
||||||
// a comment above it apologizing to the next person who has to read the code.
|
// a comment above it apologizing to the next person who has to read the code.
|
||||||
ast::StrSegment::Interpolated(_) => false,
|
ast::StrSegment::Interpolated(_) | ast::StrSegment::DeprecatedInterpolated(_) => {
|
||||||
|
false
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ast::Expr::Record(fields) => fields.iter().all(|loc_field| match loc_field.value {
|
ast::Expr::Record(fields) => fields.iter().all(|loc_field| match loc_field.value {
|
||||||
|
@ -2550,7 +2552,7 @@ fn flatten_str_lines<'a>(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Interpolated(loc_expr) => {
|
Interpolated(loc_expr) | DeprecatedInterpolated(loc_expr) => {
|
||||||
if is_valid_interpolation(loc_expr.value) {
|
if is_valid_interpolation(loc_expr.value) {
|
||||||
// Interpolations desugar to Str.concat calls
|
// Interpolations desugar to Str.concat calls
|
||||||
output.references.insert_call(Symbol::STR_CONCAT);
|
output.references.insert_call(Symbol::STR_CONCAT);
|
||||||
|
|
|
@ -634,6 +634,22 @@ fn desugar_str_segments<'a>(
|
||||||
StrSegment::Plaintext(_) | StrSegment::Unicode(_) | StrSegment::EscapedChar(_) => {
|
StrSegment::Plaintext(_) | StrSegment::Unicode(_) | StrSegment::EscapedChar(_) => {
|
||||||
*segment
|
*segment
|
||||||
}
|
}
|
||||||
|
StrSegment::DeprecatedInterpolated(loc_expr) => {
|
||||||
|
let loc_desugared = desugar_expr(
|
||||||
|
arena,
|
||||||
|
arena.alloc(Loc {
|
||||||
|
region: loc_expr.region,
|
||||||
|
value: *loc_expr.value,
|
||||||
|
}),
|
||||||
|
src,
|
||||||
|
line_info,
|
||||||
|
module_path,
|
||||||
|
);
|
||||||
|
StrSegment::DeprecatedInterpolated(Loc {
|
||||||
|
region: loc_desugared.region,
|
||||||
|
value: arena.alloc(loc_desugared.value),
|
||||||
|
})
|
||||||
|
}
|
||||||
StrSegment::Interpolated(loc_expr) => {
|
StrSegment::Interpolated(loc_expr) => {
|
||||||
let loc_desugared = desugar_expr(
|
let loc_desugared = desugar_expr(
|
||||||
arena,
|
arena,
|
||||||
|
|
|
@ -1071,7 +1071,7 @@ fn flatten_str_lines(lines: &[&[StrSegment<'_>]]) -> Pattern {
|
||||||
Unicode(loc_digits) => {
|
Unicode(loc_digits) => {
|
||||||
todo!("parse unicode digits {:?}", loc_digits);
|
todo!("parse unicode digits {:?}", loc_digits);
|
||||||
}
|
}
|
||||||
Interpolated(loc_expr) => {
|
Interpolated(loc_expr) | DeprecatedInterpolated(loc_expr) => {
|
||||||
return Pattern::UnsupportedPattern(loc_expr.region);
|
return Pattern::UnsupportedPattern(loc_expr.region);
|
||||||
}
|
}
|
||||||
EscapedChar(escaped) => buf.push(escaped.unescape()),
|
EscapedChar(escaped) => buf.push(escaped.unescape()),
|
||||||
|
|
|
@ -280,12 +280,12 @@ mod test_can {
|
||||||
#[test]
|
#[test]
|
||||||
fn correct_annotated_body() {
|
fn correct_annotated_body() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
f : Num.Int * -> Num.Int *
|
f : Num.Int * -> Num.Int *
|
||||||
f = \ a -> a
|
f = \ a -> a
|
||||||
|
|
||||||
f
|
f
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
||||||
|
@ -296,12 +296,12 @@ mod test_can {
|
||||||
#[test]
|
#[test]
|
||||||
fn correct_annotated_body_with_comments() {
|
fn correct_annotated_body_with_comments() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
f : Num.Int * -> Num.Int * # comment
|
f : Num.Int * -> Num.Int * # comment
|
||||||
f = \ a -> a
|
f = \ a -> a
|
||||||
|
|
||||||
f
|
f
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
||||||
|
@ -312,12 +312,12 @@ mod test_can {
|
||||||
#[test]
|
#[test]
|
||||||
fn name_mismatch_annotated_body() {
|
fn name_mismatch_annotated_body() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
f : Num.Int * -> Num.Int *
|
f : Num.Int * -> Num.Int *
|
||||||
g = \ a -> a
|
g = \ a -> a
|
||||||
|
|
||||||
g
|
g
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
||||||
|
@ -340,12 +340,12 @@ mod test_can {
|
||||||
#[test]
|
#[test]
|
||||||
fn name_mismatch_annotated_body_with_comment() {
|
fn name_mismatch_annotated_body_with_comment() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
f : Num.Int * -> Num.Int * # comment
|
f : Num.Int * -> Num.Int * # comment
|
||||||
g = \ a -> a
|
g = \ a -> a
|
||||||
|
|
||||||
g
|
g
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
||||||
|
@ -368,13 +368,13 @@ mod test_can {
|
||||||
#[test]
|
#[test]
|
||||||
fn separated_annotated_body() {
|
fn separated_annotated_body() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
f : Num.Int * -> Num.Int *
|
f : Num.Int * -> Num.Int *
|
||||||
|
|
||||||
f = \ a -> a
|
f = \ a -> a
|
||||||
|
|
||||||
f 42
|
f 42
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
||||||
|
@ -389,13 +389,13 @@ mod test_can {
|
||||||
#[test]
|
#[test]
|
||||||
fn separated_annotated_body_with_comment() {
|
fn separated_annotated_body_with_comment() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
f : Num.Int * -> Num.Int *
|
f : Num.Int * -> Num.Int *
|
||||||
# comment
|
# comment
|
||||||
f = \ a -> a
|
f = \ a -> a
|
||||||
|
|
||||||
f 42
|
f 42
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
||||||
|
@ -410,13 +410,13 @@ mod test_can {
|
||||||
#[test]
|
#[test]
|
||||||
fn shadowed_annotation() {
|
fn shadowed_annotation() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
f : Num.Int * -> Num.Int *
|
f : Num.Int * -> Num.Int *
|
||||||
|
|
||||||
f : Num.Int * -> Num.Int *
|
f : Num.Int * -> Num.Int *
|
||||||
|
|
||||||
f
|
f
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
||||||
|
@ -432,7 +432,7 @@ mod test_can {
|
||||||
#[test]
|
#[test]
|
||||||
fn correct_nested_unannotated_body() {
|
fn correct_nested_unannotated_body() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
f : Num.Int *
|
f : Num.Int *
|
||||||
f =
|
f =
|
||||||
g = 42
|
g = 42
|
||||||
|
@ -440,7 +440,7 @@ mod test_can {
|
||||||
g + 1
|
g + 1
|
||||||
|
|
||||||
f
|
f
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
||||||
|
@ -451,7 +451,7 @@ mod test_can {
|
||||||
#[test]
|
#[test]
|
||||||
fn correct_nested_annotated_body() {
|
fn correct_nested_annotated_body() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
f : Num.Int *
|
f : Num.Int *
|
||||||
f =
|
f =
|
||||||
g : Num.Int *
|
g : Num.Int *
|
||||||
|
@ -460,7 +460,7 @@ mod test_can {
|
||||||
g + 1
|
g + 1
|
||||||
|
|
||||||
f
|
f
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
||||||
|
@ -471,7 +471,7 @@ mod test_can {
|
||||||
#[test]
|
#[test]
|
||||||
fn correct_nested_body_annotated_multiple_lines() {
|
fn correct_nested_body_annotated_multiple_lines() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
f : Num.Int *
|
f : Num.Int *
|
||||||
f =
|
f =
|
||||||
g : Num.Int *
|
g : Num.Int *
|
||||||
|
@ -482,7 +482,7 @@ mod test_can {
|
||||||
g + h + z
|
g + h + z
|
||||||
|
|
||||||
f
|
f
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
||||||
|
@ -493,7 +493,7 @@ mod test_can {
|
||||||
#[test]
|
#[test]
|
||||||
fn correct_nested_body_unannotated_multiple_lines() {
|
fn correct_nested_body_unannotated_multiple_lines() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
f : Num.Int *
|
f : Num.Int *
|
||||||
f =
|
f =
|
||||||
g = 42
|
g = 42
|
||||||
|
@ -503,7 +503,7 @@ mod test_can {
|
||||||
g + h + z
|
g + h + z
|
||||||
|
|
||||||
f
|
f
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
||||||
|
@ -513,7 +513,7 @@ mod test_can {
|
||||||
#[test]
|
#[test]
|
||||||
fn correct_double_nested_body() {
|
fn correct_double_nested_body() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
f : Num.Int *
|
f : Num.Int *
|
||||||
f =
|
f =
|
||||||
g =
|
g =
|
||||||
|
@ -523,7 +523,7 @@ mod test_can {
|
||||||
|
|
||||||
|
|
||||||
f
|
f
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
||||||
|
@ -534,13 +534,13 @@ mod test_can {
|
||||||
#[test]
|
#[test]
|
||||||
fn annotation_followed_with_unrelated_affectation() {
|
fn annotation_followed_with_unrelated_affectation() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
F : Str
|
F : Str
|
||||||
|
|
||||||
x = 1
|
x = 1
|
||||||
|
|
||||||
x
|
x
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
||||||
|
@ -554,7 +554,7 @@ mod test_can {
|
||||||
#[test]
|
#[test]
|
||||||
fn two_annotations_followed_with_unrelated_affectation() {
|
fn two_annotations_followed_with_unrelated_affectation() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
G : Str
|
G : Str
|
||||||
|
|
||||||
F : {}
|
F : {}
|
||||||
|
@ -562,7 +562,7 @@ mod test_can {
|
||||||
x = 1
|
x = 1
|
||||||
|
|
||||||
x
|
x
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
||||||
|
@ -581,11 +581,11 @@ mod test_can {
|
||||||
// // it only exists in the closure's arguments.
|
// // it only exists in the closure's arguments.
|
||||||
// let arena = Bump::new();
|
// let arena = Bump::new();
|
||||||
// let src = indoc!(
|
// let src = indoc!(
|
||||||
// r#"
|
// r"
|
||||||
// func = \arg -> arg
|
// func = \arg -> arg
|
||||||
|
|
||||||
// func 2
|
// func 2
|
||||||
// "#
|
// "
|
||||||
// );
|
// );
|
||||||
// let (_actual, output, problems, _var_store, _vars, _constraint) =
|
// let (_actual, output, problems, _var_store, _vars, _constraint) =
|
||||||
// can_expr_with(&arena, test_home(), src);
|
// can_expr_with(&arena, test_home(), src);
|
||||||
|
@ -608,13 +608,13 @@ mod test_can {
|
||||||
// fn call_by_pointer_for_fn_args() {
|
// fn call_by_pointer_for_fn_args() {
|
||||||
// // This function will get passed in as a pointer.
|
// // This function will get passed in as a pointer.
|
||||||
// let src = indoc!(
|
// let src = indoc!(
|
||||||
// r#"
|
// r"
|
||||||
// apply = \f, x -> f x
|
// apply = \f, x -> f x
|
||||||
|
|
||||||
// identity = \a -> a
|
// identity = \a -> a
|
||||||
|
|
||||||
// apply identity 5
|
// apply identity 5
|
||||||
// "#
|
// "
|
||||||
// );
|
// );
|
||||||
// let arena = Bump::new();
|
// let arena = Bump::new();
|
||||||
// let (_actual, output, problems, _var_store, _vars, _constraint) =
|
// let (_actual, output, problems, _var_store, _vars, _constraint) =
|
||||||
|
@ -637,9 +637,9 @@ mod test_can {
|
||||||
#[test]
|
#[test]
|
||||||
fn incorrect_optional_value() {
|
fn incorrect_optional_value() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
{ x ? 42 }
|
{ x ? 42 }
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let CanExprOut {
|
let CanExprOut {
|
||||||
|
@ -911,7 +911,7 @@ mod test_can {
|
||||||
#[test]
|
#[test]
|
||||||
fn recognize_tail_calls() {
|
fn recognize_tail_calls() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
g = \x ->
|
g = \x ->
|
||||||
when x is
|
when x is
|
||||||
0 -> 0
|
0 -> 0
|
||||||
|
@ -936,7 +936,7 @@ mod test_can {
|
||||||
{ x: p, y: h }
|
{ x: p, y: h }
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let CanExprOut {
|
let CanExprOut {
|
||||||
|
@ -963,7 +963,7 @@ mod test_can {
|
||||||
// #[test]
|
// #[test]
|
||||||
// fn reproduce_incorrect_unused_defs() {
|
// fn reproduce_incorrect_unused_defs() {
|
||||||
// let src = indoc!(
|
// let src = indoc!(
|
||||||
// r#"
|
// r"
|
||||||
// g = \x ->
|
// g = \x ->
|
||||||
// when x is
|
// when x is
|
||||||
// 0 -> 0
|
// 0 -> 0
|
||||||
|
@ -983,7 +983,7 @@ mod test_can {
|
||||||
// # variables must be (indirectly) referenced in the body for analysis to work
|
// # variables must be (indirectly) referenced in the body for analysis to work
|
||||||
// # { x: p, y: h }
|
// # { x: p, y: h }
|
||||||
// g
|
// g
|
||||||
// "#
|
// "
|
||||||
// );
|
// );
|
||||||
// let arena = Bump::new();
|
// let arena = Bump::new();
|
||||||
// let CanExprOut {
|
// let CanExprOut {
|
||||||
|
@ -1012,14 +1012,14 @@ mod test_can {
|
||||||
#[test]
|
#[test]
|
||||||
fn when_tail_call() {
|
fn when_tail_call() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
g = \x ->
|
g = \x ->
|
||||||
when x is
|
when x is
|
||||||
0 -> 0
|
0 -> 0
|
||||||
_ -> g (x + 1)
|
_ -> g (x + 1)
|
||||||
|
|
||||||
g 0
|
g 0
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let CanExprOut {
|
let CanExprOut {
|
||||||
|
@ -1034,11 +1034,11 @@ mod test_can {
|
||||||
#[test]
|
#[test]
|
||||||
fn immediate_tail_call() {
|
fn immediate_tail_call() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
f = \x -> f x
|
f = \x -> f x
|
||||||
|
|
||||||
f 0
|
f 0
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let CanExprOut {
|
let CanExprOut {
|
||||||
|
@ -1055,13 +1055,13 @@ mod test_can {
|
||||||
#[test]
|
#[test]
|
||||||
fn when_condition_is_no_tail_call() {
|
fn when_condition_is_no_tail_call() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
q = \x ->
|
q = \x ->
|
||||||
when q x is
|
when q x is
|
||||||
_ -> 0
|
_ -> 0
|
||||||
|
|
||||||
q 0
|
q 0
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let CanExprOut {
|
let CanExprOut {
|
||||||
|
@ -1076,7 +1076,7 @@ mod test_can {
|
||||||
#[test]
|
#[test]
|
||||||
fn good_mutual_recursion() {
|
fn good_mutual_recursion() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
q = \x ->
|
q = \x ->
|
||||||
when x is
|
when x is
|
||||||
0 -> 0
|
0 -> 0
|
||||||
|
@ -1088,7 +1088,7 @@ mod test_can {
|
||||||
_ -> q (x - 1)
|
_ -> q (x - 1)
|
||||||
|
|
||||||
q p
|
q p
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let CanExprOut {
|
let CanExprOut {
|
||||||
|
@ -1107,11 +1107,11 @@ mod test_can {
|
||||||
#[test]
|
#[test]
|
||||||
fn valid_self_recursion() {
|
fn valid_self_recursion() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
boom = \_ -> boom {}
|
boom = \_ -> boom {}
|
||||||
|
|
||||||
boom
|
boom
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let CanExprOut {
|
let CanExprOut {
|
||||||
|
@ -1128,13 +1128,13 @@ mod test_can {
|
||||||
#[test]
|
#[test]
|
||||||
fn invalid_mutual_recursion() {
|
fn invalid_mutual_recursion() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
x = y
|
x = y
|
||||||
y = z
|
y = z
|
||||||
z = x
|
z = x
|
||||||
|
|
||||||
x
|
x
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let home = test_home();
|
let home = test_home();
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
|
@ -1176,11 +1176,11 @@ mod test_can {
|
||||||
#[test]
|
#[test]
|
||||||
fn dict() {
|
fn dict() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
x = Dict.empty {}
|
x = Dict.empty {}
|
||||||
|
|
||||||
Dict.len x
|
Dict.len x
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
||||||
|
@ -1191,7 +1191,7 @@ mod test_can {
|
||||||
#[test]
|
#[test]
|
||||||
fn unused_def_regression() {
|
fn unused_def_regression() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
Booly : [Yes, No, Maybe]
|
Booly : [Yes, No, Maybe]
|
||||||
|
|
||||||
y : Booly
|
y : Booly
|
||||||
|
@ -1205,7 +1205,7 @@ mod test_can {
|
||||||
x = [y]
|
x = [y]
|
||||||
|
|
||||||
x
|
x
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
||||||
|
@ -1216,14 +1216,14 @@ mod test_can {
|
||||||
#[test]
|
#[test]
|
||||||
fn optional_field_not_unused() {
|
fn optional_field_not_unused() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
fallbackZ = 3
|
fallbackZ = 3
|
||||||
|
|
||||||
fn = \{ x, y, z ? fallbackZ } ->
|
fn = \{ x, y, z ? fallbackZ } ->
|
||||||
{ x, y, z }
|
{ x, y, z }
|
||||||
|
|
||||||
fn { x: 0, y: 1 }
|
fn { x: 0, y: 1 }
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
||||||
|
@ -1234,12 +1234,12 @@ mod test_can {
|
||||||
#[test]
|
#[test]
|
||||||
fn issue_2534() {
|
fn issue_2534() {
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
x = { a: 1 }
|
x = { a: 1 }
|
||||||
{
|
{
|
||||||
x & a: 2
|
x & a: 2
|
||||||
}
|
}
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src);
|
||||||
|
@ -1252,13 +1252,13 @@ mod test_can {
|
||||||
// // "local" should be used, because the closure used it.
|
// // "local" should be used, because the closure used it.
|
||||||
// // However, "unused" should be unused.
|
// // However, "unused" should be unused.
|
||||||
// let (_, output, problems, _) = can_expr(indoc!(
|
// let (_, output, problems, _) = can_expr(indoc!(
|
||||||
// r#"
|
// r"
|
||||||
// local = 5
|
// local = 5
|
||||||
// unused = 6
|
// unused = 6
|
||||||
// func = \arg -> arg + local
|
// func = \arg -> arg + local
|
||||||
|
|
||||||
// 3 + func 2
|
// 3 + func 2
|
||||||
// "#
|
// "
|
||||||
// ));
|
// ));
|
||||||
|
|
||||||
// assert_eq!(
|
// assert_eq!(
|
||||||
|
@ -1283,13 +1283,13 @@ mod test_can {
|
||||||
//fn unused_closure() {
|
//fn unused_closure() {
|
||||||
// // "unused" should be unused because it's in func, which is unused.
|
// // "unused" should be unused because it's in func, which is unused.
|
||||||
// let (_, output, problems, _) = can_expr(indoc!(
|
// let (_, output, problems, _) = can_expr(indoc!(
|
||||||
// r#"
|
// r"
|
||||||
// local = 5
|
// local = 5
|
||||||
// unused = 6
|
// unused = 6
|
||||||
// func = \arg -> arg + unused
|
// func = \arg -> arg + unused
|
||||||
|
|
||||||
// local
|
// local
|
||||||
// "#
|
// "
|
||||||
// ));
|
// ));
|
||||||
|
|
||||||
// assert_eq!(
|
// assert_eq!(
|
||||||
|
@ -1316,9 +1316,9 @@ mod test_can {
|
||||||
// #[test]
|
// #[test]
|
||||||
// fn basic_unrecognized_constant() {
|
// fn basic_unrecognized_constant() {
|
||||||
// let (expr, output, problems, _) = can_expr(indoc!(
|
// let (expr, output, problems, _) = can_expr(indoc!(
|
||||||
// r#"
|
// r"
|
||||||
// x
|
// x
|
||||||
// "#
|
// "
|
||||||
// ));
|
// ));
|
||||||
|
|
||||||
// assert_eq!(
|
// assert_eq!(
|
||||||
|
@ -1342,12 +1342,12 @@ mod test_can {
|
||||||
//#[test]
|
//#[test]
|
||||||
//fn complex_unrecognized_constant() {
|
//fn complex_unrecognized_constant() {
|
||||||
// let (_, output, problems, _) = can_expr(indoc!(
|
// let (_, output, problems, _) = can_expr(indoc!(
|
||||||
// r#"
|
// r"
|
||||||
// a = 5
|
// a = 5
|
||||||
// b = 6
|
// b = 6
|
||||||
|
|
||||||
// a + b * z
|
// a + b * z
|
||||||
// "#
|
// "
|
||||||
// ));
|
// ));
|
||||||
|
|
||||||
// assert_eq!(
|
// assert_eq!(
|
||||||
|
@ -1368,20 +1368,20 @@ mod test_can {
|
||||||
// );
|
// );
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//// UNUSED
|
// // UNUSED
|
||||||
|
|
||||||
//#[test]
|
//#[test]
|
||||||
//fn mutual_unused_circular_vars() {
|
//fn mutual_unused_circular_vars() {
|
||||||
// // This should report that both a and b are unused, since the return expr never references them.
|
// // This should report that both a and b are unused, since the return expr never references them.
|
||||||
// // It should not report them as circular, since we haven't solved the halting problem here.
|
// // It should not report them as circular, since we haven't solved the halting problem here.
|
||||||
// let (_, output, problems, _) = can_expr(indoc!(
|
// let (_, output, problems, _) = can_expr(indoc!(
|
||||||
// r#"
|
// r"
|
||||||
// a = \arg -> if arg > 0 then b 7 else 0
|
// a = \arg -> if arg > 0 then b 7 else 0
|
||||||
// b = \arg -> if arg > 0 then a (arg - 1) else 0
|
// b = \arg -> if arg > 0 then a (arg - 1) else 0
|
||||||
// c = 5
|
// c = 5
|
||||||
|
|
||||||
// c
|
// c
|
||||||
// "#
|
// "
|
||||||
// ));
|
// ));
|
||||||
|
|
||||||
// assert_eq!(problems, vec![unused("a"), unused("b")]);
|
// assert_eq!(problems, vec![unused("a"), unused("b")]);
|
||||||
|
@ -1400,7 +1400,7 @@ mod test_can {
|
||||||
//#[test]
|
//#[test]
|
||||||
//fn can_fibonacci() {
|
//fn can_fibonacci() {
|
||||||
// let (_, output, problems, _) = can_expr(indoc!(
|
// let (_, output, problems, _) = can_expr(indoc!(
|
||||||
// r#"
|
// r"
|
||||||
// fibonacci = \num ->
|
// fibonacci = \num ->
|
||||||
// if num < 2 then
|
// if num < 2 then
|
||||||
// num
|
// num
|
||||||
|
@ -1408,7 +1408,7 @@ mod test_can {
|
||||||
// fibonacci (num - 1) + fibonacci (num - 2)
|
// fibonacci (num - 1) + fibonacci (num - 2)
|
||||||
|
|
||||||
// fibonacci 9
|
// fibonacci 9
|
||||||
// "#
|
// "
|
||||||
// ));
|
// ));
|
||||||
|
|
||||||
// assert_eq!(problems, vec![]);
|
// assert_eq!(problems, vec![]);
|
||||||
|
@ -1430,7 +1430,7 @@ mod test_can {
|
||||||
// // is considered a tail call, even though it only
|
// // is considered a tail call, even though it only
|
||||||
// // calls itself from one branch!
|
// // calls itself from one branch!
|
||||||
// let (_, output, problems, _) = can_expr(indoc!(
|
// let (_, output, problems, _) = can_expr(indoc!(
|
||||||
// r#"
|
// r"
|
||||||
// factorial = \num ->
|
// factorial = \num ->
|
||||||
// factorialHelp num 0
|
// factorialHelp num 0
|
||||||
|
|
||||||
|
@ -1441,7 +1441,7 @@ mod test_can {
|
||||||
// factorialHelp (num - 1) (total * num)
|
// factorialHelp (num - 1) (total * num)
|
||||||
|
|
||||||
// factorial 9
|
// factorial 9
|
||||||
// "#
|
// "
|
||||||
// ));
|
// ));
|
||||||
|
|
||||||
// assert_eq!(problems, vec![]);
|
// assert_eq!(problems, vec![]);
|
||||||
|
@ -1462,12 +1462,12 @@ mod test_can {
|
||||||
// // This should report that neither a nor b are unused,
|
// // This should report that neither a nor b are unused,
|
||||||
// // since if you never call a function but do return it, that's okay!
|
// // since if you never call a function but do return it, that's okay!
|
||||||
// let (_, output, problems, _) = can_expr(indoc!(
|
// let (_, output, problems, _) = can_expr(indoc!(
|
||||||
// r#"
|
// r"
|
||||||
// a = \_ -> 42
|
// a = \_ -> 42
|
||||||
// b = a
|
// b = a
|
||||||
|
|
||||||
// b
|
// b
|
||||||
// "#
|
// "
|
||||||
// ));
|
// ));
|
||||||
|
|
||||||
// assert_eq!(problems, Vec::new());
|
// assert_eq!(problems, Vec::new());
|
||||||
|
@ -1483,19 +1483,19 @@ mod test_can {
|
||||||
// );
|
// );
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//// ASSIGNMENT REORDERING
|
// // ASSIGNMENT REORDERING
|
||||||
|
|
||||||
//#[test]
|
//#[test]
|
||||||
//fn reorder_assignments() {
|
//fn reorder_assignments() {
|
||||||
// let (expr, output, problems, _) = can_expr(indoc!(
|
// let (expr, output, problems, _) = can_expr(indoc!(
|
||||||
// r#"
|
// r"
|
||||||
// increment = \arg -> arg + 1
|
// increment = \arg -> arg + 1
|
||||||
// z = (increment 2) + y
|
// z = (increment 2) + y
|
||||||
// y = x + 1
|
// y = x + 1
|
||||||
// x = 9
|
// x = 9
|
||||||
|
|
||||||
// z * 3
|
// z * 3
|
||||||
// "#
|
// "
|
||||||
// ));
|
// ));
|
||||||
|
|
||||||
// assert_eq!(problems, vec![]);
|
// assert_eq!(problems, vec![]);
|
||||||
|
@ -1526,7 +1526,7 @@ mod test_can {
|
||||||
//#[test]
|
//#[test]
|
||||||
//fn reorder_closed_over_assignments() {
|
//fn reorder_closed_over_assignments() {
|
||||||
// let (expr, output, problems, _) = can_expr(indoc!(
|
// let (expr, output, problems, _) = can_expr(indoc!(
|
||||||
// r#"
|
// r"
|
||||||
// z = func1 x
|
// z = func1 x
|
||||||
// x = 9
|
// x = 9
|
||||||
// y = func2 3
|
// y = func2 3
|
||||||
|
@ -1534,7 +1534,7 @@ mod test_can {
|
||||||
// func2 = \arg -> arg + x
|
// func2 = \arg -> arg + x
|
||||||
|
|
||||||
// z
|
// z
|
||||||
// "#
|
// "
|
||||||
// ));
|
// ));
|
||||||
|
|
||||||
// assert_eq!(problems, vec![]);
|
// assert_eq!(problems, vec![]);
|
||||||
|
@ -1623,19 +1623,19 @@ mod test_can {
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//// CIRCULAR ASSIGNMENT
|
// // CIRCULAR ASSIGNMENT
|
||||||
|
|
||||||
//#[test]
|
//#[test]
|
||||||
//fn circular_assignment() {
|
//fn circular_assignment() {
|
||||||
// let (_, _, problems, _) = can_expr(indoc!(
|
// let (_, _, problems, _) = can_expr(indoc!(
|
||||||
// r#"
|
// r"
|
||||||
// c = d + 3
|
// c = d + 3
|
||||||
// b = 2 + c
|
// b = 2 + c
|
||||||
// d = a + 7
|
// d = a + 7
|
||||||
// a = b + 1
|
// a = b + 1
|
||||||
|
|
||||||
// 2 + d
|
// 2 + d
|
||||||
// "#
|
// "
|
||||||
// ));
|
// ));
|
||||||
|
|
||||||
// assert_eq!(
|
// assert_eq!(
|
||||||
|
@ -1655,82 +1655,82 @@ mod test_can {
|
||||||
// // There was a bug where this reported UnusedArgument("val")
|
// // There was a bug where this reported UnusedArgument("val")
|
||||||
// // since it was used only in the returned function only.
|
// // since it was used only in the returned function only.
|
||||||
// let (_, _, problems, _) = can_expr(indoc!(
|
// let (_, _, problems, _) = can_expr(indoc!(
|
||||||
// r#"
|
// r"
|
||||||
// \val -> \_ -> val
|
// \val -> \_ -> val
|
||||||
// "#
|
// "
|
||||||
// ));
|
// ));
|
||||||
|
|
||||||
// assert_eq!(problems, vec![]);
|
// assert_eq!(problems, vec![]);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//// TODO verify that Apply handles output.references.calls correctly
|
// // TODO verify that Apply handles output.references.calls correctly
|
||||||
|
|
||||||
//// UNSUPPORTED PATTERNS
|
// // UNSUPPORTED PATTERNS
|
||||||
|
|
||||||
//// TODO verify that in closures and assignments, you can't assign to int/string/underscore/etc
|
// // TODO verify that in closures and assignments, you can't assign to int/string/underscore/etc
|
||||||
|
|
||||||
//// OPERATOR PRECEDENCE
|
// // OPERATOR PRECEDENCE
|
||||||
|
|
||||||
//// fn parse_with_precedence(input: &str) -> Result<(Expr, &str), easy::Errors<char, &str, IndentablePosition>> {
|
// // fn parse_with_precedence(input: &str) -> Result<(Expr, &str), easy::Errors<char, &str, IndentablePosition>> {
|
||||||
//// parse_without_loc(input)
|
// // parse_without_loc(input)
|
||||||
//// .map(|(expr, remaining)| (expr::apply_precedence_and_associativity(loc(expr)).unwrap().value, remaining))
|
// // .map(|(expr, remaining)| (expr::apply_precedence_and_associativity(loc(expr)).unwrap().value, remaining))
|
||||||
//// }
|
// // }
|
||||||
|
|
||||||
//// #[test]
|
// // #[test]
|
||||||
//// fn two_operator_precedence() {
|
// // fn two_operator_precedence() {
|
||||||
//// assert_eq!(
|
// // assert_eq!(
|
||||||
//// parse_with_precedence("x + y * 5"),
|
// // parse_with_precedence("x + y * 5"),
|
||||||
//// Ok((BinOp(
|
// // Ok((BinOp(
|
||||||
//// loc_box(var("x")),
|
// // loc_box(var("x")),
|
||||||
//// loc(Plus),
|
// // loc(Plus),
|
||||||
//// loc_box(
|
// // loc_box(
|
||||||
//// BinOp(
|
// // BinOp(
|
||||||
//// loc_box(var("y")),
|
// // loc_box(var("y")),
|
||||||
//// loc(Star),
|
// // loc(Star),
|
||||||
//// loc_box(Int(5))
|
// // loc_box(Int(5))
|
||||||
//// )
|
// // )
|
||||||
//// ),
|
// // ),
|
||||||
//// ),
|
// // ),
|
||||||
//// ""))
|
// // ""))
|
||||||
//// );
|
// // );
|
||||||
|
|
||||||
//// assert_eq!(
|
// // assert_eq!(
|
||||||
//// parse_with_precedence("x * y + 5"),
|
// // parse_with_precedence("x * y + 5"),
|
||||||
//// Ok((BinOp(
|
// // Ok((BinOp(
|
||||||
//// loc_box(
|
// // loc_box(
|
||||||
//// BinOp(
|
// // BinOp(
|
||||||
//// loc_box(var("x")),
|
// // loc_box(var("x")),
|
||||||
//// loc(Star),
|
// // loc(Star),
|
||||||
//// loc_box(var("y")),
|
// // loc_box(var("y")),
|
||||||
//// )
|
// // )
|
||||||
//// ),
|
// // ),
|
||||||
//// loc(Plus),
|
// // loc(Plus),
|
||||||
//// loc_box(Int(5))
|
// // loc_box(Int(5))
|
||||||
//// ),
|
// // ),
|
||||||
//// ""))
|
// // ""))
|
||||||
//// );
|
// // );
|
||||||
//// }
|
// // }
|
||||||
|
|
||||||
//// #[test]
|
// // #[test]
|
||||||
//// fn compare_and() {
|
// // fn compare_and() {
|
||||||
//// assert_eq!(
|
// // assert_eq!(
|
||||||
//// parse_with_precedence("x > 1 || True"),
|
// // parse_with_precedence("x > 1 || True"),
|
||||||
//// Ok((BinOp(
|
// // Ok((BinOp(
|
||||||
//// loc_box(
|
// // loc_box(
|
||||||
//// BinOp(
|
// // BinOp(
|
||||||
//// loc_box(var("x")),
|
// // loc_box(var("x")),
|
||||||
//// loc(GreaterThan),
|
// // loc(GreaterThan),
|
||||||
//// loc_box(Int(1))
|
// // loc_box(Int(1))
|
||||||
//// )
|
// // )
|
||||||
//// ),
|
// // ),
|
||||||
//// loc(Or),
|
// // loc(Or),
|
||||||
//// loc_box(ApplyVariant(vname("True"), None))
|
// // loc_box(ApplyVariant(vname("True"), None))
|
||||||
//// ),
|
// // ),
|
||||||
//// ""))
|
// // ""))
|
||||||
//// );
|
// // );
|
||||||
//// }
|
// // }
|
||||||
|
|
||||||
//// HELPERS
|
// // HELPERS
|
||||||
|
|
||||||
//#[test]
|
//#[test]
|
||||||
//fn sort_cyclic_idents() {
|
//fn sort_cyclic_idents() {
|
||||||
|
@ -1822,18 +1822,18 @@ mod test_can {
|
||||||
// );
|
// );
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// #[test]
|
// #[test]
|
||||||
// fn string_with_escaped_interpolation() {
|
// fn string_with_escaped_interpolation() {
|
||||||
// assert_parses_to(
|
// assert_parses_to(
|
||||||
// // This should NOT be string interpolation, because of the \\
|
// // This should NOT be string interpolation, because of the \\
|
||||||
// indoc!(
|
// indoc!(
|
||||||
// r#"
|
// r#"
|
||||||
// "abcd\\(efg)hij"
|
// "abcd\$(efg)hij"
|
||||||
// "#
|
// "#
|
||||||
// ),
|
// ),
|
||||||
// Str(r#"abcd\(efg)hij"#.into()),
|
// Str(r"abcd\(efg)hij".into()),
|
||||||
// );
|
// );
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// #[test]
|
// #[test]
|
||||||
// fn string_without_escape() {
|
// fn string_without_escape() {
|
||||||
|
@ -1848,7 +1848,7 @@ mod test_can {
|
||||||
|
|
||||||
// #[test]
|
// #[test]
|
||||||
// fn string_with_special_escapes() {
|
// fn string_with_special_escapes() {
|
||||||
// expect_parsed_str(r#"x\x"#, r#""x\\x""#);
|
// expect_parsed_str(r"x\x", r#""x\\x""#);
|
||||||
// expect_parsed_str(r#"x"x"#, r#""x\"x""#);
|
// expect_parsed_str(r#"x"x"#, r#""x\"x""#);
|
||||||
// expect_parsed_str("x\tx", r#""x\tx""#);
|
// expect_parsed_str("x\tx", r#""x\tx""#);
|
||||||
// expect_parsed_str("x\rx", r#""x\rx""#);
|
// expect_parsed_str("x\rx", r#""x\rx""#);
|
||||||
|
|
17
crates/compiler/checkmate/www/.gitignore
vendored
17
crates/compiler/checkmate/www/.gitignore
vendored
|
@ -1,17 +0,0 @@
|
||||||
/node_modules
|
|
||||||
/.pnp
|
|
||||||
.pnp.js
|
|
||||||
|
|
||||||
/coverage
|
|
||||||
|
|
||||||
/build
|
|
||||||
|
|
||||||
.DS_Store
|
|
||||||
.env.local
|
|
||||||
.env.development.local
|
|
||||||
.env.test.local
|
|
||||||
.env.production.local
|
|
||||||
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
|
@ -30,9 +30,6 @@ pub type SendMap<K, V> = im::hashmap::HashMap<K, V, BuildHasher>;
|
||||||
|
|
||||||
pub type SendSet<K> = im::hashset::HashSet<K, BuildHasher>;
|
pub type SendSet<K> = im::hashset::HashSet<K, BuildHasher>;
|
||||||
|
|
||||||
// pub type BumpMap<'a, K, V> = hashbrown::HashMap<K, V, BuildHasher, hashbrown::BumpWrapper<'a>>;
|
|
||||||
// pub type BumpSet<'a, K> = hashbrown::HashSet<K, BuildHasher, hashbrown::BumpWrapper<'a>>;
|
|
||||||
|
|
||||||
pub type BumpMap<K, V> = hashbrown::HashMap<K, V, BuildHasher>;
|
pub type BumpMap<K, V> = hashbrown::HashMap<K, V, BuildHasher>;
|
||||||
pub type BumpSet<K> = hashbrown::HashSet<K, BuildHasher>;
|
pub type BumpSet<K> = hashbrown::HashSet<K, BuildHasher>;
|
||||||
|
|
||||||
|
@ -46,32 +43,20 @@ pub trait BumpMapDefault<'a> {
|
||||||
|
|
||||||
impl<'a, K, V> BumpMapDefault<'a> for BumpMap<K, V> {
|
impl<'a, K, V> BumpMapDefault<'a> for BumpMap<K, V> {
|
||||||
fn new_in(_arena: &'a bumpalo::Bump) -> Self {
|
fn new_in(_arena: &'a bumpalo::Bump) -> Self {
|
||||||
// hashbrown::HashMap::with_hasher_in(default_hasher(), hashbrown::BumpWrapper(arena))
|
|
||||||
hashbrown::HashMap::with_hasher(default_hasher())
|
hashbrown::HashMap::with_hasher(default_hasher())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_capacity_in(capacity: usize, _arena: &'a bumpalo::Bump) -> Self {
|
fn with_capacity_in(capacity: usize, _arena: &'a bumpalo::Bump) -> Self {
|
||||||
// hashbrown::HashMap::with_capacity_and_hasher_in(
|
|
||||||
// capacity,
|
|
||||||
// default_hasher(),
|
|
||||||
// hashbrown::BumpWrapper(arena),
|
|
||||||
// )
|
|
||||||
hashbrown::HashMap::with_capacity_and_hasher(capacity, default_hasher())
|
hashbrown::HashMap::with_capacity_and_hasher(capacity, default_hasher())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, K> BumpMapDefault<'a> for BumpSet<K> {
|
impl<'a, K> BumpMapDefault<'a> for BumpSet<K> {
|
||||||
fn new_in(_arena: &'a bumpalo::Bump) -> Self {
|
fn new_in(_arena: &'a bumpalo::Bump) -> Self {
|
||||||
// hashbrown::HashSet::with_hasher_in(default_hasher(), hashbrown::BumpWrapper(arena))
|
|
||||||
hashbrown::HashSet::with_hasher(default_hasher())
|
hashbrown::HashSet::with_hasher(default_hasher())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_capacity_in(capacity: usize, _arena: &'a bumpalo::Bump) -> Self {
|
fn with_capacity_in(capacity: usize, _arena: &'a bumpalo::Bump) -> Self {
|
||||||
// hashbrown::HashSet::with_capacity_and_hasher_in(
|
|
||||||
// capacity,
|
|
||||||
// default_hasher(),
|
|
||||||
// hashbrown::BumpWrapper(arena),
|
|
||||||
// )
|
|
||||||
hashbrown::HashSet::with_capacity_and_hasher(capacity, default_hasher())
|
hashbrown::HashSet::with_capacity_and_hasher(capacity, default_hasher())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -400,7 +400,7 @@ fn hash_newtype_tag_union(
|
||||||
let hasher_var = synth_var(env.subs, Content::FlexAbleVar(None, Subs::AB_HASHER));
|
let hasher_var = synth_var(env.subs, Content::FlexAbleVar(None, Subs::AB_HASHER));
|
||||||
|
|
||||||
// A
|
// A
|
||||||
let tag_name = tag_name;
|
// let tag_name = tag_name;
|
||||||
// t1 .. tn
|
// t1 .. tn
|
||||||
let payload_vars = payload_variables;
|
let payload_vars = payload_variables;
|
||||||
// x11 .. x1n
|
// x11 .. x1n
|
||||||
|
|
|
@ -612,9 +612,20 @@ fn format_str_segment(seg: &StrSegment, buf: &mut Buf, indent: u16) {
|
||||||
buf.push('\\');
|
buf.push('\\');
|
||||||
buf.push(escaped.to_parsed_char());
|
buf.push(escaped.to_parsed_char());
|
||||||
}
|
}
|
||||||
Interpolated(loc_expr) => {
|
DeprecatedInterpolated(loc_expr) => {
|
||||||
buf.push_str("\\(");
|
buf.push_str("\\(");
|
||||||
// e.g. (name) in "Hi, \(name)!"
|
// e.g. (name) in "Hi, $(name)!"
|
||||||
|
loc_expr.value.format_with_options(
|
||||||
|
buf,
|
||||||
|
Parens::NotNeeded, // We already printed parens!
|
||||||
|
Newlines::No, // Interpolations can never have newlines
|
||||||
|
indent,
|
||||||
|
);
|
||||||
|
buf.push(')');
|
||||||
|
}
|
||||||
|
Interpolated(loc_expr) => {
|
||||||
|
buf.push_str("$(");
|
||||||
|
// e.g. (name) in "Hi, $(name)!"
|
||||||
loc_expr.value.format_with_options(
|
loc_expr.value.format_with_options(
|
||||||
buf,
|
buf,
|
||||||
Parens::NotNeeded, // We already printed parens!
|
Parens::NotNeeded, // We already printed parens!
|
||||||
|
|
|
@ -656,6 +656,9 @@ impl<'a> RemoveSpaces<'a> for StrSegment<'a> {
|
||||||
StrSegment::Unicode(t) => StrSegment::Unicode(t.remove_spaces(arena)),
|
StrSegment::Unicode(t) => StrSegment::Unicode(t.remove_spaces(arena)),
|
||||||
StrSegment::EscapedChar(c) => StrSegment::EscapedChar(c),
|
StrSegment::EscapedChar(c) => StrSegment::EscapedChar(c),
|
||||||
StrSegment::Interpolated(t) => StrSegment::Interpolated(t.remove_spaces(arena)),
|
StrSegment::Interpolated(t) => StrSegment::Interpolated(t.remove_spaces(arena)),
|
||||||
|
StrSegment::DeprecatedInterpolated(t) => {
|
||||||
|
StrSegment::DeprecatedInterpolated(t.remove_spaces(arena))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1266,6 +1266,7 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> for AArch64Assembler {
|
||||||
) {
|
) {
|
||||||
add_reg64_reg64_reg64(buf, dst, src1, src2);
|
add_reg64_reg64_reg64(buf, dst, src1, src2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn add_freg32_freg32_freg32(
|
fn add_freg32_freg32_freg32(
|
||||||
buf: &mut Vec<'_, u8>,
|
buf: &mut Vec<'_, u8>,
|
||||||
|
@ -1285,6 +1286,25 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> for AArch64Assembler {
|
||||||
fadd_freg_freg_freg(buf, FloatWidth::F64, dst, src1, src2);
|
fadd_freg_freg_freg(buf, FloatWidth::F64, dst, src1, src2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn sub_freg32_freg32_freg32(
|
||||||
|
buf: &mut Vec<'_, u8>,
|
||||||
|
dst: AArch64FloatReg,
|
||||||
|
src1: AArch64FloatReg,
|
||||||
|
src2: AArch64FloatReg,
|
||||||
|
) {
|
||||||
|
fsub_freg_freg_freg(buf, FloatWidth::F32, dst, src1, src2);
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn sub_freg64_freg64_freg64(
|
||||||
|
buf: &mut Vec<'_, u8>,
|
||||||
|
dst: AArch64FloatReg,
|
||||||
|
src1: AArch64FloatReg,
|
||||||
|
src2: AArch64FloatReg,
|
||||||
|
) {
|
||||||
|
fsub_freg_freg_freg(buf, FloatWidth::F64, dst, src1, src2);
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn call(buf: &mut Vec<'_, u8>, relocs: &mut Vec<'_, Relocation>, fn_name: String) {
|
fn call(buf: &mut Vec<'_, u8>, relocs: &mut Vec<'_, Relocation>, fn_name: String) {
|
||||||
let inst = 0b1001_0100_0000_0000_0000_0000_0000_0000u32;
|
let inst = 0b1001_0100_0000_0000_0000_0000_0000_0000u32;
|
||||||
|
@ -3894,6 +3914,27 @@ fn fadd_freg_freg_freg(
|
||||||
buf.extend(inst.bytes());
|
buf.extend(inst.bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `FSUB Sd/Dd, Sn/Dn, Sm/Dm` -> Sub Sn/Dn and Sm/Dm and place the result into Sd/Dd.
|
||||||
|
#[inline(always)]
|
||||||
|
fn fsub_freg_freg_freg(
|
||||||
|
buf: &mut Vec<'_, u8>,
|
||||||
|
ftype: FloatWidth,
|
||||||
|
dst: AArch64FloatReg,
|
||||||
|
src1: AArch64FloatReg,
|
||||||
|
src2: AArch64FloatReg,
|
||||||
|
) {
|
||||||
|
let inst =
|
||||||
|
FloatingPointDataProcessingTwoSource::new(FloatingPointDataProcessingTwoSourceParams {
|
||||||
|
opcode: 0b0011,
|
||||||
|
ptype: ftype,
|
||||||
|
rd: dst,
|
||||||
|
rn: src1,
|
||||||
|
rm: src2,
|
||||||
|
});
|
||||||
|
|
||||||
|
buf.extend(inst.bytes());
|
||||||
|
}
|
||||||
|
|
||||||
/// `FCMP Sn/Dn, Sm/Dm` -> Compare Sn/Dn and Sm/Dm, setting condition flags.
|
/// `FCMP Sn/Dn, Sm/Dm` -> Compare Sn/Dn and Sm/Dm, setting condition flags.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn fcmp_freg_freg(
|
fn fcmp_freg_freg(
|
||||||
|
|
|
@ -166,6 +166,13 @@ pub trait Assembler<GeneralReg: RegTrait, FloatReg: RegTrait>: Sized + Copy {
|
||||||
);
|
);
|
||||||
|
|
||||||
fn add_reg64_reg64_imm32(buf: &mut Vec<'_, u8>, dst: GeneralReg, src1: GeneralReg, imm32: i32);
|
fn add_reg64_reg64_imm32(buf: &mut Vec<'_, u8>, dst: GeneralReg, src1: GeneralReg, imm32: i32);
|
||||||
|
fn add_reg64_reg64_reg64(
|
||||||
|
buf: &mut Vec<'_, u8>,
|
||||||
|
dst: GeneralReg,
|
||||||
|
src1: GeneralReg,
|
||||||
|
src2: GeneralReg,
|
||||||
|
);
|
||||||
|
|
||||||
fn add_freg32_freg32_freg32(
|
fn add_freg32_freg32_freg32(
|
||||||
buf: &mut Vec<'_, u8>,
|
buf: &mut Vec<'_, u8>,
|
||||||
dst: FloatReg,
|
dst: FloatReg,
|
||||||
|
@ -178,12 +185,6 @@ pub trait Assembler<GeneralReg: RegTrait, FloatReg: RegTrait>: Sized + Copy {
|
||||||
src1: FloatReg,
|
src1: FloatReg,
|
||||||
src2: FloatReg,
|
src2: FloatReg,
|
||||||
);
|
);
|
||||||
fn add_reg64_reg64_reg64(
|
|
||||||
buf: &mut Vec<'_, u8>,
|
|
||||||
dst: GeneralReg,
|
|
||||||
src1: GeneralReg,
|
|
||||||
src2: GeneralReg,
|
|
||||||
);
|
|
||||||
|
|
||||||
fn and_reg64_reg64_reg64(
|
fn and_reg64_reg64_reg64(
|
||||||
buf: &mut Vec<'_, u8>,
|
buf: &mut Vec<'_, u8>,
|
||||||
|
@ -629,6 +630,19 @@ pub trait Assembler<GeneralReg: RegTrait, FloatReg: RegTrait>: Sized + Copy {
|
||||||
ASM: Assembler<GeneralReg, FloatReg>,
|
ASM: Assembler<GeneralReg, FloatReg>,
|
||||||
CC: CallConv<GeneralReg, FloatReg, ASM>;
|
CC: CallConv<GeneralReg, FloatReg, ASM>;
|
||||||
|
|
||||||
|
fn sub_freg32_freg32_freg32(
|
||||||
|
buf: &mut Vec<'_, u8>,
|
||||||
|
dst: FloatReg,
|
||||||
|
src1: FloatReg,
|
||||||
|
src2: FloatReg,
|
||||||
|
);
|
||||||
|
fn sub_freg64_freg64_freg64(
|
||||||
|
buf: &mut Vec<'_, u8>,
|
||||||
|
dst: FloatReg,
|
||||||
|
src1: FloatReg,
|
||||||
|
src2: FloatReg,
|
||||||
|
);
|
||||||
|
|
||||||
fn sub_reg64_reg64_imm32(buf: &mut Vec<'_, u8>, dst: GeneralReg, src1: GeneralReg, imm32: i32);
|
fn sub_reg64_reg64_imm32(buf: &mut Vec<'_, u8>, dst: GeneralReg, src1: GeneralReg, imm32: i32);
|
||||||
fn sub_reg64_reg64_reg64(
|
fn sub_reg64_reg64_reg64(
|
||||||
buf: &mut Vec<'_, u8>,
|
buf: &mut Vec<'_, u8>,
|
||||||
|
@ -1308,16 +1322,14 @@ impl<
|
||||||
|
|
||||||
fn build_num_add(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &InLayout<'a>) {
|
fn build_num_add(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &InLayout<'a>) {
|
||||||
match self.layout_interner.get_repr(*layout) {
|
match self.layout_interner.get_repr(*layout) {
|
||||||
LayoutRepr::Builtin(Builtin::Int(quadword_and_smaller!())) => {
|
LayoutRepr::Builtin(Builtin::Int(int_width)) => self.build_fn_call(
|
||||||
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
dst,
|
||||||
let src1_reg = self
|
bitcode::NUM_ADD_OR_PANIC_INT[int_width].to_string(),
|
||||||
.storage_manager
|
&[*src1, *src2],
|
||||||
.load_to_general_reg(&mut self.buf, src1);
|
&[*layout, *layout],
|
||||||
let src2_reg = self
|
layout,
|
||||||
.storage_manager
|
),
|
||||||
.load_to_general_reg(&mut self.buf, src2);
|
|
||||||
ASM::add_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
|
||||||
}
|
|
||||||
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64)) => {
|
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64)) => {
|
||||||
let dst_reg = self.storage_manager.claim_float_reg(&mut self.buf, dst);
|
let dst_reg = self.storage_manager.claim_float_reg(&mut self.buf, dst);
|
||||||
let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1);
|
let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1);
|
||||||
|
@ -1330,16 +1342,60 @@ impl<
|
||||||
let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2);
|
let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2);
|
||||||
ASM::add_freg32_freg32_freg32(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
ASM::add_freg32_freg32_freg32(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
||||||
}
|
}
|
||||||
LayoutRepr::Builtin(Builtin::Decimal) => {
|
|
||||||
self.build_fn_call(
|
LayoutRepr::DEC => self.build_fn_call(
|
||||||
dst,
|
dst,
|
||||||
bitcode::DEC_ADD_OR_PANIC.to_string(),
|
bitcode::DEC_ADD_OR_PANIC.to_string(),
|
||||||
&[*src1, *src2],
|
&[*src1, *src2],
|
||||||
&[Layout::DEC, Layout::DEC],
|
&[Layout::DEC, Layout::DEC],
|
||||||
&Layout::DEC,
|
&Layout::DEC,
|
||||||
);
|
),
|
||||||
|
|
||||||
|
other => unreachable!("NumAdd for layout {other:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_num_add_wrap(
|
||||||
|
&mut self,
|
||||||
|
dst: &Symbol,
|
||||||
|
src1: &Symbol,
|
||||||
|
src2: &Symbol,
|
||||||
|
layout: &InLayout<'a>,
|
||||||
|
) {
|
||||||
|
match self.layout_interner.get_repr(*layout) {
|
||||||
|
LayoutRepr::Builtin(Builtin::Int(quadword_and_smaller!())) => {
|
||||||
|
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::add_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
||||||
}
|
}
|
||||||
x => todo!("NumAdd: layout, {:?}", x),
|
|
||||||
|
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64)) => {
|
||||||
|
let dst_reg = self.storage_manager.claim_float_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::add_freg64_freg64_freg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
||||||
|
}
|
||||||
|
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F32)) => {
|
||||||
|
let dst_reg = self.storage_manager.claim_float_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::add_freg32_freg32_freg32(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
LayoutRepr::DEC => self.build_fn_call(
|
||||||
|
dst,
|
||||||
|
bitcode::DEC_ADD_SATURATED.to_string(),
|
||||||
|
&[*src1, *src2],
|
||||||
|
&[Layout::DEC, Layout::DEC],
|
||||||
|
&Layout::DEC,
|
||||||
|
),
|
||||||
|
|
||||||
|
other => unreachable!("NumAddWrap for layout {other:?}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1424,9 +1480,38 @@ impl<
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_num_mul(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &InLayout<'a>) {
|
fn build_num_mul(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &InLayout<'a>) {
|
||||||
// for the time being, `num_mul` is implemented as wrapping multiplication. In roc, the normal
|
match self.layout_interner.get_repr(*layout) {
|
||||||
// `mul` should panic on overflow, but we just don't do that yet
|
LayoutRepr::Builtin(Builtin::Int(int_width)) => self.build_fn_call(
|
||||||
self.build_num_mul_wrap(dst, src1, src2, layout)
|
dst,
|
||||||
|
bitcode::NUM_MUL_OR_PANIC_INT[int_width].to_string(),
|
||||||
|
&[*src1, *src2],
|
||||||
|
&[*layout, *layout],
|
||||||
|
layout,
|
||||||
|
),
|
||||||
|
|
||||||
|
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64)) => {
|
||||||
|
let dst_reg = self.storage_manager.claim_float_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::mul_freg64_freg64_freg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
||||||
|
}
|
||||||
|
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F32)) => {
|
||||||
|
let dst_reg = self.storage_manager.claim_float_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::mul_freg32_freg32_freg32(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
LayoutRepr::DEC => self.build_fn_call(
|
||||||
|
dst,
|
||||||
|
bitcode::DEC_MUL_OR_PANIC.to_string(),
|
||||||
|
&[*src1, *src2],
|
||||||
|
&[Layout::DEC, Layout::DEC],
|
||||||
|
&Layout::DEC,
|
||||||
|
),
|
||||||
|
|
||||||
|
other => unreachable!("NumMul for layout {other:?}"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_num_mul_wrap(
|
fn build_num_mul_wrap(
|
||||||
|
@ -1609,6 +1694,15 @@ impl<
|
||||||
let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2);
|
let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2);
|
||||||
ASM::div_freg32_freg32_freg32(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
ASM::div_freg32_freg32_freg32(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
||||||
}
|
}
|
||||||
|
LayoutRepr::Builtin(Builtin::Decimal) => {
|
||||||
|
self.build_fn_call(
|
||||||
|
dst,
|
||||||
|
bitcode::DEC_DIV.to_string(),
|
||||||
|
&[*src1, *src2],
|
||||||
|
&[*layout, *layout],
|
||||||
|
layout,
|
||||||
|
);
|
||||||
|
}
|
||||||
x => todo!("NumDiv: layout, {:?}", x),
|
x => todo!("NumDiv: layout, {:?}", x),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1688,9 +1782,38 @@ impl<
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_num_sub(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &InLayout<'a>) {
|
fn build_num_sub(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &InLayout<'a>) {
|
||||||
// for the time being, `num_sub` is implemented as wrapping subtraction. In roc, the normal
|
match self.layout_interner.get_repr(*layout) {
|
||||||
// `sub` should panic on overflow, but we just don't do that yet
|
LayoutRepr::Builtin(Builtin::Int(int_width)) => self.build_fn_call(
|
||||||
self.build_num_sub_wrap(dst, src1, src2, layout)
|
dst,
|
||||||
|
bitcode::NUM_SUB_OR_PANIC_INT[int_width].to_string(),
|
||||||
|
&[*src1, *src2],
|
||||||
|
&[*layout, *layout],
|
||||||
|
layout,
|
||||||
|
),
|
||||||
|
|
||||||
|
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64)) => {
|
||||||
|
let dst_reg = self.storage_manager.claim_float_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::sub_freg64_freg64_freg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
||||||
|
}
|
||||||
|
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F32)) => {
|
||||||
|
let dst_reg = self.storage_manager.claim_float_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::sub_freg32_freg32_freg32(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
LayoutRepr::DEC => self.build_fn_call(
|
||||||
|
dst,
|
||||||
|
bitcode::DEC_SUB_OR_PANIC.to_string(),
|
||||||
|
&[*src1, *src2],
|
||||||
|
&[Layout::DEC, Layout::DEC],
|
||||||
|
&Layout::DEC,
|
||||||
|
),
|
||||||
|
|
||||||
|
other => unreachable!("NumMul for layout {other:?}"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_num_sub_wrap(
|
fn build_num_sub_wrap(
|
||||||
|
|
|
@ -523,12 +523,12 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
|
||||||
use X86_64GeneralReg::*;
|
use X86_64GeneralReg::*;
|
||||||
type ASM = X86_64Assembler;
|
type ASM = X86_64Assembler;
|
||||||
|
|
||||||
// move the first argument to roc_panic (a *RocStr) into r8
|
// move the first argument to roc_panic (a *const RocStr) into r8
|
||||||
ASM::add_reg64_reg64_imm32(buf, R8, RSP, 8);
|
ASM::mov_reg64_reg64(buf, R8, RDI);
|
||||||
|
|
||||||
// move the crash tag into the second return register. We add 1 to it because the 0 value
|
// move the crash tag into the second return register. We add 1 to it because the 0 value
|
||||||
// is already used for "no crash occurred"
|
// is already used for "no crash occurred"
|
||||||
ASM::add_reg64_reg64_imm32(buf, RDX, RDI, 1);
|
ASM::add_reg64_reg64_imm32(buf, RDX, RSI, 1);
|
||||||
|
|
||||||
// the setlongjmp_buffer
|
// the setlongjmp_buffer
|
||||||
ASM::data_pointer(buf, relocs, String::from("setlongjmp_buffer"), RDI);
|
ASM::data_pointer(buf, relocs, String::from("setlongjmp_buffer"), RDI);
|
||||||
|
@ -2004,6 +2004,39 @@ impl Assembler<X86_64GeneralReg, X86_64FloatReg> for X86_64Assembler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn sub_freg32_freg32_freg32(
|
||||||
|
buf: &mut Vec<'_, u8>,
|
||||||
|
dst: X86_64FloatReg,
|
||||||
|
src1: X86_64FloatReg,
|
||||||
|
src2: X86_64FloatReg,
|
||||||
|
) {
|
||||||
|
if dst == src1 {
|
||||||
|
subss_freg32_freg32(buf, dst, src2);
|
||||||
|
} else if dst == src2 {
|
||||||
|
subss_freg32_freg32(buf, dst, src1);
|
||||||
|
} else {
|
||||||
|
movss_freg32_freg32(buf, dst, src1);
|
||||||
|
subss_freg32_freg32(buf, dst, src2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn sub_freg64_freg64_freg64(
|
||||||
|
buf: &mut Vec<'_, u8>,
|
||||||
|
dst: X86_64FloatReg,
|
||||||
|
src1: X86_64FloatReg,
|
||||||
|
src2: X86_64FloatReg,
|
||||||
|
) {
|
||||||
|
if dst == src1 {
|
||||||
|
subsd_freg64_freg64(buf, dst, src2);
|
||||||
|
} else if dst == src2 {
|
||||||
|
subsd_freg64_freg64(buf, dst, src1);
|
||||||
|
} else {
|
||||||
|
movsd_freg64_freg64(buf, dst, src1);
|
||||||
|
subsd_freg64_freg64(buf, dst, src2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn call(buf: &mut Vec<'_, u8>, relocs: &mut Vec<'_, Relocation>, fn_name: String) {
|
fn call(buf: &mut Vec<'_, u8>, relocs: &mut Vec<'_, Relocation>, fn_name: String) {
|
||||||
buf.extend([0xE8, 0x00, 0x00, 0x00, 0x00]);
|
buf.extend([0xE8, 0x00, 0x00, 0x00, 0x00]);
|
||||||
|
@ -3052,124 +3085,78 @@ fn sar_reg64_reg64(buf: &mut Vec<'_, u8>, dst: X86_64GeneralReg) {
|
||||||
buf.extend([rex, 0xD3, 0xC0 | (7 << 3) | dst_mod]);
|
buf.extend([rex, 0xD3, 0xC0 | (7 << 3) | dst_mod]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `ADDSD xmm1,xmm2/m64` -> Add the low double-precision floating-point value from xmm2/mem to xmm1 and store the result in xmm1.
|
fn double_binary_operation(
|
||||||
#[inline(always)]
|
buf: &mut Vec<'_, u8>,
|
||||||
fn addsd_freg64_freg64(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64FloatReg) {
|
dst: X86_64FloatReg,
|
||||||
|
src: X86_64FloatReg,
|
||||||
|
float_width: FloatWidth,
|
||||||
|
op_code2: u8,
|
||||||
|
) {
|
||||||
|
let op_code1 = match float_width {
|
||||||
|
FloatWidth::F32 => 0xF3,
|
||||||
|
FloatWidth::F64 => 0xF2,
|
||||||
|
};
|
||||||
let dst_high = dst as u8 > 7;
|
let dst_high = dst as u8 > 7;
|
||||||
let dst_mod = dst as u8 % 8;
|
let dst_mod = dst as u8 % 8;
|
||||||
let src_high = src as u8 > 7;
|
let src_high = src as u8 > 7;
|
||||||
let src_mod = src as u8 % 8;
|
let src_mod = src as u8 % 8;
|
||||||
if dst_high || src_high {
|
if dst_high || src_high {
|
||||||
buf.extend([
|
buf.extend([
|
||||||
0xF2,
|
op_code1,
|
||||||
0x40 | ((dst_high as u8) << 2) | (src_high as u8),
|
0x40 | ((dst_high as u8) << 2) | (src_high as u8),
|
||||||
0x0F,
|
0x0F,
|
||||||
0x58,
|
op_code2,
|
||||||
0xC0 | (dst_mod << 3) | (src_mod),
|
0xC0 | (dst_mod << 3) | (src_mod),
|
||||||
])
|
])
|
||||||
} else {
|
} else {
|
||||||
buf.extend([0xF2, 0x0F, 0x58, 0xC0 | (dst_mod << 3) | (src_mod)])
|
buf.extend([op_code1, 0x0F, op_code2, 0xC0 | (dst_mod << 3) | (src_mod)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `ADDSD xmm1,xmm2/m64` -> Add the low double-precision floating-point value from xmm2/mem to xmm1 and store the result in xmm1.
|
||||||
|
#[inline(always)]
|
||||||
|
fn addsd_freg64_freg64(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64FloatReg) {
|
||||||
|
double_binary_operation(buf, dst, src, FloatWidth::F64, 0x58)
|
||||||
|
}
|
||||||
|
|
||||||
/// `ADDSS xmm1,xmm2/m64` -> Add the low single-precision floating-point value from xmm2/mem to xmm1 and store the result in xmm1.
|
/// `ADDSS xmm1,xmm2/m64` -> Add the low single-precision floating-point value from xmm2/mem to xmm1 and store the result in xmm1.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn addss_freg32_freg32(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64FloatReg) {
|
fn addss_freg32_freg32(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64FloatReg) {
|
||||||
let dst_high = dst as u8 > 7;
|
double_binary_operation(buf, dst, src, FloatWidth::F32, 0x58)
|
||||||
let dst_mod = dst as u8 % 8;
|
}
|
||||||
let src_high = src as u8 > 7;
|
|
||||||
let src_mod = src as u8 % 8;
|
/// `SUBSD xmm1,xmm2/m64` -> Sub the low double-precision floating-point value from xmm2/mem to xmm1 and store the result in xmm1.
|
||||||
if dst_high || src_high {
|
#[inline(always)]
|
||||||
buf.extend([
|
fn subsd_freg64_freg64(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64FloatReg) {
|
||||||
0xF3,
|
double_binary_operation(buf, dst, src, FloatWidth::F64, 0x5C)
|
||||||
0x40 | ((dst_high as u8) << 2) | (src_high as u8),
|
}
|
||||||
0x0F,
|
|
||||||
0x58,
|
/// `SUBSS xmm1,xmm2/m64` -> Sub the low single-precision floating-point value from xmm2/mem to xmm1 and store the result in xmm1.
|
||||||
0xC0 | (dst_mod << 3) | (src_mod),
|
#[inline(always)]
|
||||||
])
|
fn subss_freg32_freg32(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64FloatReg) {
|
||||||
} else {
|
double_binary_operation(buf, dst, src, FloatWidth::F32, 0x5C)
|
||||||
buf.extend([0xF3, 0x0F, 0x58, 0xC0 | (dst_mod << 3) | (src_mod)])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `MULSD xmm1,xmm2/m64` -> Multiply the low double-precision floating-point value from xmm2/mem to xmm1 and store the result in xmm1.
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn mulsd_freg64_freg64(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64FloatReg) {
|
fn mulsd_freg64_freg64(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64FloatReg) {
|
||||||
let dst_high = dst as u8 > 7;
|
double_binary_operation(buf, dst, src, FloatWidth::F64, 0x59)
|
||||||
let dst_mod = dst as u8 % 8;
|
}
|
||||||
let src_high = src as u8 > 7;
|
|
||||||
let src_mod = src as u8 % 8;
|
#[inline(always)]
|
||||||
if dst_high || src_high {
|
fn mulss_freg32_freg32(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64FloatReg) {
|
||||||
buf.extend([
|
double_binary_operation(buf, dst, src, FloatWidth::F32, 0x59)
|
||||||
0xF2,
|
|
||||||
0x40 | ((dst_high as u8) << 2) | (src_high as u8),
|
|
||||||
0x0F,
|
|
||||||
0x59,
|
|
||||||
0xC0 | (dst_mod << 3) | (src_mod),
|
|
||||||
])
|
|
||||||
} else {
|
|
||||||
buf.extend([0xF2, 0x0F, 0x59, 0xC0 | (dst_mod << 3) | (src_mod)])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `DIVSS xmm1,xmm2/m64` -> Divide the low single-precision floating-point value from xmm2/mem to xmm1 and store the result in xmm1.
|
/// `DIVSS xmm1,xmm2/m64` -> Divide the low single-precision floating-point value from xmm2/mem to xmm1 and store the result in xmm1.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn divss_freg32_freg32(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64FloatReg) {
|
fn divss_freg32_freg32(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64FloatReg) {
|
||||||
let dst_high = dst as u8 > 7;
|
double_binary_operation(buf, dst, src, FloatWidth::F32, 0x5E)
|
||||||
let dst_mod = dst as u8 % 8;
|
|
||||||
let src_high = src as u8 > 7;
|
|
||||||
let src_mod = src as u8 % 8;
|
|
||||||
if dst_high || src_high {
|
|
||||||
buf.extend([
|
|
||||||
0xF3,
|
|
||||||
0x40 | ((dst_high as u8) << 2) | (src_high as u8),
|
|
||||||
0x0F,
|
|
||||||
0x5E,
|
|
||||||
0xC0 | (dst_mod << 3) | (src_mod),
|
|
||||||
])
|
|
||||||
} else {
|
|
||||||
buf.extend([0xF3, 0x0F, 0x5E, 0xC0 | (dst_mod << 3) | (src_mod)])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `DIVSD xmm1,xmm2/m64` -> Divide the low double-precision floating-point value from xmm2/mem to xmm1 and store the result in xmm1.
|
/// `DIVSD xmm1,xmm2/m64` -> Divide the low double-precision floating-point value from xmm2/mem to xmm1 and store the result in xmm1.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn divsd_freg64_freg64(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64FloatReg) {
|
fn divsd_freg64_freg64(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64FloatReg) {
|
||||||
let dst_high = dst as u8 > 7;
|
double_binary_operation(buf, dst, src, FloatWidth::F64, 0x5E)
|
||||||
let dst_mod = dst as u8 % 8;
|
|
||||||
let src_high = src as u8 > 7;
|
|
||||||
let src_mod = src as u8 % 8;
|
|
||||||
if dst_high || src_high {
|
|
||||||
buf.extend([
|
|
||||||
0xF2,
|
|
||||||
0x40 | ((dst_high as u8) << 2) | (src_high as u8),
|
|
||||||
0x0F,
|
|
||||||
0x5E,
|
|
||||||
0xC0 | (dst_mod << 3) | (src_mod),
|
|
||||||
])
|
|
||||||
} else {
|
|
||||||
buf.extend([0xF2, 0x0F, 0x5E, 0xC0 | (dst_mod << 3) | (src_mod)])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `ADDSS xmm1,xmm2/m64` -> Add the low single-precision floating-point value from xmm2/mem to xmm1 and store the result in xmm1.
|
|
||||||
#[inline(always)]
|
|
||||||
fn mulss_freg32_freg32(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64FloatReg) {
|
|
||||||
let dst_high = dst as u8 > 7;
|
|
||||||
let dst_mod = dst as u8 % 8;
|
|
||||||
let src_high = src as u8 > 7;
|
|
||||||
let src_mod = src as u8 % 8;
|
|
||||||
if dst_high || src_high {
|
|
||||||
buf.extend([
|
|
||||||
0xF3,
|
|
||||||
0x40 | ((dst_high as u8) << 2) | (src_high as u8),
|
|
||||||
0x0F,
|
|
||||||
0x59,
|
|
||||||
0xC0 | (dst_mod << 3) | (src_mod),
|
|
||||||
])
|
|
||||||
} else {
|
|
||||||
buf.extend([0xF3, 0x0F, 0x59, 0xC0 | (dst_mod << 3) | (src_mod)])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
|
|
@ -668,14 +668,22 @@ trait Backend<'a> {
|
||||||
&Literal::Int((crash_tag as u128).to_ne_bytes()),
|
&Literal::Int((crash_tag as u128).to_ne_bytes()),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// this function gets a RocStr, but the roc_panic defined by a platform expects a `*RocStr`.
|
||||||
|
// we store the value in a global variable and then use a pointer to this global
|
||||||
|
let panic_msg_ptr = self.debug_symbol("panic_msg_ptr");
|
||||||
|
let ignored = self.debug_symbol("ignored");
|
||||||
|
self.build_data_pointer(&panic_msg_ptr, "panic_msg".to_string());
|
||||||
|
self.load_literal_symbols(&[msg]);
|
||||||
|
self.build_ptr_store(ignored, panic_msg_ptr, msg, Layout::STR);
|
||||||
|
|
||||||
// Now that the arguments are needed, load them if they are literals.
|
// Now that the arguments are needed, load them if they are literals.
|
||||||
let arguments = &[msg, error_message];
|
let arguments = &[panic_msg_ptr, error_message];
|
||||||
self.load_literal_symbols(arguments);
|
self.load_literal_symbols(arguments);
|
||||||
self.build_fn_call(
|
self.build_fn_call(
|
||||||
&Symbol::DEV_TMP2,
|
&Symbol::DEV_TMP2,
|
||||||
String::from("roc_panic"),
|
String::from("roc_panic"),
|
||||||
arguments,
|
arguments,
|
||||||
&[Layout::STR, Layout::U32],
|
&[Layout::U64, Layout::U32],
|
||||||
&Layout::UNIT,
|
&Layout::UNIT,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1002,7 +1010,7 @@ trait Backend<'a> {
|
||||||
arg_layouts[0], *ret_layout,
|
arg_layouts[0], *ret_layout,
|
||||||
"NumAdd: expected to have the same argument and return layout"
|
"NumAdd: expected to have the same argument and return layout"
|
||||||
);
|
);
|
||||||
self.build_num_add(sym, &args[0], &args[1], ret_layout)
|
self.build_num_add_wrap(sym, &args[0], &args[1], ret_layout)
|
||||||
}
|
}
|
||||||
LowLevel::NumAddChecked => {
|
LowLevel::NumAddChecked => {
|
||||||
self.build_num_add_checked(sym, &args[0], &args[1], &arg_layouts[0], ret_layout)
|
self.build_num_add_checked(sym, &args[0], &args[1], &arg_layouts[0], ret_layout)
|
||||||
|
@ -1072,13 +1080,84 @@ trait Backend<'a> {
|
||||||
);
|
);
|
||||||
self.build_num_neg(sym, &args[0], ret_layout)
|
self.build_num_neg(sym, &args[0], ret_layout)
|
||||||
}
|
}
|
||||||
LowLevel::NumPowInt => self.build_fn_call(
|
LowLevel::NumPowInt => {
|
||||||
sym,
|
let repr = self.interner().get_repr(arg_layouts[0]);
|
||||||
bitcode::NUM_POW_INT[IntWidth::I64].to_string(),
|
let LayoutRepr::Builtin(Builtin::Int(int_width)) = repr else {
|
||||||
args,
|
unreachable!("invalid layout for NumPowInt")
|
||||||
arg_layouts,
|
};
|
||||||
ret_layout,
|
|
||||||
),
|
self.build_fn_call(
|
||||||
|
sym,
|
||||||
|
bitcode::NUM_POW_INT[int_width].to_string(),
|
||||||
|
args,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
LowLevel::NumPow => {
|
||||||
|
let intrinsic = match self.interner().get_repr(arg_layouts[0]) {
|
||||||
|
LayoutRepr::Builtin(Builtin::Float(float_width)) => {
|
||||||
|
&bitcode::NUM_POW[float_width]
|
||||||
|
}
|
||||||
|
LayoutRepr::DEC => todo!("exponentiation for decimals"),
|
||||||
|
_ => unreachable!("invalid layout for NumPow"),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.build_fn_call(sym, intrinsic.to_string(), args, arg_layouts, ret_layout)
|
||||||
|
}
|
||||||
|
|
||||||
|
LowLevel::NumFloor => {
|
||||||
|
let repr = self.interner().get_repr(*ret_layout);
|
||||||
|
let LayoutRepr::Builtin(Builtin::Int(int_width)) = repr else {
|
||||||
|
unreachable!("invalid return layout for NumFloor")
|
||||||
|
};
|
||||||
|
|
||||||
|
match arg_layouts[0] {
|
||||||
|
Layout::F32 => self.build_fn_call(
|
||||||
|
sym,
|
||||||
|
bitcode::NUM_FLOOR_F32[int_width].to_string(),
|
||||||
|
args,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
|
Layout::F64 => self.build_fn_call(
|
||||||
|
sym,
|
||||||
|
bitcode::NUM_FLOOR_F64[int_width].to_string(),
|
||||||
|
args,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
|
Layout::DEC => todo!("NumFloor for decimals"),
|
||||||
|
_ => unreachable!("invalid layout for NumFloor"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LowLevel::NumCeiling => {
|
||||||
|
let repr = self.interner().get_repr(*ret_layout);
|
||||||
|
let LayoutRepr::Builtin(Builtin::Int(int_width)) = repr else {
|
||||||
|
unreachable!("invalid return layout for NumCeiling")
|
||||||
|
};
|
||||||
|
|
||||||
|
match arg_layouts[0] {
|
||||||
|
Layout::F32 => self.build_fn_call(
|
||||||
|
sym,
|
||||||
|
bitcode::NUM_CEILING_F32[int_width].to_string(),
|
||||||
|
args,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
|
Layout::F64 => self.build_fn_call(
|
||||||
|
sym,
|
||||||
|
bitcode::NUM_CEILING_F64[int_width].to_string(),
|
||||||
|
args,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
|
Layout::DEC => todo!("NumCeiling for decimals"),
|
||||||
|
_ => unreachable!("invalid layout for NumCeiling"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LowLevel::NumSub => {
|
LowLevel::NumSub => {
|
||||||
debug_assert_eq!(
|
debug_assert_eq!(
|
||||||
2,
|
2,
|
||||||
|
@ -1385,6 +1464,36 @@ trait Backend<'a> {
|
||||||
|
|
||||||
self.build_num_sqrt(*sym, args[0], float_width);
|
self.build_num_sqrt(*sym, args[0], float_width);
|
||||||
}
|
}
|
||||||
|
LowLevel::NumSin => {
|
||||||
|
let intrinsic = match arg_layouts[0] {
|
||||||
|
Layout::F64 => &bitcode::NUM_SIN[FloatWidth::F64],
|
||||||
|
Layout::F32 => &bitcode::NUM_SIN[FloatWidth::F32],
|
||||||
|
Layout::DEC => bitcode::DEC_SIN,
|
||||||
|
_ => unreachable!("invalid layout for sin"),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.build_fn_call(sym, intrinsic.to_string(), args, arg_layouts, ret_layout)
|
||||||
|
}
|
||||||
|
LowLevel::NumCos => {
|
||||||
|
let intrinsic = match arg_layouts[0] {
|
||||||
|
Layout::F64 => &bitcode::NUM_COS[FloatWidth::F64],
|
||||||
|
Layout::F32 => &bitcode::NUM_COS[FloatWidth::F32],
|
||||||
|
Layout::DEC => bitcode::DEC_COS,
|
||||||
|
_ => unreachable!("invalid layout for cos"),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.build_fn_call(sym, intrinsic.to_string(), args, arg_layouts, ret_layout)
|
||||||
|
}
|
||||||
|
LowLevel::NumTan => {
|
||||||
|
let intrinsic = match arg_layouts[0] {
|
||||||
|
Layout::F64 => &bitcode::NUM_TAN[FloatWidth::F64],
|
||||||
|
Layout::F32 => &bitcode::NUM_TAN[FloatWidth::F32],
|
||||||
|
Layout::DEC => bitcode::DEC_TAN,
|
||||||
|
_ => unreachable!("invalid layout for tan"),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.build_fn_call(sym, intrinsic.to_string(), args, arg_layouts, ret_layout)
|
||||||
|
}
|
||||||
LowLevel::NumRound => self.build_fn_call(
|
LowLevel::NumRound => self.build_fn_call(
|
||||||
sym,
|
sym,
|
||||||
bitcode::NUM_ROUND_F64[IntWidth::I64].to_string(),
|
bitcode::NUM_ROUND_F64[IntWidth::I64].to_string(),
|
||||||
|
@ -1962,12 +2071,15 @@ trait Backend<'a> {
|
||||||
"NumIsZero: expected to have return layout of type Bool"
|
"NumIsZero: expected to have return layout of type Bool"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let literal = match self.interner().get_repr(arg_layouts[0]) {
|
||||||
|
LayoutRepr::Builtin(Builtin::Int(_)) => Literal::Int(0i128.to_ne_bytes()),
|
||||||
|
LayoutRepr::Builtin(Builtin::Float(_)) => Literal::Float(0.0),
|
||||||
|
LayoutRepr::DEC => Literal::Decimal([0; 16]),
|
||||||
|
_ => unreachable!("invalid layout for sin"),
|
||||||
|
};
|
||||||
|
|
||||||
self.load_literal_symbols(args);
|
self.load_literal_symbols(args);
|
||||||
self.load_literal(
|
self.load_literal(&Symbol::DEV_TMP, &arg_layouts[0], &literal);
|
||||||
&Symbol::DEV_TMP,
|
|
||||||
&arg_layouts[0],
|
|
||||||
&Literal::Int(0i128.to_ne_bytes()),
|
|
||||||
);
|
|
||||||
self.build_eq(sym, &args[0], &Symbol::DEV_TMP, &arg_layouts[0]);
|
self.build_eq(sym, &args[0], &Symbol::DEV_TMP, &arg_layouts[0]);
|
||||||
self.free_symbol(&Symbol::DEV_TMP)
|
self.free_symbol(&Symbol::DEV_TMP)
|
||||||
}
|
}
|
||||||
|
@ -2086,6 +2198,14 @@ trait Backend<'a> {
|
||||||
return_layout: &InLayout<'a>,
|
return_layout: &InLayout<'a>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
fn build_num_add_wrap(
|
||||||
|
&mut self,
|
||||||
|
dst: &Symbol,
|
||||||
|
src1: &Symbol,
|
||||||
|
src2: &Symbol,
|
||||||
|
layout: &InLayout<'a>,
|
||||||
|
);
|
||||||
|
|
||||||
/// build_num_sub_checked stores the sum of src1 and src2 into dst.
|
/// build_num_sub_checked stores the sum of src1 and src2 into dst.
|
||||||
fn build_num_sub_checked(
|
fn build_num_sub_checked(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
@ -159,6 +159,30 @@ fn define_setlongjmp_buffer(output: &mut Object) -> SymbolId {
|
||||||
symbol_id
|
symbol_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// needed to implement Crash when setjmp/longjmp is used
|
||||||
|
fn define_panic_msg(output: &mut Object) -> SymbolId {
|
||||||
|
let bss_section = output.section_id(StandardSection::Data);
|
||||||
|
|
||||||
|
// 3 words for a RocStr
|
||||||
|
const SIZE: usize = 3 * core::mem::size_of::<u64>();
|
||||||
|
|
||||||
|
let symbol = Symbol {
|
||||||
|
name: b"panic_msg".to_vec(),
|
||||||
|
value: 0,
|
||||||
|
size: SIZE as u64,
|
||||||
|
kind: SymbolKind::Data,
|
||||||
|
scope: SymbolScope::Linkage,
|
||||||
|
weak: false,
|
||||||
|
section: SymbolSection::Section(bss_section),
|
||||||
|
flags: SymbolFlags::None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let symbol_id = output.add_symbol(symbol);
|
||||||
|
output.add_symbol_data(symbol_id, bss_section, &[0x00; SIZE], 8);
|
||||||
|
|
||||||
|
symbol_id
|
||||||
|
}
|
||||||
|
|
||||||
fn generate_setjmp<'a, B: Backend<'a>>(backend: &mut B, output: &mut Object) {
|
fn generate_setjmp<'a, B: Backend<'a>>(backend: &mut B, output: &mut Object) {
|
||||||
let text_section = output.section_id(StandardSection::Text);
|
let text_section = output.section_id(StandardSection::Text);
|
||||||
let proc_symbol = Symbol {
|
let proc_symbol = Symbol {
|
||||||
|
@ -334,7 +358,7 @@ fn generate_wrapper<'a, B: Backend<'a>>(
|
||||||
let (proc_data, offset) = backend.build_wrapped_jmp();
|
let (proc_data, offset) = backend.build_wrapped_jmp();
|
||||||
let proc_offset = output.add_symbol_data(proc_id, text_section, proc_data, 16);
|
let proc_offset = output.add_symbol_data(proc_id, text_section, proc_data, 16);
|
||||||
|
|
||||||
let name = wraps.as_str().as_bytes();
|
let name = wraps.as_bytes();
|
||||||
// If the symbol is an undefined zig builtin, we need to add it here.
|
// If the symbol is an undefined zig builtin, we need to add it here.
|
||||||
let symbol = Symbol {
|
let symbol = Symbol {
|
||||||
name: name.to_vec(),
|
name: name.to_vec(),
|
||||||
|
@ -422,6 +446,7 @@ fn build_object<'a, B: Backend<'a>>(
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if backend.env().mode.generate_roc_panic() {
|
if backend.env().mode.generate_roc_panic() {
|
||||||
|
define_panic_msg(&mut output);
|
||||||
define_setlongjmp_buffer(&mut output);
|
define_setlongjmp_buffer(&mut output);
|
||||||
|
|
||||||
generate_roc_panic(&mut backend, &mut output);
|
generate_roc_panic(&mut backend, &mut output);
|
||||||
|
|
|
@ -949,6 +949,12 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_debug_info(module: &Module<'ctx>) -> (DebugInfoBuilder<'ctx>, DICompileUnit<'ctx>) {
|
pub fn new_debug_info(module: &Module<'ctx>) -> (DebugInfoBuilder<'ctx>, DICompileUnit<'ctx>) {
|
||||||
|
let debug_metadata_version = module.get_context().i32_type().const_int(3, false);
|
||||||
|
module.add_basic_value_flag(
|
||||||
|
"Debug Info Version",
|
||||||
|
inkwell::module::FlagBehavior::Warning,
|
||||||
|
debug_metadata_version,
|
||||||
|
);
|
||||||
module.create_debug_info_builder(
|
module.create_debug_info_builder(
|
||||||
true,
|
true,
|
||||||
/* language */ inkwell::debug_info::DWARFSourceLanguage::C,
|
/* language */ inkwell::debug_info::DWARFSourceLanguage::C,
|
||||||
|
@ -4104,7 +4110,6 @@ fn const_i128<'ctx>(env: &Env<'_, 'ctx, '_>, value: i128) -> IntValue<'ctx> {
|
||||||
|
|
||||||
fn const_u128<'ctx>(env: &Env<'_, 'ctx, '_>, value: u128) -> IntValue<'ctx> {
|
fn const_u128<'ctx>(env: &Env<'_, 'ctx, '_>, value: u128) -> IntValue<'ctx> {
|
||||||
// truncate the lower 64 bits
|
// truncate the lower 64 bits
|
||||||
let value = value;
|
|
||||||
let a = value as u64;
|
let a = value as u64;
|
||||||
|
|
||||||
// get the upper 64 bits
|
// get the upper 64 bits
|
||||||
|
@ -5067,6 +5072,11 @@ fn expose_function_to_host_help_c_abi<'a, 'ctx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_sjlj_buffer<'ctx>(env: &Env<'_, 'ctx, '_>) -> PointerValue<'ctx> {
|
pub fn get_sjlj_buffer<'ctx>(env: &Env<'_, 'ctx, '_>) -> PointerValue<'ctx> {
|
||||||
|
let word_type = match env.target_info.ptr_width() {
|
||||||
|
PtrWidth::Bytes4 => env.context.i32_type(),
|
||||||
|
PtrWidth::Bytes8 => env.context.i64_type(),
|
||||||
|
};
|
||||||
|
|
||||||
// The size of jump_buf is target-dependent.
|
// The size of jump_buf is target-dependent.
|
||||||
// - AArch64 needs 3 machine-sized words
|
// - AArch64 needs 3 machine-sized words
|
||||||
// - LLVM says the following about the SJLJ intrinsic:
|
// - LLVM says the following about the SJLJ intrinsic:
|
||||||
|
@ -5078,11 +5088,15 @@ pub fn get_sjlj_buffer<'ctx>(env: &Env<'_, 'ctx, '_>) -> PointerValue<'ctx> {
|
||||||
// The following three words are available for use in a target-specific manner.
|
// The following three words are available for use in a target-specific manner.
|
||||||
//
|
//
|
||||||
// So, let's create a 5-word buffer.
|
// So, let's create a 5-word buffer.
|
||||||
let word_type = match env.target_info.ptr_width() {
|
let size = if env.target_info.operating_system == roc_target::OperatingSystem::Windows {
|
||||||
PtrWidth::Bytes4 => env.context.i32_type(),
|
// Due to https://github.com/llvm/llvm-project/issues/72908
|
||||||
PtrWidth::Bytes8 => env.context.i64_type(),
|
// on windows, we store the register contents into this buffer directly!
|
||||||
|
30
|
||||||
|
} else {
|
||||||
|
5
|
||||||
};
|
};
|
||||||
let type_ = word_type.array_type(5);
|
|
||||||
|
let type_ = word_type.array_type(size);
|
||||||
|
|
||||||
let global = match env.module.get_global("roc_sjlj_buffer") {
|
let global = match env.module.get_global("roc_sjlj_buffer") {
|
||||||
Some(global) => global,
|
Some(global) => global,
|
||||||
|
@ -5100,9 +5114,12 @@ pub fn get_sjlj_buffer<'ctx>(env: &Env<'_, 'ctx, '_>) -> PointerValue<'ctx> {
|
||||||
|
|
||||||
pub fn build_setjmp_call<'ctx>(env: &Env<'_, 'ctx, '_>) -> BasicValueEnum<'ctx> {
|
pub fn build_setjmp_call<'ctx>(env: &Env<'_, 'ctx, '_>) -> BasicValueEnum<'ctx> {
|
||||||
let jmp_buf = get_sjlj_buffer(env);
|
let jmp_buf = get_sjlj_buffer(env);
|
||||||
if cfg!(target_arch = "aarch64") {
|
if env.target_info.architecture == roc_target::Architecture::Aarch64 {
|
||||||
// Due to https://github.com/roc-lang/roc/issues/2965, we use a setjmp we linked in from Zig
|
// Due to https://github.com/roc-lang/roc/issues/2965, we use a setjmp we linked in from Zig
|
||||||
call_bitcode_fn(env, &[jmp_buf.into()], bitcode::UTILS_SETJMP)
|
call_bitcode_fn(env, &[jmp_buf.into()], bitcode::UTILS_SETJMP)
|
||||||
|
} else if env.target_info.operating_system == roc_target::OperatingSystem::Windows {
|
||||||
|
// Due to https://github.com/llvm/llvm-project/issues/72908, we use a setjmp defined as asm in Zig
|
||||||
|
call_bitcode_fn(env, &[jmp_buf.into()], bitcode::UTILS_WINDOWS_SETJMP)
|
||||||
} else {
|
} else {
|
||||||
// Anywhere else, use the LLVM intrinsic.
|
// Anywhere else, use the LLVM intrinsic.
|
||||||
// https://llvm.org/docs/ExceptionHandling.html#llvm-eh-sjlj-setjmp
|
// https://llvm.org/docs/ExceptionHandling.html#llvm-eh-sjlj-setjmp
|
||||||
|
|
|
@ -315,11 +315,18 @@ pub fn add_sjlj_roc_panic(env: &Env<'_, '_, '_>) {
|
||||||
|
|
||||||
pub fn build_longjmp_call(env: &Env) {
|
pub fn build_longjmp_call(env: &Env) {
|
||||||
let jmp_buf = get_sjlj_buffer(env);
|
let jmp_buf = get_sjlj_buffer(env);
|
||||||
if cfg!(target_arch = "aarch64") {
|
if env.target_info.architecture == roc_target::Architecture::Aarch64 {
|
||||||
// Call the Zig-linked longjmp: `void longjmp(i32*, i32)`
|
// Due to https://github.com/roc-lang/roc/issues/2965, we use a setjmp we linked in from Zig
|
||||||
let tag = env.context.i32_type().const_int(1, false);
|
let tag = env.context.i32_type().const_int(1, false);
|
||||||
let _call =
|
let _call =
|
||||||
call_void_bitcode_fn(env, &[jmp_buf.into(), tag.into()], bitcode::UTILS_LONGJMP);
|
call_void_bitcode_fn(env, &[jmp_buf.into(), tag.into()], bitcode::UTILS_LONGJMP);
|
||||||
|
} else if env.target_info.operating_system == roc_target::OperatingSystem::Windows {
|
||||||
|
let tag = env.context.i32_type().const_int(1, false);
|
||||||
|
let _call = call_void_bitcode_fn(
|
||||||
|
env,
|
||||||
|
&[jmp_buf.into(), tag.into()],
|
||||||
|
bitcode::UTILS_WINDOWS_LONGJMP,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
// Call the LLVM-intrinsic longjmp: `void @llvm.eh.sjlj.longjmp(i8* %setjmp_buf)`
|
// Call the LLVM-intrinsic longjmp: `void @llvm.eh.sjlj.longjmp(i8* %setjmp_buf)`
|
||||||
let jmp_buf_i8p = env.builder.new_build_pointer_cast(
|
let jmp_buf_i8p = env.builder.new_build_pointer_cast(
|
||||||
|
|
|
@ -1853,6 +1853,11 @@ fn build_float_binop<'ctx>(
|
||||||
|
|
||||||
let bd = env.builder;
|
let bd = env.builder;
|
||||||
|
|
||||||
|
let float_type = match float_width {
|
||||||
|
FloatWidth::F32 => env.context.f32_type(),
|
||||||
|
FloatWidth::F64 => env.context.f64_type(),
|
||||||
|
};
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
NumAdd => bd.new_build_float_add(lhs, rhs, "add_float").into(),
|
NumAdd => bd.new_build_float_add(lhs, rhs, "add_float").into(),
|
||||||
NumAddChecked => {
|
NumAddChecked => {
|
||||||
|
@ -1865,10 +1870,8 @@ fn build_float_binop<'ctx>(
|
||||||
.into_int_value();
|
.into_int_value();
|
||||||
let is_infinite = bd.new_build_not(is_finite, "negate");
|
let is_infinite = bd.new_build_not(is_finite, "negate");
|
||||||
|
|
||||||
let struct_type = context.struct_type(
|
let struct_type =
|
||||||
&[context.f64_type().into(), context.bool_type().into()],
|
context.struct_type(&[float_type.into(), context.bool_type().into()], false);
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
let struct_value = {
|
let struct_value = {
|
||||||
let v1 = struct_type.const_zero();
|
let v1 = struct_type.const_zero();
|
||||||
|
@ -1894,10 +1897,8 @@ fn build_float_binop<'ctx>(
|
||||||
.into_int_value();
|
.into_int_value();
|
||||||
let is_infinite = bd.new_build_not(is_finite, "negate");
|
let is_infinite = bd.new_build_not(is_finite, "negate");
|
||||||
|
|
||||||
let struct_type = context.struct_type(
|
let struct_type =
|
||||||
&[context.f64_type().into(), context.bool_type().into()],
|
context.struct_type(&[float_type.into(), context.bool_type().into()], false);
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
let struct_value = {
|
let struct_value = {
|
||||||
let v1 = struct_type.const_zero();
|
let v1 = struct_type.const_zero();
|
||||||
|
@ -1924,10 +1925,8 @@ fn build_float_binop<'ctx>(
|
||||||
.into_int_value();
|
.into_int_value();
|
||||||
let is_infinite = bd.new_build_not(is_finite, "negate");
|
let is_infinite = bd.new_build_not(is_finite, "negate");
|
||||||
|
|
||||||
let struct_type = context.struct_type(
|
let struct_type =
|
||||||
&[context.f64_type().into(), context.bool_type().into()],
|
context.struct_type(&[float_type.into(), context.bool_type().into()], false);
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
let struct_value = {
|
let struct_value = {
|
||||||
let v1 = struct_type.const_zero();
|
let v1 = struct_type.const_zero();
|
||||||
|
|
|
@ -1295,15 +1295,25 @@ fn build_rec_union_recursive_decrement<'a, 'ctx>(
|
||||||
_ => tag_id,
|
_ => tag_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let block = env.context.append_basic_block(parent, "tag_id_decrement");
|
||||||
|
env.builder.position_at_end(block);
|
||||||
|
|
||||||
// if none of the fields are or contain anything refcounted, just move on
|
// if none of the fields are or contain anything refcounted, just move on
|
||||||
if fields_need_no_refcounting(layout_interner, field_layouts) {
|
if fields_need_no_refcounting(layout_interner, field_layouts) {
|
||||||
|
// Still make sure to decrement the refcount of the union as a whole.
|
||||||
|
if let DecOrReuse::Dec = decrement_or_reuse {
|
||||||
|
let union_layout = LayoutRepr::Union(union_layout);
|
||||||
|
refcount_ptr.modify(call_mode, union_layout, env, layout_interner);
|
||||||
|
}
|
||||||
|
|
||||||
|
// this function returns void
|
||||||
|
builder.new_build_return(None);
|
||||||
|
|
||||||
|
cases.push((tag_id_int_type.const_int(tag_id as u64, false), block));
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let block = env.context.append_basic_block(parent, "tag_id_decrement");
|
|
||||||
|
|
||||||
env.builder.position_at_end(block);
|
|
||||||
|
|
||||||
let fields_struct = LayoutRepr::struct_(field_layouts);
|
let fields_struct = LayoutRepr::struct_(field_layouts);
|
||||||
let wrapper_type = basic_type_from_layout(env, layout_interner, fields_struct);
|
let wrapper_type = basic_type_from_layout(env, layout_interner, fields_struct);
|
||||||
|
|
||||||
|
@ -1370,12 +1380,9 @@ fn build_rec_union_recursive_decrement<'a, 'ctx>(
|
||||||
// and store them on the stack, then modify (and potentially free) the current cell, then
|
// and store them on the stack, then modify (and potentially free) the current cell, then
|
||||||
// actually inc/dec the fields.
|
// actually inc/dec the fields.
|
||||||
|
|
||||||
match decrement_or_reuse {
|
if let DecOrReuse::Dec = decrement_or_reuse {
|
||||||
DecOrReuse::Reuse => {}
|
let union_layout = LayoutRepr::Union(union_layout);
|
||||||
DecOrReuse::Dec => {
|
refcount_ptr.modify(call_mode, union_layout, env, layout_interner);
|
||||||
let union_layout = LayoutRepr::Union(union_layout);
|
|
||||||
refcount_ptr.modify(call_mode, union_layout, env, layout_interner);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (field, field_layout) in deferred_nonrec {
|
for (field, field_layout) in deferred_nonrec {
|
||||||
|
|
4
crates/compiler/gen_wasm/.gitignore
vendored
4
crates/compiler/gen_wasm/.gitignore
vendored
|
@ -1,4 +0,0 @@
|
||||||
*.wasm
|
|
||||||
*.wat
|
|
||||||
/notes.md
|
|
||||||
/tmp
|
|
File diff suppressed because it is too large
Load diff
1
crates/compiler/load_internal/.gitignore
vendored
1
crates/compiler/load_internal/.gitignore
vendored
|
@ -1 +0,0 @@
|
||||||
/tmp
|
|
|
@ -325,7 +325,7 @@ fn import_transitive_alias() {
|
||||||
(
|
(
|
||||||
"RBTree",
|
"RBTree",
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
interface RBTree exposes [RedBlackTree, empty] imports []
|
interface RBTree exposes [RedBlackTree, empty] imports []
|
||||||
|
|
||||||
# The color of a node. Leaves are considered Black.
|
# The color of a node. Leaves are considered Black.
|
||||||
|
@ -337,18 +337,18 @@ fn import_transitive_alias() {
|
||||||
empty : RedBlackTree k v
|
empty : RedBlackTree k v
|
||||||
empty =
|
empty =
|
||||||
Empty
|
Empty
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"Other",
|
"Other",
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
interface Other exposes [empty] imports [RBTree]
|
interface Other exposes [empty] imports [RBTree]
|
||||||
|
|
||||||
empty : RBTree.RedBlackTree I64 I64
|
empty : RBTree.RedBlackTree I64 I64
|
||||||
empty = RBTree.empty
|
empty = RBTree.empty
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
@ -628,11 +628,11 @@ fn parse_problem() {
|
||||||
let modules = vec![(
|
let modules = vec![(
|
||||||
"Main",
|
"Main",
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
interface Main exposes [main] imports []
|
interface Main exposes [main] imports []
|
||||||
|
|
||||||
main = [
|
main = [
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
)];
|
)];
|
||||||
|
|
||||||
|
@ -820,23 +820,23 @@ fn opaque_wrapped_unwrapped_outside_defining_module() {
|
||||||
(
|
(
|
||||||
"Age",
|
"Age",
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
interface Age exposes [Age] imports []
|
interface Age exposes [Age] imports []
|
||||||
|
|
||||||
Age := U32
|
Age := U32
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"Main",
|
"Main",
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
interface Main exposes [twenty, readAge] imports [Age.{ Age }]
|
interface Main exposes [twenty, readAge] imports [Age.{ Age }]
|
||||||
|
|
||||||
twenty = @Age 20
|
twenty = @Age 20
|
||||||
|
|
||||||
readAge = \@Age n -> n
|
readAge = \@Age n -> n
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
@ -846,7 +846,7 @@ fn opaque_wrapped_unwrapped_outside_defining_module() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
err,
|
err,
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
── OPAQUE TYPE DECLARED OUTSIDE SCOPE ─ ...rapped_outside_defining_module/Main ─
|
── OPAQUE TYPE DECLARED OUTSIDE SCOPE ─ ...rapped_outside_defining_module/Main ─
|
||||||
|
|
||||||
The unwrapped opaque type Age referenced here:
|
The unwrapped opaque type Age referenced here:
|
||||||
|
@ -883,7 +883,7 @@ fn opaque_wrapped_unwrapped_outside_defining_module() {
|
||||||
^^^^^^^^^^^
|
^^^^^^^^^^^
|
||||||
|
|
||||||
Since Age isn't used, you don't need to import it.
|
Since Age isn't used, you don't need to import it.
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
"\n{}",
|
"\n{}",
|
||||||
err
|
err
|
||||||
|
@ -993,11 +993,11 @@ fn module_doesnt_match_file_path() {
|
||||||
let modules = vec![(
|
let modules = vec![(
|
||||||
"Age",
|
"Age",
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
interface NotAge exposes [Age] imports []
|
interface NotAge exposes [Age] imports []
|
||||||
|
|
||||||
Age := U32
|
Age := U32
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
)];
|
)];
|
||||||
|
|
||||||
|
@ -1005,7 +1005,7 @@ fn module_doesnt_match_file_path() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
err,
|
err,
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
── WEIRD MODULE NAME ─────────────────── tmp/module_doesnt_match_file_path/Age ─
|
── WEIRD MODULE NAME ─────────────────── tmp/module_doesnt_match_file_path/Age ─
|
||||||
|
|
||||||
This module name does not correspond with the file path it is defined
|
This module name does not correspond with the file path it is defined
|
||||||
|
@ -1016,7 +1016,7 @@ fn module_doesnt_match_file_path() {
|
||||||
|
|
||||||
Module names must correspond with the file paths they are defined in.
|
Module names must correspond with the file paths they are defined in.
|
||||||
For example, I expect to see BigNum defined in BigNum.roc, or Math.Sin
|
For example, I expect to see BigNum defined in BigNum.roc, or Math.Sin
|
||||||
defined in Math/Sin.roc."#
|
defined in Math/Sin.roc."
|
||||||
),
|
),
|
||||||
"\n{}",
|
"\n{}",
|
||||||
err
|
err
|
||||||
|
@ -1028,9 +1028,9 @@ fn module_cyclic_import_itself() {
|
||||||
let modules = vec![(
|
let modules = vec![(
|
||||||
"Age",
|
"Age",
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
interface Age exposes [] imports [Age]
|
interface Age exposes [] imports [Age]
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
)];
|
)];
|
||||||
|
|
||||||
|
@ -1038,7 +1038,7 @@ fn module_cyclic_import_itself() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
err,
|
err,
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
── IMPORT CYCLE ────────────────────────── tmp/module_cyclic_import_itself/Age ─
|
── IMPORT CYCLE ────────────────────────── tmp/module_cyclic_import_itself/Age ─
|
||||||
|
|
||||||
I can't compile Age because it depends on itself through the following
|
I can't compile Age because it depends on itself through the following
|
||||||
|
@ -1052,7 +1052,7 @@ fn module_cyclic_import_itself() {
|
||||||
|
|
||||||
Cyclic dependencies are not allowed in Roc! Can you restructure a
|
Cyclic dependencies are not allowed in Roc! Can you restructure a
|
||||||
module in this import chain so that it doesn't have to depend on
|
module in this import chain so that it doesn't have to depend on
|
||||||
itself?"#
|
itself?"
|
||||||
),
|
),
|
||||||
"\n{}",
|
"\n{}",
|
||||||
err
|
err
|
||||||
|
@ -1065,17 +1065,17 @@ fn module_cyclic_import_transitive() {
|
||||||
(
|
(
|
||||||
"Age",
|
"Age",
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
interface Age exposes [] imports [Person]
|
interface Age exposes [] imports [Person]
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"Person",
|
"Person",
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
interface Person exposes [] imports [Age]
|
interface Person exposes [] imports [Age]
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
@ -1084,7 +1084,7 @@ fn module_cyclic_import_transitive() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
err,
|
err,
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
── IMPORT CYCLE ────────────────── tmp/module_cyclic_import_transitive/Age.roc ─
|
── IMPORT CYCLE ────────────────── tmp/module_cyclic_import_transitive/Age.roc ─
|
||||||
|
|
||||||
I can't compile Age because it depends on itself through the following
|
I can't compile Age because it depends on itself through the following
|
||||||
|
@ -1100,7 +1100,7 @@ fn module_cyclic_import_transitive() {
|
||||||
|
|
||||||
Cyclic dependencies are not allowed in Roc! Can you restructure a
|
Cyclic dependencies are not allowed in Roc! Can you restructure a
|
||||||
module in this import chain so that it doesn't have to depend on
|
module in this import chain so that it doesn't have to depend on
|
||||||
itself?"#
|
itself?"
|
||||||
),
|
),
|
||||||
"\n{}",
|
"\n{}",
|
||||||
err
|
err
|
||||||
|
@ -1113,17 +1113,17 @@ fn nested_module_has_incorrect_name() {
|
||||||
(
|
(
|
||||||
"Dep/Foo.roc",
|
"Dep/Foo.roc",
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
interface Foo exposes [] imports []
|
interface Foo exposes [] imports []
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"I.roc",
|
"I.roc",
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
interface I exposes [] imports [Dep.Foo]
|
interface I exposes [] imports [Dep.Foo]
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
@ -1132,7 +1132,7 @@ fn nested_module_has_incorrect_name() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
err,
|
err,
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
── INCORRECT MODULE NAME ──── tmp/nested_module_has_incorrect_name/Dep/Foo.roc ─
|
── INCORRECT MODULE NAME ──── tmp/nested_module_has_incorrect_name/Dep/Foo.roc ─
|
||||||
|
|
||||||
This module has a different name than I expected:
|
This module has a different name than I expected:
|
||||||
|
@ -1142,7 +1142,7 @@ fn nested_module_has_incorrect_name() {
|
||||||
|
|
||||||
Based on the nesting and use of this module, I expect it to have name
|
Based on the nesting and use of this module, I expect it to have name
|
||||||
|
|
||||||
Dep.Foo"#
|
Dep.Foo"
|
||||||
),
|
),
|
||||||
"\n{}",
|
"\n{}",
|
||||||
err
|
err
|
||||||
|
|
|
@ -1047,8 +1047,8 @@ fn insert_refcount_operations_binding<'a>(
|
||||||
|
|
||||||
closure_env_layout: _,
|
closure_env_layout: _,
|
||||||
|
|
||||||
/// update mode of the higher order lowlevel itself
|
// update mode of the higher order lowlevel itself
|
||||||
update_mode: _,
|
update_mode: _,
|
||||||
|
|
||||||
passed_function,
|
passed_function,
|
||||||
}) => {
|
}) => {
|
||||||
|
|
|
@ -3085,7 +3085,9 @@ fn specialize_host_specializations<'a>(
|
||||||
let from_app = offset_variable(from_app);
|
let from_app = offset_variable(from_app);
|
||||||
let index = specialize_external_help(env, procs, layout_cache, lambda_name, from_app);
|
let index = specialize_external_help(env, procs, layout_cache, lambda_name, from_app);
|
||||||
|
|
||||||
let Some(from_platform) = opt_from_platform else { continue };
|
let Some(from_platform) = opt_from_platform else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
// now run the lambda set numbering scheme
|
// now run the lambda set numbering scheme
|
||||||
let hels = find_lambda_sets(env.arena, env.subs, from_platform);
|
let hels = find_lambda_sets(env.arena, env.subs, from_platform);
|
||||||
|
@ -3146,7 +3148,9 @@ fn specialize_host_specializations<'a>(
|
||||||
};
|
};
|
||||||
|
|
||||||
let in_progress = &mut procs.specialized.procedures[index.0];
|
let in_progress = &mut procs.specialized.procedures[index.0];
|
||||||
let InProgressProc::Done(proc) = in_progress else { unreachable!() };
|
let InProgressProc::Done(proc) = in_progress else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
|
||||||
procs.host_exposed_lambda_sets.push((proc.name, key, hels));
|
procs.host_exposed_lambda_sets.push((proc.name, key, hels));
|
||||||
}
|
}
|
||||||
|
|
|
@ -442,7 +442,7 @@ pub trait LayoutInterner<'a>: Sized {
|
||||||
pub struct InLayout<'a>(usize, std::marker::PhantomData<&'a ()>);
|
pub struct InLayout<'a>(usize, std::marker::PhantomData<&'a ()>);
|
||||||
impl<'a> Clone for InLayout<'a> {
|
impl<'a> Clone for InLayout<'a> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self(self.0, Default::default())
|
*self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -119,10 +119,11 @@ pub struct WhenPattern<'a> {
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub enum StrSegment<'a> {
|
pub enum StrSegment<'a> {
|
||||||
Plaintext(&'a str), // e.g. "foo"
|
Plaintext(&'a str), // e.g. "foo"
|
||||||
Unicode(Loc<&'a str>), // e.g. "00A0" in "\u(00A0)"
|
Unicode(Loc<&'a str>), // e.g. "00A0" in "\u(00A0)"
|
||||||
EscapedChar(EscapedChar), // e.g. '\n' in "Hello!\n"
|
EscapedChar(EscapedChar), // e.g. '\n' in "Hello!\n"
|
||||||
Interpolated(Loc<&'a Expr<'a>>), // e.g. (name) in "Hi, \(name)!"
|
Interpolated(Loc<&'a Expr<'a>>),
|
||||||
|
DeprecatedInterpolated(Loc<&'a Expr<'a>>), // The old "$(...)" syntax - will be removed someday
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
@ -141,6 +142,7 @@ pub enum EscapedChar {
|
||||||
SingleQuote, // \'
|
SingleQuote, // \'
|
||||||
Backslash, // \\
|
Backslash, // \\
|
||||||
CarriageReturn, // \r
|
CarriageReturn, // \r
|
||||||
|
Dollar, // \$
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EscapedChar {
|
impl EscapedChar {
|
||||||
|
@ -155,6 +157,7 @@ impl EscapedChar {
|
||||||
CarriageReturn => 'r',
|
CarriageReturn => 'r',
|
||||||
Tab => 't',
|
Tab => 't',
|
||||||
Newline => 'n',
|
Newline => 'n',
|
||||||
|
Dollar => '$',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,6 +171,7 @@ impl EscapedChar {
|
||||||
CarriageReturn => '\r',
|
CarriageReturn => '\r',
|
||||||
Tab => '\t',
|
Tab => '\t',
|
||||||
Newline => '\n',
|
Newline => '\n',
|
||||||
|
Dollar => '$',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -213,6 +217,7 @@ impl<'a> TryFrom<StrSegment<'a>> for SingleQuoteSegment<'a> {
|
||||||
StrSegment::Unicode(s) => Ok(SingleQuoteSegment::Unicode(s)),
|
StrSegment::Unicode(s) => Ok(SingleQuoteSegment::Unicode(s)),
|
||||||
StrSegment::EscapedChar(s) => Ok(SingleQuoteSegment::EscapedChar(s)),
|
StrSegment::EscapedChar(s) => Ok(SingleQuoteSegment::EscapedChar(s)),
|
||||||
StrSegment::Interpolated(_) => Err(ESingleQuote::InterpolationNotAllowed),
|
StrSegment::Interpolated(_) => Err(ESingleQuote::InterpolationNotAllowed),
|
||||||
|
StrSegment::DeprecatedInterpolated(_) => Err(ESingleQuote::InterpolationNotAllowed),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1587,7 +1592,9 @@ impl<'a> Malformed for StrSegment<'a> {
|
||||||
fn is_malformed(&self) -> bool {
|
fn is_malformed(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
StrSegment::Plaintext(_) | StrSegment::Unicode(_) | StrSegment::EscapedChar(_) => false,
|
StrSegment::Plaintext(_) | StrSegment::Unicode(_) | StrSegment::EscapedChar(_) => false,
|
||||||
StrSegment::Interpolated(expr) => expr.is_malformed(),
|
StrSegment::Interpolated(expr) | StrSegment::DeprecatedInterpolated(expr) => {
|
||||||
|
expr.is_malformed()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ impl<'a> Src64<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Safety: we got capacity by rounding up to the nearest 64B
|
// Safety: we got capacity by rounding up to the nearest 64B
|
||||||
let dest = unsafe { allocate_chunks(arena, capacity)? }.as_ptr() as *mut u8;
|
let dest = unsafe { allocate_chunks(arena, capacity)? }.as_ptr();
|
||||||
|
|
||||||
// Safety: `dest` has a length of `capacity`, which has been rounded up to a multiple of 64.
|
// Safety: `dest` has a length of `capacity`, which has been rounded up to a multiple of 64.
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -264,8 +264,7 @@ impl<'a> Src64<'a> {
|
||||||
|
|
||||||
// Safety: bytes_ptr came from an allocation of `capacity` bytes, it's had
|
// Safety: bytes_ptr came from an allocation of `capacity` bytes, it's had
|
||||||
// newlines filled at the end, and `file_size` bytes written over the rest.
|
// newlines filled at the end, and `file_size` bytes written over the rest.
|
||||||
let bytes =
|
let bytes = unsafe { core::slice::from_raw_parts_mut(buf.as_ptr(), capacity) };
|
||||||
unsafe { core::slice::from_raw_parts_mut(buf.as_ptr() as *mut u8, capacity) };
|
|
||||||
|
|
||||||
Ok(Self { bytes })
|
Ok(Self { bytes })
|
||||||
}
|
}
|
||||||
|
|
|
@ -349,6 +349,68 @@ pub fn parse_str_like_literal<'a>() -> impl Parser<'a, StrLikeLiteral<'a>, EStri
|
||||||
return Err((MadeProgress, EString::EndlessSingleLine(start_state.pos())));
|
return Err((MadeProgress, EString::EndlessSingleLine(start_state.pos())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
b'$' => {
|
||||||
|
// This is for the byte we're about to parse.
|
||||||
|
segment_parsed_bytes += 1;
|
||||||
|
|
||||||
|
// iff the '$' is followed by '(', this is string interpolation.
|
||||||
|
if let Some(b'(') = bytes.next() {
|
||||||
|
// We're about to begin string interpolation!
|
||||||
|
//
|
||||||
|
// End the previous segment so we can begin a new one.
|
||||||
|
// Retroactively end it right before the `$` char we parsed.
|
||||||
|
// (We can't use end_segment! here because it ends it right after
|
||||||
|
// the just-parsed character, which here would be '(' rather than '$')
|
||||||
|
// Don't push anything if the string would be empty.
|
||||||
|
if segment_parsed_bytes > 2 {
|
||||||
|
// exclude the 2 chars we just parsed, namely '$' and '('
|
||||||
|
let string_bytes = &state.bytes()[0..(segment_parsed_bytes - 2)];
|
||||||
|
|
||||||
|
match std::str::from_utf8(string_bytes) {
|
||||||
|
Ok(string) => {
|
||||||
|
state.advance_mut(string.len());
|
||||||
|
|
||||||
|
segments.push(StrSegment::Plaintext(string));
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
return Err((
|
||||||
|
MadeProgress,
|
||||||
|
EString::Space(BadInputError::BadUtf8, state.pos()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Advance past the `$(`
|
||||||
|
state.advance_mut(2);
|
||||||
|
|
||||||
|
let original_byte_count = state.bytes().len();
|
||||||
|
|
||||||
|
// Parse an arbitrary expression, followed by ')'
|
||||||
|
let (_progress, loc_expr, new_state) = skip_second!(
|
||||||
|
specialize_ref(
|
||||||
|
EString::Format,
|
||||||
|
loc(allocated(reset_min_indent(expr::expr_help())))
|
||||||
|
),
|
||||||
|
word1(b')', EString::FormatEnd)
|
||||||
|
)
|
||||||
|
.parse(arena, state, min_indent)?;
|
||||||
|
|
||||||
|
// Advance the iterator past the expr we just parsed.
|
||||||
|
for _ in 0..(original_byte_count - new_state.bytes().len()) {
|
||||||
|
bytes.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
segments.push(StrSegment::Interpolated(loc_expr));
|
||||||
|
|
||||||
|
// Reset the segment
|
||||||
|
segment_parsed_bytes = 0;
|
||||||
|
state = new_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the '$' wasn't followed by '(', then this wasn't interpolation,
|
||||||
|
// and we don't need to do anything special.
|
||||||
|
}
|
||||||
b'\\' => {
|
b'\\' => {
|
||||||
// We're about to begin an escaped segment of some sort!
|
// We're about to begin an escaped segment of some sort!
|
||||||
//
|
//
|
||||||
|
@ -386,7 +448,7 @@ pub fn parse_str_like_literal<'a>() -> impl Parser<'a, StrLikeLiteral<'a>, EStri
|
||||||
bytes.next();
|
bytes.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
segments.push(StrSegment::Interpolated(loc_expr));
|
segments.push(StrSegment::DeprecatedInterpolated(loc_expr));
|
||||||
|
|
||||||
// Reset the segment
|
// Reset the segment
|
||||||
segment_parsed_bytes = 0;
|
segment_parsed_bytes = 0;
|
||||||
|
@ -437,6 +499,9 @@ pub fn parse_str_like_literal<'a>() -> impl Parser<'a, StrLikeLiteral<'a>, EStri
|
||||||
Some(b'n') => {
|
Some(b'n') => {
|
||||||
escaped_char!(EscapedChar::Newline);
|
escaped_char!(EscapedChar::Newline);
|
||||||
}
|
}
|
||||||
|
Some(b'$') => {
|
||||||
|
escaped_char!(EscapedChar::Dollar);
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// Invalid escape! A backslash must be followed
|
// Invalid escape! A backslash must be followed
|
||||||
// by either an open paren or else one of the
|
// by either an open paren or else one of the
|
||||||
|
|
|
@ -158,9 +158,20 @@ mod test_parse {
|
||||||
|
|
||||||
// INTERPOLATION
|
// INTERPOLATION
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn escaped_interpolation() {
|
||||||
|
assert_segments(r#""Hi, \$(name)!""#, |arena| {
|
||||||
|
bumpalo::vec![in arena;
|
||||||
|
Plaintext("Hi, "),
|
||||||
|
EscapedChar(EscapedChar::Dollar),
|
||||||
|
Plaintext("(name)!"),
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn string_with_interpolation_in_middle() {
|
fn string_with_interpolation_in_middle() {
|
||||||
assert_segments(r#""Hi, \(name)!""#, |arena| {
|
assert_segments(r#""Hi, $(name)!""#, |arena| {
|
||||||
let expr = arena.alloc(Var {
|
let expr = arena.alloc(Var {
|
||||||
module_name: "",
|
module_name: "",
|
||||||
ident: "name",
|
ident: "name",
|
||||||
|
@ -176,7 +187,7 @@ mod test_parse {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn string_with_interpolation_in_front() {
|
fn string_with_interpolation_in_front() {
|
||||||
assert_segments(r#""\(name), hi!""#, |arena| {
|
assert_segments(r#""$(name), hi!""#, |arena| {
|
||||||
let expr = arena.alloc(Var {
|
let expr = arena.alloc(Var {
|
||||||
module_name: "",
|
module_name: "",
|
||||||
ident: "name",
|
ident: "name",
|
||||||
|
@ -191,7 +202,7 @@ mod test_parse {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn string_with_interpolation_in_back() {
|
fn string_with_interpolation_in_back() {
|
||||||
assert_segments(r#""Hello \(name)""#, |arena| {
|
assert_segments(r#""Hello $(name)""#, |arena| {
|
||||||
let expr = arena.alloc(Var {
|
let expr = arena.alloc(Var {
|
||||||
module_name: "",
|
module_name: "",
|
||||||
ident: "name",
|
ident: "name",
|
||||||
|
@ -206,7 +217,7 @@ mod test_parse {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn string_with_multiple_interpolations() {
|
fn string_with_multiple_interpolations() {
|
||||||
assert_segments(r#""Hi, \(name)! How is \(project) going?""#, |arena| {
|
assert_segments(r#""Hi, $(name)! How is $(project) going?""#, |arena| {
|
||||||
let expr1 = arena.alloc(Var {
|
let expr1 = arena.alloc(Var {
|
||||||
module_name: "",
|
module_name: "",
|
||||||
ident: "name",
|
ident: "name",
|
||||||
|
@ -227,6 +238,32 @@ mod test_parse {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn string_with_non_interpolation_dollar_signs() {
|
||||||
|
assert_segments(
|
||||||
|
r#""$a Hi, $(name)! $b How is $(project) going? $c""#,
|
||||||
|
|arena| {
|
||||||
|
let expr1 = arena.alloc(Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "name",
|
||||||
|
});
|
||||||
|
|
||||||
|
let expr2 = arena.alloc(Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "project",
|
||||||
|
});
|
||||||
|
|
||||||
|
bumpalo::vec![in arena;
|
||||||
|
Plaintext("$a Hi, "),
|
||||||
|
Interpolated(Loc::new(10, 14, expr1)),
|
||||||
|
Plaintext("! $b How is "),
|
||||||
|
Interpolated(Loc::new(29, 36, expr2)),
|
||||||
|
Plaintext(" going? $c")
|
||||||
|
]
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn empty_source_file() {
|
fn empty_source_file() {
|
||||||
assert_parsing_fails("", SyntaxError::Eof(Region::zero()));
|
assert_parsing_fails("", SyntaxError::Eof(Region::zero()));
|
||||||
|
@ -272,11 +309,11 @@ mod test_parse {
|
||||||
|
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
foo = \list ->
|
foo = \list ->
|
||||||
isTest = \_ -> 5
|
isTest = \_ -> 5
|
||||||
List.map list isTest
|
List.map list isTest
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
let actual = module_defs()
|
let actual = module_defs()
|
||||||
.parse(&arena, State::new(src.as_bytes()), 0)
|
.parse(&arena, State::new(src.as_bytes()), 0)
|
||||||
|
@ -295,12 +332,12 @@ mod test_parse {
|
||||||
|
|
||||||
// highlights a problem with the else branch demanding a newline after its expression
|
// highlights a problem with the else branch demanding a newline after its expression
|
||||||
let src = indoc!(
|
let src = indoc!(
|
||||||
r#"
|
r"
|
||||||
main =
|
main =
|
||||||
v = \y -> if x then y else z
|
v = \y -> if x then y else z
|
||||||
|
|
||||||
1
|
1
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
|
|
||||||
let state = State::new(src.as_bytes());
|
let state = State::new(src.as_bytes());
|
||||||
|
|
|
@ -540,6 +540,7 @@ pub(crate) fn type_to_var_help(
|
||||||
)
|
)
|
||||||
.expect("extension var could not be seen as a tag union");
|
.expect("extension var could not be seen as a tag union");
|
||||||
|
|
||||||
|
#[allow(clippy::never_loop)]
|
||||||
for _ in it {
|
for _ in it {
|
||||||
unreachable!("we assert that the ext var is empty; otherwise we'd already know it was a tag union!");
|
unreachable!("we assert that the ext var is empty; otherwise we'd already know it was a tag union!");
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
1
crates/compiler/test_gen/.gitignore
vendored
1
crates/compiler/test_gen/.gitignore
vendored
|
@ -1 +0,0 @@
|
||||||
/build
|
|
|
@ -542,7 +542,7 @@ mod encode_immediate {
|
||||||
_ -> "<bad>"
|
_ -> "<bad>"
|
||||||
"#
|
"#
|
||||||
), $num, stringify!($typ)),
|
), $num, stringify!($typ)),
|
||||||
RocStr::from(format!(r#"{}"#, $num).as_str()),
|
RocStr::from(format!(r"{}", $num).as_str()),
|
||||||
RocStr
|
RocStr
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1011,7 +1011,7 @@ fn decode_derive_decoder_for_opaque() {
|
||||||
_ -> "FAIL"
|
_ -> "FAIL"
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
RocStr::from(r#"Hello, World!"#),
|
RocStr::from(r"Hello, World!"),
|
||||||
RocStr
|
RocStr
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1458,7 +1458,7 @@ mod hash {
|
||||||
use indoc::indoc;
|
use indoc::indoc;
|
||||||
|
|
||||||
const TEST_HASHER: &str = indoc!(
|
const TEST_HASHER: &str = indoc!(
|
||||||
r#"
|
r"
|
||||||
THasher := List U8 implements [Hasher {
|
THasher := List U8 implements [Hasher {
|
||||||
addBytes: tAddBytes,
|
addBytes: tAddBytes,
|
||||||
addU8: tAddU8,
|
addU8: tAddU8,
|
||||||
|
@ -1507,7 +1507,7 @@ mod hash {
|
||||||
tComplete = \@THasher _ -> Num.maxU64
|
tComplete = \@THasher _ -> Num.maxU64
|
||||||
|
|
||||||
tRead = \@THasher bytes -> bytes
|
tRead = \@THasher bytes -> bytes
|
||||||
"#
|
"
|
||||||
);
|
);
|
||||||
|
|
||||||
fn build_test(input: &str) -> String {
|
fn build_test(input: &str) -> String {
|
||||||
|
@ -1668,7 +1668,7 @@ mod hash {
|
||||||
#[test]
|
#[test]
|
||||||
fn list_u8() {
|
fn list_u8() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
&build_test(r#"[15u8, 23u8, 37u8]"#),
|
&build_test(r"[15u8, 23u8, 37u8]"),
|
||||||
RocList::from_slice(&[15, 23, 37]),
|
RocList::from_slice(&[15, 23, 37]),
|
||||||
RocList<u8>
|
RocList<u8>
|
||||||
)
|
)
|
||||||
|
@ -1700,7 +1700,7 @@ mod hash {
|
||||||
#[test]
|
#[test]
|
||||||
fn empty_record() {
|
fn empty_record() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
&build_test(r#"{}"#),
|
&build_test(r"{}"),
|
||||||
RocList::from_slice(&[] as &[u8]),
|
RocList::from_slice(&[] as &[u8]),
|
||||||
RocList<u8>
|
RocList<u8>
|
||||||
)
|
)
|
||||||
|
@ -1728,7 +1728,7 @@ mod hash {
|
||||||
fn record_of_list_of_records() {
|
fn record_of_list_of_records() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
&build_test(
|
&build_test(
|
||||||
r#"{ a: [ { b: 15u8 }, { b: 23u8 } ], b: [ { c: 45u8 }, { c: 73u8 } ] }"#
|
r"{ a: [ { b: 15u8 }, { b: 23u8 } ], b: [ { c: 45u8 }, { c: 73u8 } ] }"
|
||||||
),
|
),
|
||||||
RocList::from_slice(&[15, 23, 45, 73]),
|
RocList::from_slice(&[15, 23, 45, 73]),
|
||||||
RocList<u8>
|
RocList<u8>
|
||||||
|
@ -1757,7 +1757,7 @@ mod hash {
|
||||||
fn tuple_of_list_of_tuples() {
|
fn tuple_of_list_of_tuples() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
&build_test(
|
&build_test(
|
||||||
r#"( [ ( 15u8, 32u8 ), ( 23u8, 41u8 ) ], [ (45u8, 63u8), (58u8, 73u8) ] )"#
|
r"( [ ( 15u8, 32u8 ), ( 23u8, 41u8 ) ], [ (45u8, 63u8), (58u8, 73u8) ] )"
|
||||||
),
|
),
|
||||||
RocList::from_slice(&[15, 32, 23, 41, 45, 63, 58, 73]),
|
RocList::from_slice(&[15, 32, 23, 41, 45, 63, 58, 73]),
|
||||||
RocList<u8>
|
RocList<u8>
|
||||||
|
@ -2152,7 +2152,7 @@ fn issue_4772_weakened_monomorphic_destructure() {
|
||||||
with_larger_debug_stack(|| {
|
with_larger_debug_stack(|| {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r###"
|
r#"
|
||||||
app "test"
|
app "test"
|
||||||
imports [TotallyNotJson]
|
imports [TotallyNotJson]
|
||||||
provides [main] to "./platform"
|
provides [main] to "./platform"
|
||||||
|
@ -2173,7 +2173,7 @@ fn issue_4772_weakened_monomorphic_destructure() {
|
||||||
|
|
||||||
main =
|
main =
|
||||||
getNumber |> Result.map .val |> Result.withDefault 0
|
getNumber |> Result.map .val |> Result.withDefault 0
|
||||||
"###
|
"#
|
||||||
),
|
),
|
||||||
1234i64,
|
1234i64,
|
||||||
i64
|
i64
|
||||||
|
@ -2302,7 +2302,7 @@ mod inspect {
|
||||||
main = Inspect.toStr (@Op {})
|
main = Inspect.toStr (@Op {})
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
RocStr::from(r#"<opaque>"#),
|
RocStr::from(r"<opaque>"),
|
||||||
RocStr
|
RocStr
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2322,7 +2322,7 @@ mod inspect {
|
||||||
main = late (@Op {})
|
main = late (@Op {})
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
RocStr::from(r#"<opaque>"#),
|
RocStr::from(r"<opaque>"),
|
||||||
RocStr
|
RocStr
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,11 +19,11 @@ use roc_std::{RocList, RocResult, RocStr};
|
||||||
fn def_closure_in_parens() {
|
fn def_closure_in_parens() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
id = (\x -> x)
|
id = (\x -> x)
|
||||||
|
|
||||||
id 42u32
|
id 42u32
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
42,
|
42,
|
||||||
u32
|
u32
|
||||||
|
@ -35,11 +35,11 @@ fn def_closure_in_parens() {
|
||||||
fn def_closure_in_multiple_parens() {
|
fn def_closure_in_multiple_parens() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
id = (((\x -> x)))
|
id = (((\x -> x)))
|
||||||
|
|
||||||
id 42u32
|
id 42u32
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
42,
|
42,
|
||||||
u32
|
u32
|
||||||
|
|
|
@ -20,9 +20,9 @@ use roc_std::{RocList, RocStr};
|
||||||
fn dict_empty_len() {
|
fn dict_empty_len() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Dict.len (Dict.empty {})
|
Dict.len (Dict.empty {})
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
0,
|
0,
|
||||||
usize
|
usize
|
||||||
|
@ -34,11 +34,11 @@ fn dict_empty_len() {
|
||||||
fn dict_insert_empty() {
|
fn dict_insert_empty() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Dict.empty {}
|
Dict.empty {}
|
||||||
|> Dict.insert 42 32
|
|> Dict.insert 42 32
|
||||||
|> Dict.len
|
|> Dict.len
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
1,
|
1,
|
||||||
usize
|
usize
|
||||||
|
@ -50,12 +50,12 @@ fn dict_insert_empty() {
|
||||||
fn dict_empty_contains() {
|
fn dict_empty_contains() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
empty : Dict.Dict I64 F64
|
empty : Dict.Dict I64 F64
|
||||||
empty = Dict.empty {}
|
empty = Dict.empty {}
|
||||||
|
|
||||||
Dict.contains empty 42
|
Dict.contains empty 42
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
false,
|
false,
|
||||||
bool
|
bool
|
||||||
|
@ -67,12 +67,12 @@ fn dict_empty_contains() {
|
||||||
fn dict_nonempty_contains() {
|
fn dict_nonempty_contains() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
empty : Dict.Dict I64 F64
|
empty : Dict.Dict I64 F64
|
||||||
empty = Dict.insert (Dict.empty {}) 42 1.23
|
empty = Dict.insert (Dict.empty {}) 42 1.23
|
||||||
|
|
||||||
Dict.contains empty 42
|
Dict.contains empty 42
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
true,
|
true,
|
||||||
bool
|
bool
|
||||||
|
@ -85,14 +85,14 @@ fn dict_nonempty_contains() {
|
||||||
fn dict_empty_remove() {
|
fn dict_empty_remove() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
empty : Dict.Dict I64 F64
|
empty : Dict.Dict I64 F64
|
||||||
empty = Dict.empty {}
|
empty = Dict.empty {}
|
||||||
|
|
||||||
empty
|
empty
|
||||||
|> Dict.remove 42
|
|> Dict.remove 42
|
||||||
|> Dict.len
|
|> Dict.len
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
0,
|
0,
|
||||||
i64
|
i64
|
||||||
|
@ -104,7 +104,7 @@ fn dict_empty_remove() {
|
||||||
fn dict_nonempty_remove() {
|
fn dict_nonempty_remove() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
empty : Dict.Dict I64 F64
|
empty : Dict.Dict I64 F64
|
||||||
empty = Dict.insert (Dict.empty {}) 42 1.23
|
empty = Dict.insert (Dict.empty {}) 42 1.23
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ fn dict_nonempty_remove() {
|
||||||
|> Dict.remove 42
|
|> Dict.remove 42
|
||||||
|> Dict.len
|
|> Dict.len
|
||||||
|> Num.toI64
|
|> Num.toI64
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
0,
|
0,
|
||||||
i64
|
i64
|
||||||
|
@ -124,7 +124,7 @@ fn dict_nonempty_remove() {
|
||||||
fn dict_nonempty_get() {
|
fn dict_nonempty_get() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
empty : Dict.Dict I64 F64
|
empty : Dict.Dict I64 F64
|
||||||
empty = Dict.insert (Dict.empty {}) 42 1.23
|
empty = Dict.insert (Dict.empty {}) 42 1.23
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ fn dict_nonempty_get() {
|
||||||
|> Dict.insert 42 1.23f64
|
|> Dict.insert 42 1.23f64
|
||||||
|> Dict.get 42
|
|> Dict.get 42
|
||||||
|> withDefault 0
|
|> withDefault 0
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
1.23,
|
1.23,
|
||||||
f64
|
f64
|
||||||
|
@ -145,7 +145,7 @@ fn dict_nonempty_get() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
withDefault = \x, def ->
|
withDefault = \x, def ->
|
||||||
when x is
|
when x is
|
||||||
Ok v -> v
|
Ok v -> v
|
||||||
|
@ -155,7 +155,7 @@ fn dict_nonempty_get() {
|
||||||
|> Dict.insert 42 1.23f64
|
|> Dict.insert 42 1.23f64
|
||||||
|> Dict.get 43
|
|> Dict.get 43
|
||||||
|> withDefault 0
|
|> withDefault 0
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
0.0,
|
0.0,
|
||||||
f64
|
f64
|
||||||
|
@ -167,7 +167,7 @@ fn dict_nonempty_get() {
|
||||||
fn keys() {
|
fn keys() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
myDict : Dict.Dict I64 I64
|
myDict : Dict.Dict I64 I64
|
||||||
myDict =
|
myDict =
|
||||||
Dict.empty {}
|
Dict.empty {}
|
||||||
|
@ -177,7 +177,7 @@ fn keys() {
|
||||||
|
|
||||||
|
|
||||||
Dict.keys myDict
|
Dict.keys myDict
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
RocList::from_slice(&[0, 1, 2]),
|
RocList::from_slice(&[0, 1, 2]),
|
||||||
RocList<i64>
|
RocList<i64>
|
||||||
|
@ -189,7 +189,7 @@ fn keys() {
|
||||||
fn values() {
|
fn values() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
myDict : Dict.Dict I64 I64
|
myDict : Dict.Dict I64 I64
|
||||||
myDict =
|
myDict =
|
||||||
Dict.empty {}
|
Dict.empty {}
|
||||||
|
@ -199,7 +199,7 @@ fn values() {
|
||||||
|
|
||||||
|
|
||||||
Dict.values myDict
|
Dict.values myDict
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
RocList::from_slice(&[100, 200, 300]),
|
RocList::from_slice(&[100, 200, 300]),
|
||||||
RocList<i64>
|
RocList<i64>
|
||||||
|
@ -211,14 +211,14 @@ fn values() {
|
||||||
fn from_list_with_fold_simple() {
|
fn from_list_with_fold_simple() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
myDict : Dict.Dict I64 I64
|
myDict : Dict.Dict I64 I64
|
||||||
myDict =
|
myDict =
|
||||||
[1,2,3]
|
[1,2,3]
|
||||||
|> List.walk (Dict.empty {}) (\accum, value -> Dict.insert accum value value)
|
|> List.walk (Dict.empty {}) (\accum, value -> Dict.insert accum value value)
|
||||||
|
|
||||||
Dict.values myDict
|
Dict.values myDict
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
RocList::from_slice(&[1, 2, 3]),
|
RocList::from_slice(&[1, 2, 3]),
|
||||||
RocList<i64>
|
RocList<i64>
|
||||||
|
@ -230,7 +230,7 @@ fn from_list_with_fold_simple() {
|
||||||
fn from_list_with_fold_reallocates() {
|
fn from_list_with_fold_reallocates() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
range : I64, I64, List I64-> List I64
|
range : I64, I64, List I64-> List I64
|
||||||
range = \low, high, accum ->
|
range = \low, high, accum ->
|
||||||
if low < high then
|
if low < high then
|
||||||
|
@ -245,7 +245,7 @@ fn from_list_with_fold_reallocates() {
|
||||||
|> List.walk (Dict.empty {}) (\accum, value -> Dict.insert accum value value)
|
|> List.walk (Dict.empty {}) (\accum, value -> Dict.insert accum value value)
|
||||||
|
|
||||||
Dict.values myDict
|
Dict.values myDict
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
RocList::from_slice(&[
|
RocList::from_slice(&[
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
|
||||||
|
@ -329,7 +329,7 @@ fn big_str_values() {
|
||||||
fn unit_values() {
|
fn unit_values() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
myDict : Dict.Dict I64 {}
|
myDict : Dict.Dict I64 {}
|
||||||
myDict =
|
myDict =
|
||||||
Dict.empty {}
|
Dict.empty {}
|
||||||
|
@ -339,7 +339,7 @@ fn unit_values() {
|
||||||
|> Dict.insert 3 {}
|
|> Dict.insert 3 {}
|
||||||
|
|
||||||
Num.toI64 (Dict.len myDict)
|
Num.toI64 (Dict.len myDict)
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
4,
|
4,
|
||||||
i64
|
i64
|
||||||
|
@ -351,13 +351,13 @@ fn unit_values() {
|
||||||
fn single() {
|
fn single() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
myDict : Dict.Dict I64 {}
|
myDict : Dict.Dict I64 {}
|
||||||
myDict =
|
myDict =
|
||||||
Dict.single 12345 {}
|
Dict.single 12345 {}
|
||||||
|
|
||||||
Num.toI64 (Dict.len myDict)
|
Num.toI64 (Dict.len myDict)
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
1,
|
1,
|
||||||
i64
|
i64
|
||||||
|
@ -369,14 +369,14 @@ fn single() {
|
||||||
fn insert_all() {
|
fn insert_all() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
myDict : Dict I64 {}
|
myDict : Dict I64 {}
|
||||||
myDict =
|
myDict =
|
||||||
Dict.insertAll (Dict.single 0 {}) (Dict.single 1 {})
|
Dict.insertAll (Dict.single 0 {}) (Dict.single 1 {})
|
||||||
|
|
||||||
Dict.len myDict
|
Dict.len myDict
|
||||||
|> Num.toI64
|
|> Num.toI64
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
2,
|
2,
|
||||||
i64
|
i64
|
||||||
|
@ -388,14 +388,14 @@ fn insert_all() {
|
||||||
fn insert_all_prefer_second() {
|
fn insert_all_prefer_second() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
myDict : Dict.Dict I64 I64
|
myDict : Dict.Dict I64 I64
|
||||||
myDict =
|
myDict =
|
||||||
(Dict.single 0 100)
|
(Dict.single 0 100)
|
||||||
|> Dict.insertAll (Dict.single 0 200)
|
|> Dict.insertAll (Dict.single 0 200)
|
||||||
|
|
||||||
Dict.values myDict
|
Dict.values myDict
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
RocList::from_slice(&[200]),
|
RocList::from_slice(&[200]),
|
||||||
RocList<i64>
|
RocList<i64>
|
||||||
|
@ -407,7 +407,7 @@ fn insert_all_prefer_second() {
|
||||||
fn keep_shared() {
|
fn keep_shared() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
dict1 : Dict.Dict I64 {}
|
dict1 : Dict.Dict I64 {}
|
||||||
dict1 =
|
dict1 =
|
||||||
Dict.empty {}
|
Dict.empty {}
|
||||||
|
@ -427,7 +427,7 @@ fn keep_shared() {
|
||||||
Dict.keepShared dict1 dict2
|
Dict.keepShared dict1 dict2
|
||||||
|> Dict.len
|
|> Dict.len
|
||||||
|> Num.toI64
|
|> Num.toI64
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
2,
|
2,
|
||||||
i64
|
i64
|
||||||
|
@ -439,7 +439,7 @@ fn keep_shared() {
|
||||||
fn keep_shared_value_must_match() {
|
fn keep_shared_value_must_match() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
dict1 : Dict.Dict I64 I64
|
dict1 : Dict.Dict I64 I64
|
||||||
dict1 =
|
dict1 =
|
||||||
Dict.empty {}
|
Dict.empty {}
|
||||||
|
@ -458,7 +458,7 @@ fn keep_shared_value_must_match() {
|
||||||
|
|
||||||
Dict.keepShared dict1 dict2
|
Dict.keepShared dict1 dict2
|
||||||
|> Dict.values
|
|> Dict.values
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
RocList::from_slice(&[2]),
|
RocList::from_slice(&[2]),
|
||||||
RocList<i64>
|
RocList<i64>
|
||||||
|
@ -470,7 +470,7 @@ fn keep_shared_value_must_match() {
|
||||||
fn remove_all() {
|
fn remove_all() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
dict1 : Dict.Dict I64 {}
|
dict1 : Dict.Dict I64 {}
|
||||||
dict1 =
|
dict1 =
|
||||||
Dict.empty {}
|
Dict.empty {}
|
||||||
|
@ -490,7 +490,7 @@ fn remove_all() {
|
||||||
Dict.removeAll dict1 dict2
|
Dict.removeAll dict1 dict2
|
||||||
|> Dict.len
|
|> Dict.len
|
||||||
|> Num.toI64
|
|> Num.toI64
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
3,
|
3,
|
||||||
i64
|
i64
|
||||||
|
@ -502,7 +502,7 @@ fn remove_all() {
|
||||||
fn remove_all_prefer_first() {
|
fn remove_all_prefer_first() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
dict1 : Dict.Dict I64 I64
|
dict1 : Dict.Dict I64 I64
|
||||||
dict1 =
|
dict1 =
|
||||||
Dict.empty {}
|
Dict.empty {}
|
||||||
|
@ -521,7 +521,7 @@ fn remove_all_prefer_first() {
|
||||||
|
|
||||||
Dict.removeAll dict1 dict2
|
Dict.removeAll dict1 dict2
|
||||||
|> Dict.values
|
|> Dict.values
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
RocList::from_slice(&[1, 5, 3]),
|
RocList::from_slice(&[1, 5, 3]),
|
||||||
RocList<i64>
|
RocList<i64>
|
||||||
|
@ -533,7 +533,7 @@ fn remove_all_prefer_first() {
|
||||||
fn walk_sum_keys() {
|
fn walk_sum_keys() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
dict1 : Dict.Dict I64 I64
|
dict1 : Dict.Dict I64 I64
|
||||||
dict1 =
|
dict1 =
|
||||||
Dict.empty {}
|
Dict.empty {}
|
||||||
|
@ -544,7 +544,7 @@ fn walk_sum_keys() {
|
||||||
|> Dict.insert 5 5
|
|> Dict.insert 5 5
|
||||||
|
|
||||||
Dict.walk dict1 0 \k, _, a -> k + a
|
Dict.walk dict1 0 \k, _, a -> k + a
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
15,
|
15,
|
||||||
i64
|
i64
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -28,11 +28,11 @@ fn basic_float() {
|
||||||
fn branch_first_float() {
|
fn branch_first_float() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
when 1.23f64 is
|
when 1.23f64 is
|
||||||
1.23 -> 12
|
1.23 -> 12
|
||||||
_ -> 34
|
_ -> 34
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
12,
|
12,
|
||||||
i64
|
i64
|
||||||
|
@ -44,11 +44,11 @@ fn branch_first_float() {
|
||||||
fn branch_second_float() {
|
fn branch_second_float() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
when 2.34 is
|
when 2.34 is
|
||||||
1.23 -> 63
|
1.23 -> 63
|
||||||
_ -> 48
|
_ -> 48
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
48,
|
48,
|
||||||
i64
|
i64
|
||||||
|
@ -60,12 +60,12 @@ fn branch_second_float() {
|
||||||
fn branch_third_float() {
|
fn branch_third_float() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
when 10.0 is
|
when 10.0 is
|
||||||
1.0 -> 63
|
1.0 -> 63
|
||||||
2.0 -> 48
|
2.0 -> 48
|
||||||
_ -> 112
|
_ -> 112
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
112,
|
112,
|
||||||
i64
|
i64
|
||||||
|
@ -77,11 +77,11 @@ fn branch_third_float() {
|
||||||
fn branch_first_int() {
|
fn branch_first_int() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
when 1 is
|
when 1 is
|
||||||
1 -> 12
|
1 -> 12
|
||||||
_ -> 34
|
_ -> 34
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
12,
|
12,
|
||||||
i64
|
i64
|
||||||
|
@ -93,11 +93,11 @@ fn branch_first_int() {
|
||||||
fn branch_second_int() {
|
fn branch_second_int() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
when 2 is
|
when 2 is
|
||||||
1 -> 63
|
1 -> 63
|
||||||
_ -> 48
|
_ -> 48
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
48,
|
48,
|
||||||
i64
|
i64
|
||||||
|
@ -109,12 +109,12 @@ fn branch_second_int() {
|
||||||
fn branch_third_int() {
|
fn branch_third_int() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
when 10 is
|
when 10 is
|
||||||
1 -> 63
|
1 -> 63
|
||||||
2 -> 48
|
2 -> 48
|
||||||
_ -> 112
|
_ -> 112
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
112,
|
112,
|
||||||
i64
|
i64
|
||||||
|
@ -126,11 +126,11 @@ fn branch_third_int() {
|
||||||
fn branch_store_variable() {
|
fn branch_store_variable() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
when 0 is
|
when 0 is
|
||||||
1 -> 12
|
1 -> 12
|
||||||
a -> a
|
a -> a
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
0,
|
0,
|
||||||
i64
|
i64
|
||||||
|
@ -142,13 +142,13 @@ fn branch_store_variable() {
|
||||||
fn when_one_element_tag() {
|
fn when_one_element_tag() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
x : [Pair (Int a) (Int a)]
|
x : [Pair (Int a) (Int a)]
|
||||||
x = Pair 0x2 0x3
|
x = Pair 0x2 0x3
|
||||||
|
|
||||||
when x is
|
when x is
|
||||||
Pair l r -> l + r
|
Pair l r -> l + r
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
5,
|
5,
|
||||||
i64
|
i64
|
||||||
|
@ -160,14 +160,14 @@ fn when_one_element_tag() {
|
||||||
fn when_two_element_tag_first() {
|
fn when_two_element_tag_first() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
x : [A (Int a), B (Int a)]
|
x : [A (Int a), B (Int a)]
|
||||||
x = A 0x2
|
x = A 0x2
|
||||||
|
|
||||||
when x is
|
when x is
|
||||||
A v -> v
|
A v -> v
|
||||||
B v -> v
|
B v -> v
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
2,
|
2,
|
||||||
i64
|
i64
|
||||||
|
@ -179,14 +179,14 @@ fn when_two_element_tag_first() {
|
||||||
fn when_two_element_tag_second() {
|
fn when_two_element_tag_second() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
x : [A (Int a), B (Int a)]
|
x : [A (Int a), B (Int a)]
|
||||||
x = B 0x3
|
x = B 0x3
|
||||||
|
|
||||||
when x is
|
when x is
|
||||||
A v -> v
|
A v -> v
|
||||||
B v -> v
|
B v -> v
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
3,
|
3,
|
||||||
i64
|
i64
|
||||||
|
@ -198,10 +198,10 @@ fn when_two_element_tag_second() {
|
||||||
fn gen_when_one_branch() {
|
fn gen_when_one_branch() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
when 1.23 is
|
when 1.23 is
|
||||||
_ -> 23
|
_ -> 23
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
23,
|
23,
|
||||||
i64
|
i64
|
||||||
|
@ -213,7 +213,7 @@ fn gen_when_one_branch() {
|
||||||
fn gen_large_when_int() {
|
fn gen_large_when_int() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
foo = \num ->
|
foo = \num ->
|
||||||
when num is
|
when num is
|
||||||
0 -> 200
|
0 -> 200
|
||||||
|
@ -224,7 +224,7 @@ fn gen_large_when_int() {
|
||||||
_ -> 1000
|
_ -> 1000
|
||||||
|
|
||||||
foo -3
|
foo -3
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
111,
|
111,
|
||||||
i64
|
i64
|
||||||
|
@ -236,7 +236,7 @@ fn gen_large_when_int() {
|
||||||
fn gen_large_when_float() {
|
fn gen_large_when_float() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
foo = \num ->
|
foo = \num ->
|
||||||
when num is
|
when num is
|
||||||
0.5f64 -> 200.1
|
0.5f64 -> 200.1
|
||||||
|
@ -247,7 +247,7 @@ fn gen_large_when_float() {
|
||||||
_ -> 1000.6f64
|
_ -> 1000.6f64
|
||||||
|
|
||||||
foo -3.6
|
foo -3.6
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
111.2,
|
111.2,
|
||||||
f64
|
f64
|
||||||
|
@ -259,11 +259,11 @@ fn gen_large_when_float() {
|
||||||
fn or_pattern() {
|
fn or_pattern() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
when 2 is
|
when 2 is
|
||||||
1 | 2 -> 42
|
1 | 2 -> 42
|
||||||
_ -> 1
|
_ -> 1
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
42,
|
42,
|
||||||
i64
|
i64
|
||||||
|
@ -275,11 +275,11 @@ fn or_pattern() {
|
||||||
fn apply_identity() {
|
fn apply_identity() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
identity = \a -> a
|
identity = \a -> a
|
||||||
|
|
||||||
identity 5
|
identity 5
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
5,
|
5,
|
||||||
i64
|
i64
|
||||||
|
@ -291,12 +291,12 @@ fn apply_identity() {
|
||||||
fn apply_unnamed_identity() {
|
fn apply_unnamed_identity() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
wrapper = \{} ->
|
wrapper = \{} ->
|
||||||
(\a -> a) 5
|
(\a -> a) 5
|
||||||
|
|
||||||
wrapper {}
|
wrapper {}
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
5,
|
5,
|
||||||
i64
|
i64
|
||||||
|
@ -308,7 +308,7 @@ fn apply_unnamed_identity() {
|
||||||
fn return_unnamed_fn() {
|
fn return_unnamed_fn() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
wrapper = \{} ->
|
wrapper = \{} ->
|
||||||
alwaysFloatIdentity : Int * -> (Frac a -> Frac a)
|
alwaysFloatIdentity : Int * -> (Frac a -> Frac a)
|
||||||
alwaysFloatIdentity = \_ ->
|
alwaysFloatIdentity = \_ ->
|
||||||
|
@ -317,7 +317,7 @@ fn return_unnamed_fn() {
|
||||||
(alwaysFloatIdentity 2) 1.23f64
|
(alwaysFloatIdentity 2) 1.23f64
|
||||||
|
|
||||||
wrapper {}
|
wrapper {}
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
1.23,
|
1.23,
|
||||||
f64
|
f64
|
||||||
|
@ -329,7 +329,7 @@ fn return_unnamed_fn() {
|
||||||
fn gen_when_fn() {
|
fn gen_when_fn() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
limitedNegate = \num ->
|
limitedNegate = \num ->
|
||||||
when num is
|
when num is
|
||||||
1 -> -1
|
1 -> -1
|
||||||
|
@ -337,7 +337,7 @@ fn gen_when_fn() {
|
||||||
_ -> num
|
_ -> num
|
||||||
|
|
||||||
limitedNegate 1
|
limitedNegate 1
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
-1,
|
-1,
|
||||||
i64
|
i64
|
||||||
|
@ -349,11 +349,11 @@ fn gen_when_fn() {
|
||||||
fn gen_basic_def() {
|
fn gen_basic_def() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
answer = 42
|
answer = 42
|
||||||
|
|
||||||
answer
|
answer
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
42,
|
42,
|
||||||
i64
|
i64
|
||||||
|
@ -361,11 +361,11 @@ fn gen_basic_def() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
float = 1.23f64
|
float = 1.23f64
|
||||||
|
|
||||||
float
|
float
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
1.23,
|
1.23,
|
||||||
f64
|
f64
|
||||||
|
@ -377,13 +377,13 @@ fn gen_basic_def() {
|
||||||
fn gen_multiple_defs() {
|
fn gen_multiple_defs() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
answer = 42
|
answer = 42
|
||||||
|
|
||||||
float = 1.23f64
|
float = 1.23f64
|
||||||
|
|
||||||
if float > 3 then answer else answer
|
if float > 3 then answer else answer
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
42,
|
42,
|
||||||
i64
|
i64
|
||||||
|
@ -391,13 +391,13 @@ fn gen_multiple_defs() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
answer = 42
|
answer = 42
|
||||||
|
|
||||||
float = 1.23f64
|
float = 1.23f64
|
||||||
|
|
||||||
if answer > 3 then float else float
|
if answer > 3 then float else float
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
1.23,
|
1.23,
|
||||||
f64
|
f64
|
||||||
|
@ -411,7 +411,7 @@ fn gen_multiple_defs() {
|
||||||
// fn gen_chained_defs() {
|
// fn gen_chained_defs() {
|
||||||
// assert_evals_to!(
|
// assert_evals_to!(
|
||||||
// indoc!(
|
// indoc!(
|
||||||
// r#"
|
// r"
|
||||||
// x = i1
|
// x = i1
|
||||||
// i3 = i2
|
// i3 = i2
|
||||||
// i1 = 1337
|
// i1 = 1337
|
||||||
|
@ -419,7 +419,7 @@ fn gen_multiple_defs() {
|
||||||
// y = 12.4
|
// y = 12.4
|
||||||
//
|
//
|
||||||
// i3
|
// i3
|
||||||
// "#
|
// "
|
||||||
// ),
|
// ),
|
||||||
// 1337,
|
// 1337,
|
||||||
// i64
|
// i64
|
||||||
|
@ -431,7 +431,7 @@ fn gen_multiple_defs() {
|
||||||
// fn gen_nested_defs_old() {
|
// fn gen_nested_defs_old() {
|
||||||
// assert_evals_to!(
|
// assert_evals_to!(
|
||||||
// indoc!(
|
// indoc!(
|
||||||
// r#"
|
// r"
|
||||||
// x = 5
|
// x = 5
|
||||||
//
|
//
|
||||||
// answer =
|
// answer =
|
||||||
|
@ -461,7 +461,7 @@ fn gen_multiple_defs() {
|
||||||
// y = 12.4
|
// y = 12.4
|
||||||
//
|
//
|
||||||
// answer
|
// answer
|
||||||
// "#
|
// "
|
||||||
// ),
|
// ),
|
||||||
// 1337,
|
// 1337,
|
||||||
// i64
|
// i64
|
||||||
|
@ -473,7 +473,7 @@ fn gen_multiple_defs() {
|
||||||
// fn let_x_in_x() {
|
// fn let_x_in_x() {
|
||||||
// assert_evals_to!(
|
// assert_evals_to!(
|
||||||
// indoc!(
|
// indoc!(
|
||||||
// r#"
|
// r"
|
||||||
// x = 5
|
// x = 5
|
||||||
//
|
//
|
||||||
// answer =
|
// answer =
|
||||||
|
@ -484,7 +484,7 @@ fn gen_multiple_defs() {
|
||||||
// nested
|
// nested
|
||||||
//
|
//
|
||||||
// answer
|
// answer
|
||||||
// "#
|
// "
|
||||||
// ),
|
// ),
|
||||||
// 1337,
|
// 1337,
|
||||||
// i64
|
// i64
|
||||||
|
@ -496,7 +496,7 @@ fn gen_multiple_defs() {
|
||||||
fn factorial() {
|
fn factorial() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
factorial = \n, accum ->
|
factorial = \n, accum ->
|
||||||
when n is
|
when n is
|
||||||
0 ->
|
0 ->
|
||||||
|
@ -506,7 +506,7 @@ fn factorial() {
|
||||||
factorial (n - 1) (n * accum)
|
factorial (n - 1) (n * accum)
|
||||||
|
|
||||||
factorial 10 1
|
factorial 10 1
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
3628800,
|
3628800,
|
||||||
i64
|
i64
|
||||||
|
@ -518,7 +518,7 @@ fn factorial() {
|
||||||
fn peano1() {
|
fn peano1() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Peano : [S Peano, Z]
|
Peano : [S Peano, Z]
|
||||||
|
|
||||||
three : Peano
|
three : Peano
|
||||||
|
@ -527,7 +527,7 @@ fn peano1() {
|
||||||
when three is
|
when three is
|
||||||
Z -> 2
|
Z -> 2
|
||||||
S _ -> 1
|
S _ -> 1
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
1,
|
1,
|
||||||
i64
|
i64
|
||||||
|
@ -539,7 +539,7 @@ fn peano1() {
|
||||||
fn peano2() {
|
fn peano2() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Peano : [S Peano, Z]
|
Peano : [S Peano, Z]
|
||||||
|
|
||||||
three : Peano
|
three : Peano
|
||||||
|
@ -549,7 +549,7 @@ fn peano2() {
|
||||||
S (S _) -> 1
|
S (S _) -> 1
|
||||||
S (_) -> 0
|
S (_) -> 0
|
||||||
Z -> 0
|
Z -> 0
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
1,
|
1,
|
||||||
i64
|
i64
|
||||||
|
@ -833,7 +833,7 @@ fn linked_list_map() {
|
||||||
fn when_nested_maybe() {
|
fn when_nested_maybe() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Maybe a : [Nothing, Just a]
|
Maybe a : [Nothing, Just a]
|
||||||
|
|
||||||
x : Maybe (Maybe (Int a))
|
x : Maybe (Maybe (Int a))
|
||||||
|
@ -842,7 +842,7 @@ fn when_nested_maybe() {
|
||||||
when x is
|
when x is
|
||||||
Just (Just v) -> v + 0x1
|
Just (Just v) -> v + 0x1
|
||||||
_ -> 0x1
|
_ -> 0x1
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
42,
|
42,
|
||||||
i64
|
i64
|
||||||
|
@ -850,7 +850,7 @@ fn when_nested_maybe() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Maybe a : [Nothing, Just a]
|
Maybe a : [Nothing, Just a]
|
||||||
|
|
||||||
x : Maybe (Maybe (Int *))
|
x : Maybe (Maybe (Int *))
|
||||||
|
@ -860,7 +860,7 @@ fn when_nested_maybe() {
|
||||||
Just (Just v) -> v + 0x1
|
Just (Just v) -> v + 0x1
|
||||||
Just Nothing -> 0x2
|
Just Nothing -> 0x2
|
||||||
Nothing -> 0x1
|
Nothing -> 0x1
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
2,
|
2,
|
||||||
i64
|
i64
|
||||||
|
@ -868,7 +868,7 @@ fn when_nested_maybe() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Maybe a : [Nothing, Just a]
|
Maybe a : [Nothing, Just a]
|
||||||
|
|
||||||
x : Maybe (Maybe (Int *))
|
x : Maybe (Maybe (Int *))
|
||||||
|
@ -878,7 +878,7 @@ fn when_nested_maybe() {
|
||||||
Just (Just v) -> v + 0x1
|
Just (Just v) -> v + 0x1
|
||||||
Just Nothing -> 0x2
|
Just Nothing -> 0x2
|
||||||
Nothing -> 0x1
|
Nothing -> 0x1
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
1,
|
1,
|
||||||
i64
|
i64
|
||||||
|
@ -890,7 +890,7 @@ fn when_nested_maybe() {
|
||||||
fn when_peano() {
|
fn when_peano() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Peano : [S Peano, Z]
|
Peano : [S Peano, Z]
|
||||||
|
|
||||||
three : Peano
|
three : Peano
|
||||||
|
@ -900,7 +900,7 @@ fn when_peano() {
|
||||||
S (S _) -> 1
|
S (S _) -> 1
|
||||||
S (_) -> 2
|
S (_) -> 2
|
||||||
Z -> 3
|
Z -> 3
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
1,
|
1,
|
||||||
i64
|
i64
|
||||||
|
@ -908,7 +908,7 @@ fn when_peano() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Peano : [S Peano, Z]
|
Peano : [S Peano, Z]
|
||||||
|
|
||||||
three : Peano
|
three : Peano
|
||||||
|
@ -918,7 +918,7 @@ fn when_peano() {
|
||||||
S (S _) -> 1
|
S (S _) -> 1
|
||||||
S (_) -> 2
|
S (_) -> 2
|
||||||
Z -> 3
|
Z -> 3
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
2,
|
2,
|
||||||
i64
|
i64
|
||||||
|
@ -926,7 +926,7 @@ fn when_peano() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Peano : [S Peano, Z]
|
Peano : [S Peano, Z]
|
||||||
|
|
||||||
three : Peano
|
three : Peano
|
||||||
|
@ -936,7 +936,7 @@ fn when_peano() {
|
||||||
S (S _) -> 1
|
S (S _) -> 1
|
||||||
S (_) -> 2
|
S (_) -> 2
|
||||||
Z -> 3
|
Z -> 3
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
3,
|
3,
|
||||||
i64
|
i64
|
||||||
|
@ -955,7 +955,7 @@ fn when_peano() {
|
||||||
fn overflow_frees_list() {
|
fn overflow_frees_list() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
myList = [1,2,3]
|
myList = [1,2,3]
|
||||||
|
|
||||||
# integer overflow; must use the list so it is defined before the overflow
|
# integer overflow; must use the list so it is defined before the overflow
|
||||||
|
@ -967,7 +967,7 @@ fn overflow_frees_list() {
|
||||||
index = Num.intCast n
|
index = Num.intCast n
|
||||||
|
|
||||||
List.get myList index
|
List.get myList index
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(3, 0),
|
(3, 0),
|
||||||
(i64, i8)
|
(i64, i8)
|
||||||
|
@ -980,12 +980,12 @@ fn overflow_frees_list() {
|
||||||
fn undefined_variable() {
|
fn undefined_variable() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
if Bool.true then
|
if Bool.true then
|
||||||
x + z
|
x + z
|
||||||
else
|
else
|
||||||
y + z
|
y + z
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
3,
|
3,
|
||||||
i64
|
i64
|
||||||
|
@ -1016,12 +1016,12 @@ fn a_crash() {
|
||||||
fn annotation_without_body() {
|
fn annotation_without_body() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
foo : Int *
|
foo : Int *
|
||||||
|
|
||||||
|
|
||||||
foo
|
foo
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
3,
|
3,
|
||||||
i64
|
i64
|
||||||
|
@ -2022,11 +2022,11 @@ fn hof_conditional() {
|
||||||
// exposed issue with the if condition being just a symbol
|
// exposed issue with the if condition being just a symbol
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
passTrue = \f -> f Bool.true
|
passTrue = \f -> f Bool.true
|
||||||
|
|
||||||
passTrue (\trueVal -> if trueVal then Bool.false else Bool.true)
|
passTrue (\trueVal -> if trueVal then Bool.false else Bool.true)
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
0,
|
0,
|
||||||
u8
|
u8
|
||||||
|
@ -2041,12 +2041,12 @@ fn hof_conditional() {
|
||||||
fn pattern_shadowing() {
|
fn pattern_shadowing() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
x = 4
|
x = 4
|
||||||
|
|
||||||
when 4 is
|
when 4 is
|
||||||
x -> x
|
x -> x
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
0,
|
0,
|
||||||
i64
|
i64
|
||||||
|
@ -2060,11 +2060,11 @@ fn pattern_shadowing() {
|
||||||
fn unsupported_pattern_str_interp() {
|
fn unsupported_pattern_str_interp() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
{ x: 4 } = { x : 4 }
|
{ x: 4 } = { x : 4 }
|
||||||
|
|
||||||
x
|
x
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
0,
|
0,
|
||||||
i64
|
i64
|
||||||
|
@ -2120,14 +2120,14 @@ fn case_or_pattern() {
|
||||||
// it is currently duplicated
|
// it is currently duplicated
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
x : [Red, Green, Blue]
|
x : [Red, Green, Blue]
|
||||||
x = Red
|
x = Red
|
||||||
|
|
||||||
when x is
|
when x is
|
||||||
Red | Green -> 0
|
Red | Green -> 0
|
||||||
Blue -> 1
|
Blue -> 1
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
0,
|
0,
|
||||||
i64
|
i64
|
||||||
|
@ -2517,11 +2517,11 @@ fn backpassing_result() {
|
||||||
fn function_malformed_pattern() {
|
fn function_malformed_pattern() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
x = 3
|
x = 3
|
||||||
|
|
||||||
(\x -> x) 42
|
(\x -> x) 42
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
3,
|
3,
|
||||||
i64
|
i64
|
||||||
|
@ -2534,12 +2534,12 @@ fn function_malformed_pattern() {
|
||||||
fn call_invalid_layout() {
|
fn call_invalid_layout() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
f : I64 -> I64
|
f : I64 -> I64
|
||||||
f = \x -> x
|
f = \x -> x
|
||||||
|
|
||||||
f {}
|
f {}
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
3,
|
3,
|
||||||
i64,
|
i64,
|
||||||
|
@ -3261,12 +3261,12 @@ fn polymophic_expression_captured_inside_closure() {
|
||||||
fn issue_2322() {
|
fn issue_2322() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
double = \x -> x * 2
|
double = \x -> x * 2
|
||||||
doubleBind = \x -> (\_ -> double x)
|
doubleBind = \x -> (\_ -> double x)
|
||||||
doubleThree = doubleBind 3
|
doubleThree = doubleBind 3
|
||||||
doubleThree {}
|
doubleThree {}
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
6,
|
6,
|
||||||
i64
|
i64
|
||||||
|
@ -3312,14 +3312,14 @@ fn box_and_unbox_big_string() {
|
||||||
fn box_and_unbox_nonrecursive_tag() {
|
fn box_and_unbox_nonrecursive_tag() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
result : Result U64 U64
|
result : Result U64 U64
|
||||||
result = Ok 42
|
result = Ok 42
|
||||||
|
|
||||||
result
|
result
|
||||||
|> Box.box
|
|> Box.box
|
||||||
|> Box.unbox
|
|> Box.unbox
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
roc_std::RocResult::ok(42),
|
roc_std::RocResult::ok(42),
|
||||||
roc_std::RocResult<u64, u64>
|
roc_std::RocResult<u64, u64>
|
||||||
|
@ -3409,9 +3409,9 @@ fn box_and_unbox_f32() {
|
||||||
fn box_and_unbox_record_2_u64() {
|
fn box_and_unbox_record_2_u64() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Box.unbox (Box.box { a: 15u64, b: 27u64 })
|
Box.unbox (Box.box { a: 15u64, b: 27u64 })
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(15, 27),
|
(15, 27),
|
||||||
(u64, u64)
|
(u64, u64)
|
||||||
|
@ -3423,9 +3423,9 @@ fn box_and_unbox_record_2_u64() {
|
||||||
fn box_and_unbox_record_3_u64() {
|
fn box_and_unbox_record_3_u64() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Box.unbox (Box.box { a: 15u64, b: 27u64, c: 34u64 })
|
Box.unbox (Box.box { a: 15u64, b: 27u64, c: 34u64 })
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(15, 27, 34),
|
(15, 27, 34),
|
||||||
(u64, u64, u64)
|
(u64, u64, u64)
|
||||||
|
@ -3437,9 +3437,9 @@ fn box_and_unbox_record_3_u64() {
|
||||||
fn box_and_unbox_record_2_u8() {
|
fn box_and_unbox_record_2_u8() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Box.unbox (Box.box { a: 15u8, b: 27u8 })
|
Box.unbox (Box.box { a: 15u8, b: 27u8 })
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(15, 27),
|
(15, 27),
|
||||||
(u8, u8)
|
(u8, u8)
|
||||||
|
@ -3451,9 +3451,9 @@ fn box_and_unbox_record_2_u8() {
|
||||||
fn box_and_unbox_record_3_u8() {
|
fn box_and_unbox_record_3_u8() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Box.unbox (Box.box { a: 15u8, b: 27u8, c: 34u8 })
|
Box.unbox (Box.box { a: 15u8, b: 27u8, c: 34u8 })
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(15, 27, 34),
|
(15, 27, 34),
|
||||||
(u8, u8, u8)
|
(u8, u8, u8)
|
||||||
|
@ -3465,12 +3465,12 @@ fn box_and_unbox_record_3_u8() {
|
||||||
fn box_and_unbox_tag_union() {
|
fn box_and_unbox_tag_union() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
v : [A U8, B U8] # usually stack allocated
|
v : [A U8, B U8] # usually stack allocated
|
||||||
v = B 27u8
|
v = B 27u8
|
||||||
|
|
||||||
Box.unbox (Box.box v)
|
Box.unbox (Box.box v)
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(27, 1),
|
(27, 1),
|
||||||
(u8, u8)
|
(u8, u8)
|
||||||
|
@ -3534,7 +3534,7 @@ fn issue_2894() {
|
||||||
fn polymorphic_def_used_in_closure() {
|
fn polymorphic_def_used_in_closure() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
a : I64 -> _
|
a : I64 -> _
|
||||||
a = \g ->
|
a = \g ->
|
||||||
f = { r: g, h: 32 }
|
f = { r: g, h: 32 }
|
||||||
|
@ -3543,7 +3543,7 @@ fn polymorphic_def_used_in_closure() {
|
||||||
h1 = (\{} -> f.h) {}
|
h1 = (\{} -> f.h) {}
|
||||||
h1
|
h1
|
||||||
a 1
|
a 1
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
32,
|
32,
|
||||||
u64
|
u64
|
||||||
|
@ -3555,13 +3555,13 @@ fn polymorphic_def_used_in_closure() {
|
||||||
fn polymorphic_lambda_set_usage() {
|
fn polymorphic_lambda_set_usage() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
id1 = \x -> x
|
id1 = \x -> x
|
||||||
id2 = \y -> y
|
id2 = \y -> y
|
||||||
id = if Bool.true then id1 else id2
|
id = if Bool.true then id1 else id2
|
||||||
|
|
||||||
id 9u8
|
id 9u8
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
9,
|
9,
|
||||||
u8
|
u8
|
||||||
|
@ -3573,7 +3573,7 @@ fn polymorphic_lambda_set_usage() {
|
||||||
fn polymorphic_lambda_set_multiple_specializations() {
|
fn polymorphic_lambda_set_multiple_specializations() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
id1 = \x -> x
|
id1 = \x -> x
|
||||||
id2 = \y -> y
|
id2 = \y -> y
|
||||||
id = \z ->
|
id = \z ->
|
||||||
|
@ -3581,7 +3581,7 @@ fn polymorphic_lambda_set_multiple_specializations() {
|
||||||
f z
|
f z
|
||||||
|
|
||||||
(id 9u8) + Num.toU8 (id 16u16)
|
(id 9u8) + Num.toU8 (id 16u16)
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
25,
|
25,
|
||||||
u8
|
u8
|
||||||
|
@ -3642,14 +3642,14 @@ fn mutual_recursion_top_level_defs() {
|
||||||
fn polymorphic_lambda_captures_polymorphic_value() {
|
fn polymorphic_lambda_captures_polymorphic_value() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
x = 2
|
x = 2
|
||||||
|
|
||||||
f1 = \_ -> x
|
f1 = \_ -> x
|
||||||
|
|
||||||
f = if Bool.true then f1 else f1
|
f = if Bool.true then f1 else f1
|
||||||
f {}
|
f {}
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
2,
|
2,
|
||||||
u64
|
u64
|
||||||
|
@ -3661,7 +3661,7 @@ fn polymorphic_lambda_captures_polymorphic_value() {
|
||||||
fn lambda_capture_niche_u64_vs_u8_capture() {
|
fn lambda_capture_niche_u64_vs_u8_capture() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
capture : _ -> ({} -> Str)
|
capture : _ -> ({} -> Str)
|
||||||
capture = \val ->
|
capture = \val ->
|
||||||
\{} ->
|
\{} ->
|
||||||
|
@ -3677,7 +3677,7 @@ fn lambda_capture_niche_u64_vs_u8_capture() {
|
||||||
capture 18u8
|
capture 18u8
|
||||||
|
|
||||||
fun {}
|
fun {}
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
RocStr::from("123"),
|
RocStr::from("123"),
|
||||||
RocStr
|
RocStr
|
||||||
|
@ -3789,14 +3789,14 @@ fn lambda_capture_niches_have_captured_function_in_closure() {
|
||||||
fn recursive_call_capturing_function() {
|
fn recursive_call_capturing_function() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
a = \b ->
|
a = \b ->
|
||||||
c = \d ->
|
c = \d ->
|
||||||
if d == 7 then d else c (d + b)
|
if d == 7 then d else c (d + b)
|
||||||
c 1
|
c 1
|
||||||
|
|
||||||
a 6
|
a 6
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
7,
|
7,
|
||||||
i64
|
i64
|
||||||
|
@ -3808,13 +3808,13 @@ fn recursive_call_capturing_function() {
|
||||||
fn shared_pattern_variable_in_when_branches() {
|
fn shared_pattern_variable_in_when_branches() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
f = \t ->
|
f = \t ->
|
||||||
when t is
|
when t is
|
||||||
A x | B x -> x
|
A x | B x -> x
|
||||||
|
|
||||||
{a: f (A 15u8), b: (B 31u8)}
|
{a: f (A 15u8), b: (B 31u8)}
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(15u8, 31u8),
|
(15u8, 31u8),
|
||||||
(u8, u8)
|
(u8, u8)
|
||||||
|
@ -3826,12 +3826,12 @@ fn shared_pattern_variable_in_when_branches() {
|
||||||
fn symbol_not_bound_in_all_patterns_runs_when_no_bound_symbol_used() {
|
fn symbol_not_bound_in_all_patterns_runs_when_no_bound_symbol_used() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
f = \t -> when t is
|
f = \t -> when t is
|
||||||
A x | B y -> 31u8
|
A x | B y -> 31u8
|
||||||
|
|
||||||
{a: f (A 15u8), b: f (B 15u8)}
|
{a: f (A 15u8), b: f (B 15u8)}
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(31u8, 31u8),
|
(31u8, 31u8),
|
||||||
(u8, u8),
|
(u8, u8),
|
||||||
|
@ -3845,10 +3845,10 @@ fn symbol_not_bound_in_all_patterns_runs_when_no_bound_symbol_used() {
|
||||||
fn symbol_not_bound_in_all_patterns_runs_when_bound_pattern_reached() {
|
fn symbol_not_bound_in_all_patterns_runs_when_bound_pattern_reached() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
when A 15u8 is
|
when A 15u8 is
|
||||||
A x | B y -> x
|
A x | B y -> x
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
15u8,
|
15u8,
|
||||||
u8,
|
u8,
|
||||||
|
@ -3865,10 +3865,10 @@ fn symbol_not_bound_in_all_patterns_runs_when_bound_pattern_reached() {
|
||||||
fn runtime_error_when_degenerate_pattern_reached() {
|
fn runtime_error_when_degenerate_pattern_reached() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
when B 15u8 is
|
when B 15u8 is
|
||||||
A x | B y -> x + 5u8
|
A x | B y -> x + 5u8
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
15u8,
|
15u8,
|
||||||
u8,
|
u8,
|
||||||
|
@ -4399,7 +4399,7 @@ fn pattern_as_of_symbol() {
|
||||||
fn function_specialization_information_in_lambda_set_thunk() {
|
fn function_specialization_information_in_lambda_set_thunk() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r###"
|
r#"
|
||||||
app "test" provides [main] to "./platform"
|
app "test" provides [main] to "./platform"
|
||||||
|
|
||||||
andThen = \{} ->
|
andThen = \{} ->
|
||||||
|
@ -4409,7 +4409,7 @@ fn function_specialization_information_in_lambda_set_thunk() {
|
||||||
between = andThen {}
|
between = andThen {}
|
||||||
|
|
||||||
main = between \{} -> between \{} -> 10u8
|
main = between \{} -> between \{} -> 10u8
|
||||||
"###
|
"#
|
||||||
),
|
),
|
||||||
30,
|
30,
|
||||||
u8
|
u8
|
||||||
|
@ -4421,7 +4421,7 @@ fn function_specialization_information_in_lambda_set_thunk() {
|
||||||
fn function_specialization_information_in_lambda_set_thunk_independent_defs() {
|
fn function_specialization_information_in_lambda_set_thunk_independent_defs() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r###"
|
r#"
|
||||||
app "test" provides [main] to "./platform"
|
app "test" provides [main] to "./platform"
|
||||||
|
|
||||||
andThen = \{} ->
|
andThen = \{} ->
|
||||||
|
@ -4433,7 +4433,7 @@ fn function_specialization_information_in_lambda_set_thunk_independent_defs() {
|
||||||
between2 = andThen {}
|
between2 = andThen {}
|
||||||
|
|
||||||
main = between1 \{} -> between2 \{} -> 10u8
|
main = between1 \{} -> between2 \{} -> 10u8
|
||||||
"###
|
"#
|
||||||
),
|
),
|
||||||
30,
|
30,
|
||||||
u8
|
u8
|
||||||
|
@ -4526,7 +4526,7 @@ fn layout_cache_structure_with_multiple_recursive_structures() {
|
||||||
fn reset_recursive_type_wraps_in_named_type() {
|
fn reset_recursive_type_wraps_in_named_type() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r###"
|
r#"
|
||||||
app "test" provides [main] to "./platform"
|
app "test" provides [main] to "./platform"
|
||||||
|
|
||||||
main : Str
|
main : Str
|
||||||
|
@ -4553,7 +4553,7 @@ fn reset_recursive_type_wraps_in_named_type() {
|
||||||
strX = f x
|
strX = f x
|
||||||
strXs = printLinkedList xs f
|
strXs = printLinkedList xs f
|
||||||
"Cons \(strX) (\(strXs))"
|
"Cons \(strX) (\(strXs))"
|
||||||
"###
|
"#
|
||||||
),
|
),
|
||||||
RocStr::from("Cons 2 (Cons 3 (Cons 4 (Nil)))"),
|
RocStr::from("Cons 2 (Cons 3 (Cons 4 (Nil)))"),
|
||||||
RocStr
|
RocStr
|
||||||
|
@ -4619,12 +4619,12 @@ fn many_arguments() {
|
||||||
// exhausts all argument registers on x86 and aarch
|
// exhausts all argument registers on x86 and aarch
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
fun = \a,b,c,d, e,f,g,h, i ->
|
fun = \a,b,c,d, e,f,g,h, i ->
|
||||||
(a + b + c + d) + (e + f + g + h) + i
|
(a + b + c + d) + (e + f + g + h) + i
|
||||||
|
|
||||||
fun 0i64 1 2 3 4 5 6 7 8
|
fun 0i64 1 2 3 4 5 6 7 8
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
1 + 2 + 3 + 4 + 5 + 6 + 7 + 8,
|
1 + 2 + 3 + 4 + 5 + 6 + 7 + 8,
|
||||||
i64
|
i64
|
||||||
|
@ -4636,9 +4636,9 @@ fn many_arguments() {
|
||||||
fn multiple_uses_of_bool_true_record() {
|
fn multiple_uses_of_bool_true_record() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
(Bool.true, Bool.true).0
|
(Bool.true, Bool.true).0
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
true,
|
true,
|
||||||
bool
|
bool
|
||||||
|
@ -4650,14 +4650,14 @@ fn multiple_uses_of_bool_true_record() {
|
||||||
fn multiple_uses_of_bool_true_tag_union() {
|
fn multiple_uses_of_bool_true_tag_union() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
x : [ One Bool Bool, Empty ]
|
x : [ One Bool Bool, Empty ]
|
||||||
x = One Bool.true Bool.true
|
x = One Bool.true Bool.true
|
||||||
|
|
||||||
when x is
|
when x is
|
||||||
One a _ -> a
|
One a _ -> a
|
||||||
Empty -> Bool.false
|
Empty -> Bool.false
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
true,
|
true,
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -18,9 +18,9 @@ use roc_std::{RocList, RocStr};
|
||||||
fn basic_record() {
|
fn basic_record() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
{ y: 17, x: 15, z: 19 }.x
|
{ y: 17, x: 15, z: 19 }.x
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
15,
|
15,
|
||||||
i64
|
i64
|
||||||
|
@ -28,9 +28,9 @@ fn basic_record() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
{ x: 15, y: 17, z: 19 }.y
|
{ x: 15, y: 17, z: 19 }.y
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
17,
|
17,
|
||||||
i64
|
i64
|
||||||
|
@ -38,9 +38,9 @@ fn basic_record() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
{ x: 15, y: 17, z: 19 }.z
|
{ x: 15, y: 17, z: 19 }.z
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
19,
|
19,
|
||||||
i64
|
i64
|
||||||
|
@ -52,11 +52,11 @@ fn basic_record() {
|
||||||
fn f64_record() {
|
fn f64_record() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
rec = { y: 17.2f64, x: 15.1f64, z: 19.3f64 }
|
rec = { y: 17.2f64, x: 15.1f64, z: 19.3f64 }
|
||||||
|
|
||||||
rec.x
|
rec.x
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
15.1,
|
15.1,
|
||||||
f64
|
f64
|
||||||
|
@ -64,11 +64,11 @@ fn f64_record() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
rec = { y: 17.2f64, x: 15.1f64, z: 19.3f64 }
|
rec = { y: 17.2f64, x: 15.1f64, z: 19.3f64 }
|
||||||
|
|
||||||
rec.y
|
rec.y
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
17.2,
|
17.2,
|
||||||
f64
|
f64
|
||||||
|
@ -76,11 +76,11 @@ fn f64_record() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
rec = { y: 17.2f64, x: 15.1f64, z: 19.3f64 }
|
rec = { y: 17.2f64, x: 15.1f64, z: 19.3f64 }
|
||||||
|
|
||||||
rec.z
|
rec.z
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
19.3,
|
19.3,
|
||||||
f64
|
f64
|
||||||
|
@ -93,14 +93,14 @@ fn pass_bool_record() {
|
||||||
// found a bug there the register to use was not incremented correctly
|
// found a bug there the register to use was not incremented correctly
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
true : Bool
|
true : Bool
|
||||||
true = Bool.true
|
true = Bool.true
|
||||||
|
|
||||||
f = \_, x -> x
|
f = \_, x -> x
|
||||||
|
|
||||||
f { x: true, y: true } 23
|
f { x: true, y: true } 23
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
23,
|
23,
|
||||||
i64
|
i64
|
||||||
|
@ -124,11 +124,11 @@ fn fn_record() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
rec = { x: 15, y: 17, z: 19 }
|
rec = { x: 15, y: 17, z: 19 }
|
||||||
|
|
||||||
rec.z + rec.x
|
rec.z + rec.x
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
34,
|
34,
|
||||||
i64
|
i64
|
||||||
|
@ -140,11 +140,11 @@ fn fn_record() {
|
||||||
fn def_record() {
|
fn def_record() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
rec = { y: 17, x: 15, z: 19 }
|
rec = { y: 17, x: 15, z: 19 }
|
||||||
|
|
||||||
rec.x
|
rec.x
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
15,
|
15,
|
||||||
i64
|
i64
|
||||||
|
@ -152,11 +152,11 @@ fn def_record() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
rec = { x: 15, y: 17, z: 19 }
|
rec = { x: 15, y: 17, z: 19 }
|
||||||
|
|
||||||
rec.y
|
rec.y
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
17,
|
17,
|
||||||
i64
|
i64
|
||||||
|
@ -164,11 +164,11 @@ fn def_record() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
rec = { x: 15, y: 17, z: 19 }
|
rec = { x: 15, y: 17, z: 19 }
|
||||||
|
|
||||||
rec.z
|
rec.z
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
19,
|
19,
|
||||||
i64
|
i64
|
||||||
|
@ -180,10 +180,10 @@ fn def_record() {
|
||||||
fn when_on_record() {
|
fn when_on_record() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
when { x: 0x2 } is
|
when { x: 0x2 } is
|
||||||
{ x } -> x + 3
|
{ x } -> x + 3
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
5,
|
5,
|
||||||
i64
|
i64
|
||||||
|
@ -195,10 +195,10 @@ fn when_on_record() {
|
||||||
fn when_record_with_guard_pattern() {
|
fn when_record_with_guard_pattern() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
when { x: 0x2, y: 1.23 } is
|
when { x: 0x2, y: 1.23 } is
|
||||||
{ x: var } -> var + 3
|
{ x: var } -> var + 3
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
5,
|
5,
|
||||||
i64
|
i64
|
||||||
|
@ -210,11 +210,11 @@ fn when_record_with_guard_pattern() {
|
||||||
fn let_with_record_pattern() {
|
fn let_with_record_pattern() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
{ x } = { x: 0x2, y: 1.23 }
|
{ x } = { x: 0x2, y: 1.23 }
|
||||||
|
|
||||||
x
|
x
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
2,
|
2,
|
||||||
i64
|
i64
|
||||||
|
@ -226,11 +226,11 @@ fn let_with_record_pattern() {
|
||||||
fn record_guard_pattern() {
|
fn record_guard_pattern() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
when { x: 0x2, y: 1.23 } is
|
when { x: 0x2, y: 1.23 } is
|
||||||
{ x: 0x4 } -> 5
|
{ x: 0x4 } -> 5
|
||||||
{ x } -> x + 3
|
{ x } -> x + 3
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
5,
|
5,
|
||||||
i64
|
i64
|
||||||
|
@ -242,11 +242,11 @@ fn record_guard_pattern() {
|
||||||
fn twice_record_access() {
|
fn twice_record_access() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
x = {a: 0x2, b: 0x3 }
|
x = {a: 0x2, b: 0x3 }
|
||||||
|
|
||||||
x.a + x.b
|
x.a + x.b
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
5,
|
5,
|
||||||
i64
|
i64
|
||||||
|
@ -257,11 +257,11 @@ fn twice_record_access() {
|
||||||
fn empty_record() {
|
fn empty_record() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
v = {}
|
v = {}
|
||||||
|
|
||||||
v
|
v
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(),
|
(),
|
||||||
()
|
()
|
||||||
|
@ -272,9 +272,9 @@ fn empty_record() {
|
||||||
fn i64_record2_literal() {
|
fn i64_record2_literal() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
{ x: 3, y: 5 }
|
{ x: 3, y: 5 }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(3, 5),
|
(3, 5),
|
||||||
(i64, i64)
|
(i64, i64)
|
||||||
|
@ -286,9 +286,9 @@ fn i64_record2_literal() {
|
||||||
// fn i64_record3_literal() {
|
// fn i64_record3_literal() {
|
||||||
// assert_evals_to!(
|
// assert_evals_to!(
|
||||||
// indoc!(
|
// indoc!(
|
||||||
// r#"
|
// r"
|
||||||
// { x: 3, y: 5, z: 17 }
|
// { x: 3, y: 5, z: 17 }
|
||||||
// "#
|
// "
|
||||||
// ),
|
// ),
|
||||||
// (3, 5, 17),
|
// (3, 5, 17),
|
||||||
// (i64, i64, i64)
|
// (i64, i64, i64)
|
||||||
|
@ -299,9 +299,9 @@ fn i64_record2_literal() {
|
||||||
fn f64_record2_literal() {
|
fn f64_record2_literal() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
{ x: 3.1f64, y: 5.1f64 }
|
{ x: 3.1f64, y: 5.1f64 }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(3.1, 5.1),
|
(3.1, 5.1),
|
||||||
(f64, f64)
|
(f64, f64)
|
||||||
|
@ -313,9 +313,9 @@ fn f64_record2_literal() {
|
||||||
// fn f64_record3_literal() {
|
// fn f64_record3_literal() {
|
||||||
// assert_evals_to!(
|
// assert_evals_to!(
|
||||||
// indoc!(
|
// indoc!(
|
||||||
// r#"
|
// r"
|
||||||
// { x: 3.1, y: 5.1, z: 17.1 }
|
// { x: 3.1, y: 5.1, z: 17.1 }
|
||||||
// "#
|
// "
|
||||||
// ),
|
// ),
|
||||||
// (3.1, 5.1, 17.1),
|
// (3.1, 5.1, 17.1),
|
||||||
// (f64, f64, f64)
|
// (f64, f64, f64)
|
||||||
|
@ -327,12 +327,12 @@ fn f64_record2_literal() {
|
||||||
// fn bool_record4_literal() {
|
// fn bool_record4_literal() {
|
||||||
// assert_evals_to!(
|
// assert_evals_to!(
|
||||||
// indoc!(
|
// indoc!(
|
||||||
// r#"
|
// r"
|
||||||
// record : { a : Bool, b : Bool, c : Bool, d : Bool }
|
// record : { a : Bool, b : Bool, c : Bool, d : Bool }
|
||||||
// record = { a: Bool.true, b: Bool.true, c : Bool.true, d : Bool }
|
// record = { a: Bool.true, b: Bool.true, c : Bool.true, d : Bool }
|
||||||
|
|
||||||
// record
|
// record
|
||||||
// "#
|
// "
|
||||||
// ),
|
// ),
|
||||||
// (true, false, false, true),
|
// (true, false, false, true),
|
||||||
// (bool, bool, bool, bool)
|
// (bool, bool, bool, bool)
|
||||||
|
@ -343,9 +343,9 @@ fn f64_record2_literal() {
|
||||||
fn i64_record1_literal() {
|
fn i64_record1_literal() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
{ a: 3 }
|
{ a: 3 }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
3,
|
3,
|
||||||
i64
|
i64
|
||||||
|
@ -357,9 +357,9 @@ fn i64_record1_literal() {
|
||||||
// fn i64_record9_literal() {
|
// fn i64_record9_literal() {
|
||||||
// assert_evals_to!(
|
// assert_evals_to!(
|
||||||
// indoc!(
|
// indoc!(
|
||||||
// r#"
|
// r"
|
||||||
// { a: 3, b: 5, c: 17, d: 1, e: 9, f: 12, g: 13, h: 14, i: 15 }
|
// { a: 3, b: 5, c: 17, d: 1, e: 9, f: 12, g: 13, h: 14, i: 15 }
|
||||||
// "#
|
// "
|
||||||
// ),
|
// ),
|
||||||
// (3, 5, 17, 1, 9, 12, 13, 14, 15),
|
// (3, 5, 17, 1, 9, 12, 13, 14, 15),
|
||||||
// (i64, i64, i64, i64, i64, i64, i64, i64, i64)
|
// (i64, i64, i64, i64, i64, i64, i64, i64, i64)
|
||||||
|
@ -371,9 +371,9 @@ fn i64_record1_literal() {
|
||||||
// fn f64_record3_literal() {
|
// fn f64_record3_literal() {
|
||||||
// assert_evals_to!(
|
// assert_evals_to!(
|
||||||
// indoc!(
|
// indoc!(
|
||||||
// r#"
|
// r"
|
||||||
// { x: 3.1, y: 5.1, z: 17.1 }
|
// { x: 3.1, y: 5.1, z: 17.1 }
|
||||||
// "#
|
// "
|
||||||
// ),
|
// ),
|
||||||
// (3.1, 5.1, 17.1),
|
// (3.1, 5.1, 17.1),
|
||||||
// (f64, f64, f64)
|
// (f64, f64, f64)
|
||||||
|
@ -384,12 +384,12 @@ fn i64_record1_literal() {
|
||||||
fn bool_literal() {
|
fn bool_literal() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
x : Bool
|
x : Bool
|
||||||
x = Bool.true
|
x = Bool.true
|
||||||
|
|
||||||
x
|
x
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
true,
|
true,
|
||||||
bool
|
bool
|
||||||
|
@ -401,12 +401,12 @@ fn bool_literal() {
|
||||||
fn return_record() {
|
fn return_record() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
x = 4
|
x = 4
|
||||||
y = 3
|
y = 3
|
||||||
|
|
||||||
{ x, y }
|
{ x, y }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(4, 3),
|
(4, 3),
|
||||||
(i64, i64)
|
(i64, i64)
|
||||||
|
@ -446,7 +446,7 @@ fn optional_field_when_use_default() {
|
||||||
fn optional_field_when_use_default_nested() {
|
fn optional_field_when_use_default_nested() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
f = \r ->
|
f = \r ->
|
||||||
when r is
|
when r is
|
||||||
{ x: Blue, y ? 3 } -> y
|
{ x: Blue, y ? 3 } -> y
|
||||||
|
@ -458,7 +458,7 @@ fn optional_field_when_use_default_nested() {
|
||||||
d = f { x: Red }
|
d = f { x: Red }
|
||||||
|
|
||||||
a * b * c * d
|
a * b * c * d
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
3 * 5 * 7 * 11,
|
3 * 5 * 7 * 11,
|
||||||
i64
|
i64
|
||||||
|
@ -491,13 +491,13 @@ fn optional_field_destructure_module() {
|
||||||
fn optional_field_destructure_expr() {
|
fn optional_field_destructure_expr() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
fn = \r ->
|
fn = \r ->
|
||||||
{ x ? 10, y } = r
|
{ x ? 10, y } = r
|
||||||
x + y
|
x + y
|
||||||
|
|
||||||
fn { x: 4, y: 9 }
|
fn { x: 4, y: 9 }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
13,
|
13,
|
||||||
i64
|
i64
|
||||||
|
@ -551,13 +551,13 @@ fn optional_field_let_no_use_default() {
|
||||||
fn optional_field_let_no_use_default_nested() {
|
fn optional_field_let_no_use_default_nested() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
f = \r ->
|
f = \r ->
|
||||||
{ x ? 10, y } = r
|
{ x ? 10, y } = r
|
||||||
x + y
|
x + y
|
||||||
|
|
||||||
f { y: 9, x: 4 }
|
f { y: 9, x: 4 }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
13,
|
13,
|
||||||
i64
|
i64
|
||||||
|
@ -569,12 +569,12 @@ fn optional_field_let_no_use_default_nested() {
|
||||||
fn optional_field_function_use_default() {
|
fn optional_field_function_use_default() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
f = \{ x ? 10, y } -> x + y
|
f = \{ x ? 10, y } -> x + y
|
||||||
|
|
||||||
|
|
||||||
f { y: 9 }
|
f { y: 9 }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
19,
|
19,
|
||||||
i64
|
i64
|
||||||
|
@ -605,12 +605,12 @@ fn optional_field_function_no_use_default() {
|
||||||
fn optional_field_function_no_use_default_nested() {
|
fn optional_field_function_no_use_default_nested() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
f = \{ x ? 10, y } -> x + y
|
f = \{ x ? 10, y } -> x + y
|
||||||
|
|
||||||
|
|
||||||
f { x: 4, y: 9 }
|
f { x: 4, y: 9 }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
13,
|
13,
|
||||||
i64
|
i64
|
||||||
|
@ -622,10 +622,10 @@ fn optional_field_function_no_use_default_nested() {
|
||||||
fn optional_field_singleton_record() {
|
fn optional_field_singleton_record() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
when { x : 4 } is
|
when { x : 4 } is
|
||||||
{ x ? 3 } -> x
|
{ x ? 3 } -> x
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
4,
|
4,
|
||||||
i64
|
i64
|
||||||
|
@ -637,10 +637,10 @@ fn optional_field_singleton_record() {
|
||||||
fn optional_field_empty_record() {
|
fn optional_field_empty_record() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
when { } is
|
when { } is
|
||||||
{ x ? 3 } -> x
|
{ x ? 3 } -> x
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
3,
|
3,
|
||||||
i64
|
i64
|
||||||
|
@ -652,9 +652,9 @@ fn optional_field_empty_record() {
|
||||||
fn return_record_2() {
|
fn return_record_2() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
{ x: 3, y: 5 }
|
{ x: 3, y: 5 }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
[3, 5],
|
[3, 5],
|
||||||
[i64; 2]
|
[i64; 2]
|
||||||
|
@ -666,9 +666,9 @@ fn return_record_2() {
|
||||||
fn return_record_3() {
|
fn return_record_3() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
{ x: 3, y: 5, z: 4 }
|
{ x: 3, y: 5, z: 4 }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(3, 5, 4),
|
(3, 5, 4),
|
||||||
(i64, i64, i64)
|
(i64, i64, i64)
|
||||||
|
@ -680,9 +680,9 @@ fn return_record_3() {
|
||||||
fn return_record_4() {
|
fn return_record_4() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
{ a: 3, b: 5, c: 4, d: 2 }
|
{ a: 3, b: 5, c: 4, d: 2 }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
[3, 5, 4, 2],
|
[3, 5, 4, 2],
|
||||||
[i64; 4]
|
[i64; 4]
|
||||||
|
@ -694,9 +694,9 @@ fn return_record_4() {
|
||||||
fn return_record_5() {
|
fn return_record_5() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
{ a: 3, b: 5, c: 4, d: 2, e: 1 }
|
{ a: 3, b: 5, c: 4, d: 2, e: 1 }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
[3, 5, 4, 2, 1],
|
[3, 5, 4, 2, 1],
|
||||||
[i64; 5]
|
[i64; 5]
|
||||||
|
@ -708,9 +708,9 @@ fn return_record_5() {
|
||||||
fn return_record_6() {
|
fn return_record_6() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
{ a: 3, b: 5, c: 4, d: 2, e: 1, f: 7 }
|
{ a: 3, b: 5, c: 4, d: 2, e: 1, f: 7 }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
[3, 5, 4, 2, 1, 7],
|
[3, 5, 4, 2, 1, 7],
|
||||||
[i64; 6]
|
[i64; 6]
|
||||||
|
@ -722,9 +722,9 @@ fn return_record_6() {
|
||||||
fn return_record_7() {
|
fn return_record_7() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
{ a: 3, b: 5, c: 4, d: 2, e: 1, f: 7, g: 8 }
|
{ a: 3, b: 5, c: 4, d: 2, e: 1, f: 7, g: 8 }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
[3, 5, 4, 2, 1, 7, 8],
|
[3, 5, 4, 2, 1, 7, 8],
|
||||||
[i64; 7]
|
[i64; 7]
|
||||||
|
@ -736,9 +736,9 @@ fn return_record_7() {
|
||||||
fn return_record_float_int() {
|
fn return_record_float_int() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
{ a: 1.23f64, b: 0x1 }
|
{ a: 1.23f64, b: 0x1 }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(1.23, 0x1),
|
(1.23, 0x1),
|
||||||
(f64, i64)
|
(f64, i64)
|
||||||
|
@ -750,9 +750,9 @@ fn return_record_float_int() {
|
||||||
fn return_record_int_float() {
|
fn return_record_int_float() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
{ a: 0x1, b: 1.23f64 }
|
{ a: 0x1, b: 1.23f64 }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(0x1, 1.23),
|
(0x1, 1.23),
|
||||||
(i64, f64)
|
(i64, f64)
|
||||||
|
@ -764,9 +764,9 @@ fn return_record_int_float() {
|
||||||
fn return_record_float_float() {
|
fn return_record_float_float() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
{ a: 2.46f64, b: 1.23f64 }
|
{ a: 2.46f64, b: 1.23f64 }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(2.46, 1.23),
|
(2.46, 1.23),
|
||||||
(f64, f64)
|
(f64, f64)
|
||||||
|
@ -778,9 +778,9 @@ fn return_record_float_float() {
|
||||||
fn return_record_float_float_float() {
|
fn return_record_float_float_float() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
{ a: 2.46f64, b: 1.23f64, c: 0.1f64 }
|
{ a: 2.46f64, b: 1.23f64, c: 0.1f64 }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(2.46, 1.23, 0.1),
|
(2.46, 1.23, 0.1),
|
||||||
(f64, f64, f64)
|
(f64, f64, f64)
|
||||||
|
@ -792,9 +792,9 @@ fn return_record_float_float_float() {
|
||||||
fn return_nested_record() {
|
fn return_nested_record() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
{ flag: 0x0, payload: { a: 2.46f64, b: 1.23f64, c: 0.1f64 } }
|
{ flag: 0x0, payload: { a: 2.46f64, b: 1.23f64, c: 0.1f64 } }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(0x0, (2.46, 1.23, 0.1)),
|
(0x0, (2.46, 1.23, 0.1)),
|
||||||
(i64, (f64, f64, f64))
|
(i64, (f64, f64, f64))
|
||||||
|
@ -806,13 +806,13 @@ fn return_nested_record() {
|
||||||
fn nested_record_load() {
|
fn nested_record_load() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
x = { a : { b : 0x5 } }
|
x = { a : { b : 0x5 } }
|
||||||
|
|
||||||
y = x.a
|
y = x.a
|
||||||
|
|
||||||
y.b
|
y.b
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
5,
|
5,
|
||||||
i64
|
i64
|
||||||
|
@ -844,9 +844,9 @@ fn accessor_multi_element_record() {
|
||||||
fn accessor_single_element_record() {
|
fn accessor_single_element_record() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
.foo { foo: 4 }
|
.foo { foo: 4 }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
4,
|
4,
|
||||||
i64
|
i64
|
||||||
|
@ -858,11 +858,11 @@ fn accessor_single_element_record() {
|
||||||
fn update_record() {
|
fn update_record() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
rec = { foo: 42, bar: 2.46f64 }
|
rec = { foo: 42, bar: 2.46f64 }
|
||||||
|
|
||||||
{ rec & foo: rec.foo + 1 }
|
{ rec & foo: rec.foo + 1 }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(2.46, 43),
|
(2.46, 43),
|
||||||
(f64, i64)
|
(f64, i64)
|
||||||
|
@ -874,11 +874,11 @@ fn update_record() {
|
||||||
fn update_single_element_record() {
|
fn update_single_element_record() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
rec = { foo: 42}
|
rec = { foo: 42}
|
||||||
|
|
||||||
{ rec & foo: rec.foo + 1 }
|
{ rec & foo: rec.foo + 1 }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
43,
|
43,
|
||||||
i64
|
i64
|
||||||
|
@ -927,14 +927,14 @@ fn alignment_in_record() {
|
||||||
fn blue_and_present() {
|
fn blue_and_present() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
f = \r ->
|
f = \r ->
|
||||||
when r is
|
when r is
|
||||||
{ x: Blue, y ? 3 } -> y
|
{ x: Blue, y ? 3 } -> y
|
||||||
{ x: Red, y ? 5 } -> y
|
{ x: Red, y ? 5 } -> y
|
||||||
|
|
||||||
f { x: Blue, y: 7 }
|
f { x: Blue, y: 7 }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
7,
|
7,
|
||||||
i64
|
i64
|
||||||
|
@ -946,14 +946,14 @@ fn blue_and_present() {
|
||||||
fn blue_and_absent() {
|
fn blue_and_absent() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
f = \r ->
|
f = \r ->
|
||||||
when r is
|
when r is
|
||||||
{ x: Blue, y ? 3 } -> y
|
{ x: Blue, y ? 3 } -> y
|
||||||
{ x: Red, y ? 5 } -> y
|
{ x: Red, y ? 5 } -> y
|
||||||
|
|
||||||
f { x: Blue }
|
f { x: Blue }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
3,
|
3,
|
||||||
i64
|
i64
|
||||||
|
@ -965,7 +965,7 @@ fn blue_and_absent() {
|
||||||
fn update_the_only_field() {
|
fn update_the_only_field() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Model : { foo : I64 }
|
Model : { foo : I64 }
|
||||||
|
|
||||||
model : Model
|
model : Model
|
||||||
|
@ -977,7 +977,7 @@ fn update_the_only_field() {
|
||||||
newModel = { model & foo }
|
newModel = { model & foo }
|
||||||
|
|
||||||
newModel.foo
|
newModel.foo
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
4,
|
4,
|
||||||
i64
|
i64
|
||||||
|
@ -990,7 +990,7 @@ fn update_the_only_field() {
|
||||||
fn both_have_unique_fields() {
|
fn both_have_unique_fields() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
a = { x: 42, y: 43 }
|
a = { x: 42, y: 43 }
|
||||||
b = { x: 42, z: 44 }
|
b = { x: 42, z: 44 }
|
||||||
|
|
||||||
|
@ -998,7 +998,7 @@ fn both_have_unique_fields() {
|
||||||
f = \{ x: x1}, { x: x2 } -> x1 + x2
|
f = \{ x: x1}, { x: x2 } -> x1 + x2
|
||||||
|
|
||||||
f a b
|
f a b
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
84,
|
84,
|
||||||
i64
|
i64
|
||||||
|
|
|
@ -17,12 +17,12 @@ use roc_std::{RocResult, RocStr};
|
||||||
fn with_default_ok() {
|
fn with_default_ok() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
result : Result I64 {}
|
result : Result I64 {}
|
||||||
result = Ok 12345
|
result = Ok 12345
|
||||||
|
|
||||||
Result.withDefault result 0
|
Result.withDefault result 0
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
12345,
|
12345,
|
||||||
i64
|
i64
|
||||||
|
@ -34,12 +34,12 @@ fn with_default_ok() {
|
||||||
fn with_default_err() {
|
fn with_default_err() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
result : Result I64 {}
|
result : Result I64 {}
|
||||||
result = Err {}
|
result = Err {}
|
||||||
|
|
||||||
Result.withDefault result 0
|
Result.withDefault result 0
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
0,
|
0,
|
||||||
i64
|
i64
|
||||||
|
@ -51,14 +51,14 @@ fn with_default_err() {
|
||||||
fn result_map() {
|
fn result_map() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
result : Result I64 {}
|
result : Result I64 {}
|
||||||
result = Ok 2
|
result = Ok 2
|
||||||
|
|
||||||
result
|
result
|
||||||
|> Result.map (\x -> x + 1)
|
|> Result.map (\x -> x + 1)
|
||||||
|> Result.withDefault 0
|
|> Result.withDefault 0
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
3,
|
3,
|
||||||
i64
|
i64
|
||||||
|
@ -66,14 +66,14 @@ fn result_map() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
result : Result I64 {}
|
result : Result I64 {}
|
||||||
result = Err {}
|
result = Err {}
|
||||||
|
|
||||||
result
|
result
|
||||||
|> Result.map (\x -> x + 1)
|
|> Result.map (\x -> x + 1)
|
||||||
|> Result.withDefault 0
|
|> Result.withDefault 0
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
0,
|
0,
|
||||||
i64
|
i64
|
||||||
|
@ -85,14 +85,14 @@ fn result_map() {
|
||||||
fn result_map_err() {
|
fn result_map_err() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
result : Result {} I64
|
result : Result {} I64
|
||||||
result = Err 2
|
result = Err 2
|
||||||
|
|
||||||
when Result.mapErr result (\x -> x + 1) is
|
when Result.mapErr result (\x -> x + 1) is
|
||||||
Err n -> n
|
Err n -> n
|
||||||
Ok _ -> 0
|
Ok _ -> 0
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
3,
|
3,
|
||||||
i64
|
i64
|
||||||
|
@ -100,14 +100,14 @@ fn result_map_err() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
result : Result {} I64
|
result : Result {} I64
|
||||||
result = Ok {}
|
result = Ok {}
|
||||||
|
|
||||||
when Result.mapErr result (\x -> x + 1) is
|
when Result.mapErr result (\x -> x + 1) is
|
||||||
Err n -> n
|
Err n -> n
|
||||||
Ok _ -> 0
|
Ok _ -> 0
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
0,
|
0,
|
||||||
i64
|
i64
|
||||||
|
@ -119,10 +119,10 @@ fn result_map_err() {
|
||||||
fn err_type_var() {
|
fn err_type_var() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Result.map (Ok 3) (\x -> x + 1)
|
Result.map (Ok 3) (\x -> x + 1)
|
||||||
|> Result.withDefault -1
|
|> Result.withDefault -1
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
4,
|
4,
|
||||||
i64
|
i64
|
||||||
|
@ -134,13 +134,13 @@ fn err_type_var() {
|
||||||
fn err_type_var_annotation() {
|
fn err_type_var_annotation() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
ok : Result I64 *
|
ok : Result I64 *
|
||||||
ok = Ok 3
|
ok = Ok 3
|
||||||
|
|
||||||
Result.map ok (\x -> x + 1)
|
Result.map ok (\x -> x + 1)
|
||||||
|> Result.withDefault -1
|
|> Result.withDefault -1
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
4,
|
4,
|
||||||
i64
|
i64
|
||||||
|
@ -152,13 +152,13 @@ fn err_type_var_annotation() {
|
||||||
fn err_empty_tag_union() {
|
fn err_empty_tag_union() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
ok : Result I64 []
|
ok : Result I64 []
|
||||||
ok = Ok 3
|
ok = Ok 3
|
||||||
|
|
||||||
Result.map ok (\x -> x + 1)
|
Result.map ok (\x -> x + 1)
|
||||||
|> Result.withDefault -1
|
|> Result.withDefault -1
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
4,
|
4,
|
||||||
i64
|
i64
|
||||||
|
@ -170,12 +170,12 @@ fn err_empty_tag_union() {
|
||||||
fn is_ok() {
|
fn is_ok() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
result : Result I64 {}
|
result : Result I64 {}
|
||||||
result = Ok 2
|
result = Ok 2
|
||||||
|
|
||||||
Result.isOk result
|
Result.isOk result
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
true,
|
true,
|
||||||
bool
|
bool
|
||||||
|
@ -183,12 +183,12 @@ fn is_ok() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
result : Result I64 {}
|
result : Result I64 {}
|
||||||
result = Err {}
|
result = Err {}
|
||||||
|
|
||||||
Result.isOk result
|
Result.isOk result
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
false,
|
false,
|
||||||
bool
|
bool
|
||||||
|
@ -200,12 +200,12 @@ fn is_ok() {
|
||||||
fn is_err() {
|
fn is_err() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
result : Result I64 {}
|
result : Result I64 {}
|
||||||
result = Ok 2
|
result = Ok 2
|
||||||
|
|
||||||
Result.isErr result
|
Result.isErr result
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
false,
|
false,
|
||||||
bool
|
bool
|
||||||
|
@ -213,12 +213,12 @@ fn is_err() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
result : Result I64 {}
|
result : Result I64 {}
|
||||||
result = Err {}
|
result = Err {}
|
||||||
|
|
||||||
Result.isErr result
|
Result.isErr result
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
true,
|
true,
|
||||||
bool
|
bool
|
||||||
|
@ -230,12 +230,12 @@ fn is_err() {
|
||||||
fn roc_result_ok_i64() {
|
fn roc_result_ok_i64() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
result : Result I64 {}
|
result : Result I64 {}
|
||||||
result = Ok 42
|
result = Ok 42
|
||||||
|
|
||||||
result
|
result
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
RocResult::ok(42),
|
RocResult::ok(42),
|
||||||
RocResult<i64, ()>
|
RocResult<i64, ()>
|
||||||
|
@ -250,12 +250,12 @@ fn roc_result_ok_f64() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
result : Result F64 {}
|
result : Result F64 {}
|
||||||
result = Ok 42.0
|
result = Ok 42.0
|
||||||
|
|
||||||
result
|
result
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
RocResult::ok(42.0),
|
RocResult::ok(42.0),
|
||||||
RocResult<f64, ()>
|
RocResult<f64, ()>
|
||||||
|
|
|
@ -20,9 +20,9 @@ use roc_std::RocList;
|
||||||
fn empty_len() {
|
fn empty_len() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Set.len (Set.empty {})
|
Set.len (Set.empty {})
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
0,
|
0,
|
||||||
usize
|
usize
|
||||||
|
@ -34,9 +34,9 @@ fn empty_len() {
|
||||||
fn single_len() {
|
fn single_len() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Set.len (Set.single 42)
|
Set.len (Set.single 42)
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
1,
|
1,
|
||||||
usize
|
usize
|
||||||
|
@ -48,9 +48,9 @@ fn single_len() {
|
||||||
fn single_to_list() {
|
fn single_to_list() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Set.toList (Set.single 42)
|
Set.toList (Set.single 42)
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
RocList::from_slice(&[42]),
|
RocList::from_slice(&[42]),
|
||||||
RocList<i64>
|
RocList<i64>
|
||||||
|
@ -58,9 +58,9 @@ fn single_to_list() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Set.toList (Set.single 1)
|
Set.toList (Set.single 1)
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
RocList::from_slice(&[1]),
|
RocList::from_slice(&[1]),
|
||||||
RocList<i64>
|
RocList<i64>
|
||||||
|
@ -72,13 +72,13 @@ fn single_to_list() {
|
||||||
fn insert() {
|
fn insert() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Set.empty {}
|
Set.empty {}
|
||||||
|> Set.insert 0
|
|> Set.insert 0
|
||||||
|> Set.insert 1
|
|> Set.insert 1
|
||||||
|> Set.insert 2
|
|> Set.insert 2
|
||||||
|> Set.toList
|
|> Set.toList
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
RocList::from_slice(&[0, 1, 2]),
|
RocList::from_slice(&[0, 1, 2]),
|
||||||
RocList<i64>
|
RocList<i64>
|
||||||
|
@ -90,14 +90,14 @@ fn insert() {
|
||||||
fn remove() {
|
fn remove() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Set.empty {}
|
Set.empty {}
|
||||||
|> Set.insert 0
|
|> Set.insert 0
|
||||||
|> Set.insert 1
|
|> Set.insert 1
|
||||||
|> Set.remove 1
|
|> Set.remove 1
|
||||||
|> Set.remove 2
|
|> Set.remove 2
|
||||||
|> Set.toList
|
|> Set.toList
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
RocList::from_slice(&[0]),
|
RocList::from_slice(&[0]),
|
||||||
RocList<i64>
|
RocList<i64>
|
||||||
|
@ -109,7 +109,7 @@ fn remove() {
|
||||||
fn union() {
|
fn union() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
set1 : Set.Set I64
|
set1 : Set.Set I64
|
||||||
set1 = Set.fromList [1,2]
|
set1 = Set.fromList [1,2]
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ fn union() {
|
||||||
|
|
||||||
Set.union set1 set2
|
Set.union set1 set2
|
||||||
|> Set.toList
|
|> Set.toList
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
RocList::from_slice(&[1, 3, 4, 2]),
|
RocList::from_slice(&[1, 3, 4, 2]),
|
||||||
RocList<i64>
|
RocList<i64>
|
||||||
|
@ -130,7 +130,7 @@ fn union() {
|
||||||
fn difference() {
|
fn difference() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
set1 : Set.Set I64
|
set1 : Set.Set I64
|
||||||
set1 = Set.fromList [1,2]
|
set1 = Set.fromList [1,2]
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ fn difference() {
|
||||||
|
|
||||||
Set.difference set1 set2
|
Set.difference set1 set2
|
||||||
|> Set.toList
|
|> Set.toList
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
RocList::from_slice(&[2]),
|
RocList::from_slice(&[2]),
|
||||||
RocList<i64>
|
RocList<i64>
|
||||||
|
@ -151,7 +151,7 @@ fn difference() {
|
||||||
fn intersection() {
|
fn intersection() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
set1 : Set.Set I64
|
set1 : Set.Set I64
|
||||||
set1 = Set.fromList [1,2]
|
set1 = Set.fromList [1,2]
|
||||||
|
|
||||||
|
@ -160,7 +160,7 @@ fn intersection() {
|
||||||
|
|
||||||
Set.intersection set1 set2
|
Set.intersection set1 set2
|
||||||
|> Set.toList
|
|> Set.toList
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
RocList::from_slice(&[1]),
|
RocList::from_slice(&[1]),
|
||||||
RocList<i64>
|
RocList<i64>
|
||||||
|
@ -172,9 +172,9 @@ fn intersection() {
|
||||||
fn walk_sum() {
|
fn walk_sum() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Set.walk (Set.fromList [1,2,3]) 0 (\x, y -> x + y)
|
Set.walk (Set.fromList [1,2,3]) 0 (\x, y -> x + y)
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
6,
|
6,
|
||||||
i64
|
i64
|
||||||
|
@ -186,9 +186,9 @@ fn walk_sum() {
|
||||||
fn contains() {
|
fn contains() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Set.contains (Set.fromList [1,3,4]) 4
|
Set.contains (Set.fromList [1,3,4]) 4
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
true,
|
true,
|
||||||
bool
|
bool
|
||||||
|
@ -196,9 +196,9 @@ fn contains() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Set.contains (Set.fromList [1,3,4]) 2
|
Set.contains (Set.fromList [1,3,4]) 2
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
false,
|
false,
|
||||||
bool
|
bool
|
||||||
|
@ -210,11 +210,11 @@ fn contains() {
|
||||||
fn from_list() {
|
fn from_list() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
[1,2,2,3,1,4]
|
[1,2,2,3,1,4]
|
||||||
|> Set.fromList
|
|> Set.fromList
|
||||||
|> Set.toList
|
|> Set.toList
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
RocList::from_slice(&[1, 2, 3, 4]),
|
RocList::from_slice(&[1, 2, 3, 4]),
|
||||||
RocList<i64>
|
RocList<i64>
|
||||||
|
@ -222,14 +222,14 @@ fn from_list() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
empty : List I64
|
empty : List I64
|
||||||
empty = []
|
empty = []
|
||||||
|
|
||||||
empty
|
empty
|
||||||
|> Set.fromList
|
|> Set.fromList
|
||||||
|> Set.toList
|
|> Set.toList
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
RocList::<i64>::default(),
|
RocList::<i64>::default(),
|
||||||
RocList<i64>
|
RocList<i64>
|
||||||
|
@ -242,11 +242,11 @@ fn from_list() {
|
||||||
fn from_list_void() {
|
fn from_list_void() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
[]
|
[]
|
||||||
|> Set.fromList
|
|> Set.fromList
|
||||||
|> Set.toList
|
|> Set.toList
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
RocList::<i64>::default(),
|
RocList::<i64>::default(),
|
||||||
RocList<i64>
|
RocList<i64>
|
||||||
|
@ -258,9 +258,9 @@ fn from_list_void() {
|
||||||
fn to_list_empty() {
|
fn to_list_empty() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Set.toList (Set.empty {})
|
Set.toList (Set.empty {})
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
RocList::<std::convert::Infallible>::default(),
|
RocList::<std::convert::Infallible>::default(),
|
||||||
RocList<std::convert::Infallible>
|
RocList<std::convert::Infallible>
|
||||||
|
|
|
@ -39,14 +39,14 @@ fn width_and_alignment_u8_u8() {
|
||||||
fn applied_tag_nothing() {
|
fn applied_tag_nothing() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Maybe a : [Just a, Nothing]
|
Maybe a : [Just a, Nothing]
|
||||||
|
|
||||||
x : Maybe I64
|
x : Maybe I64
|
||||||
x = Nothing
|
x = Nothing
|
||||||
|
|
||||||
x
|
x
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
1,
|
1,
|
||||||
(i64, u8),
|
(i64, u8),
|
||||||
|
@ -59,14 +59,14 @@ fn applied_tag_nothing() {
|
||||||
fn applied_tag_just() {
|
fn applied_tag_just() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Maybe a : [Just a, Nothing]
|
Maybe a : [Just a, Nothing]
|
||||||
|
|
||||||
y : Maybe I64
|
y : Maybe I64
|
||||||
y = Just 0x4
|
y = Just 0x4
|
||||||
|
|
||||||
y
|
y
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(0x4, 0),
|
(0x4, 0),
|
||||||
(i64, u8)
|
(i64, u8)
|
||||||
|
@ -78,7 +78,7 @@ fn applied_tag_just() {
|
||||||
fn applied_tag_just_enum() {
|
fn applied_tag_just_enum() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Fruit : [Orange, Apple, Banana]
|
Fruit : [Orange, Apple, Banana]
|
||||||
Maybe a : [Just a, Nothing]
|
Maybe a : [Just a, Nothing]
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ fn applied_tag_just_enum() {
|
||||||
y = Just orange
|
y = Just orange
|
||||||
|
|
||||||
y
|
y
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(2, 0),
|
(2, 0),
|
||||||
(u8, u8)
|
(u8, u8)
|
||||||
|
@ -101,12 +101,12 @@ fn applied_tag_just_enum() {
|
||||||
fn true_is_true() {
|
fn true_is_true() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
bool : Bool
|
bool : Bool
|
||||||
bool = Bool.true
|
bool = Bool.true
|
||||||
|
|
||||||
bool
|
bool
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
true,
|
true,
|
||||||
bool
|
bool
|
||||||
|
@ -118,12 +118,12 @@ fn true_is_true() {
|
||||||
fn false_is_false() {
|
fn false_is_false() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
bool : Bool
|
bool : Bool
|
||||||
bool = Bool.false
|
bool = Bool.false
|
||||||
|
|
||||||
bool
|
bool
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
false,
|
false,
|
||||||
bool
|
bool
|
||||||
|
@ -135,7 +135,7 @@ fn false_is_false() {
|
||||||
fn basic_enum() {
|
fn basic_enum() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Fruit : [Apple, Orange, Banana]
|
Fruit : [Apple, Orange, Banana]
|
||||||
|
|
||||||
apple : Fruit
|
apple : Fruit
|
||||||
|
@ -145,7 +145,7 @@ fn basic_enum() {
|
||||||
orange = Orange
|
orange = Orange
|
||||||
|
|
||||||
apple == orange
|
apple == orange
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
false,
|
false,
|
||||||
bool
|
bool
|
||||||
|
@ -157,7 +157,7 @@ fn basic_enum() {
|
||||||
fn even_odd() {
|
fn even_odd() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
even = \n ->
|
even = \n ->
|
||||||
when n is
|
when n is
|
||||||
0 -> Bool.true
|
0 -> Bool.true
|
||||||
|
@ -171,7 +171,7 @@ fn even_odd() {
|
||||||
_ -> even (n - 1)
|
_ -> even (n - 1)
|
||||||
|
|
||||||
odd 5 && even 42
|
odd 5 && even 42
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
true,
|
true,
|
||||||
bool
|
bool
|
||||||
|
@ -183,9 +183,9 @@ fn even_odd() {
|
||||||
fn gen_literal_true() {
|
fn gen_literal_true() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
if Bool.true then -1 else 1
|
if Bool.true then -1 else 1
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
-1,
|
-1,
|
||||||
i64
|
i64
|
||||||
|
@ -197,9 +197,9 @@ fn gen_literal_true() {
|
||||||
fn gen_if_float() {
|
fn gen_if_float() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
if Bool.true then -1.0 else 1.0f64
|
if Bool.true then -1.0 else 1.0f64
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
-1.0,
|
-1.0,
|
||||||
f64
|
f64
|
||||||
|
@ -210,14 +210,14 @@ fn gen_if_float() {
|
||||||
fn when_on_nothing() {
|
fn when_on_nothing() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
x : [Nothing, Just I64]
|
x : [Nothing, Just I64]
|
||||||
x = Nothing
|
x = Nothing
|
||||||
|
|
||||||
when x is
|
when x is
|
||||||
Nothing -> 0x2
|
Nothing -> 0x2
|
||||||
Just _ -> 0x1
|
Just _ -> 0x1
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
2,
|
2,
|
||||||
i64
|
i64
|
||||||
|
@ -229,14 +229,14 @@ fn when_on_nothing() {
|
||||||
fn when_on_just() {
|
fn when_on_just() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
x : [Nothing, Just I64]
|
x : [Nothing, Just I64]
|
||||||
x = Just 41
|
x = Just 41
|
||||||
|
|
||||||
when x is
|
when x is
|
||||||
Just v -> v + 0x1
|
Just v -> v + 0x1
|
||||||
Nothing -> 0x1
|
Nothing -> 0x1
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
42,
|
42,
|
||||||
i64
|
i64
|
||||||
|
@ -248,14 +248,14 @@ fn when_on_just() {
|
||||||
fn when_on_result() {
|
fn when_on_result() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
x : Result I64 I64
|
x : Result I64 I64
|
||||||
x = Err 41
|
x = Err 41
|
||||||
|
|
||||||
when x is
|
when x is
|
||||||
Err v -> v + 1
|
Err v -> v + 1
|
||||||
Ok _ -> 1
|
Ok _ -> 1
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
42,
|
42,
|
||||||
i64
|
i64
|
||||||
|
@ -267,7 +267,7 @@ fn when_on_result() {
|
||||||
fn when_on_these() {
|
fn when_on_these() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
These a b : [This a, That b, These a b]
|
These a b : [This a, That b, These a b]
|
||||||
|
|
||||||
x : These I64 I64
|
x : These I64 I64
|
||||||
|
@ -277,7 +277,7 @@ fn when_on_these() {
|
||||||
These a b -> a + b
|
These a b -> a + b
|
||||||
That v -> v
|
That v -> v
|
||||||
This v -> v
|
This v -> v
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
5,
|
5,
|
||||||
i64
|
i64
|
||||||
|
@ -290,11 +290,11 @@ fn match_on_two_values() {
|
||||||
// this will produce a Chain internally
|
// this will produce a Chain internally
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
when Pair 2 3 is
|
when Pair 2 3 is
|
||||||
Pair 4 3 -> 9
|
Pair 4 3 -> 9
|
||||||
Pair a b -> a + b
|
Pair a b -> a + b
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
5,
|
5,
|
||||||
i64
|
i64
|
||||||
|
@ -306,12 +306,12 @@ fn match_on_two_values() {
|
||||||
fn pair_with_underscore() {
|
fn pair_with_underscore() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
when Pair 2 3 is
|
when Pair 2 3 is
|
||||||
Pair 4 _ -> 1
|
Pair 4 _ -> 1
|
||||||
Pair 3 _ -> 2
|
Pair 3 _ -> 2
|
||||||
Pair a b -> a + b
|
Pair a b -> a + b
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
5,
|
5,
|
||||||
i64
|
i64
|
||||||
|
@ -324,7 +324,7 @@ fn result_with_underscore() {
|
||||||
// This test revealed an issue with hashing Test values
|
// This test revealed an issue with hashing Test values
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
x : Result I64 I64
|
x : Result I64 I64
|
||||||
x = Ok 2
|
x = Ok 2
|
||||||
|
|
||||||
|
@ -332,7 +332,7 @@ fn result_with_underscore() {
|
||||||
Ok 3 -> 1
|
Ok 3 -> 1
|
||||||
Ok _ -> 2
|
Ok _ -> 2
|
||||||
Err _ -> 3
|
Err _ -> 3
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
2,
|
2,
|
||||||
i64
|
i64
|
||||||
|
@ -369,7 +369,7 @@ fn maybe_is_just_not_nested() {
|
||||||
fn maybe_is_just_nested() {
|
fn maybe_is_just_nested() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Maybe a : [Just a, Nothing]
|
Maybe a : [Just a, Nothing]
|
||||||
|
|
||||||
isJust : Maybe a -> Bool
|
isJust : Maybe a -> Bool
|
||||||
|
@ -379,7 +379,7 @@ fn maybe_is_just_nested() {
|
||||||
Just _ -> Bool.true
|
Just _ -> Bool.true
|
||||||
|
|
||||||
isJust (Just 42)
|
isJust (Just 42)
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
true,
|
true,
|
||||||
bool
|
bool
|
||||||
|
@ -391,7 +391,7 @@ fn maybe_is_just_nested() {
|
||||||
fn nested_pattern_match() {
|
fn nested_pattern_match() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Maybe a : [Nothing, Just a]
|
Maybe a : [Nothing, Just a]
|
||||||
|
|
||||||
x : Maybe (Maybe I64)
|
x : Maybe (Maybe I64)
|
||||||
|
@ -400,7 +400,7 @@ fn nested_pattern_match() {
|
||||||
when x is
|
when x is
|
||||||
Just (Just v) -> v + 0x1
|
Just (Just v) -> v + 0x1
|
||||||
_ -> 0x1
|
_ -> 0x1
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
42,
|
42,
|
||||||
i64
|
i64
|
||||||
|
@ -428,11 +428,11 @@ fn if_guard_vanilla() {
|
||||||
fn when_on_single_value_tag() {
|
fn when_on_single_value_tag() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
when Identity 0 is
|
when Identity 0 is
|
||||||
Identity 0 -> 6
|
Identity 0 -> 6
|
||||||
Identity s -> s
|
Identity s -> s
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
6,
|
6,
|
||||||
i64
|
i64
|
||||||
|
@ -444,7 +444,7 @@ fn when_on_single_value_tag() {
|
||||||
fn if_guard_multiple() {
|
fn if_guard_multiple() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
f = \n ->
|
f = \n ->
|
||||||
when Identity n 0 is
|
when Identity n 0 is
|
||||||
Identity x _ if x == 0 -> x + 0
|
Identity x _ if x == 0 -> x + 0
|
||||||
|
@ -453,7 +453,7 @@ fn if_guard_multiple() {
|
||||||
Identity x _ -> x - x
|
Identity x _ -> x - x
|
||||||
|
|
||||||
{ a: f 0, b: f 1, c: f 2, d: f 4 }
|
{ a: f 0, b: f 1, c: f 2, d: f 4 }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
[0, 1, 2, 0],
|
[0, 1, 2, 0],
|
||||||
[i64; 4]
|
[i64; 4]
|
||||||
|
@ -465,13 +465,13 @@ fn if_guard_multiple() {
|
||||||
fn if_guard_constructor_switch() {
|
fn if_guard_constructor_switch() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
when Identity 32 0 is
|
when Identity 32 0 is
|
||||||
Identity 41 _ -> 0
|
Identity 41 _ -> 0
|
||||||
Identity s 0 if s == 32 -> 3
|
Identity s 0 if s == 32 -> 3
|
||||||
# Identity s 0 -> s
|
# Identity s 0 -> s
|
||||||
Identity z _ -> z
|
Identity z _ -> z
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
3,
|
3,
|
||||||
i64
|
i64
|
||||||
|
@ -509,12 +509,12 @@ fn if_guard_constructor_switch() {
|
||||||
fn if_guard_constructor_chain() {
|
fn if_guard_constructor_chain() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
when Identity 43 0 is
|
when Identity 43 0 is
|
||||||
Identity 42 _ if 3 == 3 -> 43
|
Identity 42 _ if 3 == 3 -> 43
|
||||||
# Identity 42 _ -> 1
|
# Identity 42 _ -> 1
|
||||||
Identity z _ -> z
|
Identity z _ -> z
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
43,
|
43,
|
||||||
i64
|
i64
|
||||||
|
@ -526,14 +526,14 @@ fn if_guard_constructor_chain() {
|
||||||
fn if_guard_pattern_false() {
|
fn if_guard_pattern_false() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
wrapper = \{} ->
|
wrapper = \{} ->
|
||||||
when 2 is
|
when 2 is
|
||||||
2 if Bool.false -> 0
|
2 if Bool.false -> 0
|
||||||
_ -> 42
|
_ -> 42
|
||||||
|
|
||||||
wrapper {}
|
wrapper {}
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
42,
|
42,
|
||||||
i64
|
i64
|
||||||
|
@ -545,14 +545,14 @@ fn if_guard_pattern_false() {
|
||||||
fn if_guard_switch() {
|
fn if_guard_switch() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
wrapper = \{} ->
|
wrapper = \{} ->
|
||||||
when 2 is
|
when 2 is
|
||||||
2 | 3 if Bool.false -> 0
|
2 | 3 if Bool.false -> 0
|
||||||
_ -> 42
|
_ -> 42
|
||||||
|
|
||||||
wrapper {}
|
wrapper {}
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
42,
|
42,
|
||||||
i64
|
i64
|
||||||
|
@ -564,14 +564,14 @@ fn if_guard_switch() {
|
||||||
fn if_guard_pattern_true() {
|
fn if_guard_pattern_true() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
wrapper = \{} ->
|
wrapper = \{} ->
|
||||||
when 2 is
|
when 2 is
|
||||||
2 if Bool.true -> 42
|
2 if Bool.true -> 42
|
||||||
_ -> 0
|
_ -> 0
|
||||||
|
|
||||||
wrapper {}
|
wrapper {}
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
42,
|
42,
|
||||||
i64
|
i64
|
||||||
|
@ -583,14 +583,14 @@ fn if_guard_pattern_true() {
|
||||||
fn if_guard_exhaustiveness() {
|
fn if_guard_exhaustiveness() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
wrapper = \{} ->
|
wrapper = \{} ->
|
||||||
when 2 is
|
when 2 is
|
||||||
_ if Bool.false -> 0
|
_ if Bool.false -> 0
|
||||||
_ -> 42
|
_ -> 42
|
||||||
|
|
||||||
wrapper {}
|
wrapper {}
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
42,
|
42,
|
||||||
i64
|
i64
|
||||||
|
@ -602,7 +602,7 @@ fn if_guard_exhaustiveness() {
|
||||||
fn when_on_enum() {
|
fn when_on_enum() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Fruit : [Apple, Orange, Banana]
|
Fruit : [Apple, Orange, Banana]
|
||||||
|
|
||||||
apple : Fruit
|
apple : Fruit
|
||||||
|
@ -612,7 +612,7 @@ fn when_on_enum() {
|
||||||
Apple -> 1
|
Apple -> 1
|
||||||
Banana -> 2
|
Banana -> 2
|
||||||
Orange -> 3
|
Orange -> 3
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
1,
|
1,
|
||||||
i64
|
i64
|
||||||
|
@ -624,14 +624,14 @@ fn when_on_enum() {
|
||||||
fn pattern_matching_unit() {
|
fn pattern_matching_unit() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Unit : [Unit]
|
Unit : [Unit]
|
||||||
|
|
||||||
f : Unit -> I64
|
f : Unit -> I64
|
||||||
f = \Unit -> 42
|
f = \Unit -> 42
|
||||||
|
|
||||||
f Unit
|
f Unit
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
42,
|
42,
|
||||||
i64
|
i64
|
||||||
|
@ -639,7 +639,7 @@ fn pattern_matching_unit() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Unit : [Unit]
|
Unit : [Unit]
|
||||||
|
|
||||||
x : Unit
|
x : Unit
|
||||||
|
@ -647,7 +647,7 @@ fn pattern_matching_unit() {
|
||||||
|
|
||||||
when x is
|
when x is
|
||||||
Unit -> 42
|
Unit -> 42
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
42,
|
42,
|
||||||
i64
|
i64
|
||||||
|
@ -655,12 +655,12 @@ fn pattern_matching_unit() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
f : {} -> I64
|
f : {} -> I64
|
||||||
f = \{} -> 42
|
f = \{} -> 42
|
||||||
|
|
||||||
f {}
|
f {}
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
42,
|
42,
|
||||||
i64
|
i64
|
||||||
|
@ -668,10 +668,10 @@ fn pattern_matching_unit() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
when {} is
|
when {} is
|
||||||
{} -> 42
|
{} -> 42
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
42,
|
42,
|
||||||
i64
|
i64
|
||||||
|
@ -683,12 +683,12 @@ fn pattern_matching_unit() {
|
||||||
fn one_element_tag() {
|
fn one_element_tag() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
x : [Pair I64]
|
x : [Pair I64]
|
||||||
x = Pair 2
|
x = Pair 2
|
||||||
|
|
||||||
x
|
x
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
2,
|
2,
|
||||||
i64
|
i64
|
||||||
|
@ -721,14 +721,14 @@ fn nested_tag_union() {
|
||||||
fn unit_type() {
|
fn unit_type() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Unit : [Unit]
|
Unit : [Unit]
|
||||||
|
|
||||||
v : Unit
|
v : Unit
|
||||||
v = Unit
|
v = Unit
|
||||||
|
|
||||||
v
|
v
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(),
|
(),
|
||||||
()
|
()
|
||||||
|
@ -740,12 +740,12 @@ fn unit_type() {
|
||||||
fn join_point_if() {
|
fn join_point_if() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
x =
|
x =
|
||||||
if Bool.true then 1 else 2
|
if Bool.true then 1 else 2
|
||||||
|
|
||||||
x
|
x
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
1,
|
1,
|
||||||
i64
|
i64
|
||||||
|
@ -757,7 +757,7 @@ fn join_point_if() {
|
||||||
fn join_point_when() {
|
fn join_point_when() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
wrapper = \{} ->
|
wrapper = \{} ->
|
||||||
x : [Red, White, Blue]
|
x : [Red, White, Blue]
|
||||||
x = Blue
|
x = Blue
|
||||||
|
@ -771,7 +771,7 @@ fn join_point_when() {
|
||||||
y
|
y
|
||||||
|
|
||||||
wrapper {}
|
wrapper {}
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
3.1,
|
3.1,
|
||||||
f64
|
f64
|
||||||
|
@ -783,7 +783,7 @@ fn join_point_when() {
|
||||||
fn join_point_with_cond_expr() {
|
fn join_point_with_cond_expr() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
wrapper = \{} ->
|
wrapper = \{} ->
|
||||||
y =
|
y =
|
||||||
when 1 + 2 is
|
when 1 + 2 is
|
||||||
|
@ -794,7 +794,7 @@ fn join_point_with_cond_expr() {
|
||||||
y
|
y
|
||||||
|
|
||||||
wrapper {}
|
wrapper {}
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
3,
|
3,
|
||||||
i64
|
i64
|
||||||
|
@ -802,7 +802,7 @@ fn join_point_with_cond_expr() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
y =
|
y =
|
||||||
if 1 + 2 > 0 then
|
if 1 + 2 > 0 then
|
||||||
3
|
3
|
||||||
|
@ -810,7 +810,7 @@ fn join_point_with_cond_expr() {
|
||||||
0
|
0
|
||||||
|
|
||||||
y
|
y
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
3,
|
3,
|
||||||
i64
|
i64
|
||||||
|
@ -1135,12 +1135,12 @@ fn applied_tag_function_pair() {
|
||||||
fn tag_must_be_its_own_type() {
|
fn tag_must_be_its_own_type() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
z : [A, B, C]
|
z : [A, B, C]
|
||||||
z = Z
|
z = Z
|
||||||
|
|
||||||
z
|
z
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
1,
|
1,
|
||||||
i64
|
i64
|
||||||
|
@ -1171,12 +1171,12 @@ fn recursive_tag_union_into_flat_tag_union() {
|
||||||
fn monomorphized_tag() {
|
fn monomorphized_tag() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
b = \{} -> Bar
|
b = \{} -> Bar
|
||||||
f : [Foo, Bar], [Bar, Baz] -> U8
|
f : [Foo, Bar], [Bar, Baz] -> U8
|
||||||
f = \_, _ -> 18
|
f = \_, _ -> 18
|
||||||
f (b {}) (b {})
|
f (b {}) (b {})
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
18,
|
18,
|
||||||
u8
|
u8
|
||||||
|
@ -1391,7 +1391,7 @@ fn issue_2445() {
|
||||||
fn issue_2458() {
|
fn issue_2458() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Foo a : [Blah (Bar a), Nothing {}]
|
Foo a : [Blah (Bar a), Nothing {}]
|
||||||
Bar a : Foo a
|
Bar a : Foo a
|
||||||
|
|
||||||
|
@ -1401,7 +1401,7 @@ fn issue_2458() {
|
||||||
when v is
|
when v is
|
||||||
Blah (Blah (Nothing {})) -> 15
|
Blah (Blah (Nothing {})) -> 15
|
||||||
_ -> 25
|
_ -> 25
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
15,
|
15,
|
||||||
u8
|
u8
|
||||||
|
@ -1471,11 +1471,11 @@ fn issue_1162() {
|
||||||
fn polymorphic_tag() {
|
fn polymorphic_tag() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
x : [Y U8]
|
x : [Y U8]
|
||||||
x = Y 3
|
x = Y 3
|
||||||
x
|
x
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
3, // Y is a newtype, it gets unwrapped
|
3, // Y is a newtype, it gets unwrapped
|
||||||
u8
|
u8
|
||||||
|
@ -1487,11 +1487,11 @@ fn polymorphic_tag() {
|
||||||
fn issue_2725_alias_polymorphic_lambda() {
|
fn issue_2725_alias_polymorphic_lambda() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
wrap = \value -> Tag value
|
wrap = \value -> Tag value
|
||||||
wrapIt = wrap
|
wrapIt = wrap
|
||||||
wrapIt 42
|
wrapIt 42
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
42, // Tag is a newtype, it gets unwrapped
|
42, // Tag is a newtype, it gets unwrapped
|
||||||
i64
|
i64
|
||||||
|
@ -1717,7 +1717,7 @@ fn instantiate_annotated_as_recursive_alias_multiple_polymorphic_expr() {
|
||||||
fn issue_3560_nested_tag_constructor_is_newtype() {
|
fn issue_3560_nested_tag_constructor_is_newtype() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
f : _ -> u8
|
f : _ -> u8
|
||||||
f = \t ->
|
f = \t ->
|
||||||
when t is
|
when t is
|
||||||
|
@ -1725,7 +1725,7 @@ fn issue_3560_nested_tag_constructor_is_newtype() {
|
||||||
Wrapper (AlternatePayload it) -> it
|
Wrapper (AlternatePayload it) -> it
|
||||||
|
|
||||||
{a: f (Wrapper (Payload 15u8)), b: f(Wrapper (AlternatePayload 31u8))}
|
{a: f (Wrapper (Payload 15u8)), b: f(Wrapper (AlternatePayload 31u8))}
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(15, 31),
|
(15, 31),
|
||||||
(u8, u8)
|
(u8, u8)
|
||||||
|
@ -1737,7 +1737,7 @@ fn issue_3560_nested_tag_constructor_is_newtype() {
|
||||||
fn issue_3560_nested_tag_constructor_is_record_newtype() {
|
fn issue_3560_nested_tag_constructor_is_record_newtype() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
f : _ -> u8
|
f : _ -> u8
|
||||||
f = \t ->
|
f = \t ->
|
||||||
when t is
|
when t is
|
||||||
|
@ -1745,7 +1745,7 @@ fn issue_3560_nested_tag_constructor_is_record_newtype() {
|
||||||
{wrapper: (AlternatePayload it)} -> it
|
{wrapper: (AlternatePayload it)} -> it
|
||||||
|
|
||||||
{a: f {wrapper: (Payload 15u8)}, b: f {wrapper: (AlternatePayload 31u8)}}
|
{a: f {wrapper: (Payload 15u8)}, b: f {wrapper: (AlternatePayload 31u8)}}
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(15, 31),
|
(15, 31),
|
||||||
(u8, u8)
|
(u8, u8)
|
||||||
|
@ -1791,7 +1791,7 @@ fn alignment_i128() {
|
||||||
fn error_type_in_tag_union_payload() {
|
fn error_type_in_tag_union_payload() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
f : ([] -> Bool) -> Bool
|
f : ([] -> Bool) -> Bool
|
||||||
f = \fun ->
|
f = \fun ->
|
||||||
if Bool.true then
|
if Bool.true then
|
||||||
|
@ -1800,7 +1800,7 @@ fn error_type_in_tag_union_payload() {
|
||||||
Bool.false
|
Bool.false
|
||||||
|
|
||||||
f (\x -> x)
|
f (\x -> x)
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
0,
|
0,
|
||||||
u8,
|
u8,
|
||||||
|
@ -1864,7 +1864,7 @@ fn issue_3653_recursion_pointer_in_naked_opaque_localized() {
|
||||||
fn issue_2165_recursive_tag_destructure() {
|
fn issue_2165_recursive_tag_destructure() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
SomeTag : [ Ctor { rec : List SomeTag } ]
|
SomeTag : [ Ctor { rec : List SomeTag } ]
|
||||||
|
|
||||||
x : SomeTag
|
x : SomeTag
|
||||||
|
@ -1872,7 +1872,7 @@ fn issue_2165_recursive_tag_destructure() {
|
||||||
|
|
||||||
when x is
|
when x is
|
||||||
Ctor { rec } -> Num.toStr (List.len rec)
|
Ctor { rec } -> Num.toStr (List.len rec)
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
RocStr::from("0"),
|
RocStr::from("0"),
|
||||||
RocStr
|
RocStr
|
||||||
|
@ -2183,7 +2183,7 @@ fn issue_5162_recast_nested_nullable_unwrapped_layout() {
|
||||||
with_larger_debug_stack(|| {
|
with_larger_debug_stack(|| {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r###"
|
r#"
|
||||||
app "test" provides [main] to "./platform"
|
app "test" provides [main] to "./platform"
|
||||||
|
|
||||||
Concept : [
|
Concept : [
|
||||||
|
@ -2197,7 +2197,7 @@ fn issue_5162_recast_nested_nullable_unwrapped_layout() {
|
||||||
main =
|
main =
|
||||||
when Dict.single bottom 0 is
|
when Dict.single bottom 0 is
|
||||||
_ -> Bool.true
|
_ -> Bool.true
|
||||||
"###
|
"#
|
||||||
),
|
),
|
||||||
true,
|
true,
|
||||||
bool
|
bool
|
||||||
|
@ -2210,7 +2210,7 @@ fn issue_5162_recast_nested_nullable_unwrapped_layout() {
|
||||||
fn nullable_wrapped_eq_issue_5434() {
|
fn nullable_wrapped_eq_issue_5434() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r###"
|
r#"
|
||||||
app "test" provides [main] to "./platform"
|
app "test" provides [main] to "./platform"
|
||||||
|
|
||||||
Value : [
|
Value : [
|
||||||
|
@ -2229,7 +2229,7 @@ fn nullable_wrapped_eq_issue_5434() {
|
||||||
Bool.true
|
Bool.true
|
||||||
else
|
else
|
||||||
Bool.false
|
Bool.false
|
||||||
"###
|
"#
|
||||||
),
|
),
|
||||||
false,
|
false,
|
||||||
bool
|
bool
|
||||||
|
@ -2241,7 +2241,7 @@ fn nullable_wrapped_eq_issue_5434() {
|
||||||
fn recursive_tag_id_in_allocation_basic() {
|
fn recursive_tag_id_in_allocation_basic() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r###"
|
r#"
|
||||||
app "test" provides [main] to "./platform"
|
app "test" provides [main] to "./platform"
|
||||||
|
|
||||||
Value : [
|
Value : [
|
||||||
|
@ -2270,7 +2270,7 @@ fn recursive_tag_id_in_allocation_basic() {
|
||||||
G _ -> "G"
|
G _ -> "G"
|
||||||
H _ -> "H"
|
H _ -> "H"
|
||||||
I _ -> "I"
|
I _ -> "I"
|
||||||
"###
|
"#
|
||||||
),
|
),
|
||||||
RocStr::from("H"),
|
RocStr::from("H"),
|
||||||
RocStr
|
RocStr
|
||||||
|
@ -2282,7 +2282,7 @@ fn recursive_tag_id_in_allocation_basic() {
|
||||||
fn recursive_tag_id_in_allocation_eq() {
|
fn recursive_tag_id_in_allocation_eq() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r###"
|
r#"
|
||||||
app "test" provides [main] to "./platform"
|
app "test" provides [main] to "./platform"
|
||||||
|
|
||||||
Value : [
|
Value : [
|
||||||
|
@ -2304,7 +2304,7 @@ fn recursive_tag_id_in_allocation_eq() {
|
||||||
y = H 42
|
y = H 42
|
||||||
|
|
||||||
main = (x == x) && (x != y) && (y == y)
|
main = (x == x) && (x != y) && (y == y)
|
||||||
"###
|
"#
|
||||||
),
|
),
|
||||||
true,
|
true,
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -18,9 +18,9 @@ use roc_std::RocStr;
|
||||||
fn basic_tuple() {
|
fn basic_tuple() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
( 15, 17, 19 ).0
|
( 15, 17, 19 ).0
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
15,
|
15,
|
||||||
i64
|
i64
|
||||||
|
@ -28,9 +28,9 @@ fn basic_tuple() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
( 15, 17, 19 ).1
|
( 15, 17, 19 ).1
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
17,
|
17,
|
||||||
i64
|
i64
|
||||||
|
@ -38,9 +38,9 @@ fn basic_tuple() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
( 15, 17, 19 ).2
|
( 15, 17, 19 ).2
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
19,
|
19,
|
||||||
i64
|
i64
|
||||||
|
@ -52,11 +52,11 @@ fn basic_tuple() {
|
||||||
fn f64_tuple() {
|
fn f64_tuple() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
tup = (17.2f64, 15.1f64, 19.3f64)
|
tup = (17.2f64, 15.1f64, 19.3f64)
|
||||||
|
|
||||||
tup.0
|
tup.0
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
17.2,
|
17.2,
|
||||||
f64
|
f64
|
||||||
|
@ -64,11 +64,11 @@ fn f64_tuple() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
tup = (17.2f64, 15.1f64, 19.3f64)
|
tup = (17.2f64, 15.1f64, 19.3f64)
|
||||||
|
|
||||||
tup.1
|
tup.1
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
15.1,
|
15.1,
|
||||||
f64
|
f64
|
||||||
|
@ -76,11 +76,11 @@ fn f64_tuple() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
tup = (17.2f64, 15.1f64, 19.3f64)
|
tup = (17.2f64, 15.1f64, 19.3f64)
|
||||||
|
|
||||||
tup.2
|
tup.2
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
19.3,
|
19.3,
|
||||||
f64
|
f64
|
||||||
|
@ -104,11 +104,11 @@ fn fn_tuple() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
rec = (15, 17, 19)
|
rec = (15, 17, 19)
|
||||||
|
|
||||||
rec.2 + rec.0
|
rec.2 + rec.0
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
34,
|
34,
|
||||||
i64
|
i64
|
||||||
|
@ -120,11 +120,11 @@ fn fn_tuple() {
|
||||||
fn int_tuple() {
|
fn int_tuple() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
rec = (15, 17, 19)
|
rec = (15, 17, 19)
|
||||||
|
|
||||||
rec.0
|
rec.0
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
15,
|
15,
|
||||||
i64
|
i64
|
||||||
|
@ -132,11 +132,11 @@ fn int_tuple() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
rec = (15, 17, 19)
|
rec = (15, 17, 19)
|
||||||
|
|
||||||
rec.1
|
rec.1
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
17,
|
17,
|
||||||
i64
|
i64
|
||||||
|
@ -144,11 +144,11 @@ fn int_tuple() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
rec = (15, 17, 19)
|
rec = (15, 17, 19)
|
||||||
|
|
||||||
rec.2
|
rec.2
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
19,
|
19,
|
||||||
i64
|
i64
|
||||||
|
@ -160,10 +160,10 @@ fn int_tuple() {
|
||||||
fn when_on_tuple() {
|
fn when_on_tuple() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
when (0x2, 0x3) is
|
when (0x2, 0x3) is
|
||||||
(x, y) -> x + y
|
(x, y) -> x + y
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
5,
|
5,
|
||||||
i64
|
i64
|
||||||
|
@ -175,10 +175,10 @@ fn when_on_tuple() {
|
||||||
fn when_tuple_with_guard_pattern() {
|
fn when_tuple_with_guard_pattern() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
when (0x2, 1.23) is
|
when (0x2, 1.23) is
|
||||||
(var, _) -> var + 3
|
(var, _) -> var + 3
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
5,
|
5,
|
||||||
i64
|
i64
|
||||||
|
@ -190,11 +190,11 @@ fn when_tuple_with_guard_pattern() {
|
||||||
fn let_with_tuple_pattern() {
|
fn let_with_tuple_pattern() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
(x, _ ) = (0x2, 1.23)
|
(x, _ ) = (0x2, 1.23)
|
||||||
|
|
||||||
x
|
x
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
2,
|
2,
|
||||||
i64
|
i64
|
||||||
|
@ -202,11 +202,11 @@ fn let_with_tuple_pattern() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
(_, y) = (0x2, 0x3)
|
(_, y) = (0x2, 0x3)
|
||||||
|
|
||||||
y
|
y
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
3,
|
3,
|
||||||
i64
|
i64
|
||||||
|
@ -218,11 +218,11 @@ fn let_with_tuple_pattern() {
|
||||||
fn tuple_guard_pattern() {
|
fn tuple_guard_pattern() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
when (0x2, 1.23) is
|
when (0x2, 1.23) is
|
||||||
(0x4, _) -> 5
|
(0x4, _) -> 5
|
||||||
(x, _) -> x + 4
|
(x, _) -> x + 4
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
6,
|
6,
|
||||||
i64
|
i64
|
||||||
|
@ -230,11 +230,11 @@ fn tuple_guard_pattern() {
|
||||||
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
when (0x2, 0x3) is
|
when (0x2, 0x3) is
|
||||||
(_, 0x4) -> 5
|
(_, 0x4) -> 5
|
||||||
(_, x) -> x + 4
|
(_, x) -> x + 4
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
7,
|
7,
|
||||||
i64
|
i64
|
||||||
|
@ -246,11 +246,11 @@ fn tuple_guard_pattern() {
|
||||||
fn twice_tuple_access() {
|
fn twice_tuple_access() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
x = (0x2, 0x3)
|
x = (0x2, 0x3)
|
||||||
|
|
||||||
x.0 + x.1
|
x.0 + x.1
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
5,
|
5,
|
||||||
i64
|
i64
|
||||||
|
@ -262,9 +262,9 @@ fn twice_tuple_access() {
|
||||||
fn i64_tuple2_literal() {
|
fn i64_tuple2_literal() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
(3, 5)
|
(3, 5)
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(3, 5),
|
(3, 5),
|
||||||
(i64, i64)
|
(i64, i64)
|
||||||
|
@ -276,9 +276,9 @@ fn i64_tuple2_literal() {
|
||||||
fn i64_tuple3_literal() {
|
fn i64_tuple3_literal() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
(3, 5, 17)
|
(3, 5, 17)
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(3, 5, 17),
|
(3, 5, 17),
|
||||||
(i64, i64, i64)
|
(i64, i64, i64)
|
||||||
|
@ -290,9 +290,9 @@ fn i64_tuple3_literal() {
|
||||||
fn f64_tuple2_literal() {
|
fn f64_tuple2_literal() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
(3.1f64, 5.1f64)
|
(3.1f64, 5.1f64)
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(3.1, 5.1),
|
(3.1, 5.1),
|
||||||
(f64, f64)
|
(f64, f64)
|
||||||
|
@ -304,12 +304,12 @@ fn f64_tuple2_literal() {
|
||||||
fn bool_tuple4_literal() {
|
fn bool_tuple4_literal() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
tuple : (Bool, Bool, Bool, Bool)
|
tuple : (Bool, Bool, Bool, Bool)
|
||||||
tuple = (Bool.true, Bool.false, Bool.false, Bool.true)
|
tuple = (Bool.true, Bool.false, Bool.false, Bool.true)
|
||||||
|
|
||||||
tuple
|
tuple
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(true, false, false, true),
|
(true, false, false, true),
|
||||||
(bool, bool, bool, bool)
|
(bool, bool, bool, bool)
|
||||||
|
@ -323,9 +323,9 @@ fn bool_tuple4_literal() {
|
||||||
fn i64_tuple9_literal() {
|
fn i64_tuple9_literal() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
( 3, 5, 17, 1, 9, 12, 13, 14, 15 )
|
( 3, 5, 17, 1, 9, 12, 13, 14, 15 )
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
[3, 5, 17, 1, 9, 12, 13, 14, 15],
|
[3, 5, 17, 1, 9, 12, 13, 14, 15],
|
||||||
[i64; 9]
|
[i64; 9]
|
||||||
|
@ -337,12 +337,12 @@ fn i64_tuple9_literal() {
|
||||||
fn return_tuple() {
|
fn return_tuple() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
x = 4
|
x = 4
|
||||||
y = 3
|
y = 3
|
||||||
|
|
||||||
(x, y)
|
(x, y)
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(4, 3),
|
(4, 3),
|
||||||
(i64, i64)
|
(i64, i64)
|
||||||
|
@ -354,9 +354,9 @@ fn return_tuple() {
|
||||||
fn return_tuple_2() {
|
fn return_tuple_2() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
(3, 5)
|
(3, 5)
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
[3, 5],
|
[3, 5],
|
||||||
[i64; 2]
|
[i64; 2]
|
||||||
|
@ -368,9 +368,9 @@ fn return_tuple_2() {
|
||||||
fn return_tuple_3() {
|
fn return_tuple_3() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
( 3, 5, 4 )
|
( 3, 5, 4 )
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(3, 5, 4),
|
(3, 5, 4),
|
||||||
(i64, i64, i64)
|
(i64, i64, i64)
|
||||||
|
@ -382,9 +382,9 @@ fn return_tuple_3() {
|
||||||
fn return_tuple_4() {
|
fn return_tuple_4() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
( 3, 5, 4, 2 )
|
( 3, 5, 4, 2 )
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
[3, 5, 4, 2],
|
[3, 5, 4, 2],
|
||||||
[i64; 4]
|
[i64; 4]
|
||||||
|
@ -398,9 +398,9 @@ fn return_tuple_4() {
|
||||||
fn return_tuple_5() {
|
fn return_tuple_5() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
( 3, 5, 4, 2, 1 )
|
( 3, 5, 4, 2, 1 )
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
[3, 5, 4, 2, 1],
|
[3, 5, 4, 2, 1],
|
||||||
[i64; 5]
|
[i64; 5]
|
||||||
|
@ -414,9 +414,9 @@ fn return_tuple_5() {
|
||||||
fn return_tuple_6() {
|
fn return_tuple_6() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
( 3, 5, 4, 2, 1, 7 )
|
( 3, 5, 4, 2, 1, 7 )
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
[3, 5, 4, 2, 1, 7],
|
[3, 5, 4, 2, 1, 7],
|
||||||
[i64; 6]
|
[i64; 6]
|
||||||
|
@ -430,9 +430,9 @@ fn return_tuple_6() {
|
||||||
fn return_tuple_7() {
|
fn return_tuple_7() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
( 3, 5, 4, 2, 1, 7, 8 )
|
( 3, 5, 4, 2, 1, 7, 8 )
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
[3, 5, 4, 2, 1, 7, 8],
|
[3, 5, 4, 2, 1, 7, 8],
|
||||||
[i64; 7]
|
[i64; 7]
|
||||||
|
@ -444,9 +444,9 @@ fn return_tuple_7() {
|
||||||
fn return_tuple_float_int() {
|
fn return_tuple_float_int() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
(1.23f64, 0x1)
|
(1.23f64, 0x1)
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(1.23, 0x1),
|
(1.23, 0x1),
|
||||||
(f64, i64)
|
(f64, i64)
|
||||||
|
@ -458,9 +458,9 @@ fn return_tuple_float_int() {
|
||||||
fn return_tuple_int_float() {
|
fn return_tuple_int_float() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
( 0x1, 1.23f64 )
|
( 0x1, 1.23f64 )
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(0x1, 1.23),
|
(0x1, 1.23),
|
||||||
(i64, f64)
|
(i64, f64)
|
||||||
|
@ -472,9 +472,9 @@ fn return_tuple_int_float() {
|
||||||
fn return_tuple_float_float() {
|
fn return_tuple_float_float() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
( 2.46f64, 1.23f64 )
|
( 2.46f64, 1.23f64 )
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(2.46, 1.23),
|
(2.46, 1.23),
|
||||||
(f64, f64)
|
(f64, f64)
|
||||||
|
@ -486,9 +486,9 @@ fn return_tuple_float_float() {
|
||||||
fn return_tuple_float_float_float() {
|
fn return_tuple_float_float_float() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
( 2.46f64, 1.23f64, 0.1f64 )
|
( 2.46f64, 1.23f64, 0.1f64 )
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(2.46, 1.23, 0.1),
|
(2.46, 1.23, 0.1),
|
||||||
(f64, f64, f64)
|
(f64, f64, f64)
|
||||||
|
@ -500,9 +500,9 @@ fn return_tuple_float_float_float() {
|
||||||
fn return_nested_tuple() {
|
fn return_nested_tuple() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
(0x0, (2.46f64, 1.23f64, 0.1f64))
|
(0x0, (2.46f64, 1.23f64, 0.1f64))
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
(0x0, (2.46, 1.23, 0.1)),
|
(0x0, (2.46, 1.23, 0.1)),
|
||||||
(i64, (f64, f64, f64))
|
(i64, (f64, f64, f64))
|
||||||
|
@ -514,13 +514,13 @@ fn return_nested_tuple() {
|
||||||
fn nested_tuple_load() {
|
fn nested_tuple_load() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
x = (0, (0x2, 0x5, 0x6))
|
x = (0, (0x2, 0x5, 0x6))
|
||||||
|
|
||||||
y = x.1
|
y = x.1
|
||||||
|
|
||||||
y.2
|
y.2
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
6,
|
6,
|
||||||
i64
|
i64
|
||||||
|
@ -572,7 +572,7 @@ fn alignment_in_tuple() {
|
||||||
fn tuple_length_polymorphism() {
|
fn tuple_length_polymorphism() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
a = (42, 43)
|
a = (42, 43)
|
||||||
b = (1, 2, 44)
|
b = (1, 2, 44)
|
||||||
|
|
||||||
|
@ -580,7 +580,7 @@ fn tuple_length_polymorphism() {
|
||||||
f = \(x1, x2), (x3, x4) -> x1 + x2 + x3 + x4
|
f = \(x1, x2), (x3, x4) -> x1 + x2 + x3 + x4
|
||||||
|
|
||||||
f a b
|
f a b
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
88,
|
88,
|
||||||
i64
|
i64
|
||||||
|
|
File diff suppressed because it is too large
Load diff
3
crates/compiler/test_syntax/fuzz/.gitignore
vendored
3
crates/compiler/test_syntax/fuzz/.gitignore
vendored
|
@ -1,3 +0,0 @@
|
||||||
target
|
|
||||||
corpus
|
|
||||||
artifacts
|
|
File diff suppressed because it is too large
Load diff
|
@ -731,7 +731,7 @@ mod test_snapshots {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn string_with_interpolation_in_middle() {
|
fn string_with_interpolation_in_middle() {
|
||||||
assert_segments(r#""Hi, \(name)!""#, |arena| {
|
assert_segments(r#""Hi, $(name)!""#, |arena| {
|
||||||
let expr = arena.alloc(Var {
|
let expr = arena.alloc(Var {
|
||||||
module_name: "",
|
module_name: "",
|
||||||
ident: "name",
|
ident: "name",
|
||||||
|
@ -747,7 +747,7 @@ mod test_snapshots {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn string_with_interpolation_in_front() {
|
fn string_with_interpolation_in_front() {
|
||||||
assert_segments(r#""\(name), hi!""#, |arena| {
|
assert_segments(r#""$(name), hi!""#, |arena| {
|
||||||
let expr = arena.alloc(Var {
|
let expr = arena.alloc(Var {
|
||||||
module_name: "",
|
module_name: "",
|
||||||
ident: "name",
|
ident: "name",
|
||||||
|
@ -762,7 +762,7 @@ mod test_snapshots {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn string_with_interpolation_in_back() {
|
fn string_with_interpolation_in_back() {
|
||||||
assert_segments(r#""Hello \(name)""#, |arena| {
|
assert_segments(r#""Hello $(name)""#, |arena| {
|
||||||
let expr = arena.alloc(Var {
|
let expr = arena.alloc(Var {
|
||||||
module_name: "",
|
module_name: "",
|
||||||
ident: "name",
|
ident: "name",
|
||||||
|
@ -777,7 +777,7 @@ mod test_snapshots {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn string_with_multiple_interpolations() {
|
fn string_with_multiple_interpolations() {
|
||||||
assert_segments(r#""Hi, \(name)! How is \(project) going?""#, |arena| {
|
assert_segments(r#""Hi, $(name)! How is $(project) going?""#, |arena| {
|
||||||
let expr1 = arena.alloc(Var {
|
let expr1 = arena.alloc(Var {
|
||||||
module_name: "",
|
module_name: "",
|
||||||
ident: "name",
|
ident: "name",
|
||||||
|
|
|
@ -566,10 +566,7 @@ impl<T> Copy for SubsIndex<T> {}
|
||||||
|
|
||||||
impl<T> Clone for SubsIndex<T> {
|
impl<T> Clone for SubsIndex<T> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
*self
|
||||||
index: self.index,
|
|
||||||
_marker: self._marker,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -577,11 +574,7 @@ impl<T> Copy for SubsSlice<T> {}
|
||||||
|
|
||||||
impl<T> Clone for SubsSlice<T> {
|
impl<T> Clone for SubsSlice<T> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
*self
|
||||||
start: self.start,
|
|
||||||
length: self.length,
|
|
||||||
_marker: self._marker,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1300,17 +1300,21 @@ mod debug_types {
|
||||||
Arg,
|
Arg,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn always_true() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! maybe_paren {
|
macro_rules! maybe_paren {
|
||||||
($paren_if_above:expr, $my_prec:expr, $doc:expr) => {
|
($paren_if_above:expr, $my_prec:expr, $doc:expr) => {
|
||||||
maybe_paren!($paren_if_above, $my_prec, || true, $doc)
|
maybe_paren!($paren_if_above, $my_prec, always_true, $doc)
|
||||||
};
|
};
|
||||||
($paren_if_above:expr, $my_prec:expr, $extra_cond:expr, $doc:expr) => {
|
($paren_if_above:expr, $my_prec:expr, $extra_cond:expr, $doc:expr) => {{
|
||||||
if $my_prec > $paren_if_above && $extra_cond() {
|
if $my_prec > $paren_if_above && $extra_cond() {
|
||||||
$doc.parens().group()
|
$doc.parens().group()
|
||||||
} else {
|
} else {
|
||||||
$doc
|
$doc
|
||||||
}
|
}
|
||||||
};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn typ<'a>(
|
fn typ<'a>(
|
||||||
|
|
1
crates/docs/.gitignore
vendored
1
crates/docs/.gitignore
vendored
|
@ -1 +0,0 @@
|
||||||
/build
|
|
3
crates/glue/.gitignore
vendored
3
crates/glue/.gitignore
vendored
|
@ -1,3 +0,0 @@
|
||||||
*.so
|
|
||||||
*.dylib
|
|
||||||
*.dll
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
12
crates/glue/tests/fixtures/.gitignore
vendored
12
crates/glue/tests/fixtures/.gitignore
vendored
|
@ -1,12 +0,0 @@
|
||||||
Cargo.lock
|
|
||||||
Cargo.toml
|
|
||||||
build.rs
|
|
||||||
host.c
|
|
||||||
test_glue
|
|
||||||
roc_externs.rs
|
|
||||||
main.rs
|
|
||||||
app
|
|
||||||
dynhost
|
|
||||||
libapp.so
|
|
||||||
metadata
|
|
||||||
preprocessedhost
|
|
|
@ -37,7 +37,7 @@ macro_rules! tokens {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Token {
|
impl Token {
|
||||||
pub const LEGEND: &[SemanticTokenType] = &[
|
pub const LEGEND: &'static [SemanticTokenType] = &[
|
||||||
$(SemanticTokenType::new($lsp_token)),*
|
$(SemanticTokenType::new($lsp_token)),*
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -438,11 +438,19 @@ impl<R: Read> Read for ProgressReporter<R> {
|
||||||
self.read += size;
|
self.read += size;
|
||||||
|
|
||||||
if let Some(total) = self.total {
|
if let Some(total) = self.total {
|
||||||
eprint!(
|
let total = total as f32 / 1_000_000.0;
|
||||||
"\u{001b}[2K\u{001b}[G[{:.1} / {:.1} MB]",
|
let read = self.read as f32 / 1_000_000.0;
|
||||||
self.read as f32 / 1_000_000.0,
|
|
||||||
total as f32 / 1_000_000.0,
|
if total < 1.0 {
|
||||||
);
|
eprint!(
|
||||||
|
"\u{001b}[2K\u{001b}[G[{:.1} / {:.1} KB]",
|
||||||
|
// Convert MB to KB
|
||||||
|
read * 1000.0,
|
||||||
|
total * 1000.0,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
eprint!("\u{001b}[2K\u{001b}[G[{:.1} / {:.1} MB]", read, total,);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
eprint!(
|
eprint!(
|
||||||
"\u{001b}[2K\u{001b}[G[{:.1} MB]",
|
"\u{001b}[2K\u{001b}[G[{:.1} MB]",
|
||||||
|
|
|
@ -18,7 +18,7 @@ macro_rules! deref_number {
|
||||||
|
|
||||||
impl ReplAppMemory for ExpectMemory {
|
impl ReplAppMemory for ExpectMemory {
|
||||||
fn deref_bool(&self, addr: usize) -> bool {
|
fn deref_bool(&self, addr: usize) -> bool {
|
||||||
let ptr = unsafe { self.start.add(addr) } as *const u8;
|
let ptr = unsafe { self.start.add(addr) };
|
||||||
let value = unsafe { std::ptr::read_unaligned(ptr) };
|
let value = unsafe { std::ptr::read_unaligned(ptr) };
|
||||||
|
|
||||||
// bool values should only ever be 0 or 1
|
// bool values should only ever be 0 or 1
|
||||||
|
|
|
@ -238,12 +238,12 @@ mod test {
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
This expectation failed:
|
This expectation failed:
|
||||||
|
|
||||||
5│ expect 1 == 2
|
5│ expect 1 == 2
|
||||||
^^^^^^^^^^^^^
|
^^^^^^^^^^^^^
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -265,7 +265,7 @@ mod test {
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
This expectation failed:
|
This expectation failed:
|
||||||
|
|
||||||
5│> expect
|
5│> expect
|
||||||
|
@ -281,7 +281,7 @@ mod test {
|
||||||
|
|
||||||
b : Num *
|
b : Num *
|
||||||
b = 2
|
b = 2
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -380,7 +380,7 @@ mod test {
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
This expectation failed:
|
This expectation failed:
|
||||||
|
|
||||||
5│> expect
|
5│> expect
|
||||||
|
@ -397,7 +397,7 @@ mod test {
|
||||||
|
|
||||||
expected : Result I64 [OutOfBounds]
|
expected : Result I64 [OutOfBounds]
|
||||||
expected = Ok 42
|
expected = Ok 42
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -463,7 +463,7 @@ mod test {
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
This expectation failed:
|
This expectation failed:
|
||||||
|
|
||||||
5│> expect
|
5│> expect
|
||||||
|
@ -485,7 +485,7 @@ mod test {
|
||||||
y : U8,
|
y : U8,
|
||||||
}
|
}
|
||||||
vec2 = { x: 4, y: 8 }
|
vec2 = { x: 4, y: 8 }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -965,22 +965,22 @@ mod test {
|
||||||
fn issue_i4389() {
|
fn issue_i4389() {
|
||||||
run_expect_test(
|
run_expect_test(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
interface Test exposes [] imports []
|
interface Test exposes [] imports []
|
||||||
|
|
||||||
expect
|
expect
|
||||||
totalCount = \{} -> 1u8
|
totalCount = \{} -> 1u8
|
||||||
totalCount {} == 96u8
|
totalCount {} == 96u8
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
This expectation failed:
|
This expectation failed:
|
||||||
|
|
||||||
3│> expect
|
3│> expect
|
||||||
4│> totalCount = \{} -> 1u8
|
4│> totalCount = \{} -> 1u8
|
||||||
5│> totalCount {} == 96u8
|
5│> totalCount {} == 96u8
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -989,7 +989,7 @@ mod test {
|
||||||
fn adjacent_lists() {
|
fn adjacent_lists() {
|
||||||
run_expect_test(
|
run_expect_test(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
interface Test exposes [] imports []
|
interface Test exposes [] imports []
|
||||||
|
|
||||||
expect
|
expect
|
||||||
|
@ -1007,10 +1007,10 @@ mod test {
|
||||||
x: [115, 116, 117],
|
x: [115, 116, 117],
|
||||||
}
|
}
|
||||||
actual == expected
|
actual == expected
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
This expectation failed:
|
This expectation failed:
|
||||||
|
|
||||||
3│> expect
|
3│> expect
|
||||||
|
@ -1044,7 +1044,7 @@ mod test {
|
||||||
x : List (Int Unsigned8),
|
x : List (Int Unsigned8),
|
||||||
}
|
}
|
||||||
expected = { body: [42, 43, 44], headers: [15, 16, 17], x: [115, 116, 117] }
|
expected = { body: [42, 43, 44], headers: [15, 16, 17], x: [115, 116, 117] }
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1113,7 +1113,7 @@ mod test {
|
||||||
fn tag_payloads_of_different_size() {
|
fn tag_payloads_of_different_size() {
|
||||||
run_expect_test(
|
run_expect_test(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
interface Test exposes [] imports []
|
interface Test exposes [] imports []
|
||||||
|
|
||||||
actual : [Leftover (List U8), TooShort]
|
actual : [Leftover (List U8), TooShort]
|
||||||
|
@ -1124,10 +1124,10 @@ mod test {
|
||||||
expected = TooShort
|
expected = TooShort
|
||||||
|
|
||||||
actual == expected
|
actual == expected
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
This expectation failed:
|
This expectation failed:
|
||||||
|
|
||||||
6│> expect
|
6│> expect
|
||||||
|
@ -1143,7 +1143,7 @@ mod test {
|
||||||
TooShort,
|
TooShort,
|
||||||
]
|
]
|
||||||
expected = TooShort
|
expected = TooShort
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1220,7 +1220,7 @@ mod test {
|
||||||
fn match_on_opaque_number_type() {
|
fn match_on_opaque_number_type() {
|
||||||
run_expect_test(
|
run_expect_test(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
interface Test exposes [] imports []
|
interface Test exposes [] imports []
|
||||||
|
|
||||||
hexToByte : U8, U8 -> U8
|
hexToByte : U8, U8 -> U8
|
||||||
|
@ -1231,10 +1231,10 @@ mod test {
|
||||||
actual = hexToByte 7 4
|
actual = hexToByte 7 4
|
||||||
expected = 't'
|
expected = 't'
|
||||||
actual == expected
|
actual == expected
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
This expectation failed:
|
This expectation failed:
|
||||||
|
|
||||||
7│> expect
|
7│> expect
|
||||||
|
@ -1249,7 +1249,7 @@ mod test {
|
||||||
|
|
||||||
expected : Int Unsigned8
|
expected : Int Unsigned8
|
||||||
expected = 116
|
expected = 116
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,11 +124,11 @@ fn bool_basic_equality() {
|
||||||
fn bool_true() {
|
fn bool_true() {
|
||||||
expect_success(
|
expect_success(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Bool.true
|
Bool.true
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
r#"Bool.true : Bool"#,
|
r"Bool.true : Bool",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,11 +136,11 @@ fn bool_true() {
|
||||||
fn bool_false() {
|
fn bool_false() {
|
||||||
expect_success(
|
expect_success(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Bool.false
|
Bool.false
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
r#"Bool.false : Bool"#,
|
r"Bool.false : Bool",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,24 +315,24 @@ fn nested_string_list() {
|
||||||
#[test]
|
#[test]
|
||||||
fn nested_num_list() {
|
fn nested_num_list() {
|
||||||
expect_success(
|
expect_success(
|
||||||
r#"[[[4, 3, 2], [1, 0]], [[]], []]"#,
|
r"[[[4, 3, 2], [1, 0]], [[]], []]",
|
||||||
r#"[[[4, 3, 2], [1, 0]], [[]], []] : List (List (List (Num *)))"#,
|
r"[[[4, 3, 2], [1, 0]], [[]], []] : List (List (List (Num *)))",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn nested_int_list() {
|
fn nested_int_list() {
|
||||||
expect_success(
|
expect_success(
|
||||||
r#"[[[4, 3, 2], [1, 0x0]], [[]], []]"#,
|
r"[[[4, 3, 2], [1, 0x0]], [[]], []]",
|
||||||
r#"[[[4, 3, 2], [1, 0]], [[]], []] : List (List (List (Int *)))"#,
|
r"[[[4, 3, 2], [1, 0]], [[]], []] : List (List (List (Int *)))",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn nested_float_list() {
|
fn nested_float_list() {
|
||||||
expect_success(
|
expect_success(
|
||||||
r#"[[[4, 3, 2], [1, 0.0]], [[]], []]"#,
|
r"[[[4, 3, 2], [1, 0.0]], [[]], []]",
|
||||||
r#"[[[4, 3, 2], [1, 0]], [[]], []] : List (List (List (Frac *)))"#,
|
r"[[[4, 3, 2], [1, 0]], [[]], []] : List (List (List (Frac *)))",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -641,7 +641,7 @@ fn too_few_args() {
|
||||||
expect_failure(
|
expect_failure(
|
||||||
"Num.add 2",
|
"Num.add 2",
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
── TOO FEW ARGS ────────────────────────────────────────────────────────────────
|
── TOO FEW ARGS ────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
The add function expects 2 arguments, but it got only 1:
|
The add function expects 2 arguments, but it got only 1:
|
||||||
|
@ -651,7 +651,7 @@ fn too_few_args() {
|
||||||
|
|
||||||
Roc does not allow functions to be partially applied. Use a closure to
|
Roc does not allow functions to be partially applied. Use a closure to
|
||||||
make partial application explicit.
|
make partial application explicit.
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -970,7 +970,7 @@ fn large_nullable_wrapped_tag_union() {
|
||||||
fn issue_2300() {
|
fn issue_2300() {
|
||||||
expect_success(
|
expect_success(
|
||||||
r#"\Email str -> str == """#,
|
r#"\Email str -> str == """#,
|
||||||
r#"<function> : [Email Str] -> Bool"#,
|
r"<function> : [Email Str] -> Bool",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -978,8 +978,8 @@ fn issue_2300() {
|
||||||
#[test]
|
#[test]
|
||||||
fn function_in_list() {
|
fn function_in_list() {
|
||||||
expect_success(
|
expect_success(
|
||||||
r#"[\x -> x + 1, \s -> s * 2]"#,
|
r"[\x -> x + 1, \s -> s * 2]",
|
||||||
r#"[<function>, <function>] : List (Num a -> Num a)"#,
|
r"[<function>, <function>] : List (Num a -> Num a)",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -987,8 +987,8 @@ fn function_in_list() {
|
||||||
#[test]
|
#[test]
|
||||||
fn function_in_record() {
|
fn function_in_record() {
|
||||||
expect_success(
|
expect_success(
|
||||||
r#"{ n: 1, adder: \x -> x + 1 }"#,
|
r"{ n: 1, adder: \x -> x + 1 }",
|
||||||
r#"{ adder: <function>, n: 1 } : { adder : Num a -> Num a, n : Num * }"#,
|
r"{ adder: <function>, n: 1 } : { adder : Num a -> Num a, n : Num * }",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -996,8 +996,8 @@ fn function_in_record() {
|
||||||
#[test]
|
#[test]
|
||||||
fn function_in_unwrapped_record() {
|
fn function_in_unwrapped_record() {
|
||||||
expect_success(
|
expect_success(
|
||||||
r#"{ adder: \x -> x + 1 }"#,
|
r"{ adder: \x -> x + 1 }",
|
||||||
r#"{ adder: <function> } : { adder : Num a -> Num a }"#,
|
r"{ adder: <function> } : { adder : Num a -> Num a }",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1005,16 +1005,16 @@ fn function_in_unwrapped_record() {
|
||||||
#[test]
|
#[test]
|
||||||
fn function_in_tag() {
|
fn function_in_tag() {
|
||||||
expect_success(
|
expect_success(
|
||||||
r#"Adder (\x -> x + 1)"#,
|
r"Adder (\x -> x + 1)",
|
||||||
r#"Adder <function> : [Adder (Num a -> Num a)]"#,
|
r"Adder <function> : [Adder (Num a -> Num a)]",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn newtype_of_record_of_tag_of_record_of_tag() {
|
fn newtype_of_record_of_tag_of_record_of_tag() {
|
||||||
expect_success(
|
expect_success(
|
||||||
r#"A {b: C {d: 1}}"#,
|
r"A {b: C {d: 1}}",
|
||||||
r#"A { b: C { d: 1 } } : [A { b : [C { d : Num * }] }]"#,
|
r"A { b: C { d: 1 } } : [A { b : [C { d : Num * }] }]",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1022,11 +1022,11 @@ fn newtype_of_record_of_tag_of_record_of_tag() {
|
||||||
fn print_u8s() {
|
fn print_u8s() {
|
||||||
expect_success(
|
expect_success(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
x : U8
|
x : U8
|
||||||
x = 129
|
x = 129
|
||||||
x
|
x
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
"129 : U8",
|
"129 : U8",
|
||||||
)
|
)
|
||||||
|
@ -1062,17 +1062,17 @@ fn parse_problem() {
|
||||||
fn issue_2343_complete_mono_with_shadowed_vars() {
|
fn issue_2343_complete_mono_with_shadowed_vars() {
|
||||||
expect_failure(
|
expect_failure(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
b = False
|
b = False
|
||||||
f = \b ->
|
f = \b ->
|
||||||
when b is
|
when b is
|
||||||
True -> 5
|
True -> 5
|
||||||
False -> 15
|
False -> 15
|
||||||
f b
|
f b
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
── DUPLICATE NAME ──────────────────────────────────────────────────────────────
|
── DUPLICATE NAME ──────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
The b name is first defined here:
|
The b name is first defined here:
|
||||||
|
@ -1087,7 +1087,7 @@ fn issue_2343_complete_mono_with_shadowed_vars() {
|
||||||
|
|
||||||
Since these variables have the same name, it's easy to use the wrong
|
Since these variables have the same name, it's easy to use the wrong
|
||||||
one by accident. Give one of them a new name.
|
one by accident. Give one of them a new name.
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1126,12 +1126,12 @@ fn tag_with_type_behind_alias() {
|
||||||
fn issue_2588_record_with_function_and_nonfunction() {
|
fn issue_2588_record_with_function_and_nonfunction() {
|
||||||
expect_success(
|
expect_success(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
x = 1
|
x = 1
|
||||||
f = \n -> n * 2
|
f = \n -> n * 2
|
||||||
{ y: f x, f }"#
|
{ y: f x, f }"
|
||||||
),
|
),
|
||||||
r#"{ f: <function>, y: 2 } : { f : Num a -> Num a, y : Num * }"#,
|
r"{ f: <function>, y: 2 } : { f : Num a -> Num a, y : Num * }",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1139,10 +1139,10 @@ fn issue_2588_record_with_function_and_nonfunction() {
|
||||||
fn opaque_apply() {
|
fn opaque_apply() {
|
||||||
expect_success(
|
expect_success(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Age := U32
|
Age := U32
|
||||||
|
|
||||||
@Age 23"#
|
@Age 23"
|
||||||
),
|
),
|
||||||
"@Age 23 : Age",
|
"@Age 23 : Age",
|
||||||
)
|
)
|
||||||
|
@ -1165,14 +1165,14 @@ fn opaque_apply_polymorphic() {
|
||||||
fn opaque_pattern_and_call() {
|
fn opaque_pattern_and_call() {
|
||||||
expect_success(
|
expect_success(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
F t u := [Package t u]
|
F t u := [Package t u]
|
||||||
|
|
||||||
f = \@F (Package A {}) -> @F (Package {} A)
|
f = \@F (Package A {}) -> @F (Package {} A)
|
||||||
|
|
||||||
f (@F (Package A {}))"#
|
f (@F (Package A {}))"
|
||||||
),
|
),
|
||||||
r#"@F (Package {} A) : F {} [A]"#,
|
r"@F (Package {} A) : F {} [A]",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1180,10 +1180,10 @@ fn opaque_pattern_and_call() {
|
||||||
fn dec_in_repl() {
|
fn dec_in_repl() {
|
||||||
expect_success(
|
expect_success(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
x: Dec
|
x: Dec
|
||||||
x=1.23
|
x=1.23
|
||||||
x"#
|
x"
|
||||||
),
|
),
|
||||||
"1.23 : Dec",
|
"1.23 : Dec",
|
||||||
)
|
)
|
||||||
|
@ -1193,12 +1193,12 @@ fn dec_in_repl() {
|
||||||
fn print_i8_issue_2710() {
|
fn print_i8_issue_2710() {
|
||||||
expect_success(
|
expect_success(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
a : I8
|
a : I8
|
||||||
a = -1
|
a = -1
|
||||||
a"#
|
a"
|
||||||
),
|
),
|
||||||
r#"-1 : I8"#,
|
r"-1 : I8",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1243,11 +1243,11 @@ fn issue_2582_specialize_result_value() {
|
||||||
fn issue_2818() {
|
fn issue_2818() {
|
||||||
expect_success(
|
expect_success(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
f : {} -> List Str
|
f : {} -> List Str
|
||||||
f = \_ ->
|
f = \_ ->
|
||||||
x = []
|
x = []
|
||||||
x"#
|
x"
|
||||||
),
|
),
|
||||||
r"<function> : {} -> List Str",
|
r"<function> : {} -> List Str",
|
||||||
)
|
)
|
||||||
|
@ -1257,7 +1257,7 @@ fn issue_2818() {
|
||||||
fn issue_2810_recursive_layout_inside_nonrecursive() {
|
fn issue_2810_recursive_layout_inside_nonrecursive() {
|
||||||
expect_success(
|
expect_success(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Command : [Command Tool]
|
Command : [Command Tool]
|
||||||
|
|
||||||
Job : [Job Command]
|
Job : [Job Command]
|
||||||
|
@ -1266,7 +1266,7 @@ fn issue_2810_recursive_layout_inside_nonrecursive() {
|
||||||
|
|
||||||
a : Job
|
a : Job
|
||||||
a = Job (Command (FromJob (Job (Command SystemTool))))
|
a = Job (Command (FromJob (Job (Command SystemTool))))
|
||||||
a"#
|
a"
|
||||||
),
|
),
|
||||||
"Job (Command (FromJob (Job (Command SystemTool)))) : Job",
|
"Job (Command (FromJob (Job (Command SystemTool)))) : Job",
|
||||||
)
|
)
|
||||||
|
@ -1276,12 +1276,12 @@ fn issue_2810_recursive_layout_inside_nonrecursive() {
|
||||||
fn render_nullable_unwrapped_passing_through_alias() {
|
fn render_nullable_unwrapped_passing_through_alias() {
|
||||||
expect_success(
|
expect_success(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Deep : [L DeepList]
|
Deep : [L DeepList]
|
||||||
DeepList : [Nil, Cons Deep]
|
DeepList : [Nil, Cons Deep]
|
||||||
v : DeepList
|
v : DeepList
|
||||||
v = (Cons (L (Cons (L (Cons (L Nil))))))
|
v = (Cons (L (Cons (L (Cons (L Nil))))))
|
||||||
v"#
|
v"
|
||||||
),
|
),
|
||||||
"Cons (L (Cons (L (Cons (L Nil))))) : DeepList",
|
"Cons (L (Cons (L (Cons (L Nil))))) : DeepList",
|
||||||
)
|
)
|
||||||
|
@ -1291,9 +1291,9 @@ fn render_nullable_unwrapped_passing_through_alias() {
|
||||||
fn opaque_wrap_function() {
|
fn opaque_wrap_function() {
|
||||||
expect_success(
|
expect_success(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
A a := a
|
A a := a
|
||||||
List.map [1u8, 2u8, 3u8] @A"#
|
List.map [1u8, 2u8, 3u8] @A"
|
||||||
),
|
),
|
||||||
"[@A 1, @A 2, @A 3] : List (A U8)",
|
"[@A 1, @A 2, @A 3] : List (A U8)",
|
||||||
);
|
);
|
||||||
|
@ -1305,10 +1305,10 @@ fn opaque_wrap_function() {
|
||||||
fn dict_get_single() {
|
fn dict_get_single() {
|
||||||
expect_success(
|
expect_success(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Dict.single 0 {a: 1, c: 2} |> Dict.get 0"#
|
Dict.single 0 {a: 1, c: 2} |> Dict.get 0"
|
||||||
),
|
),
|
||||||
r#"Ok { a: 1, c: 2 } : Result { a : Num *, c : Num * } [KeyNotFound]"#,
|
r"Ok { a: 1, c: 2 } : Result { a : Num *, c : Num * } [KeyNotFound]",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1319,7 +1319,7 @@ fn record_of_poly_function() {
|
||||||
r#"
|
r#"
|
||||||
{ a: \_ -> "a" }"#
|
{ a: \_ -> "a" }"#
|
||||||
),
|
),
|
||||||
r#"{ a: <function> } : { a : * -> Str }"#,
|
r"{ a: <function> } : { a : * -> Str }",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1338,18 +1338,18 @@ fn record_of_poly_function_and_string() {
|
||||||
fn newtype_by_void_is_wrapped() {
|
fn newtype_by_void_is_wrapped() {
|
||||||
expect_success(
|
expect_success(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Result.try (Err 42) (\x -> Err (x+1))"#
|
Result.try (Err 42) (\x -> Err (x+1))"
|
||||||
),
|
),
|
||||||
r#"Err 42 : Result b (Num *)"#,
|
r"Err 42 : Result b (Num *)",
|
||||||
);
|
);
|
||||||
|
|
||||||
expect_success(
|
expect_success(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Result.try (Ok 42) (\x -> Ok (x+1))"#
|
Result.try (Ok 42) (\x -> Ok (x+1))"
|
||||||
),
|
),
|
||||||
r#"Ok 43 : Result (Num *) err"#,
|
r"Ok 43 : Result (Num *) err",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1357,11 +1357,11 @@ fn newtype_by_void_is_wrapped() {
|
||||||
fn enum_tag_union_in_list() {
|
fn enum_tag_union_in_list() {
|
||||||
expect_success(
|
expect_success(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
[E, F, G, H]
|
[E, F, G, H]
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
r#"[E, F, G, H] : List [E, F, G, H]"#,
|
r"[E, F, G, H] : List [E, F, G, H]",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1373,7 +1373,7 @@ fn str_to_dec() {
|
||||||
Str.toDec "1234.1234"
|
Str.toDec "1234.1234"
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
r#"Ok 1234.1234 : Result Dec [InvalidNumStr]"#,
|
r"Ok 1234.1234 : Result Dec [InvalidNumStr]",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1405,7 +1405,7 @@ fn nested_tuple() {
|
||||||
fn ordered_tag_union_memory_layout() {
|
fn ordered_tag_union_memory_layout() {
|
||||||
expect_success(
|
expect_success(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
Loc : { line: U32, column: U32 }
|
Loc : { line: U32, column: U32 }
|
||||||
|
|
||||||
Node : [ A Loc, Height U8 Loc ]
|
Node : [ A Loc, Height U8 Loc ]
|
||||||
|
@ -1413,9 +1413,9 @@ fn ordered_tag_union_memory_layout() {
|
||||||
x : Node
|
x : Node
|
||||||
x = Height 1 { line: 2, column: 3 }
|
x = Height 1 { line: 2, column: 3 }
|
||||||
x
|
x
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
r#"Height 1 { column: 3, line: 2 } : Node"#,
|
r"Height 1 { column: 3, line: 2 } : Node",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
5
crates/repl_wasm/.gitignore
vendored
5
crates/repl_wasm/.gitignore
vendored
|
@ -1,5 +0,0 @@
|
||||||
# wasm-pack
|
|
||||||
/pkg
|
|
||||||
|
|
||||||
# shell script output
|
|
||||||
/build
|
|
|
@ -9,7 +9,7 @@
|
||||||
# We use this two-step process because Netlify times out if we try to build the Web REPL there.
|
# We use this two-step process because Netlify times out if we try to build the Web REPL there.
|
||||||
|
|
||||||
# https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/
|
# https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/
|
||||||
set -euxo pipefail
|
set -exo pipefail
|
||||||
|
|
||||||
if ! which wasm-pack
|
if ! which wasm-pack
|
||||||
then
|
then
|
||||||
|
@ -23,9 +23,22 @@ cd $SCRIPT_RELATIVE_DIR
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
rm -rf build/*
|
rm -rf build/*
|
||||||
|
|
||||||
# We want a release build, but with debug info (to get stack traces for Wasm backend panics)
|
# c++abi is not needed for wasm-pack and causes an error, see #6303 for more info
|
||||||
# This configuration is called `--profiling`
|
REMOVE_STR="-C link-arg=-lc++abi"
|
||||||
wasm-pack build --profiling --target web -- --features console_error_panic_hook
|
|
||||||
|
( # start subshell to limit scope of export RUSTFLAGS
|
||||||
|
# Check if RUSTFLAGS contains the string to be removed
|
||||||
|
if [[ $RUSTFLAGS == *"$REMOVE_STR"* ]]; then
|
||||||
|
# Remove the string
|
||||||
|
RUSTFLAGS=$(echo "$RUSTFLAGS" | sed "s/$REMOVE_STR//g")
|
||||||
|
|
||||||
|
export RUSTFLAGS
|
||||||
|
fi
|
||||||
|
|
||||||
|
# We want a release build, but with debug info (to get stack traces for Wasm backend panics)
|
||||||
|
# This configuration is called `--profiling`
|
||||||
|
wasm-pack build --profiling --target web -- --features console_error_panic_hook
|
||||||
|
)
|
||||||
cp -v pkg/roc_repl_wasm.js build
|
cp -v pkg/roc_repl_wasm.js build
|
||||||
|
|
||||||
# To disable optimizations while debugging, do `export REPL_DEBUG=1` before running the script
|
# To disable optimizations while debugging, do `export REPL_DEBUG=1` before running the script
|
||||||
|
|
1
crates/reporting/.gitignore
vendored
1
crates/reporting/.gitignore
vendored
|
@ -1 +0,0 @@
|
||||||
/tmp
|
|
|
@ -2,6 +2,7 @@ use std::path::PathBuf;
|
||||||
|
|
||||||
use roc_collections::MutMap;
|
use roc_collections::MutMap;
|
||||||
use roc_module::symbol::{Interns, ModuleId};
|
use roc_module::symbol::{Interns, ModuleId};
|
||||||
|
use roc_problem::can::Problem;
|
||||||
use roc_region::all::LineInfo;
|
use roc_region::all::LineInfo;
|
||||||
use roc_solve_problem::TypeError;
|
use roc_solve_problem::TypeError;
|
||||||
|
|
||||||
|
@ -87,29 +88,6 @@ pub fn report_problems(
|
||||||
// Report parsing and canonicalization problems
|
// Report parsing and canonicalization problems
|
||||||
let alloc = RocDocAllocator::new(&src_lines, *home, interns);
|
let alloc = RocDocAllocator::new(&src_lines, *home, interns);
|
||||||
|
|
||||||
let problems = can_problems.remove(home).unwrap_or_default();
|
|
||||||
|
|
||||||
for problem in problems.into_iter() {
|
|
||||||
let report = can_problem(&alloc, &lines, module_path.clone(), problem);
|
|
||||||
let severity = report.severity;
|
|
||||||
let mut buf = String::new();
|
|
||||||
|
|
||||||
report.render_color_terminal(&mut buf, &alloc, &palette);
|
|
||||||
|
|
||||||
match severity {
|
|
||||||
Warning => {
|
|
||||||
warnings.push(buf);
|
|
||||||
}
|
|
||||||
RuntimeError => {
|
|
||||||
errors.push(buf);
|
|
||||||
}
|
|
||||||
Fatal => {
|
|
||||||
fatally_errored = true;
|
|
||||||
errors.push(buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let problems = type_problems.remove(home).unwrap_or_default();
|
let problems = type_problems.remove(home).unwrap_or_default();
|
||||||
|
|
||||||
for problem in problems {
|
for problem in problems {
|
||||||
|
@ -133,6 +111,43 @@ pub fn report_problems(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shadowing errors often cause cryptic type errors. To make it easy to spot the root cause,
|
||||||
|
// we print the shadowing errors last.
|
||||||
|
let problems = can_problems.remove(home).unwrap_or_default();
|
||||||
|
let (shadowing_errs, mut ordered): (Vec<Problem>, Vec<Problem>) =
|
||||||
|
problems.into_iter().partition(|p| {
|
||||||
|
matches!(
|
||||||
|
p,
|
||||||
|
Problem::Shadowing {
|
||||||
|
original_region: _,
|
||||||
|
shadow: _,
|
||||||
|
kind: _,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
});
|
||||||
|
ordered.extend(shadowing_errs);
|
||||||
|
|
||||||
|
for problem in ordered.into_iter() {
|
||||||
|
let report = can_problem(&alloc, &lines, module_path.clone(), problem);
|
||||||
|
let severity = report.severity;
|
||||||
|
let mut buf = String::new();
|
||||||
|
|
||||||
|
report.render_color_terminal(&mut buf, &alloc, &palette);
|
||||||
|
|
||||||
|
match severity {
|
||||||
|
Warning => {
|
||||||
|
warnings.push(buf);
|
||||||
|
}
|
||||||
|
RuntimeError => {
|
||||||
|
errors.push(buf);
|
||||||
|
}
|
||||||
|
Fatal => {
|
||||||
|
fatally_errored = true;
|
||||||
|
errors.push(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_assert!(can_problems.is_empty() && type_problems.is_empty(), "After reporting problems, there were {:?} can_problems and {:?} type_problems that could not be reported because they did not have corresponding entries in `sources`.", can_problems.len(), type_problems.len());
|
debug_assert!(can_problems.is_empty() && type_problems.is_empty(), "After reporting problems, there were {:?} can_problems and {:?} type_problems that could not be reported because they did not have corresponding entries in `sources`.", can_problems.len(), type_problems.len());
|
||||||
|
|
|
@ -711,9 +711,9 @@ fn to_expr_report<'b>(
|
||||||
let thing = match annotation_source {
|
let thing = match annotation_source {
|
||||||
TypedIfBranch {
|
TypedIfBranch {
|
||||||
index,
|
index,
|
||||||
num_branches,
|
num_branches: 2,
|
||||||
..
|
..
|
||||||
} if num_branches == 2 => alloc.concat([
|
} => alloc.concat([
|
||||||
alloc.keyword(if index == HumanIndex::FIRST {
|
alloc.keyword(if index == HumanIndex::FIRST {
|
||||||
"then"
|
"then"
|
||||||
} else {
|
} else {
|
||||||
|
|
2
crates/roc_std/.gitignore
vendored
2
crates/roc_std/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
||||||
*.o
|
|
||||||
*.a
|
|
|
@ -495,7 +495,7 @@ impl PartialEq for I128 {
|
||||||
|
|
||||||
impl PartialOrd for I128 {
|
impl PartialOrd for I128 {
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
i128::from(*self).partial_cmp(&i128::from(*other))
|
Some(self.cmp(other))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -547,7 +547,7 @@ impl PartialEq for U128 {
|
||||||
|
|
||||||
impl PartialOrd for U128 {
|
impl PartialOrd for U128 {
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
u128::from(*self).partial_cmp(&u128::from(*other))
|
Some(self.cmp(other))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ impl<T> RocBox<T> {
|
||||||
///
|
///
|
||||||
/// The box must be unique in order to leak it safely
|
/// The box must be unique in order to leak it safely
|
||||||
pub unsafe fn leak(self) -> *mut T {
|
pub unsafe fn leak(self) -> *mut T {
|
||||||
let ptr = self.contents.as_ptr() as *mut T;
|
let ptr = self.contents.as_ptr();
|
||||||
core::mem::forget(self);
|
core::mem::forget(self);
|
||||||
ptr
|
ptr
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ impl<T> RocBox<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_inner(self) -> T {
|
pub fn into_inner(self) -> T {
|
||||||
unsafe { ptr::read(self.contents.as_ptr() as *mut T) }
|
unsafe { ptr::read(self.contents.as_ptr()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn storage(&self) -> &Cell<Storage> {
|
fn storage(&self) -> &Cell<Storage> {
|
||||||
|
|
|
@ -388,7 +388,6 @@ impl RocStr {
|
||||||
// The backing list was not unique, so we can't mutate it in-place.
|
// The backing list was not unique, so we can't mutate it in-place.
|
||||||
// ask for `len + 1` to store the original string and the terminator
|
// ask for `len + 1` to store the original string and the terminator
|
||||||
with_stack_bytes(len + 1, |alloc_ptr: *mut u8| {
|
with_stack_bytes(len + 1, |alloc_ptr: *mut u8| {
|
||||||
let alloc_ptr = alloc_ptr as *mut u8;
|
|
||||||
let elem_ptr = big_string.ptr_to_first_elem() as *mut u8;
|
let elem_ptr = big_string.ptr_to_first_elem() as *mut u8;
|
||||||
|
|
||||||
// memcpy the bytes into the stack allocation
|
// memcpy the bytes into the stack allocation
|
||||||
|
@ -406,7 +405,7 @@ impl RocStr {
|
||||||
|
|
||||||
// Even if the small string is at capacity, there will be room to write
|
// Even if the small string is at capacity, there will be room to write
|
||||||
// a terminator in the byte that's used to store the length.
|
// a terminator in the byte that's used to store the length.
|
||||||
terminate(bytes.as_mut_ptr() as *mut u8, small_str.len())
|
terminate(bytes.as_mut_ptr(), small_str.len())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -716,7 +715,7 @@ impl Eq for RocStr {}
|
||||||
|
|
||||||
impl PartialOrd for RocStr {
|
impl PartialOrd for RocStr {
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
|
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
|
||||||
self.as_str().partial_cmp(other.as_str())
|
Some(self.cmp(other))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -149,7 +149,7 @@ fn run_with_valgrind(binary_path: &std::path::Path) {
|
||||||
let memory_errors = extract_valgrind_errors(&raw_xml).unwrap_or_else(|err| {
|
let memory_errors = extract_valgrind_errors(&raw_xml).unwrap_or_else(|err| {
|
||||||
panic!(
|
panic!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r"
|
||||||
failed to parse the `valgrind` xml output:
|
failed to parse the `valgrind` xml output:
|
||||||
|
|
||||||
Error was:
|
Error was:
|
||||||
|
@ -167,7 +167,7 @@ fn run_with_valgrind(binary_path: &std::path::Path) {
|
||||||
valgrind stderr was:
|
valgrind stderr was:
|
||||||
|
|
||||||
{}
|
{}
|
||||||
"#
|
"
|
||||||
),
|
),
|
||||||
err, raw_xml, valgrind_out.stdout, valgrind_out.stderr
|
err, raw_xml, valgrind_out.stdout, valgrind_out.stderr
|
||||||
);
|
);
|
||||||
|
@ -214,7 +214,7 @@ fn list_concat_consumes_first_argument() {
|
||||||
#[test]
|
#[test]
|
||||||
fn list_concat_consumes_second_argument() {
|
fn list_concat_consumes_second_argument() {
|
||||||
valgrind_test(indoc!(
|
valgrind_test(indoc!(
|
||||||
r#"
|
r"
|
||||||
(
|
(
|
||||||
a : List U8
|
a : List U8
|
||||||
a = []
|
a = []
|
||||||
|
@ -223,7 +223,7 @@ fn list_concat_consumes_second_argument() {
|
||||||
|> List.len
|
|> List.len
|
||||||
|> Num.toStr
|
|> Num.toStr
|
||||||
)
|
)
|
||||||
"#
|
"
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,7 +273,7 @@ fn str_concat_first_argument_not_unique() {
|
||||||
#[test]
|
#[test]
|
||||||
fn list_concat_empty_list_zero_sized_type() {
|
fn list_concat_empty_list_zero_sized_type() {
|
||||||
valgrind_test(indoc!(
|
valgrind_test(indoc!(
|
||||||
r#"
|
r"
|
||||||
(
|
(
|
||||||
a = List.reserve [] 11
|
a = List.reserve [] 11
|
||||||
b = []
|
b = []
|
||||||
|
@ -281,7 +281,7 @@ fn list_concat_empty_list_zero_sized_type() {
|
||||||
|> List.len
|
|> List.len
|
||||||
|> Num.toStr
|
|> Num.toStr
|
||||||
)
|
)
|
||||||
"#
|
"
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,7 +316,7 @@ fn str_trim_start_capacity() {
|
||||||
#[test]
|
#[test]
|
||||||
fn str_concat_later_referencing_empty_list_with_capacity() {
|
fn str_concat_later_referencing_empty_list_with_capacity() {
|
||||||
valgrind_test(indoc!(
|
valgrind_test(indoc!(
|
||||||
r#"
|
r"
|
||||||
(
|
(
|
||||||
a : List U8
|
a : List U8
|
||||||
a = List.withCapacity 1
|
a = List.withCapacity 1
|
||||||
|
@ -326,7 +326,7 @@ fn str_concat_later_referencing_empty_list_with_capacity() {
|
||||||
|> Num.addWrap (List.len a)
|
|> Num.addWrap (List.len a)
|
||||||
|> Num.toStr
|
|> Num.toStr
|
||||||
)
|
)
|
||||||
"#
|
"
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -504,7 +504,7 @@ fn tree_rebalance() {
|
||||||
#[test]
|
#[test]
|
||||||
fn lowlevel_list_calls() {
|
fn lowlevel_list_calls() {
|
||||||
valgrind_test(indoc!(
|
valgrind_test(indoc!(
|
||||||
r#"
|
r"
|
||||||
(
|
(
|
||||||
a = List.map [1,1,1,1,1] (\x -> x + 0)
|
a = List.map [1,1,1,1,1] (\x -> x + 0)
|
||||||
b = List.map2 a [1,1,1,1,1] (\x, y -> x + y)
|
b = List.map2 a [1,1,1,1,1] (\x, y -> x + y)
|
||||||
|
@ -514,7 +514,7 @@ fn lowlevel_list_calls() {
|
||||||
|
|
||||||
Num.toStr (List.len e)
|
Num.toStr (List.len e)
|
||||||
)
|
)
|
||||||
"#
|
"
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -550,3 +550,29 @@ fn joinpoint_nullpointer() {
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn freeing_boxes() {
|
||||||
|
valgrind_test(indoc!(
|
||||||
|
r#"
|
||||||
|
(
|
||||||
|
# Without refcounted field
|
||||||
|
a : I32
|
||||||
|
a = 7
|
||||||
|
|> Box.box
|
||||||
|
|> Box.unbox
|
||||||
|
|
||||||
|
# With refcounted field
|
||||||
|
b : Str
|
||||||
|
b =
|
||||||
|
"Testing123. This will definitely be a large string that is on the heap."
|
||||||
|
|> Box.box
|
||||||
|
|> Box.unbox
|
||||||
|
|
||||||
|
a
|
||||||
|
|> Num.toStr
|
||||||
|
|> Str.concat b
|
||||||
|
)
|
||||||
|
"#
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
2
crates/valgrind/zig-platform/.gitignore
vendored
2
crates/valgrind/zig-platform/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
||||||
dynhost
|
|
||||||
libapp.so
|
|
2
crates/vendor/morphic_lib/.gitignore
vendored
2
crates/vendor/morphic_lib/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
||||||
/target
|
|
||||||
Cargo.lock
|
|
|
@ -1,6 +1,8 @@
|
||||||
mod frame;
|
mod frame;
|
||||||
mod instance;
|
mod instance;
|
||||||
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
mod value_store;
|
mod value_store;
|
||||||
pub mod wasi;
|
pub mod wasi;
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,7 @@ macro_rules! section_impl {
|
||||||
let mut bytes = Vec::<u8>::with_capacity_in(range.len() * 2, arena);
|
let mut bytes = Vec::<u8>::with_capacity_in(range.len() * 2, arena);
|
||||||
*cursor = range.end;
|
*cursor = range.end;
|
||||||
bytes.extend_from_slice(&module_bytes[range]);
|
bytes.extend_from_slice(&module_bytes[range]);
|
||||||
|
#[allow(clippy::redundant_closure_call)]
|
||||||
Ok($from_count_and_bytes(count, bytes))
|
Ok($from_count_and_bytes(count, bytes))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
18
examples/.gitignore
vendored
18
examples/.gitignore
vendored
|
@ -1,18 +0,0 @@
|
||||||
*.dSYM
|
|
||||||
libhost.a
|
|
||||||
libapp.so
|
|
||||||
dynhost
|
|
||||||
*.rm
|
|
||||||
*.rh
|
|
||||||
|
|
||||||
helloWorld
|
|
||||||
helloWorldNoURL
|
|
||||||
inspect-gui
|
|
||||||
inspect-logging
|
|
||||||
swiftui
|
|
||||||
parser/examples/example
|
|
||||||
gui/hello-gui
|
|
||||||
gui/breakout/breakout
|
|
||||||
gui/breakout/hello-gui
|
|
||||||
webserver/echo
|
|
||||||
webserver/http
|
|
13
examples/cli/.gitignore
vendored
13
examples/cli/.gitignore
vendored
|
@ -1,13 +0,0 @@
|
||||||
args
|
|
||||||
countdown
|
|
||||||
echo
|
|
||||||
effects
|
|
||||||
file
|
|
||||||
form
|
|
||||||
tui
|
|
||||||
http-get
|
|
||||||
file-io
|
|
||||||
env
|
|
||||||
ingested-file
|
|
||||||
ingested-file-bytes
|
|
||||||
out.txt
|
|
1
examples/cli/false-interpreter/.gitignore
vendored
1
examples/cli/false-interpreter/.gitignore
vendored
|
@ -1 +0,0 @@
|
||||||
false
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue