mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 21:39:07 +00:00
Merge branch 'main' into str-withprefix
This commit is contained in:
commit
aef15ac1e8
57 changed files with 1388 additions and 631 deletions
145
Cargo.lock
generated
145
Cargo.lock
generated
|
@ -75,15 +75,6 @@ dependencies = [
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ansi_term"
|
|
||||||
version = "0.12.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
|
|
||||||
dependencies = [
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "approx"
|
name = "approx"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
@ -253,34 +244,13 @@ version = "0.1.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
|
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "block-buffer"
|
|
||||||
version = "0.7.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
|
|
||||||
dependencies = [
|
|
||||||
"block-padding",
|
|
||||||
"byte-tools",
|
|
||||||
"byteorder",
|
|
||||||
"generic-array 0.12.4",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
version = "0.10.2"
|
version = "0.10.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
|
checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"generic-array 0.14.5",
|
"generic-array",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "block-padding"
|
|
||||||
version = "0.1.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
|
|
||||||
dependencies = [
|
|
||||||
"byte-tools",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -301,12 +271,6 @@ version = "3.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
|
checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "byte-tools"
|
|
||||||
version = "0.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytecheck"
|
name = "bytecheck"
|
||||||
version = "0.6.8"
|
version = "0.6.8"
|
||||||
|
@ -1023,7 +987,7 @@ version = "0.1.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2ccfd8c0ee4cce11e45b3fd6f9d5e69e0cc62912aa6a0cb1bf4617b0eba5a12f"
|
checksum = "2ccfd8c0ee4cce11e45b3fd6f9d5e69e0cc62912aa6a0cb1bf4617b0eba5a12f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"generic-array 0.14.5",
|
"generic-array",
|
||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1129,22 +1093,13 @@ version = "0.1.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
|
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "digest"
|
|
||||||
version = "0.8.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
|
|
||||||
dependencies = [
|
|
||||||
"generic-array 0.12.4",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "digest"
|
name = "digest"
|
||||||
version = "0.10.3"
|
version = "0.10.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
|
checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"block-buffer 0.10.2",
|
"block-buffer",
|
||||||
"crypto-common",
|
"crypto-common",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1242,9 +1197,9 @@ checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dunce"
|
name = "dunce"
|
||||||
version = "1.0.2"
|
version = "1.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "453440c271cf5577fd2a40e4942540cb7d0d2f85e27c8d07dd0023c925a67541"
|
checksum = "0bd4b30a6560bbd9b4620f4de34c3f14f60848e58a9b7216801afcb4c7b31c3c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dynasm"
|
name = "dynasm"
|
||||||
|
@ -1378,12 +1333,6 @@ dependencies = [
|
||||||
"str-buf",
|
"str-buf",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fake-simd"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fallible-iterator"
|
name = "fallible-iterator"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
@ -1575,15 +1524,6 @@ dependencies = [
|
||||||
"cfg-if 0.1.10",
|
"cfg-if 0.1.10",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "generic-array"
|
|
||||||
version = "0.12.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
|
|
||||||
dependencies = [
|
|
||||||
"typenum",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generic-array"
|
name = "generic-array"
|
||||||
version = "0.14.5"
|
version = "0.14.5"
|
||||||
|
@ -2449,6 +2389,16 @@ version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09f1f8e5676e1a1f2ee8b21f38238e1243c827531c9435624c7bfb305102cee4"
|
checksum = "09f1f8e5676e1a1f2ee8b21f38238e1243c827531c9435624c7bfb305102cee4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nu-ansi-term"
|
||||||
|
version = "0.46.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
|
||||||
|
dependencies = [
|
||||||
|
"overload",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-derive"
|
name = "num-derive"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
|
@ -2617,12 +2567,6 @@ version = "11.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
|
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "opaque-debug"
|
|
||||||
version = "0.2.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ordered-float"
|
name = "ordered-float"
|
||||||
version = "3.0.0"
|
version = "3.0.0"
|
||||||
|
@ -2647,6 +2591,12 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "overload"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "owned_ttf_parser"
|
name = "owned_ttf_parser"
|
||||||
version = "0.15.0"
|
version = "0.15.0"
|
||||||
|
@ -2811,9 +2761,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pest_derive"
|
name = "pest_derive"
|
||||||
version = "2.1.0"
|
version = "2.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0"
|
checksum = "502b62a6d0245378b04ffe0a7fb4f4419a4815fce813bd8a0ec89a56e07d67b1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pest",
|
"pest",
|
||||||
"pest_generator",
|
"pest_generator",
|
||||||
|
@ -2821,9 +2771,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pest_generator"
|
name = "pest_generator"
|
||||||
version = "2.1.3"
|
version = "2.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55"
|
checksum = "451e629bf49b750254da26132f1a5a9d11fd8a95a3df51d15c4abd1ba154cb6c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pest",
|
"pest",
|
||||||
"pest_meta",
|
"pest_meta",
|
||||||
|
@ -2834,13 +2784,13 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pest_meta"
|
name = "pest_meta"
|
||||||
version = "2.1.3"
|
version = "2.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d"
|
checksum = "bcec162c71c45e269dfc3fc2916eaeb97feab22993a21bcce4721d08cd7801a6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"maplit",
|
"once_cell",
|
||||||
"pest",
|
"pest",
|
||||||
"sha-1",
|
"sha1 0.10.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -4458,18 +4408,6 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "sha-1"
|
|
||||||
version = "0.8.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
|
|
||||||
dependencies = [
|
|
||||||
"block-buffer 0.7.3",
|
|
||||||
"digest 0.8.1",
|
|
||||||
"fake-simd",
|
|
||||||
"opaque-debug",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha1"
|
name = "sha1"
|
||||||
version = "0.6.1"
|
version = "0.6.1"
|
||||||
|
@ -4479,6 +4417,17 @@ dependencies = [
|
||||||
"sha1_smol",
|
"sha1_smol",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha1"
|
||||||
|
version = "0.10.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "006769ba83e921b3085caa8334186b00cf92b4cb1a6cf4632fbccc8eff5c7549"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha1_smol"
|
name = "sha1_smol"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -4493,7 +4442,7 @@ checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"cpufeatures",
|
"cpufeatures",
|
||||||
"digest 0.10.3",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -4736,7 +4685,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha1",
|
"sha1 0.6.1",
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -5114,9 +5063,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-core"
|
name = "tracing-core"
|
||||||
version = "0.1.29"
|
version = "0.1.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7"
|
checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"valuable",
|
"valuable",
|
||||||
|
@ -5135,12 +5084,12 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-subscriber"
|
name = "tracing-subscriber"
|
||||||
version = "0.3.15"
|
version = "0.3.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b"
|
checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term",
|
|
||||||
"matchers",
|
"matchers",
|
||||||
|
"nu-ansi-term",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"regex",
|
"regex",
|
||||||
"sharded-slab",
|
"sharded-slab",
|
||||||
|
|
|
@ -15,7 +15,7 @@ lazy_static = "1.4.0"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
# dunce can be removed once ziglang/zig#5109 is fixed
|
# dunce can be removed once ziglang/zig#5109 is fixed
|
||||||
dunce = "1.0.2"
|
dunce = "1.0.3"
|
||||||
|
|
||||||
[target.'cfg(target_os = "macos")'.build-dependencies]
|
[target.'cfg(target_os = "macos")'.build-dependencies]
|
||||||
tempfile = "3.2.0"
|
tempfile = "3.2.0"
|
||||||
|
|
|
@ -93,20 +93,6 @@ pub const RocList = extern struct {
|
||||||
return (ptr - 1)[0] == utils.REFCOUNT_ONE;
|
return (ptr - 1)[0] == utils.REFCOUNT_ONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocate(
|
|
||||||
alignment: u32,
|
|
||||||
length: usize,
|
|
||||||
element_size: usize,
|
|
||||||
) RocList {
|
|
||||||
const data_bytes = length * element_size;
|
|
||||||
|
|
||||||
return RocList{
|
|
||||||
.bytes = utils.allocateWithRefcount(data_bytes, alignment),
|
|
||||||
.length = length,
|
|
||||||
.capacity = length,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn makeUniqueExtra(self: RocList, alignment: u32, element_width: usize, update_mode: UpdateMode) RocList {
|
pub fn makeUniqueExtra(self: RocList, alignment: u32, element_width: usize, update_mode: UpdateMode) RocList {
|
||||||
if (update_mode == .InPlace) {
|
if (update_mode == .InPlace) {
|
||||||
return self;
|
return self;
|
||||||
|
@ -140,11 +126,117 @@ pub const RocList = extern struct {
|
||||||
return new_list;
|
return new_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We follow roughly the [fbvector](https://github.com/facebook/folly/blob/main/folly/docs/FBVector.md) when it comes to growing a RocList.
|
||||||
|
// Here is [their growth strategy](https://github.com/facebook/folly/blob/3e0525988fd444201b19b76b390a5927c15cb697/folly/FBVector.h#L1128) for push_back:
|
||||||
|
//
|
||||||
|
// (1) initial size
|
||||||
|
// Instead of growing to size 1 from empty, fbvector allocates at least
|
||||||
|
// 64 bytes. You may still use reserve to reserve a lesser amount of
|
||||||
|
// memory.
|
||||||
|
// (2) 1.5x
|
||||||
|
// For medium-sized vectors, the growth strategy is 1.5x. See the docs
|
||||||
|
// for details.
|
||||||
|
// This does not apply to very small or very large fbvectors. This is a
|
||||||
|
// heuristic.
|
||||||
|
//
|
||||||
|
// In our case, we exposed allocate and reallocate, which will use a smart growth stategy.
|
||||||
|
// We also expose allocateExact and reallocateExact for case where a specific number of elements is requested.
|
||||||
|
|
||||||
|
// calculateCapacity should only be called in cases the list will be growing.
|
||||||
|
// requested_length should always be greater than old_capacity.
|
||||||
|
inline fn calculateCapacity(
|
||||||
|
old_capacity: usize,
|
||||||
|
requested_length: usize,
|
||||||
|
element_width: usize,
|
||||||
|
) usize {
|
||||||
|
// TODO: there are two adjustments that would likely lead to better results for Roc.
|
||||||
|
// 1. Deal with the fact we allocate an extra u64 for refcount.
|
||||||
|
// This may lead to allocating page size + 8 bytes.
|
||||||
|
// That could mean allocating an entire page for 8 bytes of data which isn't great.
|
||||||
|
// 2. Deal with the fact that we can request more than 1 element at a time.
|
||||||
|
// fbvector assumes just appending 1 element at a time when using this algorithm.
|
||||||
|
// As such, they will generally grow in a way that should better match certain memory multiple.
|
||||||
|
// This is also the normal case for roc, but we could also grow by a much larger amount.
|
||||||
|
// We may want to round to multiples of 2 or something similar.
|
||||||
|
var new_capacity: usize = 0;
|
||||||
|
if (element_width == 0) {
|
||||||
|
return requested_length;
|
||||||
|
} else if (old_capacity == 0) {
|
||||||
|
new_capacity = 64 / element_width;
|
||||||
|
} else if (old_capacity < 4096 / element_width) {
|
||||||
|
new_capacity = old_capacity * 2;
|
||||||
|
} else if (old_capacity > 4096 * 32 / element_width) {
|
||||||
|
new_capacity = old_capacity * 2;
|
||||||
|
} else {
|
||||||
|
new_capacity = (old_capacity * 3 + 1) / 2;
|
||||||
|
}
|
||||||
|
return @maximum(new_capacity, requested_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn allocate(
|
||||||
|
alignment: u32,
|
||||||
|
length: usize,
|
||||||
|
element_width: usize,
|
||||||
|
) RocList {
|
||||||
|
if (length == 0) {
|
||||||
|
return empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
const capacity = calculateCapacity(0, length, element_width);
|
||||||
|
const data_bytes = capacity * element_width;
|
||||||
|
return RocList{
|
||||||
|
.bytes = utils.allocateWithRefcount(data_bytes, alignment),
|
||||||
|
.length = length,
|
||||||
|
.capacity = capacity,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn allocateExact(
|
||||||
|
alignment: u32,
|
||||||
|
length: usize,
|
||||||
|
element_width: usize,
|
||||||
|
) RocList {
|
||||||
|
if (length == 0) {
|
||||||
|
return empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
const data_bytes = length * element_width;
|
||||||
|
return RocList{
|
||||||
|
.bytes = utils.allocateWithRefcount(data_bytes, alignment),
|
||||||
|
.length = length,
|
||||||
|
.capacity = length,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn reallocate(
|
pub fn reallocate(
|
||||||
self: RocList,
|
self: RocList,
|
||||||
alignment: u32,
|
alignment: u32,
|
||||||
new_length: usize,
|
new_length: usize,
|
||||||
element_width: usize,
|
element_width: usize,
|
||||||
|
) RocList {
|
||||||
|
if (self.bytes) |source_ptr| {
|
||||||
|
if (self.isUnique()) {
|
||||||
|
if (self.capacity >= new_length) {
|
||||||
|
return RocList{ .bytes = self.bytes, .length = new_length, .capacity = self.capacity };
|
||||||
|
} else {
|
||||||
|
const new_capacity = calculateCapacity(self.capacity, new_length, element_width);
|
||||||
|
const new_source = utils.unsafeReallocate(source_ptr, alignment, self.len(), new_capacity, element_width);
|
||||||
|
return RocList{ .bytes = new_source, .length = new_length, .capacity = new_capacity };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: Investigate the performance of this.
|
||||||
|
// Maybe we should just always reallocate to the new_length instead of expanding capacity?
|
||||||
|
const new_capacity = if (self.capacity >= new_length) self.capacity else calculateCapacity(self.capacity, new_length, element_width);
|
||||||
|
return self.reallocateFresh(alignment, new_length, new_capacity, element_width);
|
||||||
|
}
|
||||||
|
return RocList.allocate(alignment, new_length, element_width);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reallocateExact(
|
||||||
|
self: RocList,
|
||||||
|
alignment: u32,
|
||||||
|
new_length: usize,
|
||||||
|
element_width: usize,
|
||||||
) RocList {
|
) RocList {
|
||||||
if (self.bytes) |source_ptr| {
|
if (self.bytes) |source_ptr| {
|
||||||
if (self.isUnique()) {
|
if (self.isUnique()) {
|
||||||
|
@ -155,9 +247,9 @@ pub const RocList = extern struct {
|
||||||
return RocList{ .bytes = new_source, .length = new_length, .capacity = new_length };
|
return RocList{ .bytes = new_source, .length = new_length, .capacity = new_length };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return self.reallocateFresh(alignment, new_length, new_length, element_width);
|
||||||
}
|
}
|
||||||
|
return RocList.allocateExact(alignment, new_length, element_width);
|
||||||
return self.reallocateFresh(alignment, new_length, element_width);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// reallocate by explicitly making a new allocation and copying elements over
|
/// reallocate by explicitly making a new allocation and copying elements over
|
||||||
|
@ -165,16 +257,16 @@ pub const RocList = extern struct {
|
||||||
self: RocList,
|
self: RocList,
|
||||||
alignment: u32,
|
alignment: u32,
|
||||||
new_length: usize,
|
new_length: usize,
|
||||||
|
new_capacity: usize,
|
||||||
element_width: usize,
|
element_width: usize,
|
||||||
) RocList {
|
) RocList {
|
||||||
const old_length = self.length;
|
const old_length = self.length;
|
||||||
const delta_length = new_length - old_length;
|
const delta_length = new_length - old_length;
|
||||||
|
|
||||||
const data_bytes = new_length * element_width;
|
const data_bytes = new_capacity * element_width;
|
||||||
const first_slot = utils.allocateWithRefcount(data_bytes, alignment);
|
const first_slot = utils.allocateWithRefcount(data_bytes, alignment);
|
||||||
|
|
||||||
// transfer the memory
|
// transfer the memory
|
||||||
|
|
||||||
if (self.bytes) |source_ptr| {
|
if (self.bytes) |source_ptr| {
|
||||||
const dest_ptr = first_slot;
|
const dest_ptr = first_slot;
|
||||||
|
|
||||||
|
@ -185,7 +277,7 @@ pub const RocList = extern struct {
|
||||||
const result = RocList{
|
const result = RocList{
|
||||||
.bytes = first_slot,
|
.bytes = first_slot,
|
||||||
.length = new_length,
|
.length = new_length,
|
||||||
.capacity = new_length,
|
.capacity = new_capacity,
|
||||||
};
|
};
|
||||||
|
|
||||||
utils.decref(self.bytes, old_length * element_width, alignment);
|
utils.decref(self.bytes, old_length * element_width, alignment);
|
||||||
|
@ -412,7 +504,7 @@ pub fn listWithCapacity(
|
||||||
alignment: u32,
|
alignment: u32,
|
||||||
element_width: usize,
|
element_width: usize,
|
||||||
) callconv(.C) RocList {
|
) callconv(.C) RocList {
|
||||||
var output = RocList.allocate(alignment, capacity, element_width);
|
var output = RocList.allocateExact(alignment, capacity, element_width);
|
||||||
output.length = 0;
|
output.length = 0;
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,6 +144,7 @@ comptime {
|
||||||
exportStrFn(str.strTrimLeft, "trim_left");
|
exportStrFn(str.strTrimLeft, "trim_left");
|
||||||
exportStrFn(str.strTrimRight, "trim_right");
|
exportStrFn(str.strTrimRight, "trim_right");
|
||||||
exportStrFn(str.strCloneTo, "clone_to");
|
exportStrFn(str.strCloneTo, "clone_to");
|
||||||
|
exportStrFn(str.withCapacity, "with_capacity");
|
||||||
|
|
||||||
inline for (INTEGERS) |T| {
|
inline for (INTEGERS) |T| {
|
||||||
str.exportFromInt(T, ROC_BUILTINS ++ "." ++ STR ++ ".from_int.");
|
str.exportFromInt(T, ROC_BUILTINS ++ "." ++ STR ++ ".from_int.");
|
||||||
|
|
|
@ -2596,6 +2596,10 @@ pub fn reserve(string: RocStr, capacity: usize) callconv(.C) RocStr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn withCapacity(capacity: usize) callconv(.C) RocStr {
|
||||||
|
return RocStr.allocate(0, capacity);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn getScalarUnsafe(string: RocStr, index: usize) callconv(.C) extern struct { bytesParsed: usize, scalar: u32 } {
|
pub fn getScalarUnsafe(string: RocStr, index: usize) callconv(.C) extern struct { bytesParsed: usize, scalar: u32 } {
|
||||||
const slice = string.asSlice();
|
const slice = string.asSlice();
|
||||||
const bytesParsed = @intCast(usize, std.unicode.utf8ByteSequenceLength(slice[index]) catch unreachable);
|
const bytesParsed = @intCast(usize, std.unicode.utf8ByteSequenceLength(slice[index]) catch unreachable);
|
||||||
|
|
|
@ -61,6 +61,7 @@ interface List
|
||||||
sortAsc,
|
sortAsc,
|
||||||
sortDesc,
|
sortDesc,
|
||||||
reserve,
|
reserve,
|
||||||
|
walkBackwardsUntil,
|
||||||
]
|
]
|
||||||
imports [
|
imports [
|
||||||
Bool.{ Bool },
|
Bool.{ Bool },
|
||||||
|
@ -88,9 +89,8 @@ interface List
|
||||||
##
|
##
|
||||||
## ## Performance Details
|
## ## Performance Details
|
||||||
##
|
##
|
||||||
## Under the hood, a list is a record containing a `len : Nat` field as well
|
## Under the hood, a list is a record containing a `len : Nat` field, a `capacity : Nat`
|
||||||
## as a pointer to a reference count and a flat array of bytes. Unique lists
|
## field, and a pointer to a reference count and a flat array of bytes.
|
||||||
## store a capacity #Nat instead of a reference count.
|
|
||||||
##
|
##
|
||||||
## ## Shared Lists
|
## ## Shared Lists
|
||||||
##
|
##
|
||||||
|
@ -112,9 +112,8 @@ interface List
|
||||||
## begins with a refcount of 1, because so far only `ratings` is referencing it.
|
## begins with a refcount of 1, because so far only `ratings` is referencing it.
|
||||||
##
|
##
|
||||||
## The second line alters this refcount. `{ foo: ratings` references
|
## The second line alters this refcount. `{ foo: ratings` references
|
||||||
## the `ratings` list, which will result in its refcount getting incremented
|
## the `ratings` list, and so does `bar: ratings }`. This will result in its
|
||||||
## from 0 to 1. Similarly, `bar: ratings }` also references the `ratings` list,
|
## refcount getting incremented from 1 to 3.
|
||||||
## which will result in its refcount getting incremented from 1 to 2.
|
|
||||||
##
|
##
|
||||||
## Let's turn this example into a function.
|
## Let's turn this example into a function.
|
||||||
##
|
##
|
||||||
|
@ -132,11 +131,11 @@ interface List
|
||||||
##
|
##
|
||||||
## Since `ratings` represented a way to reference the list, and that way is no
|
## Since `ratings` represented a way to reference the list, and that way is no
|
||||||
## longer accessible, the list's refcount gets decremented when `ratings` goes
|
## longer accessible, the list's refcount gets decremented when `ratings` goes
|
||||||
## out of scope. It will decrease from 2 back down to 1.
|
## out of scope. It will decrease from 3 back down to 2.
|
||||||
##
|
##
|
||||||
## Putting these together, when we call `getRatings 5`, what we get back is
|
## Putting these together, when we call `getRatings 5`, what we get back is
|
||||||
## a record with two fields, `foo`, and `bar`, each of which refers to the same
|
## a record with two fields, `foo`, and `bar`, each of which refers to the same
|
||||||
## list, and that list has a refcount of 1.
|
## list, and that list has a refcount of 2.
|
||||||
##
|
##
|
||||||
## Let's change the last line to be `(getRatings 5).bar` instead of `getRatings 5`:
|
## Let's change the last line to be `(getRatings 5).bar` instead of `getRatings 5`:
|
||||||
##
|
##
|
||||||
|
@ -436,6 +435,13 @@ walkUntil = \list, initial, step ->
|
||||||
Continue new -> new
|
Continue new -> new
|
||||||
Break new -> new
|
Break new -> new
|
||||||
|
|
||||||
|
## Same as [List.walkUntil], but does it from the end of the list instead.
|
||||||
|
walkBackwardsUntil : List elem, state, (state, elem -> [Continue state, Break state]) -> state
|
||||||
|
walkBackwardsUntil = \list, initial, func ->
|
||||||
|
when List.iterateBackwards list initial func is
|
||||||
|
Continue new -> new
|
||||||
|
Break new -> new
|
||||||
|
|
||||||
sum : List (Num a) -> Num a
|
sum : List (Num a) -> Num a
|
||||||
sum = \list ->
|
sum = \list ->
|
||||||
List.walk list 0 Num.add
|
List.walk list 0 Num.add
|
||||||
|
|
|
@ -43,6 +43,7 @@ interface Str
|
||||||
appendScalar,
|
appendScalar,
|
||||||
walkScalars,
|
walkScalars,
|
||||||
walkScalarsUntil,
|
walkScalarsUntil,
|
||||||
|
withCapacity,
|
||||||
withPrefix,
|
withPrefix,
|
||||||
]
|
]
|
||||||
imports [
|
imports [
|
||||||
|
@ -145,6 +146,9 @@ Utf8Problem : { byteIndex : Nat, problem : Utf8ByteProblem }
|
||||||
isEmpty : Str -> Bool
|
isEmpty : Str -> Bool
|
||||||
concat : Str, Str -> Str
|
concat : Str, Str -> Str
|
||||||
|
|
||||||
|
## Returns a string of the specified capacity without any content
|
||||||
|
withCapacity : Nat -> Str
|
||||||
|
|
||||||
## Combine a list of strings into a single string, with a separator
|
## Combine a list of strings into a single string, with a separator
|
||||||
## string in between each.
|
## string in between each.
|
||||||
##
|
##
|
||||||
|
|
|
@ -361,6 +361,7 @@ pub const STR_RESERVE: &str = "roc_builtins.str.reserve";
|
||||||
pub const STR_APPEND_SCALAR: &str = "roc_builtins.str.append_scalar";
|
pub const STR_APPEND_SCALAR: &str = "roc_builtins.str.append_scalar";
|
||||||
pub const STR_GET_SCALAR_UNSAFE: &str = "roc_builtins.str.get_scalar_unsafe";
|
pub const STR_GET_SCALAR_UNSAFE: &str = "roc_builtins.str.get_scalar_unsafe";
|
||||||
pub const STR_CLONE_TO: &str = "roc_builtins.str.clone_to";
|
pub const STR_CLONE_TO: &str = "roc_builtins.str.clone_to";
|
||||||
|
pub const STR_WITH_CAPACITY: &str = "roc_builtins.str.with_capacity";
|
||||||
|
|
||||||
pub const LIST_MAP: &str = "roc_builtins.list.map";
|
pub const LIST_MAP: &str = "roc_builtins.list.map";
|
||||||
pub const LIST_MAP2: &str = "roc_builtins.list.map2";
|
pub const LIST_MAP2: &str = "roc_builtins.list.map2";
|
||||||
|
|
|
@ -123,6 +123,7 @@ map_symbol_to_lowlevel_and_arity! {
|
||||||
StrGetScalarUnsafe; STR_GET_SCALAR_UNSAFE; 2,
|
StrGetScalarUnsafe; STR_GET_SCALAR_UNSAFE; 2,
|
||||||
StrToNum; STR_TO_NUM; 1,
|
StrToNum; STR_TO_NUM; 1,
|
||||||
StrGetCapacity; STR_CAPACITY; 1,
|
StrGetCapacity; STR_CAPACITY; 1,
|
||||||
|
StrWithCapacity; STR_WITH_CAPACITY; 1,
|
||||||
|
|
||||||
ListLen; LIST_LEN; 1,
|
ListLen; LIST_LEN; 1,
|
||||||
ListWithCapacity; LIST_WITH_CAPACITY; 1,
|
ListWithCapacity; LIST_WITH_CAPACITY; 1,
|
||||||
|
|
|
@ -60,8 +60,6 @@ trait CopyEnv {
|
||||||
|
|
||||||
fn clone_name(&mut self, name: SubsIndex<Lowercase>) -> SubsIndex<Lowercase>;
|
fn clone_name(&mut self, name: SubsIndex<Lowercase>) -> SubsIndex<Lowercase>;
|
||||||
|
|
||||||
fn clone_tag_name(&mut self, tag_name: SubsIndex<TagName>) -> SubsIndex<TagName>;
|
|
||||||
|
|
||||||
fn clone_field_names(&mut self, field_names: SubsSlice<Lowercase>) -> SubsSlice<Lowercase>;
|
fn clone_field_names(&mut self, field_names: SubsSlice<Lowercase>) -> SubsSlice<Lowercase>;
|
||||||
|
|
||||||
fn clone_tag_names(&mut self, tag_names: SubsSlice<TagName>) -> SubsSlice<TagName>;
|
fn clone_tag_names(&mut self, tag_names: SubsSlice<TagName>) -> SubsSlice<TagName>;
|
||||||
|
@ -95,11 +93,6 @@ impl CopyEnv for Subs {
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn clone_tag_name(&mut self, tag_name: SubsIndex<TagName>) -> SubsIndex<TagName> {
|
|
||||||
tag_name
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn clone_field_names(&mut self, field_names: SubsSlice<Lowercase>) -> SubsSlice<Lowercase> {
|
fn clone_field_names(&mut self, field_names: SubsSlice<Lowercase>) -> SubsSlice<Lowercase> {
|
||||||
field_names
|
field_names
|
||||||
|
@ -150,11 +143,6 @@ impl<'a> CopyEnv for AcrossSubs<'a> {
|
||||||
SubsIndex::push_new(&mut self.target.field_names, self.source[name].clone())
|
SubsIndex::push_new(&mut self.target.field_names, self.source[name].clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn clone_tag_name(&mut self, tag_name: SubsIndex<TagName>) -> SubsIndex<TagName> {
|
|
||||||
SubsIndex::push_new(&mut self.target.tag_names, self.source[tag_name].clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn clone_field_names(&mut self, field_names: SubsSlice<Lowercase>) -> SubsSlice<Lowercase> {
|
fn clone_field_names(&mut self, field_names: SubsSlice<Lowercase>) -> SubsSlice<Lowercase> {
|
||||||
SubsSlice::extend_new(
|
SubsSlice::extend_new(
|
||||||
|
@ -935,12 +923,13 @@ fn deep_copy_type_vars<C: CopyEnv>(
|
||||||
Structure(RecursiveTagUnion(new_rec_var, new_union_tags, new_ext_var))
|
Structure(RecursiveTagUnion(new_rec_var, new_union_tags, new_ext_var))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
FunctionOrTagUnion(tag_name, symbol, ext_var) => {
|
FunctionOrTagUnion(tag_names, symbols, ext_var) => {
|
||||||
let new_ext_var = descend_var!(ext_var);
|
let new_ext_var = descend_var!(ext_var);
|
||||||
let new_tag_name = env.clone_tag_name(tag_name);
|
let new_tag_names = env.clone_tag_names(tag_names);
|
||||||
|
let new_symbols = env.clone_lambda_names(symbols);
|
||||||
perform_clone!(Structure(FunctionOrTagUnion(
|
perform_clone!(Structure(FunctionOrTagUnion(
|
||||||
new_tag_name,
|
new_tag_names,
|
||||||
symbol,
|
new_symbols,
|
||||||
new_ext_var
|
new_ext_var
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use roc_module::{
|
||||||
ident::{Lowercase, TagName},
|
ident::{Lowercase, TagName},
|
||||||
symbol::Symbol,
|
symbol::Symbol,
|
||||||
};
|
};
|
||||||
use roc_types::subs::{Content, FlatType, Subs, Variable};
|
use roc_types::subs::{Content, FlatType, GetSubsSlice, Subs, Variable};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
util::{check_derivable_ext_var, debug_name_record},
|
util::{check_derivable_ext_var, debug_name_record},
|
||||||
|
@ -107,9 +107,14 @@ impl FlatEncodable {
|
||||||
|
|
||||||
Ok(Key(FlatEncodableKey::TagUnion(tag_names_and_payload_sizes)))
|
Ok(Key(FlatEncodableKey::TagUnion(tag_names_and_payload_sizes)))
|
||||||
}
|
}
|
||||||
FlatType::FunctionOrTagUnion(name_index, _, _) => Ok(Key(
|
FlatType::FunctionOrTagUnion(names_index, _, _) => {
|
||||||
FlatEncodableKey::TagUnion(vec![(subs[name_index].clone(), 0)]),
|
Ok(Key(FlatEncodableKey::TagUnion(
|
||||||
)),
|
subs.get_subs_slice(names_index)
|
||||||
|
.iter()
|
||||||
|
.map(|t| (t.clone(), 0))
|
||||||
|
.collect(),
|
||||||
|
)))
|
||||||
|
}
|
||||||
FlatType::EmptyRecord => Ok(Key(FlatEncodableKey::Record(vec![]))),
|
FlatType::EmptyRecord => Ok(Key(FlatEncodableKey::Record(vec![]))),
|
||||||
FlatType::EmptyTagUnion => Ok(Key(FlatEncodableKey::TagUnion(vec![]))),
|
FlatType::EmptyTagUnion => Ok(Key(FlatEncodableKey::TagUnion(vec![]))),
|
||||||
//
|
//
|
||||||
|
|
|
@ -6035,6 +6035,20 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
bitcode::STR_TRIM_RIGHT,
|
bitcode::STR_TRIM_RIGHT,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
StrWithCapacity => {
|
||||||
|
// Str.withCapacity : Nat -> Str
|
||||||
|
debug_assert_eq!(args.len(), 1);
|
||||||
|
|
||||||
|
let str_len = load_symbol(scope, &args[0]);
|
||||||
|
|
||||||
|
call_str_bitcode_fn(
|
||||||
|
env,
|
||||||
|
&[],
|
||||||
|
&[str_len],
|
||||||
|
BitcodeReturns::Str,
|
||||||
|
bitcode::STR_WITH_CAPACITY,
|
||||||
|
)
|
||||||
|
}
|
||||||
ListLen => {
|
ListLen => {
|
||||||
// List.len : List * -> Nat
|
// List.len : List * -> Nat
|
||||||
debug_assert_eq!(args.len(), 1);
|
debug_assert_eq!(args.len(), 1);
|
||||||
|
@ -6157,7 +6171,7 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
list_prepend(env, original_wrapper, elem, elem_layout)
|
list_prepend(env, original_wrapper, elem, elem_layout)
|
||||||
}
|
}
|
||||||
StrGetUnsafe => {
|
StrGetUnsafe => {
|
||||||
// List.getUnsafe : Str, Nat -> u8
|
// Str.getUnsafe : Str, Nat -> u8
|
||||||
debug_assert_eq!(args.len(), 2);
|
debug_assert_eq!(args.len(), 2);
|
||||||
|
|
||||||
let wrapper_struct = load_symbol(scope, &args[0]);
|
let wrapper_struct = load_symbol(scope, &args[0]);
|
||||||
|
|
|
@ -302,6 +302,7 @@ impl<'a> LowLevelCall<'a> {
|
||||||
StrSubstringUnsafe => {
|
StrSubstringUnsafe => {
|
||||||
self.load_args_and_call_zig(backend, bitcode::STR_SUBSTRING_UNSAFE)
|
self.load_args_and_call_zig(backend, bitcode::STR_SUBSTRING_UNSAFE)
|
||||||
}
|
}
|
||||||
|
StrWithCapacity => self.load_args_and_call_zig(backend, bitcode::STR_WITH_CAPACITY),
|
||||||
|
|
||||||
// List
|
// List
|
||||||
ListLen => match backend.storage.get(&self.arguments[0]) {
|
ListLen => match backend.storage.get(&self.arguments[0]) {
|
||||||
|
|
|
@ -30,6 +30,7 @@ pub enum LowLevel {
|
||||||
StrAppendScalar,
|
StrAppendScalar,
|
||||||
StrGetScalarUnsafe,
|
StrGetScalarUnsafe,
|
||||||
StrGetCapacity,
|
StrGetCapacity,
|
||||||
|
StrWithCapacity,
|
||||||
ListLen,
|
ListLen,
|
||||||
ListWithCapacity,
|
ListWithCapacity,
|
||||||
ListReserve,
|
ListReserve,
|
||||||
|
@ -249,6 +250,7 @@ map_symbol_to_lowlevel! {
|
||||||
StrGetScalarUnsafe <= STR_GET_SCALAR_UNSAFE,
|
StrGetScalarUnsafe <= STR_GET_SCALAR_UNSAFE,
|
||||||
StrToNum <= STR_TO_NUM,
|
StrToNum <= STR_TO_NUM,
|
||||||
StrGetCapacity <= STR_CAPACITY,
|
StrGetCapacity <= STR_CAPACITY,
|
||||||
|
StrWithCapacity <= STR_WITH_CAPACITY,
|
||||||
ListLen <= LIST_LEN,
|
ListLen <= LIST_LEN,
|
||||||
ListGetCapacity <= LIST_CAPACITY,
|
ListGetCapacity <= LIST_CAPACITY,
|
||||||
ListWithCapacity <= LIST_WITH_CAPACITY,
|
ListWithCapacity <= LIST_WITH_CAPACITY,
|
||||||
|
|
|
@ -1296,7 +1296,8 @@ define_builtins! {
|
||||||
50 STR_REPLACE_EACH: "replaceEach"
|
50 STR_REPLACE_EACH: "replaceEach"
|
||||||
51 STR_REPLACE_FIRST: "replaceFirst"
|
51 STR_REPLACE_FIRST: "replaceFirst"
|
||||||
52 STR_REPLACE_LAST: "replaceLast"
|
52 STR_REPLACE_LAST: "replaceLast"
|
||||||
53 STR_WITH_PREFIX: "withPrefix"
|
53 STR_WITH_CAPACITY: "withCapacity"
|
||||||
|
54 STR_WITH_PREFIX: "withPrefix"
|
||||||
}
|
}
|
||||||
6 LIST: "List" => {
|
6 LIST: "List" => {
|
||||||
0 LIST_LIST: "List" exposed_apply_type=true // the List.List type alias
|
0 LIST_LIST: "List" exposed_apply_type=true // the List.List type alias
|
||||||
|
@ -1375,6 +1376,7 @@ define_builtins! {
|
||||||
73 LIST_CAPACITY: "capacity"
|
73 LIST_CAPACITY: "capacity"
|
||||||
74 LIST_MAP_TRY: "mapTry"
|
74 LIST_MAP_TRY: "mapTry"
|
||||||
75 LIST_WALK_TRY: "walkTry"
|
75 LIST_WALK_TRY: "walkTry"
|
||||||
|
76 LIST_WALK_BACKWARDS_UNTIL: "walkBackwardsUntil"
|
||||||
}
|
}
|
||||||
7 RESULT: "Result" => {
|
7 RESULT: "Result" => {
|
||||||
0 RESULT_RESULT: "Result" exposed_type=true // the Result.Result type alias
|
0 RESULT_RESULT: "Result" exposed_type=true // the Result.Result type alias
|
||||||
|
|
|
@ -881,7 +881,7 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] {
|
||||||
Unreachable => arena.alloc_slice_copy(&[irrelevant]),
|
Unreachable => arena.alloc_slice_copy(&[irrelevant]),
|
||||||
ListLen | StrIsEmpty | StrToScalars | StrCountGraphemes | StrCountUtf8Bytes
|
ListLen | StrIsEmpty | StrToScalars | StrCountGraphemes | StrCountUtf8Bytes
|
||||||
| StrGetCapacity | ListGetCapacity => arena.alloc_slice_copy(&[borrowed]),
|
| StrGetCapacity | ListGetCapacity => arena.alloc_slice_copy(&[borrowed]),
|
||||||
ListWithCapacity => arena.alloc_slice_copy(&[irrelevant]),
|
ListWithCapacity | StrWithCapacity => arena.alloc_slice_copy(&[irrelevant]),
|
||||||
ListReplaceUnsafe => arena.alloc_slice_copy(&[owned, irrelevant, irrelevant]),
|
ListReplaceUnsafe => arena.alloc_slice_copy(&[owned, irrelevant, irrelevant]),
|
||||||
StrGetUnsafe | ListGetUnsafe => arena.alloc_slice_copy(&[borrowed, irrelevant]),
|
StrGetUnsafe | ListGetUnsafe => arena.alloc_slice_copy(&[borrowed, irrelevant]),
|
||||||
ListConcat => arena.alloc_slice_copy(&[owned, owned]),
|
ListConcat => arena.alloc_slice_copy(&[owned, owned]),
|
||||||
|
|
|
@ -12,7 +12,7 @@ use roc_problem::can::RuntimeError;
|
||||||
use roc_target::{PtrWidth, TargetInfo};
|
use roc_target::{PtrWidth, TargetInfo};
|
||||||
use roc_types::num::NumericRange;
|
use roc_types::num::NumericRange;
|
||||||
use roc_types::subs::{
|
use roc_types::subs::{
|
||||||
self, Content, FlatType, GetSubsSlice, Label, OptVariable, RecordFields, Subs, UnionTags,
|
self, Content, FlatType, GetSubsSlice, Label, OptVariable, RecordFields, Subs,
|
||||||
UnsortedUnionLabels, Variable,
|
UnsortedUnionLabels, Variable,
|
||||||
};
|
};
|
||||||
use roc_types::types::{gather_fields_unsorted_iter, RecordField, RecordFieldsError};
|
use roc_types::types::{gather_fields_unsorted_iter, RecordField, RecordFieldsError};
|
||||||
|
@ -3152,16 +3152,18 @@ fn layout_from_flat_type<'a>(
|
||||||
|
|
||||||
layout_from_non_recursive_union(env, &tags).map(Ok)
|
layout_from_non_recursive_union(env, &tags).map(Ok)
|
||||||
}
|
}
|
||||||
FunctionOrTagUnion(tag_name, _, ext_var) => {
|
FunctionOrTagUnion(tag_names, _, ext_var) => {
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
ext_var_is_empty_tag_union(subs, ext_var),
|
ext_var_is_empty_tag_union(subs, ext_var),
|
||||||
"If ext_var wasn't empty, this wouldn't be a FunctionOrTagUnion!"
|
"If ext_var wasn't empty, this wouldn't be a FunctionOrTagUnion!"
|
||||||
);
|
);
|
||||||
|
|
||||||
let union_tags = UnionTags::from_tag_name_index(tag_name);
|
let tag_names = subs.get_subs_slice(tag_names);
|
||||||
let (tags, _) = union_tags.unsorted_tags_and_ext(subs, ext_var);
|
let unsorted_tags = UnsortedUnionLabels {
|
||||||
|
tags: tag_names.iter().map(|t| (t, &[] as &[Variable])).collect(),
|
||||||
|
};
|
||||||
|
|
||||||
layout_from_non_recursive_union(env, &tags).map(Ok)
|
layout_from_non_recursive_union(env, &unsorted_tags).map(Ok)
|
||||||
}
|
}
|
||||||
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
||||||
let (tags, ext_var) = tags.unsorted_tags_and_ext(subs, ext_var);
|
let (tags, ext_var) = tags.unsorted_tags_and_ext(subs, ext_var);
|
||||||
|
|
|
@ -345,7 +345,12 @@ fn eat_spaces<'a>(
|
||||||
state = state.advance(1);
|
state = state.advance(1);
|
||||||
return eat_line_comment(state, comments_and_newlines);
|
return eat_line_comment(state, comments_and_newlines);
|
||||||
}
|
}
|
||||||
_ => break,
|
_ => {
|
||||||
|
if !comments_and_newlines.is_empty() {
|
||||||
|
state = state.mark_current_indent();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,7 +403,10 @@ fn eat_line_comment<'a>(
|
||||||
index += 1;
|
index += 1;
|
||||||
continue 'outer;
|
continue 'outer;
|
||||||
}
|
}
|
||||||
_ => break,
|
_ => {
|
||||||
|
state = state.mark_current_indent();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
index += 1;
|
index += 1;
|
||||||
|
@ -490,7 +498,10 @@ fn eat_line_comment<'a>(
|
||||||
index += 1;
|
index += 1;
|
||||||
continue 'outer;
|
continue 'outer;
|
||||||
}
|
}
|
||||||
_ => break,
|
_ => {
|
||||||
|
state = state.mark_current_indent();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
index += 1;
|
index += 1;
|
||||||
|
@ -554,7 +565,10 @@ fn eat_line_comment<'a>(
|
||||||
index += 1;
|
index += 1;
|
||||||
continue 'outer;
|
continue 'outer;
|
||||||
}
|
}
|
||||||
_ => break,
|
_ => {
|
||||||
|
state = state.mark_current_indent();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
index += 1;
|
index += 1;
|
||||||
|
|
|
@ -8,8 +8,8 @@ use crate::blankspace::{
|
||||||
use crate::ident::{lowercase_ident, parse_ident, Ident};
|
use crate::ident::{lowercase_ident, parse_ident, Ident};
|
||||||
use crate::keyword;
|
use crate::keyword;
|
||||||
use crate::parser::{
|
use crate::parser::{
|
||||||
self, backtrackable, optional, sep_by1, sep_by1_e, specialize, specialize_ref, then,
|
self, backtrackable, optional, parse_word1, sep_by1, sep_by1_e, specialize, specialize_ref,
|
||||||
trailing_sep_by0, word1, word2, EExpect, EExpr, EIf, EInParens, ELambda, EList, ENumber,
|
then, trailing_sep_by0, word1, word2, EClosure, EExpect, EExpr, EIf, EInParens, EList, ENumber,
|
||||||
EPattern, ERecord, EString, EType, EWhen, Either, ParseResult, Parser,
|
EPattern, ERecord, EString, EType, EWhen, Either, ParseResult, Parser,
|
||||||
};
|
};
|
||||||
use crate::pattern::{loc_closure_param, loc_has_parser};
|
use crate::pattern::{loc_closure_param, loc_has_parser};
|
||||||
|
@ -205,7 +205,10 @@ fn parse_loc_term_or_underscore_or_conditional<'a>(
|
||||||
loc!(specialize(EExpr::Str, string_literal_help())),
|
loc!(specialize(EExpr::Str, string_literal_help())),
|
||||||
loc!(specialize(EExpr::SingleQuote, single_quote_literal_help())),
|
loc!(specialize(EExpr::SingleQuote, single_quote_literal_help())),
|
||||||
loc!(specialize(EExpr::Number, positive_number_literal_help())),
|
loc!(specialize(EExpr::Number, positive_number_literal_help())),
|
||||||
loc!(specialize(EExpr::Lambda, closure_help(min_indent, options))),
|
loc!(specialize(
|
||||||
|
EExpr::Closure,
|
||||||
|
closure_help(min_indent, options)
|
||||||
|
)),
|
||||||
loc!(underscore_expression()),
|
loc!(underscore_expression()),
|
||||||
loc!(record_literal_help(min_indent)),
|
loc!(record_literal_help(min_indent)),
|
||||||
loc!(specialize(EExpr::List, list_literal_help(min_indent))),
|
loc!(specialize(EExpr::List, list_literal_help(min_indent))),
|
||||||
|
@ -230,7 +233,10 @@ fn parse_loc_term_or_underscore<'a>(
|
||||||
loc!(specialize(EExpr::Str, string_literal_help())),
|
loc!(specialize(EExpr::Str, string_literal_help())),
|
||||||
loc!(specialize(EExpr::SingleQuote, single_quote_literal_help())),
|
loc!(specialize(EExpr::SingleQuote, single_quote_literal_help())),
|
||||||
loc!(specialize(EExpr::Number, positive_number_literal_help())),
|
loc!(specialize(EExpr::Number, positive_number_literal_help())),
|
||||||
loc!(specialize(EExpr::Lambda, closure_help(min_indent, options))),
|
loc!(specialize(
|
||||||
|
EExpr::Closure,
|
||||||
|
closure_help(min_indent, options)
|
||||||
|
)),
|
||||||
loc!(underscore_expression()),
|
loc!(underscore_expression()),
|
||||||
loc!(record_literal_help(min_indent)),
|
loc!(record_literal_help(min_indent)),
|
||||||
loc!(specialize(EExpr::List, list_literal_help(min_indent))),
|
loc!(specialize(EExpr::List, list_literal_help(min_indent))),
|
||||||
|
@ -253,7 +259,10 @@ fn parse_loc_term<'a>(
|
||||||
loc!(specialize(EExpr::Str, string_literal_help())),
|
loc!(specialize(EExpr::Str, string_literal_help())),
|
||||||
loc!(specialize(EExpr::SingleQuote, single_quote_literal_help())),
|
loc!(specialize(EExpr::SingleQuote, single_quote_literal_help())),
|
||||||
loc!(specialize(EExpr::Number, positive_number_literal_help())),
|
loc!(specialize(EExpr::Number, positive_number_literal_help())),
|
||||||
loc!(specialize(EExpr::Lambda, closure_help(min_indent, options))),
|
loc!(specialize(
|
||||||
|
EExpr::Closure,
|
||||||
|
closure_help(min_indent, options)
|
||||||
|
)),
|
||||||
loc!(record_literal_help(min_indent)),
|
loc!(record_literal_help(min_indent)),
|
||||||
loc!(specialize(EExpr::List, list_literal_help(min_indent))),
|
loc!(specialize(EExpr::List, list_literal_help(min_indent))),
|
||||||
loc!(map_with_arena!(
|
loc!(map_with_arena!(
|
||||||
|
@ -344,7 +353,6 @@ fn unary_negate<'a>() -> impl Parser<'a, (), EExpr<'a>> {
|
||||||
fn parse_expr_start<'a>(
|
fn parse_expr_start<'a>(
|
||||||
min_indent: u32,
|
min_indent: u32,
|
||||||
options: ExprParseOptions,
|
options: ExprParseOptions,
|
||||||
start_column: u32,
|
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
state: State<'a>,
|
state: State<'a>,
|
||||||
) -> ParseResult<'a, Loc<Expr<'a>>, EExpr<'a>> {
|
) -> ParseResult<'a, Loc<Expr<'a>>, EExpr<'a>> {
|
||||||
|
@ -355,8 +363,11 @@ fn parse_expr_start<'a>(
|
||||||
when::expr_help(min_indent, options)
|
when::expr_help(min_indent, options)
|
||||||
)),
|
)),
|
||||||
loc!(specialize(EExpr::Expect, expect_help(min_indent, options))),
|
loc!(specialize(EExpr::Expect, expect_help(min_indent, options))),
|
||||||
loc!(specialize(EExpr::Lambda, closure_help(min_indent, options))),
|
loc!(specialize(
|
||||||
loc!(move |a, s| parse_expr_operator_chain(min_indent, options, start_column, a, s)),
|
EExpr::Closure,
|
||||||
|
closure_help(min_indent, options)
|
||||||
|
)),
|
||||||
|
loc!(move |a, s| parse_expr_operator_chain(min_indent, options, a, s)),
|
||||||
fail_expr_start_e()
|
fail_expr_start_e()
|
||||||
]
|
]
|
||||||
.parse(arena, state)
|
.parse(arena, state)
|
||||||
|
@ -365,10 +376,11 @@ fn parse_expr_start<'a>(
|
||||||
fn parse_expr_operator_chain<'a>(
|
fn parse_expr_operator_chain<'a>(
|
||||||
min_indent: u32,
|
min_indent: u32,
|
||||||
options: ExprParseOptions,
|
options: ExprParseOptions,
|
||||||
start_column: u32,
|
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
state: State<'a>,
|
state: State<'a>,
|
||||||
) -> ParseResult<'a, Expr<'a>, EExpr<'a>> {
|
) -> ParseResult<'a, Expr<'a>, EExpr<'a>> {
|
||||||
|
let min_indent = state.check_indent(min_indent, EExpr::IndentStart)?;
|
||||||
|
|
||||||
let (_, expr, state) =
|
let (_, expr, state) =
|
||||||
loc_possibly_negative_or_negated_term(min_indent, options).parse(arena, state)?;
|
loc_possibly_negative_or_negated_term(min_indent, options).parse(arena, state)?;
|
||||||
|
|
||||||
|
@ -387,7 +399,7 @@ fn parse_expr_operator_chain<'a>(
|
||||||
end,
|
end,
|
||||||
};
|
};
|
||||||
|
|
||||||
parse_expr_end(min_indent, options, start_column, expr_state, arena, state)
|
parse_expr_end(min_indent, options, expr_state, arena, state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -604,13 +616,11 @@ fn numeric_negate_expression<'a, T>(
|
||||||
|
|
||||||
fn parse_defs_end<'a>(
|
fn parse_defs_end<'a>(
|
||||||
_options: ExprParseOptions,
|
_options: ExprParseOptions,
|
||||||
start_column: u32,
|
min_indent: u32,
|
||||||
mut defs: Defs<'a>,
|
mut defs: Defs<'a>,
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
state: State<'a>,
|
state: State<'a>,
|
||||||
) -> ParseResult<'a, Defs<'a>, EExpr<'a>> {
|
) -> ParseResult<'a, Defs<'a>, EExpr<'a>> {
|
||||||
let min_indent = start_column;
|
|
||||||
|
|
||||||
let mut global_state = state;
|
let mut global_state = state;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
@ -723,7 +733,7 @@ fn parse_defs_end<'a>(
|
||||||
loc_has_parser(min_indent).parse(arena, state.clone())
|
loc_has_parser(min_indent).parse(arena, state.clone())
|
||||||
{
|
{
|
||||||
let (_, (type_def, def_region), state) = finish_parsing_ability_def_help(
|
let (_, (type_def, def_region), state) = finish_parsing_ability_def_help(
|
||||||
start_column,
|
min_indent,
|
||||||
Loc::at(name_region, name),
|
Loc::at(name_region, name),
|
||||||
args,
|
args,
|
||||||
loc_has,
|
loc_has,
|
||||||
|
@ -967,14 +977,12 @@ fn parse_defs_end<'a>(
|
||||||
|
|
||||||
fn parse_defs_expr<'a>(
|
fn parse_defs_expr<'a>(
|
||||||
options: ExprParseOptions,
|
options: ExprParseOptions,
|
||||||
start_column: u32,
|
min_indent: u32,
|
||||||
defs: Defs<'a>,
|
defs: Defs<'a>,
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
state: State<'a>,
|
state: State<'a>,
|
||||||
) -> ParseResult<'a, Expr<'a>, EExpr<'a>> {
|
) -> ParseResult<'a, Expr<'a>, EExpr<'a>> {
|
||||||
let min_indent = start_column;
|
match parse_defs_end(options, min_indent, defs, arena, state) {
|
||||||
|
|
||||||
match parse_defs_end(options, start_column, defs, arena, state) {
|
|
||||||
Err(bad) => Err(bad),
|
Err(bad) => Err(bad),
|
||||||
Ok((_, def_state, state)) => {
|
Ok((_, def_state, state)) => {
|
||||||
// this is no def, because there is no `=` or `:`; parse as an expr
|
// this is no def, because there is no `=` or `:`; parse as an expr
|
||||||
|
@ -1050,7 +1058,6 @@ enum AliasOrOpaque {
|
||||||
fn finish_parsing_alias_or_opaque<'a>(
|
fn finish_parsing_alias_or_opaque<'a>(
|
||||||
min_indent: u32,
|
min_indent: u32,
|
||||||
options: ExprParseOptions,
|
options: ExprParseOptions,
|
||||||
start_column: u32,
|
|
||||||
expr_state: ExprState<'a>,
|
expr_state: ExprState<'a>,
|
||||||
loc_op: Loc<BinOp>,
|
loc_op: Loc<BinOp>,
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
|
@ -1059,7 +1066,7 @@ fn finish_parsing_alias_or_opaque<'a>(
|
||||||
kind: AliasOrOpaque,
|
kind: AliasOrOpaque,
|
||||||
) -> ParseResult<'a, Expr<'a>, EExpr<'a>> {
|
) -> ParseResult<'a, Expr<'a>, EExpr<'a>> {
|
||||||
let expr_region = expr_state.expr.region;
|
let expr_region = expr_state.expr.region;
|
||||||
let indented_more = start_column + 1;
|
let indented_more = min_indent + 1;
|
||||||
|
|
||||||
let (expr, arguments) = expr_state
|
let (expr, arguments) = expr_state
|
||||||
.validate_is_type_def(arena, loc_op, kind)
|
.validate_is_type_def(arena, loc_op, kind)
|
||||||
|
@ -1175,7 +1182,7 @@ fn finish_parsing_alias_or_opaque<'a>(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
parse_defs_expr(options, start_column, defs, arena, state)
|
parse_defs_expr(options, min_indent, defs, arena, state)
|
||||||
}
|
}
|
||||||
|
|
||||||
mod ability {
|
mod ability {
|
||||||
|
@ -1364,7 +1371,6 @@ fn finish_parsing_ability_def_help<'a>(
|
||||||
fn parse_expr_operator<'a>(
|
fn parse_expr_operator<'a>(
|
||||||
min_indent: u32,
|
min_indent: u32,
|
||||||
options: ExprParseOptions,
|
options: ExprParseOptions,
|
||||||
start_column: u32,
|
|
||||||
mut expr_state: ExprState<'a>,
|
mut expr_state: ExprState<'a>,
|
||||||
loc_op: Loc<BinOp>,
|
loc_op: Loc<BinOp>,
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
|
@ -1405,11 +1411,11 @@ fn parse_expr_operator<'a>(
|
||||||
expr_state.spaces_after = spaces;
|
expr_state.spaces_after = spaces;
|
||||||
expr_state.end = new_end;
|
expr_state.end = new_end;
|
||||||
|
|
||||||
parse_expr_end(min_indent, options, start_column, expr_state, arena, state)
|
parse_expr_end(min_indent, options, expr_state, arena, state)
|
||||||
}
|
}
|
||||||
BinOp::Assignment => {
|
BinOp::Assignment => {
|
||||||
let expr_region = expr_state.expr.region;
|
let expr_region = expr_state.expr.region;
|
||||||
let indented_more = start_column + 1;
|
let indented_more = min_indent + 1;
|
||||||
|
|
||||||
let call = expr_state
|
let call = expr_state
|
||||||
.validate_assignment_or_backpassing(arena, loc_op, EExpr::ElmStyleFunction)
|
.validate_assignment_or_backpassing(arena, loc_op, EExpr::ElmStyleFunction)
|
||||||
|
@ -1448,11 +1454,11 @@ fn parse_expr_operator<'a>(
|
||||||
let mut defs = Defs::default();
|
let mut defs = Defs::default();
|
||||||
defs.push_value_def(value_def, def_region, &[], &[]);
|
defs.push_value_def(value_def, def_region, &[], &[]);
|
||||||
|
|
||||||
parse_defs_expr(options, start_column, defs, arena, state)
|
parse_defs_expr(options, min_indent, defs, arena, state)
|
||||||
}
|
}
|
||||||
BinOp::Backpassing => {
|
BinOp::Backpassing => {
|
||||||
let expr_region = expr_state.expr.region;
|
let expr_region = expr_state.expr.region;
|
||||||
let indented_more = start_column + 1;
|
let indented_more = min_indent + 1;
|
||||||
|
|
||||||
let call = expr_state
|
let call = expr_state
|
||||||
.validate_assignment_or_backpassing(arena, loc_op, |_, pos| {
|
.validate_assignment_or_backpassing(arena, loc_op, |_, pos| {
|
||||||
|
@ -1502,7 +1508,6 @@ fn parse_expr_operator<'a>(
|
||||||
BinOp::IsAliasType | BinOp::IsOpaqueType => finish_parsing_alias_or_opaque(
|
BinOp::IsAliasType | BinOp::IsOpaqueType => finish_parsing_alias_or_opaque(
|
||||||
min_indent,
|
min_indent,
|
||||||
options,
|
options,
|
||||||
start_column,
|
|
||||||
expr_state,
|
expr_state,
|
||||||
loc_op,
|
loc_op,
|
||||||
arena,
|
arena,
|
||||||
|
@ -1552,7 +1557,7 @@ fn parse_expr_operator<'a>(
|
||||||
expr_state.spaces_after = spaces;
|
expr_state.spaces_after = spaces;
|
||||||
|
|
||||||
// TODO new start?
|
// TODO new start?
|
||||||
parse_expr_end(min_indent, options, start_column, expr_state, arena, state)
|
parse_expr_end(min_indent, options, expr_state, arena, state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1566,7 +1571,6 @@ fn parse_expr_operator<'a>(
|
||||||
fn parse_expr_end<'a>(
|
fn parse_expr_end<'a>(
|
||||||
min_indent: u32,
|
min_indent: u32,
|
||||||
options: ExprParseOptions,
|
options: ExprParseOptions,
|
||||||
start_column: u32,
|
|
||||||
mut expr_state: ExprState<'a>,
|
mut expr_state: ExprState<'a>,
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
state: State<'a>,
|
state: State<'a>,
|
||||||
|
@ -1626,13 +1630,13 @@ fn parse_expr_end<'a>(
|
||||||
|
|
||||||
let args = arguments.into_bump_slice();
|
let args = arguments.into_bump_slice();
|
||||||
let (_, (type_def, def_region), state) =
|
let (_, (type_def, def_region), state) =
|
||||||
finish_parsing_ability_def_help(start_column, name, args, has, arena, state)?;
|
finish_parsing_ability_def_help(min_indent, name, args, has, arena, state)?;
|
||||||
|
|
||||||
let mut defs = Defs::default();
|
let mut defs = Defs::default();
|
||||||
|
|
||||||
defs.push_type_def(type_def, def_region, &[], &[]);
|
defs.push_type_def(type_def, def_region, &[], &[]);
|
||||||
|
|
||||||
parse_defs_expr(options, start_column, defs, arena, state)
|
parse_defs_expr(options, min_indent, defs, arena, state)
|
||||||
}
|
}
|
||||||
Ok((_, mut arg, state)) => {
|
Ok((_, mut arg, state)) => {
|
||||||
let new_end = state.pos();
|
let new_end = state.pos();
|
||||||
|
@ -1660,7 +1664,7 @@ fn parse_expr_end<'a>(
|
||||||
expr_state.end = new_end;
|
expr_state.end = new_end;
|
||||||
expr_state.spaces_after = new_spaces;
|
expr_state.spaces_after = new_spaces;
|
||||||
|
|
||||||
parse_expr_end(min_indent, options, start_column, expr_state, arena, state)
|
parse_expr_end(min_indent, options, expr_state, arena, state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1672,15 +1676,7 @@ fn parse_expr_end<'a>(
|
||||||
Ok((_, loc_op, state)) => {
|
Ok((_, loc_op, state)) => {
|
||||||
expr_state.consume_spaces(arena);
|
expr_state.consume_spaces(arena);
|
||||||
expr_state.initial = before_op;
|
expr_state.initial = before_op;
|
||||||
parse_expr_operator(
|
parse_expr_operator(min_indent, options, expr_state, loc_op, arena, state)
|
||||||
min_indent,
|
|
||||||
options,
|
|
||||||
start_column,
|
|
||||||
expr_state,
|
|
||||||
loc_op,
|
|
||||||
arena,
|
|
||||||
state,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Err((NoProgress, _, mut state)) => {
|
Err((NoProgress, _, mut state)) => {
|
||||||
// try multi-backpassing
|
// try multi-backpassing
|
||||||
|
@ -1714,8 +1710,6 @@ fn parse_expr_end<'a>(
|
||||||
match word2(b'<', b'-', EExpr::BackpassArrow).parse(arena, state) {
|
match word2(b'<', b'-', EExpr::BackpassArrow).parse(arena, state) {
|
||||||
Err((_, fail, state)) => Err((MadeProgress, fail, state)),
|
Err((_, fail, state)) => Err((MadeProgress, fail, state)),
|
||||||
Ok((_, _, state)) => {
|
Ok((_, _, state)) => {
|
||||||
let min_indent = start_column;
|
|
||||||
|
|
||||||
let parse_body = space0_before_e(
|
let parse_body = space0_before_e(
|
||||||
move |a, s| parse_loc_expr(min_indent + 1, a, s),
|
move |a, s| parse_loc_expr(min_indent + 1, a, s),
|
||||||
min_indent,
|
min_indent,
|
||||||
|
@ -1793,8 +1787,7 @@ fn parse_loc_expr_with_options<'a>(
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
state: State<'a>,
|
state: State<'a>,
|
||||||
) -> ParseResult<'a, Loc<Expr<'a>>, EExpr<'a>> {
|
) -> ParseResult<'a, Loc<Expr<'a>>, EExpr<'a>> {
|
||||||
let column = state.column();
|
parse_expr_start(min_indent, options, arena, state)
|
||||||
parse_expr_start(min_indent, options, column, arena, state)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If the given Expr would parse the same way as a valid Pattern, convert it.
|
/// If the given Expr would parse the same way as a valid Pattern, convert it.
|
||||||
|
@ -1973,47 +1966,67 @@ pub fn toplevel_defs<'a>(min_indent: u32) -> impl Parser<'a, Defs<'a>, EExpr<'a>
|
||||||
fn closure_help<'a>(
|
fn closure_help<'a>(
|
||||||
min_indent: u32,
|
min_indent: u32,
|
||||||
options: ExprParseOptions,
|
options: ExprParseOptions,
|
||||||
) -> impl Parser<'a, Expr<'a>, ELambda<'a>> {
|
) -> impl Parser<'a, Expr<'a>, EClosure<'a>> {
|
||||||
map_with_arena!(
|
move |arena, state| parse_closure_help(arena, state, min_indent, options)
|
||||||
skip_first!(
|
}
|
||||||
// All closures start with a '\' - e.g. (\x -> x + 1)
|
|
||||||
word1(b'\\', ELambda::Start),
|
|
||||||
// Once we see the '\', we're committed to parsing this as a closure.
|
|
||||||
// It may turn out to be malformed, but it is definitely a closure.
|
|
||||||
and!(
|
|
||||||
// Parse the params
|
|
||||||
// Params are comma-separated
|
|
||||||
sep_by1_e(
|
|
||||||
word1(b',', ELambda::Comma),
|
|
||||||
space0_around_ee(
|
|
||||||
specialize(ELambda::Pattern, loc_closure_param(min_indent)),
|
|
||||||
min_indent,
|
|
||||||
ELambda::IndentArg,
|
|
||||||
ELambda::IndentArrow
|
|
||||||
),
|
|
||||||
ELambda::Arg,
|
|
||||||
),
|
|
||||||
skip_first!(
|
|
||||||
// Parse the -> which separates params from body
|
|
||||||
word2(b'-', b'>', ELambda::Arrow),
|
|
||||||
// Parse the body
|
|
||||||
space0_before_e(
|
|
||||||
specialize_ref(ELambda::Body, move |arena, state| {
|
|
||||||
parse_loc_expr_with_options(min_indent, options, arena, state)
|
|
||||||
}),
|
|
||||||
min_indent,
|
|
||||||
ELambda::IndentBody
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
|arena: &'a Bump, (params, loc_body)| {
|
|
||||||
let params: Vec<'a, Loc<Pattern<'a>>> = params;
|
|
||||||
let params: &'a [Loc<Pattern<'a>>] = params.into_bump_slice();
|
|
||||||
|
|
||||||
Expr::Closure(params, arena.alloc(loc_body))
|
fn parse_closure_help<'a>(
|
||||||
}
|
arena: &'a Bump,
|
||||||
|
state: State<'a>,
|
||||||
|
_min_indent: u32,
|
||||||
|
options: ExprParseOptions,
|
||||||
|
) -> ParseResult<'a, Expr<'a>, EClosure<'a>> {
|
||||||
|
let start_indent = state.line_indent();
|
||||||
|
|
||||||
|
let min_indent = start_indent;
|
||||||
|
|
||||||
|
// All closures start with a '\' - e.g. (\x -> x + 1)
|
||||||
|
let (_, (), state) = parse_word1(state, min_indent, b'\\', EClosure::Start)?;
|
||||||
|
|
||||||
|
// After the first token, all other tokens must be indented past the start of the line
|
||||||
|
let min_indent = min_indent + 1;
|
||||||
|
|
||||||
|
// Once we see the '\', we're committed to parsing this as a closure.
|
||||||
|
// It may turn out to be malformed, but it is definitely a closure.
|
||||||
|
|
||||||
|
// Parse the params
|
||||||
|
// Params are comma-separated
|
||||||
|
let (_, params, state) = sep_by1_e(
|
||||||
|
word1(b',', EClosure::Comma),
|
||||||
|
space0_around_ee(
|
||||||
|
specialize(EClosure::Pattern, loc_closure_param(min_indent)),
|
||||||
|
min_indent,
|
||||||
|
EClosure::IndentArg,
|
||||||
|
EClosure::IndentArrow,
|
||||||
|
),
|
||||||
|
EClosure::Arg,
|
||||||
)
|
)
|
||||||
|
.parse(arena, state)
|
||||||
|
.map_err(|(_p, e, s)| (MadeProgress, e, s))?;
|
||||||
|
|
||||||
|
let (_, loc_body, state) = skip_first!(
|
||||||
|
// Parse the -> which separates params from body
|
||||||
|
word2(b'-', b'>', EClosure::Arrow),
|
||||||
|
// Parse the body
|
||||||
|
space0_before_e(
|
||||||
|
specialize_ref(EClosure::Body, move |arena, state| {
|
||||||
|
parse_loc_expr_with_options(min_indent, options, arena, state)
|
||||||
|
}),
|
||||||
|
min_indent,
|
||||||
|
EClosure::IndentBody
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.parse(arena, state)
|
||||||
|
.map_err(|(_p, e, s)| (MadeProgress, e, s))?;
|
||||||
|
|
||||||
|
let params: Vec<'a, Loc<Pattern<'a>>> = params;
|
||||||
|
let params: &'a [Loc<Pattern<'a>>] = params.into_bump_slice();
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
MadeProgress,
|
||||||
|
Expr::Closure(params, arena.alloc(loc_body)),
|
||||||
|
state,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
mod when {
|
mod when {
|
||||||
|
|
|
@ -89,7 +89,7 @@ impl_space_problem! {
|
||||||
EIf<'a>,
|
EIf<'a>,
|
||||||
EImports,
|
EImports,
|
||||||
EInParens<'a>,
|
EInParens<'a>,
|
||||||
ELambda<'a>,
|
EClosure<'a>,
|
||||||
EList<'a>,
|
EList<'a>,
|
||||||
EPackageEntry<'a>,
|
EPackageEntry<'a>,
|
||||||
EPackages<'a>,
|
EPackages<'a>,
|
||||||
|
@ -354,7 +354,7 @@ pub enum EExpr<'a> {
|
||||||
|
|
||||||
Expect(EExpect<'a>, Position),
|
Expect(EExpect<'a>, Position),
|
||||||
|
|
||||||
Lambda(ELambda<'a>, Position),
|
Closure(EClosure<'a>, Position),
|
||||||
Underscore(Position),
|
Underscore(Position),
|
||||||
|
|
||||||
InParens(EInParens<'a>, Position),
|
InParens(EInParens<'a>, Position),
|
||||||
|
@ -428,7 +428,7 @@ pub enum EInParens<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum ELambda<'a> {
|
pub enum EClosure<'a> {
|
||||||
Space(BadInputError, Position),
|
Space(BadInputError, Position),
|
||||||
Start(Position),
|
Start(Position),
|
||||||
Arrow(Position),
|
Arrow(Position),
|
||||||
|
@ -1452,6 +1452,31 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_word1<'a, ToError, E>(
|
||||||
|
state: State<'a>,
|
||||||
|
min_indent: u32,
|
||||||
|
word: u8,
|
||||||
|
to_error: ToError,
|
||||||
|
) -> ParseResult<'a, (), E>
|
||||||
|
where
|
||||||
|
ToError: Fn(Position) -> E,
|
||||||
|
E: 'a,
|
||||||
|
{
|
||||||
|
debug_assert_ne!(word, b'\n');
|
||||||
|
|
||||||
|
if min_indent > state.column() {
|
||||||
|
return Err((NoProgress, to_error(state.pos()), state));
|
||||||
|
}
|
||||||
|
|
||||||
|
match state.bytes().first() {
|
||||||
|
Some(x) if *x == word => {
|
||||||
|
let state = state.advance(1);
|
||||||
|
Ok((MadeProgress, (), state))
|
||||||
|
}
|
||||||
|
_ => Err((NoProgress, to_error(state.pos()), state)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn word2<'a, ToError, E>(word_1: u8, word_2: u8, to_error: ToError) -> impl Parser<'a, (), E>
|
pub fn word2<'a, ToError, E>(word_1: u8, word_2: u8, to_error: ToError) -> impl Parser<'a, (), E>
|
||||||
where
|
where
|
||||||
ToError: Fn(Position) -> E,
|
ToError: Fn(Position) -> E,
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
use roc_region::all::{Position, Region};
|
use roc_region::all::{Position, Region};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
use crate::parser::Progress;
|
||||||
|
|
||||||
/// A position in a source file.
|
/// A position in a source file.
|
||||||
// NB: [Copy] is explicitly NOT derived to reduce the chance of bugs due to accidentally re-using
|
// NB: [Copy] is explicitly NOT derived to reduce the chance of bugs due to accidentally re-using
|
||||||
// parser state.
|
// parser state.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct State<'a> {
|
pub struct State<'a> {
|
||||||
/// The raw input bytes from the file.
|
/// The raw input bytes from the file.
|
||||||
/// Beware: original_bytes[0] always points the the start of the file.
|
/// Beware: original_bytes[0] always points at the start of the file.
|
||||||
/// Use bytes()[0] to access the current byte the parser is inspecting
|
/// Use bytes()[0] to access the current byte the parser is inspecting
|
||||||
original_bytes: &'a [u8],
|
original_bytes: &'a [u8],
|
||||||
|
|
||||||
|
@ -16,6 +18,9 @@ pub struct State<'a> {
|
||||||
|
|
||||||
/// Position of the start of the current line
|
/// Position of the start of the current line
|
||||||
pub(crate) line_start: Position,
|
pub(crate) line_start: Position,
|
||||||
|
|
||||||
|
/// Position of the first non-whitespace character on the current line
|
||||||
|
pub(crate) line_start_after_whitespace: Position,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> State<'a> {
|
impl<'a> State<'a> {
|
||||||
|
@ -24,6 +29,10 @@ impl<'a> State<'a> {
|
||||||
original_bytes: bytes,
|
original_bytes: bytes,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
line_start: Position::zero(),
|
line_start: Position::zero(),
|
||||||
|
|
||||||
|
// Technically not correct.
|
||||||
|
// We don't know the position of the first non-whitespace character yet.
|
||||||
|
line_start_after_whitespace: Position::zero(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +48,24 @@ impl<'a> State<'a> {
|
||||||
self.pos().offset - self.line_start.offset
|
self.pos().offset - self.line_start.offset
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn line_indent(&self) -> u32 {
|
||||||
|
self.line_start_after_whitespace.offset - self.line_start.offset
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check that the indent is at least `indent` spaces.
|
||||||
|
/// Return a new indent if the current indent is greater than `indent`.
|
||||||
|
pub fn check_indent<E>(
|
||||||
|
&self,
|
||||||
|
indent: u32,
|
||||||
|
e: impl Fn(Position) -> E,
|
||||||
|
) -> Result<u32, (Progress, E, State<'a>)> {
|
||||||
|
if self.column() < indent {
|
||||||
|
Err((Progress::NoProgress, e(self.pos()), self.clone()))
|
||||||
|
} else {
|
||||||
|
Ok(std::cmp::max(indent, self.line_indent()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Mutably advance the state by a given offset
|
/// Mutably advance the state by a given offset
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn advance_mut(&mut self, offset: usize) {
|
pub(crate) fn advance_mut(&mut self, offset: usize) {
|
||||||
|
@ -70,6 +97,18 @@ impl<'a> State<'a> {
|
||||||
pub(crate) const fn advance_newline(mut self) -> State<'a> {
|
pub(crate) const fn advance_newline(mut self) -> State<'a> {
|
||||||
self.offset += 1;
|
self.offset += 1;
|
||||||
self.line_start = self.pos();
|
self.line_start = self.pos();
|
||||||
|
|
||||||
|
// WARNING! COULD CAUSE BUGS IF WE FORGET TO CALL mark_current_ident LATER!
|
||||||
|
// We really need to be stricter about this.
|
||||||
|
self.line_start_after_whitespace = self.line_start;
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
#[inline(always)]
|
||||||
|
pub(crate) const fn mark_current_indent(mut self) -> State<'a> {
|
||||||
|
self.line_start_after_whitespace = self.pos();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Expr(Closure(Arg(@1), @1), @0)
|
|
@ -0,0 +1 @@
|
||||||
|
\,x -> 1
|
|
@ -0,0 +1 @@
|
||||||
|
Expr(Closure(IndentBody(@5), @3), @0)
|
|
@ -0,0 +1,2 @@
|
||||||
|
\x ->
|
||||||
|
1
|
|
@ -0,0 +1,71 @@
|
||||||
|
BinOps(
|
||||||
|
[
|
||||||
|
(
|
||||||
|
@0-10 SpaceAfter(
|
||||||
|
Str(
|
||||||
|
PlainLine(
|
||||||
|
"a string",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
@11-13 Pizza,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
@14-24 SpaceAfter(
|
||||||
|
Var {
|
||||||
|
module_name: "Str",
|
||||||
|
ident: "toUtf8",
|
||||||
|
},
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
@25-27 Pizza,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
@28-54 SpaceAfter(
|
||||||
|
Apply(
|
||||||
|
@28-36 Var {
|
||||||
|
module_name: "List",
|
||||||
|
ident: "map",
|
||||||
|
},
|
||||||
|
[
|
||||||
|
@37-54 Closure(
|
||||||
|
[
|
||||||
|
@38-42 Identifier(
|
||||||
|
"byte",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
@46-54 BinOps(
|
||||||
|
[
|
||||||
|
(
|
||||||
|
@46-50 Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "byte",
|
||||||
|
},
|
||||||
|
@51-52 Plus,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
@53-54 Num(
|
||||||
|
"1",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
Space,
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
@55-57 Pizza,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
@58-70 Var {
|
||||||
|
module_name: "List",
|
||||||
|
ident: "reverse",
|
||||||
|
},
|
||||||
|
)
|
|
@ -0,0 +1,4 @@
|
||||||
|
"a string"
|
||||||
|
|> Str.toUtf8
|
||||||
|
|> List.map \byte -> byte + 1
|
||||||
|
|> List.reverse
|
|
@ -0,0 +1,15 @@
|
||||||
|
Closure(
|
||||||
|
[
|
||||||
|
@1-2 Identifier(
|
||||||
|
"x",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
@8-9 SpaceBefore(
|
||||||
|
Num(
|
||||||
|
"1",
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
|
@ -0,0 +1,2 @@
|
||||||
|
\x ->
|
||||||
|
1
|
|
@ -120,6 +120,8 @@ mod test_parse {
|
||||||
|
|
||||||
// see tests/snapshots to see test input(.roc) and expected output(.result-ast)
|
// see tests/snapshots to see test input(.roc) and expected output(.result-ast)
|
||||||
snapshot_tests! {
|
snapshot_tests! {
|
||||||
|
fail/lambda_extra_comma.expr,
|
||||||
|
fail/lambda_missing_indent.expr,
|
||||||
fail/type_argument_no_arrow.expr,
|
fail/type_argument_no_arrow.expr,
|
||||||
fail/type_double_comma.expr,
|
fail/type_double_comma.expr,
|
||||||
pass/ability_demand_signature_is_multiline.expr,
|
pass/ability_demand_signature_is_multiline.expr,
|
||||||
|
@ -157,6 +159,7 @@ mod test_parse {
|
||||||
pass/empty_string.expr,
|
pass/empty_string.expr,
|
||||||
pass/equals_with_spaces.expr,
|
pass/equals_with_spaces.expr,
|
||||||
pass/equals.expr,
|
pass/equals.expr,
|
||||||
|
pass/expect_fx.module,
|
||||||
pass/expect.expr,
|
pass/expect.expr,
|
||||||
pass/float_with_underscores.expr,
|
pass/float_with_underscores.expr,
|
||||||
pass/full_app_header_trailing_commas.header,
|
pass/full_app_header_trailing_commas.header,
|
||||||
|
@ -167,6 +170,8 @@ mod test_parse {
|
||||||
pass/if_def.expr,
|
pass/if_def.expr,
|
||||||
pass/int_with_underscore.expr,
|
pass/int_with_underscore.expr,
|
||||||
pass/interface_with_newline.header,
|
pass/interface_with_newline.header,
|
||||||
|
pass/lambda_in_chain.expr,
|
||||||
|
pass/lambda_indent.expr,
|
||||||
pass/list_closing_indent_not_enough.expr,
|
pass/list_closing_indent_not_enough.expr,
|
||||||
pass/list_closing_same_indent_no_trailing_comma.expr,
|
pass/list_closing_same_indent_no_trailing_comma.expr,
|
||||||
pass/list_closing_same_indent_with_trailing_comma.expr,
|
pass/list_closing_same_indent_with_trailing_comma.expr,
|
||||||
|
@ -181,6 +186,7 @@ mod test_parse {
|
||||||
pass/module_def_newline.module,
|
pass/module_def_newline.module,
|
||||||
pass/multi_backpassing.expr,
|
pass/multi_backpassing.expr,
|
||||||
pass/multi_char_string.expr,
|
pass/multi_char_string.expr,
|
||||||
|
pass/multiline_string.expr,
|
||||||
pass/multiline_type_signature_with_comment.expr,
|
pass/multiline_type_signature_with_comment.expr,
|
||||||
pass/multiline_type_signature.expr,
|
pass/multiline_type_signature.expr,
|
||||||
pass/multiple_fields.expr,
|
pass/multiple_fields.expr,
|
||||||
|
@ -204,7 +210,6 @@ mod test_parse {
|
||||||
pass/not_docs.expr,
|
pass/not_docs.expr,
|
||||||
pass/number_literal_suffixes.expr,
|
pass/number_literal_suffixes.expr,
|
||||||
pass/one_backpassing.expr,
|
pass/one_backpassing.expr,
|
||||||
pass/multiline_string.expr,
|
|
||||||
pass/one_char_string.expr,
|
pass/one_char_string.expr,
|
||||||
pass/one_def.expr,
|
pass/one_def.expr,
|
||||||
pass/one_minus_two.expr,
|
pass/one_minus_two.expr,
|
||||||
|
@ -251,7 +256,6 @@ mod test_parse {
|
||||||
pass/spaced_singleton_list.expr,
|
pass/spaced_singleton_list.expr,
|
||||||
pass/spaces_inside_empty_list.expr,
|
pass/spaces_inside_empty_list.expr,
|
||||||
pass/standalone_module_defs.module,
|
pass/standalone_module_defs.module,
|
||||||
pass/expect_fx.module,
|
|
||||||
pass/string_without_escape.expr,
|
pass/string_without_escape.expr,
|
||||||
pass/sub_var_with_spaces.expr,
|
pass/sub_var_with_spaces.expr,
|
||||||
pass/sub_with_spaces.expr,
|
pass/sub_with_spaces.expr,
|
||||||
|
@ -277,9 +281,9 @@ mod test_parse {
|
||||||
pass/var_minus_two.expr,
|
pass/var_minus_two.expr,
|
||||||
pass/var_then.expr,
|
pass/var_then.expr,
|
||||||
pass/var_when.expr,
|
pass/var_when.expr,
|
||||||
|
pass/when_if_guard.expr,
|
||||||
pass/when_in_assignment.expr,
|
pass/when_in_assignment.expr,
|
||||||
pass/when_in_function.expr,
|
pass/when_in_function.expr,
|
||||||
pass/when_if_guard.expr,
|
|
||||||
pass/when_in_parens_indented.expr,
|
pass/when_in_parens_indented.expr,
|
||||||
pass/when_in_parens.expr,
|
pass/when_in_parens.expr,
|
||||||
pass/when_with_alternative_patterns.expr,
|
pass/when_with_alternative_patterns.expr,
|
||||||
|
|
|
@ -1522,8 +1522,9 @@ fn solve(
|
||||||
|
|
||||||
symbols.iter().any(|(s, _)| {
|
symbols.iter().any(|(s, _)| {
|
||||||
let var = env.get_var_by_symbol(s).expect("Symbol not solved!");
|
let var = env.get_var_by_symbol(s).expect("Symbol not solved!");
|
||||||
let content = subs.get_content_without_compacting(var);
|
let (_, underlying_content) = chase_alias_content(subs, var);
|
||||||
!matches!(content, Error | Structure(FlatType::Func(..)))
|
|
||||||
|
!matches!(underlying_content, Error | Structure(FlatType::Func(..)))
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1555,6 +1556,17 @@ fn solve(
|
||||||
state
|
state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn chase_alias_content(subs: &Subs, mut var: Variable) -> (Variable, &Content) {
|
||||||
|
loop {
|
||||||
|
match subs.get_content_without_compacting(var) {
|
||||||
|
Content::Alias(_, _, real_var, _) => {
|
||||||
|
var = *real_var;
|
||||||
|
}
|
||||||
|
content => return (var, content),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn compact_lambdas_and_check_obligations(
|
fn compact_lambdas_and_check_obligations(
|
||||||
arena: &Bump,
|
arena: &Bump,
|
||||||
|
@ -2299,10 +2311,11 @@ fn type_to_variable<'a>(
|
||||||
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!");
|
||||||
}
|
}
|
||||||
|
|
||||||
let slice = SubsIndex::new(subs.tag_names.len() as u32);
|
let tag_names = SubsSlice::extend_new(&mut subs.tag_names, [tag_name.clone()]);
|
||||||
subs.tag_names.push(tag_name.clone());
|
let symbols = SubsSlice::extend_new(&mut subs.closure_names, [*symbol]);
|
||||||
|
|
||||||
let content = Content::Structure(FlatType::FunctionOrTagUnion(slice, *symbol, ext));
|
let content =
|
||||||
|
Content::Structure(FlatType::FunctionOrTagUnion(tag_names, symbols, ext));
|
||||||
|
|
||||||
register_with_known_var(subs, destination, rank, pools, content)
|
register_with_known_var(subs, destination, rank, pools, content)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7842,6 +7842,20 @@ mod solve_expr {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn dispatch_tag_union_function_inferred() {
|
||||||
|
infer_eq_without_problem(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
g = if Bool.true then A else B
|
||||||
|
|
||||||
|
g ""
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
"[A Str, B Str]*",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_char_as_u8() {
|
fn check_char_as_u8() {
|
||||||
infer_eq_without_problem(
|
infer_eq_without_problem(
|
||||||
|
@ -7940,4 +7954,22 @@ mod solve_expr {
|
||||||
"U32 -> U32",
|
"U32 -> U32",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_4246_admit_recursion_between_opaque_functions() {
|
||||||
|
infer_eq_without_problem(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
app "test" provides [b] to "./platform"
|
||||||
|
|
||||||
|
O := {} -> {}
|
||||||
|
|
||||||
|
a = @O \{} -> ((\@O f -> f {}) b)
|
||||||
|
|
||||||
|
b = a
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
"O",
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3395,3 +3395,59 @@ fn list_let_generalization() {
|
||||||
usize
|
usize
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||||
|
fn list_walk_backwards_until_sum() {
|
||||||
|
assert_evals_to!(
|
||||||
|
r#"List.walkBackwardsUntil [1, 2] 0 \a,b -> Continue (a + b)"#,
|
||||||
|
3,
|
||||||
|
i64
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||||
|
fn list_walk_backwards_implements_position() {
|
||||||
|
assert_evals_to!(
|
||||||
|
r#"
|
||||||
|
Option a : [Some a, None]
|
||||||
|
|
||||||
|
find : List a, a -> Option Nat
|
||||||
|
find = \list, needle ->
|
||||||
|
findHelp list needle
|
||||||
|
|> .v
|
||||||
|
|
||||||
|
findHelp = \list, needle ->
|
||||||
|
List.walkBackwardsUntil list { n: 0, v: None } \{ n, v }, element ->
|
||||||
|
if element == needle then
|
||||||
|
Break { n, v: Some n }
|
||||||
|
else
|
||||||
|
Continue { n: n + 1, v }
|
||||||
|
|
||||||
|
when find [1, 2, 3] 3 is
|
||||||
|
None -> 0
|
||||||
|
Some v -> v
|
||||||
|
"#,
|
||||||
|
0,
|
||||||
|
usize
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||||
|
fn list_walk_backwards_until_even_prefix_sum() {
|
||||||
|
assert_evals_to!(
|
||||||
|
r#"
|
||||||
|
helper = \a, b ->
|
||||||
|
if Num.isEven b then
|
||||||
|
Continue (a + b)
|
||||||
|
|
||||||
|
else
|
||||||
|
Break a
|
||||||
|
|
||||||
|
List.walkBackwardsUntil [9, 8, 4, 2] 0 helper"#,
|
||||||
|
2 + 4 + 8,
|
||||||
|
i64
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -1931,6 +1931,34 @@ fn when_on_strings() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||||
|
fn with_capacity() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
Str.withCapacity 10
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
RocStr::from(""),
|
||||||
|
RocStr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||||
|
fn with_capacity_concat() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
Str.withCapacity 10 |> Str.concat "Forty-two"
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
RocStr::from("Forty-two"),
|
||||||
|
RocStr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||||
fn str_with_prefix() {
|
fn str_with_prefix() {
|
||||||
|
|
|
@ -2004,3 +2004,21 @@ fn match_on_result_with_uninhabited_error_branch() {
|
||||||
RocStr
|
RocStr
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||||
|
fn dispatch_tag_union_function_inferred() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
g = \b -> if b then H else J
|
||||||
|
|
||||||
|
when P ((g Bool.true) "") ((g Bool.false) "") is
|
||||||
|
P (H _) (J _) -> "okay"
|
||||||
|
_ -> "FAIL"
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
RocStr::from("okay"),
|
||||||
|
RocStr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -1156,11 +1156,15 @@ fn write_flat_type<'a>(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionOrTagUnion(tag_name, _, ext_var) => {
|
FunctionOrTagUnion(tag_names, _, ext_var) => {
|
||||||
buf.push('[');
|
buf.push('[');
|
||||||
|
|
||||||
let mut tags: MutMap<TagName, _> = MutMap::default();
|
let mut tags: MutMap<TagName, _> = MutMap::default();
|
||||||
tags.insert(subs[*tag_name].clone(), vec![]);
|
tags.extend(
|
||||||
|
subs.get_subs_slice(*tag_names)
|
||||||
|
.iter()
|
||||||
|
.map(|t| (t.clone(), vec![])),
|
||||||
|
);
|
||||||
let ext_content = write_sorted_tags(env, ctx, subs, buf, &tags, *ext_var);
|
let ext_content = write_sorted_tags(env, ctx, subs, buf, &tags, *ext_var);
|
||||||
|
|
||||||
buf.push(']');
|
buf.push(']');
|
||||||
|
@ -1241,8 +1245,12 @@ pub fn chase_ext_tag_union(
|
||||||
push_union(subs, tags, fields);
|
push_union(subs, tags, fields);
|
||||||
chase_ext_tag_union(subs, *ext_var, fields)
|
chase_ext_tag_union(subs, *ext_var, fields)
|
||||||
}
|
}
|
||||||
Content::Structure(FunctionOrTagUnion(tag_name, _, ext_var)) => {
|
Content::Structure(FunctionOrTagUnion(tag_names, _, ext_var)) => {
|
||||||
fields.push((subs[*tag_name].clone(), vec![]));
|
fields.extend(
|
||||||
|
subs.get_subs_slice(*tag_names)
|
||||||
|
.iter()
|
||||||
|
.map(|t| (t.clone(), vec![])),
|
||||||
|
);
|
||||||
|
|
||||||
chase_ext_tag_union(subs, *ext_var, fields)
|
chase_ext_tag_union(subs, *ext_var, fields)
|
||||||
}
|
}
|
||||||
|
|
|
@ -962,13 +962,13 @@ fn subs_fmt_flat_type(this: &FlatType, subs: &Subs, f: &mut fmt::Formatter) -> f
|
||||||
|
|
||||||
write!(f, "]<{:?}>", new_ext)
|
write!(f, "]<{:?}>", new_ext)
|
||||||
}
|
}
|
||||||
FlatType::FunctionOrTagUnion(tagname_index, symbol, ext) => {
|
FlatType::FunctionOrTagUnion(tagnames, symbol, ext) => {
|
||||||
let tagname: &TagName = &subs[*tagname_index];
|
let tagnames: &[TagName] = subs.get_subs_slice(*tagnames);
|
||||||
|
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"FunctionOrTagUnion({:?}, {:?}, {:?})",
|
"FunctionOrTagUnion({:?}, {:?}, {:?})",
|
||||||
tagname, symbol, ext
|
tagnames, symbol, ext
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
FlatType::RecursiveTagUnion(rec, tags, ext) => {
|
FlatType::RecursiveTagUnion(rec, tags, ext) => {
|
||||||
|
@ -2424,7 +2424,12 @@ pub enum FlatType {
|
||||||
Func(VariableSubsSlice, Variable, Variable),
|
Func(VariableSubsSlice, Variable, Variable),
|
||||||
Record(RecordFields, Variable),
|
Record(RecordFields, Variable),
|
||||||
TagUnion(UnionTags, Variable),
|
TagUnion(UnionTags, Variable),
|
||||||
FunctionOrTagUnion(SubsIndex<TagName>, Symbol, Variable),
|
|
||||||
|
/// `A` might either be a function
|
||||||
|
/// x -> A x : a -> [A a, B a, C a]
|
||||||
|
/// or a tag `[A, B, C]`
|
||||||
|
FunctionOrTagUnion(SubsSlice<TagName>, SubsSlice<Symbol>, Variable),
|
||||||
|
|
||||||
RecursiveTagUnion(Variable, UnionTags, Variable),
|
RecursiveTagUnion(Variable, UnionTags, Variable),
|
||||||
Erroneous(SubsIndex<Problem>),
|
Erroneous(SubsIndex<Problem>),
|
||||||
EmptyRecord,
|
EmptyRecord,
|
||||||
|
@ -3881,12 +3886,12 @@ fn flat_type_to_err_type(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionOrTagUnion(tag_name, _, ext_var) => {
|
FunctionOrTagUnion(tag_names, _, ext_var) => {
|
||||||
let tag_name = subs[tag_name].clone();
|
let tag_names = subs.get_subs_slice(tag_names);
|
||||||
|
|
||||||
let mut err_tags = SendMap::default();
|
let mut err_tags: SendMap<TagName, Vec<_>> = SendMap::default();
|
||||||
|
|
||||||
err_tags.insert(tag_name, vec![]);
|
err_tags.extend(tag_names.iter().map(|t| (t.clone(), vec![])));
|
||||||
|
|
||||||
match var_to_err_type(subs, state, ext_var).unwrap_structural_alias() {
|
match var_to_err_type(subs, state, ext_var).unwrap_structural_alias() {
|
||||||
ErrorType::TagUnion(sub_tags, sub_ext) => {
|
ErrorType::TagUnion(sub_tags, sub_ext) => {
|
||||||
|
@ -4202,8 +4207,8 @@ impl StorageSubs {
|
||||||
Self::offset_tag_union(offsets, *union_tags),
|
Self::offset_tag_union(offsets, *union_tags),
|
||||||
Self::offset_variable(offsets, *ext),
|
Self::offset_variable(offsets, *ext),
|
||||||
),
|
),
|
||||||
FlatType::FunctionOrTagUnion(tag_name, symbol, ext) => FlatType::FunctionOrTagUnion(
|
FlatType::FunctionOrTagUnion(tag_names, symbol, ext) => FlatType::FunctionOrTagUnion(
|
||||||
Self::offset_tag_name_index(offsets, *tag_name),
|
Self::offset_tag_name_slice(offsets, *tag_names),
|
||||||
*symbol,
|
*symbol,
|
||||||
Self::offset_variable(offsets, *ext),
|
Self::offset_variable(offsets, *ext),
|
||||||
),
|
),
|
||||||
|
@ -4295,13 +4300,13 @@ impl StorageSubs {
|
||||||
record_fields
|
record_fields
|
||||||
}
|
}
|
||||||
|
|
||||||
fn offset_tag_name_index(
|
fn offset_tag_name_slice(
|
||||||
offsets: &StorageSubsOffsets,
|
offsets: &StorageSubsOffsets,
|
||||||
mut tag_name: SubsIndex<TagName>,
|
mut tag_names: SubsSlice<TagName>,
|
||||||
) -> SubsIndex<TagName> {
|
) -> SubsSlice<TagName> {
|
||||||
tag_name.index += offsets.tag_names;
|
tag_names.start += offsets.tag_names;
|
||||||
|
|
||||||
tag_name
|
tag_names
|
||||||
}
|
}
|
||||||
|
|
||||||
fn offset_variable(offsets: &StorageSubsOffsets, variable: Variable) -> Variable {
|
fn offset_variable(offsets: &StorageSubsOffsets, variable: Variable) -> Variable {
|
||||||
|
@ -4542,12 +4547,22 @@ fn storage_copy_var_to_help(env: &mut StorageCopyVarToEnv<'_>, var: Variable) ->
|
||||||
TagUnion(union_tags, new_ext)
|
TagUnion(union_tags, new_ext)
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionOrTagUnion(tag_name, symbol, ext_var) => {
|
FunctionOrTagUnion(tag_names, symbols, ext_var) => {
|
||||||
let new_tag_name = SubsIndex::new(env.target.tag_names.len() as u32);
|
let new_tag_names = SubsSlice::extend_new(
|
||||||
|
&mut env.target.tag_names,
|
||||||
|
env.source.get_subs_slice(tag_names).iter().cloned(),
|
||||||
|
);
|
||||||
|
|
||||||
env.target.tag_names.push(env.source[tag_name].clone());
|
let new_symbols = SubsSlice::extend_new(
|
||||||
|
&mut env.target.closure_names,
|
||||||
|
env.source.get_subs_slice(symbols).iter().cloned(),
|
||||||
|
);
|
||||||
|
|
||||||
FunctionOrTagUnion(new_tag_name, symbol, storage_copy_var_to_help(env, ext_var))
|
FunctionOrTagUnion(
|
||||||
|
new_tag_names,
|
||||||
|
new_symbols,
|
||||||
|
storage_copy_var_to_help(env, ext_var),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
||||||
|
@ -4981,14 +4996,20 @@ fn copy_import_to_help(env: &mut CopyImportEnv<'_>, max_rank: Rank, var: Variabl
|
||||||
TagUnion(union_tags, new_ext)
|
TagUnion(union_tags, new_ext)
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionOrTagUnion(tag_name, symbol, ext_var) => {
|
FunctionOrTagUnion(tag_names, symbols, ext_var) => {
|
||||||
let new_tag_name = SubsIndex::new(env.target.tag_names.len() as u32);
|
let new_tag_names = SubsSlice::extend_new(
|
||||||
|
&mut env.target.tag_names,
|
||||||
|
env.source.get_subs_slice(tag_names).iter().cloned(),
|
||||||
|
);
|
||||||
|
|
||||||
env.target.tag_names.push(env.source[tag_name].clone());
|
let new_symbols = SubsSlice::extend_new(
|
||||||
|
&mut env.target.closure_names,
|
||||||
|
env.source.get_subs_slice(symbols).iter().cloned(),
|
||||||
|
);
|
||||||
|
|
||||||
FunctionOrTagUnion(
|
FunctionOrTagUnion(
|
||||||
new_tag_name,
|
new_tag_names,
|
||||||
symbol,
|
new_symbols,
|
||||||
copy_import_to_help(env, max_rank, ext_var),
|
copy_import_to_help(env, max_rank, ext_var),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2657,13 +2657,13 @@ fn unify_flat_type<M: MetaCollector>(
|
||||||
|
|
||||||
outcome
|
outcome
|
||||||
}
|
}
|
||||||
(FunctionOrTagUnion(tag_name, tag_symbol, ext), Func(args, closure, ret)) => {
|
(FunctionOrTagUnion(tag_names, tag_symbols, ext), Func(args, closure, ret)) => {
|
||||||
unify_function_or_tag_union_and_func(
|
unify_function_or_tag_union_and_func(
|
||||||
env,
|
env,
|
||||||
pool,
|
pool,
|
||||||
ctx,
|
ctx,
|
||||||
tag_name,
|
*tag_names,
|
||||||
*tag_symbol,
|
*tag_symbols,
|
||||||
*ext,
|
*ext,
|
||||||
*args,
|
*args,
|
||||||
*ret,
|
*ret,
|
||||||
|
@ -2671,13 +2671,13 @@ fn unify_flat_type<M: MetaCollector>(
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
(Func(args, closure, ret), FunctionOrTagUnion(tag_name, tag_symbol, ext)) => {
|
(Func(args, closure, ret), FunctionOrTagUnion(tag_names, tag_symbols, ext)) => {
|
||||||
unify_function_or_tag_union_and_func(
|
unify_function_or_tag_union_and_func(
|
||||||
env,
|
env,
|
||||||
pool,
|
pool,
|
||||||
ctx,
|
ctx,
|
||||||
tag_name,
|
*tag_names,
|
||||||
*tag_symbol,
|
*tag_symbols,
|
||||||
*ext,
|
*ext,
|
||||||
*args,
|
*args,
|
||||||
*ret,
|
*ret,
|
||||||
|
@ -2685,50 +2685,61 @@ fn unify_flat_type<M: MetaCollector>(
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
(FunctionOrTagUnion(tag_name_1, _, ext1), FunctionOrTagUnion(tag_name_2, _, ext2)) => {
|
(
|
||||||
let tag_name_1_ref = &env.subs[*tag_name_1];
|
FunctionOrTagUnion(tag_names_1, tag_symbols_1, ext1),
|
||||||
let tag_name_2_ref = &env.subs[*tag_name_2];
|
FunctionOrTagUnion(tag_names_2, tag_symbols_2, ext2),
|
||||||
|
) => unify_two_function_or_tag_unions(
|
||||||
if tag_name_1_ref == tag_name_2_ref {
|
env,
|
||||||
let outcome = unify_pool(env, pool, *ext1, *ext2, ctx.mode);
|
pool,
|
||||||
if outcome.mismatches.is_empty() {
|
ctx,
|
||||||
let content = *env.subs.get_content_without_compacting(ctx.second);
|
*tag_names_1,
|
||||||
merge(env, ctx, content)
|
*tag_symbols_1,
|
||||||
} else {
|
*ext1,
|
||||||
outcome
|
*tag_names_2,
|
||||||
}
|
*tag_symbols_2,
|
||||||
} else {
|
*ext2,
|
||||||
let tags1 = UnionTags::from_tag_name_index(*tag_name_1);
|
),
|
||||||
let tags2 = UnionTags::from_tag_name_index(*tag_name_2);
|
(TagUnion(tags1, ext1), FunctionOrTagUnion(tag_names, _, ext2)) => {
|
||||||
|
let empty_tag_var_slices = SubsSlice::extend_new(
|
||||||
unify_tag_unions(env, pool, ctx, tags1, *ext1, tags2, *ext2, Rec::None)
|
&mut env.subs.variable_slices,
|
||||||
}
|
std::iter::repeat(Default::default()).take(tag_names.len()),
|
||||||
}
|
);
|
||||||
(TagUnion(tags1, ext1), FunctionOrTagUnion(tag_name, _, ext2)) => {
|
let tags2 = UnionTags::from_slices(*tag_names, empty_tag_var_slices);
|
||||||
let tags2 = UnionTags::from_tag_name_index(*tag_name);
|
|
||||||
|
|
||||||
unify_tag_unions(env, pool, ctx, *tags1, *ext1, tags2, *ext2, Rec::None)
|
unify_tag_unions(env, pool, ctx, *tags1, *ext1, tags2, *ext2, Rec::None)
|
||||||
}
|
}
|
||||||
(FunctionOrTagUnion(tag_name, _, ext1), TagUnion(tags2, ext2)) => {
|
(FunctionOrTagUnion(tag_names, _, ext1), TagUnion(tags2, ext2)) => {
|
||||||
let tags1 = UnionTags::from_tag_name_index(*tag_name);
|
let empty_tag_var_slices = SubsSlice::extend_new(
|
||||||
|
&mut env.subs.variable_slices,
|
||||||
|
std::iter::repeat(Default::default()).take(tag_names.len()),
|
||||||
|
);
|
||||||
|
let tags1 = UnionTags::from_slices(*tag_names, empty_tag_var_slices);
|
||||||
|
|
||||||
unify_tag_unions(env, pool, ctx, tags1, *ext1, *tags2, *ext2, Rec::None)
|
unify_tag_unions(env, pool, ctx, tags1, *ext1, *tags2, *ext2, Rec::None)
|
||||||
}
|
}
|
||||||
|
|
||||||
(RecursiveTagUnion(recursion_var, tags1, ext1), FunctionOrTagUnion(tag_name, _, ext2)) => {
|
(RecursiveTagUnion(recursion_var, tags1, ext1), FunctionOrTagUnion(tag_names, _, ext2)) => {
|
||||||
// this never happens in type-correct programs, but may happen if there is a type error
|
// this never happens in type-correct programs, but may happen if there is a type error
|
||||||
debug_assert!(is_recursion_var(env.subs, *recursion_var));
|
debug_assert!(is_recursion_var(env.subs, *recursion_var));
|
||||||
|
|
||||||
let tags2 = UnionTags::from_tag_name_index(*tag_name);
|
let empty_tag_var_slices = SubsSlice::extend_new(
|
||||||
|
&mut env.subs.variable_slices,
|
||||||
|
std::iter::repeat(Default::default()).take(tag_names.len()),
|
||||||
|
);
|
||||||
|
let tags2 = UnionTags::from_slices(*tag_names, empty_tag_var_slices);
|
||||||
let rec = Rec::Left(*recursion_var);
|
let rec = Rec::Left(*recursion_var);
|
||||||
|
|
||||||
unify_tag_unions(env, pool, ctx, *tags1, *ext1, tags2, *ext2, rec)
|
unify_tag_unions(env, pool, ctx, *tags1, *ext1, tags2, *ext2, rec)
|
||||||
}
|
}
|
||||||
|
|
||||||
(FunctionOrTagUnion(tag_name, _, ext1), RecursiveTagUnion(recursion_var, tags2, ext2)) => {
|
(FunctionOrTagUnion(tag_names, _, ext1), RecursiveTagUnion(recursion_var, tags2, ext2)) => {
|
||||||
debug_assert!(is_recursion_var(env.subs, *recursion_var));
|
debug_assert!(is_recursion_var(env.subs, *recursion_var));
|
||||||
|
|
||||||
let tags1 = UnionTags::from_tag_name_index(*tag_name);
|
let empty_tag_var_slices = SubsSlice::extend_new(
|
||||||
|
&mut env.subs.variable_slices,
|
||||||
|
std::iter::repeat(Default::default()).take(tag_names.len()),
|
||||||
|
);
|
||||||
|
let tags1 = UnionTags::from_slices(*tag_names, empty_tag_var_slices);
|
||||||
let rec = Rec::Right(*recursion_var);
|
let rec = Rec::Right(*recursion_var);
|
||||||
|
|
||||||
unify_tag_unions(env, pool, ctx, tags1, *ext1, *tags2, *ext2, rec)
|
unify_tag_unions(env, pool, ctx, tags1, *ext1, *tags2, *ext2, rec)
|
||||||
|
@ -3133,17 +3144,20 @@ fn unify_function_or_tag_union_and_func<M: MetaCollector>(
|
||||||
env: &mut Env,
|
env: &mut Env,
|
||||||
pool: &mut Pool,
|
pool: &mut Pool,
|
||||||
ctx: &Context,
|
ctx: &Context,
|
||||||
tag_name_index: &SubsIndex<TagName>,
|
tag_names_slice: SubsSlice<TagName>,
|
||||||
tag_symbol: Symbol,
|
tag_fn_lambdas: SubsSlice<Symbol>,
|
||||||
tag_ext: Variable,
|
tag_ext: Variable,
|
||||||
function_arguments: VariableSubsSlice,
|
function_arguments: VariableSubsSlice,
|
||||||
function_return: Variable,
|
function_return: Variable,
|
||||||
function_lambda_set: Variable,
|
function_lambda_set: Variable,
|
||||||
left: bool,
|
left: bool,
|
||||||
) -> Outcome<M> {
|
) -> Outcome<M> {
|
||||||
let tag_name = env.subs[*tag_name_index].clone();
|
let tag_names = env.subs.get_subs_slice(tag_names_slice).to_vec();
|
||||||
|
|
||||||
let union_tags = UnionTags::insert_slices_into_subs(env.subs, [(tag_name, function_arguments)]);
|
let union_tags = UnionTags::insert_slices_into_subs(
|
||||||
|
env.subs,
|
||||||
|
tag_names.into_iter().map(|tag| (tag, function_arguments)),
|
||||||
|
);
|
||||||
let content = Content::Structure(FlatType::TagUnion(union_tags, tag_ext));
|
let content = Content::Structure(FlatType::TagUnion(union_tags, tag_ext));
|
||||||
|
|
||||||
let new_tag_union_var = fresh(env, pool, ctx, content);
|
let new_tag_union_var = fresh(env, pool, ctx, content);
|
||||||
|
@ -3155,7 +3169,14 @@ fn unify_function_or_tag_union_and_func<M: MetaCollector>(
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
let union_tags = UnionLambdas::tag_without_arguments(env.subs, tag_symbol);
|
let lambda_names = env.subs.get_subs_slice(tag_fn_lambdas).to_vec();
|
||||||
|
let new_lambda_names = SubsSlice::extend_new(&mut env.subs.closure_names, lambda_names);
|
||||||
|
let empty_captures_slices = SubsSlice::extend_new(
|
||||||
|
&mut env.subs.variable_slices,
|
||||||
|
std::iter::repeat(Default::default()).take(new_lambda_names.len()),
|
||||||
|
);
|
||||||
|
let union_tags = UnionLambdas::from_slices(new_lambda_names, empty_captures_slices);
|
||||||
|
|
||||||
let ambient_function_var = if left { ctx.first } else { ctx.second };
|
let ambient_function_var = if left { ctx.first } else { ctx.second };
|
||||||
let lambda_set_content = LambdaSet(self::LambdaSet {
|
let lambda_set_content = LambdaSet(self::LambdaSet {
|
||||||
solved: union_tags,
|
solved: union_tags,
|
||||||
|
@ -3196,3 +3217,53 @@ fn unify_function_or_tag_union_and_func<M: MetaCollector>(
|
||||||
|
|
||||||
outcome
|
outcome
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
fn unify_two_function_or_tag_unions<M: MetaCollector>(
|
||||||
|
env: &mut Env,
|
||||||
|
pool: &mut Pool,
|
||||||
|
ctx: &Context,
|
||||||
|
tag_names_1: SubsSlice<TagName>,
|
||||||
|
tag_symbols_1: SubsSlice<Symbol>,
|
||||||
|
ext1: Variable,
|
||||||
|
tag_names_2: SubsSlice<TagName>,
|
||||||
|
tag_symbols_2: SubsSlice<Symbol>,
|
||||||
|
ext2: Variable,
|
||||||
|
) -> Outcome<M> {
|
||||||
|
let merged_tags = {
|
||||||
|
let mut all_tags: Vec<_> = (env.subs.get_subs_slice(tag_names_1).iter())
|
||||||
|
.chain(env.subs.get_subs_slice(tag_names_2))
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
all_tags.sort();
|
||||||
|
all_tags.dedup();
|
||||||
|
SubsSlice::extend_new(&mut env.subs.tag_names, all_tags)
|
||||||
|
};
|
||||||
|
let merged_lambdas = {
|
||||||
|
let mut all_lambdas: Vec<_> = (env.subs.get_subs_slice(tag_symbols_1).iter())
|
||||||
|
.chain(env.subs.get_subs_slice(tag_symbols_2))
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
all_lambdas.sort();
|
||||||
|
all_lambdas.dedup();
|
||||||
|
SubsSlice::extend_new(&mut env.subs.closure_names, all_lambdas)
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut outcome = unify_pool(env, pool, ext1, ext2, ctx.mode);
|
||||||
|
if !outcome.mismatches.is_empty() {
|
||||||
|
return outcome;
|
||||||
|
}
|
||||||
|
|
||||||
|
let merge_outcome = merge(
|
||||||
|
env,
|
||||||
|
ctx,
|
||||||
|
Content::Structure(FlatType::FunctionOrTagUnion(
|
||||||
|
merged_tags,
|
||||||
|
merged_lambdas,
|
||||||
|
ext1,
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
|
||||||
|
outcome.union(merge_outcome);
|
||||||
|
outcome
|
||||||
|
}
|
||||||
|
|
|
@ -44,4 +44,21 @@
|
||||||
searchBox.addEventListener("input", search);
|
searchBox.addEventListener("input", search);
|
||||||
|
|
||||||
search();
|
search();
|
||||||
|
|
||||||
|
// Capture '/' keypress for quick search
|
||||||
|
window.addEventListener("keyup", (e) => {
|
||||||
|
|
||||||
|
if (e.code === "Slash") {
|
||||||
|
e.preventDefault;
|
||||||
|
searchBox.focus();
|
||||||
|
searchBox.value = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.code === "Escape" && document.activeElement === searchBox) {
|
||||||
|
e.preventDefault;
|
||||||
|
searchBox.blur();
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -47,7 +47,7 @@ cgmath = "0.18.0"
|
||||||
snafu = { version = "0.7.1", features = ["backtraces"] }
|
snafu = { version = "0.7.1", features = ["backtraces"] }
|
||||||
colored = "2.0.0"
|
colored = "2.0.0"
|
||||||
pest = "2.3.1"
|
pest = "2.3.1"
|
||||||
pest_derive = "2.1.0"
|
pest_derive = "2.3.1"
|
||||||
copypasta = "0.8.1"
|
copypasta = "0.8.1"
|
||||||
palette = "0.6.1"
|
palette = "0.6.1"
|
||||||
confy = { git = 'https://github.com/rust-cli/confy', features = [
|
confy = { git = 'https://github.com/rust-cli/confy', features = [
|
||||||
|
|
|
@ -20,7 +20,7 @@ use roc_gen_llvm::{run_jit_function, run_jit_function_dynamic_type};
|
||||||
use roc_load::{EntryPoint, MonomorphizedModule};
|
use roc_load::{EntryPoint, MonomorphizedModule};
|
||||||
use roc_mono::ir::OptLevel;
|
use roc_mono::ir::OptLevel;
|
||||||
use roc_parse::ast::Expr;
|
use roc_parse::ast::Expr;
|
||||||
use roc_parse::parser::{EExpr, ELambda, SyntaxError};
|
use roc_parse::parser::{EClosure, EExpr, SyntaxError};
|
||||||
use roc_repl_eval::eval::jit_to_ast;
|
use roc_repl_eval::eval::jit_to_ast;
|
||||||
use roc_repl_eval::gen::{compile_to_mono, format_answer, ReplOutput};
|
use roc_repl_eval::gen::{compile_to_mono, format_answer, ReplOutput};
|
||||||
use roc_repl_eval::{ReplApp, ReplAppMemory};
|
use roc_repl_eval::{ReplApp, ReplAppMemory};
|
||||||
|
@ -136,7 +136,7 @@ impl Validator for InputValidator {
|
||||||
// Special case some syntax errors to allow for multi-line inputs
|
// Special case some syntax errors to allow for multi-line inputs
|
||||||
Err((_, EExpr::DefMissingFinalExpr(_), _))
|
Err((_, EExpr::DefMissingFinalExpr(_), _))
|
||||||
| Err((_, EExpr::DefMissingFinalExpr2(_, _), _))
|
| Err((_, EExpr::DefMissingFinalExpr2(_, _), _))
|
||||||
| Err((_, EExpr::Lambda(ELambda::Body(_, _), _), _)) => {
|
| Err((_, EExpr::Closure(EClosure::Body(_, _), _), _)) => {
|
||||||
Ok(ValidationResult::Incomplete)
|
Ok(ValidationResult::Incomplete)
|
||||||
}
|
}
|
||||||
_ => Ok(ValidationResult::Valid(None)),
|
_ => Ok(ValidationResult::Valid(None)),
|
||||||
|
|
|
@ -450,8 +450,8 @@ fn jit_to_ast_help<'a, A: ReplApp<'a>>(
|
||||||
payload_vars,
|
payload_vars,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
Content::Structure(FlatType::FunctionOrTagUnion(tag_name, _, _)) => {
|
Content::Structure(FlatType::FunctionOrTagUnion(tag_names, _, _)) => {
|
||||||
let tag_name = &env.subs[*tag_name];
|
let tag_name = &env.subs.get_subs_slice(*tag_names)[0];
|
||||||
|
|
||||||
Ok(single_tag_union_to_ast(
|
Ok(single_tag_union_to_ast(
|
||||||
env,
|
env,
|
||||||
|
@ -631,8 +631,8 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
|
||||||
let (tag_name, payload_vars) = unpack_single_element_tag_union(env.subs, *tags);
|
let (tag_name, payload_vars) = unpack_single_element_tag_union(env.subs, *tags);
|
||||||
single_tag_union_to_ast(env, mem, addr, field_layouts, tag_name, payload_vars)
|
single_tag_union_to_ast(env, mem, addr, field_layouts, tag_name, payload_vars)
|
||||||
}
|
}
|
||||||
Content::Structure(FlatType::FunctionOrTagUnion(tag_name, _, _)) => {
|
Content::Structure(FlatType::FunctionOrTagUnion(tag_names, _, _)) => {
|
||||||
let tag_name = &env.subs[*tag_name];
|
let tag_name = &env.subs.get_subs_slice(*tag_names)[0];
|
||||||
single_tag_union_to_ast(env, mem, addr, field_layouts, tag_name, &[])
|
single_tag_union_to_ast(env, mem, addr, field_layouts, tag_name, &[])
|
||||||
}
|
}
|
||||||
Content::Structure(FlatType::EmptyRecord) => {
|
Content::Structure(FlatType::EmptyRecord) => {
|
||||||
|
@ -1200,6 +1200,19 @@ fn bool_to_ast<'a, M: ReplAppMemory>(
|
||||||
|
|
||||||
tag_name_to_expr(env, tag_name)
|
tag_name_to_expr(env, tag_name)
|
||||||
}
|
}
|
||||||
|
FlatType::FunctionOrTagUnion(tags, _, _) if tags.len() == 2 => {
|
||||||
|
let tags = env.subs.get_subs_slice(*tags);
|
||||||
|
let tag_name_1 = &tags[0];
|
||||||
|
let tag_name_2 = &tags[1];
|
||||||
|
|
||||||
|
let tag_name = if value {
|
||||||
|
max_by_key(tag_name_1, tag_name_2, |n| n.as_ident_str())
|
||||||
|
} else {
|
||||||
|
min_by_key(tag_name_1, tag_name_2, |n| n.as_ident_str())
|
||||||
|
};
|
||||||
|
|
||||||
|
tag_name_to_expr(env, tag_name)
|
||||||
|
}
|
||||||
other => {
|
other => {
|
||||||
unreachable!("Unexpected FlatType {:?} in bool_to_ast", other);
|
unreachable!("Unexpected FlatType {:?} in bool_to_ast", other);
|
||||||
}
|
}
|
||||||
|
@ -1293,6 +1306,37 @@ fn byte_to_ast<'a, M: ReplAppMemory>(
|
||||||
_ => unreachable!("invalid union variant for a Byte!"),
|
_ => unreachable!("invalid union variant for a Byte!"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
FlatType::FunctionOrTagUnion(tags, _, _) => {
|
||||||
|
// anything with fewer tags is not a byte
|
||||||
|
debug_assert!(tags.len() > 2);
|
||||||
|
|
||||||
|
let tags_vec: std::vec::Vec<(TagName, std::vec::Vec<Variable>)> = env
|
||||||
|
.subs
|
||||||
|
.get_subs_slice(*tags)
|
||||||
|
.iter()
|
||||||
|
.map(|t| (t.clone(), vec![]))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let union_variant = {
|
||||||
|
let mut layout_env = layout::Env::from_components(
|
||||||
|
&mut env.layout_cache,
|
||||||
|
env.subs,
|
||||||
|
env.arena,
|
||||||
|
env.target_info,
|
||||||
|
);
|
||||||
|
union_sorted_tags_pub(&mut layout_env, tags_vec, None)
|
||||||
|
};
|
||||||
|
|
||||||
|
match union_variant {
|
||||||
|
UnionVariant::ByteUnion(tagnames) => {
|
||||||
|
let tag_name = &tagnames[value as usize].expect_tag_ref();
|
||||||
|
let tag_expr = tag_name_to_expr(env, tag_name);
|
||||||
|
let loc_tag_expr = Loc::at_zero(tag_expr);
|
||||||
|
Expr::Apply(env.arena.alloc(loc_tag_expr), &[], CalledVia::Space)
|
||||||
|
}
|
||||||
|
_ => unreachable!("invalid union variant for a Byte!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
other => {
|
other => {
|
||||||
unreachable!("Unexpected FlatType {:?} in byte_to_ast", other);
|
unreachable!("Unexpected FlatType {:?} in byte_to_ast", other);
|
||||||
}
|
}
|
||||||
|
|
|
@ -178,7 +178,7 @@ fn to_expr_report<'a>(
|
||||||
match parse_problem {
|
match parse_problem {
|
||||||
EExpr::If(if_, pos) => to_if_report(alloc, lines, filename, context, if_, *pos),
|
EExpr::If(if_, pos) => to_if_report(alloc, lines, filename, context, if_, *pos),
|
||||||
EExpr::When(when, pos) => to_when_report(alloc, lines, filename, context, when, *pos),
|
EExpr::When(when, pos) => to_when_report(alloc, lines, filename, context, when, *pos),
|
||||||
EExpr::Lambda(lambda, pos) => {
|
EExpr::Closure(lambda, pos) => {
|
||||||
to_lambda_report(alloc, lines, filename, context, lambda, *pos)
|
to_lambda_report(alloc, lines, filename, context, lambda, *pos)
|
||||||
}
|
}
|
||||||
EExpr::List(list, pos) => to_list_report(alloc, lines, filename, context, list, *pos),
|
EExpr::List(list, pos) => to_list_report(alloc, lines, filename, context, list, *pos),
|
||||||
|
@ -557,13 +557,13 @@ fn to_lambda_report<'a>(
|
||||||
lines: &LineInfo,
|
lines: &LineInfo,
|
||||||
filename: PathBuf,
|
filename: PathBuf,
|
||||||
_context: Context,
|
_context: Context,
|
||||||
parse_problem: &roc_parse::parser::ELambda<'a>,
|
parse_problem: &roc_parse::parser::EClosure<'a>,
|
||||||
start: Position,
|
start: Position,
|
||||||
) -> Report<'a> {
|
) -> Report<'a> {
|
||||||
use roc_parse::parser::ELambda;
|
use roc_parse::parser::EClosure;
|
||||||
|
|
||||||
match *parse_problem {
|
match *parse_problem {
|
||||||
ELambda::Arrow(pos) => match what_is_next(alloc.src_lines, lines.convert_pos(pos)) {
|
EClosure::Arrow(pos) => match what_is_next(alloc.src_lines, lines.convert_pos(pos)) {
|
||||||
Next::Token("=>") => {
|
Next::Token("=>") => {
|
||||||
let surroundings = Region::new(start, pos);
|
let surroundings = Region::new(start, pos);
|
||||||
let region = LineColumnRegion::from_pos(lines.convert_pos(pos));
|
let region = LineColumnRegion::from_pos(lines.convert_pos(pos));
|
||||||
|
@ -610,7 +610,7 @@ fn to_lambda_report<'a>(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
ELambda::Comma(pos) => match what_is_next(alloc.src_lines, lines.convert_pos(pos)) {
|
EClosure::Comma(pos) => match what_is_next(alloc.src_lines, lines.convert_pos(pos)) {
|
||||||
Next::Token("=>") => {
|
Next::Token("=>") => {
|
||||||
let surroundings = Region::new(start, pos);
|
let surroundings = Region::new(start, pos);
|
||||||
let region = LineColumnRegion::from_pos(lines.convert_pos(pos));
|
let region = LineColumnRegion::from_pos(lines.convert_pos(pos));
|
||||||
|
@ -657,7 +657,7 @@ fn to_lambda_report<'a>(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
ELambda::Arg(pos) => match what_is_next(alloc.src_lines, lines.convert_pos(pos)) {
|
EClosure::Arg(pos) => match what_is_next(alloc.src_lines, lines.convert_pos(pos)) {
|
||||||
Next::Other(Some(',')) => {
|
Next::Other(Some(',')) => {
|
||||||
let surroundings = Region::new(start, pos);
|
let surroundings = Region::new(start, pos);
|
||||||
let region = LineColumnRegion::from_pos(lines.convert_pos(pos));
|
let region = LineColumnRegion::from_pos(lines.convert_pos(pos));
|
||||||
|
@ -702,17 +702,17 @@ fn to_lambda_report<'a>(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
ELambda::Start(_pos) => unreachable!("another branch would have been taken"),
|
EClosure::Start(_pos) => unreachable!("another branch would have been taken"),
|
||||||
|
|
||||||
ELambda::Body(expr, pos) => {
|
EClosure::Body(expr, pos) => {
|
||||||
to_expr_report(alloc, lines, filename, Context::InDef(start), expr, pos)
|
to_expr_report(alloc, lines, filename, Context::InDef(start), expr, pos)
|
||||||
}
|
}
|
||||||
ELambda::Pattern(ref pattern, pos) => {
|
EClosure::Pattern(ref pattern, pos) => {
|
||||||
to_pattern_report(alloc, lines, filename, pattern, pos)
|
to_pattern_report(alloc, lines, filename, pattern, pos)
|
||||||
}
|
}
|
||||||
ELambda::Space(error, pos) => to_space_report(alloc, lines, filename, &error, pos),
|
EClosure::Space(error, pos) => to_space_report(alloc, lines, filename, &error, pos),
|
||||||
|
|
||||||
ELambda::IndentArrow(pos) => to_unfinished_lambda_report(
|
EClosure::IndentArrow(pos) => to_unfinished_lambda_report(
|
||||||
alloc,
|
alloc,
|
||||||
lines,
|
lines,
|
||||||
filename,
|
filename,
|
||||||
|
@ -725,7 +725,7 @@ fn to_lambda_report<'a>(
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
|
|
||||||
ELambda::IndentBody(pos) => to_unfinished_lambda_report(
|
EClosure::IndentBody(pos) => to_unfinished_lambda_report(
|
||||||
alloc,
|
alloc,
|
||||||
lines,
|
lines,
|
||||||
filename,
|
filename,
|
||||||
|
@ -738,7 +738,7 @@ fn to_lambda_report<'a>(
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
|
|
||||||
ELambda::IndentArg(pos) => to_unfinished_lambda_report(
|
EClosure::IndentArg(pos) => to_unfinished_lambda_report(
|
||||||
alloc,
|
alloc,
|
||||||
lines,
|
lines,
|
||||||
filename,
|
filename,
|
||||||
|
|
|
@ -8,5 +8,5 @@ description = "Utilities for setting up tracing at various executable entry poin
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tracing = { version = "0.1.36", features = ["release_max_level_off"] }
|
tracing = { version = "0.1.36", features = ["release_max_level_off"] }
|
||||||
tracing-subscriber = { version = "0.3.15", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3.16", features = ["env-filter"] }
|
||||||
tracing-appender = "0.2.2"
|
tracing-appender = "0.2.2"
|
||||||
|
|
|
@ -10,7 +10,7 @@ main = Program.withArgs \args ->
|
||||||
Arg.succeed (\dividend -> \divisor -> Div (Num.toF64 dividend) (Num.toF64 divisor))
|
Arg.succeed (\dividend -> \divisor -> Div (Num.toF64 dividend) (Num.toF64 divisor))
|
||||||
|> Arg.withParser
|
|> Arg.withParser
|
||||||
(
|
(
|
||||||
Arg.i64 {
|
Arg.i64Option {
|
||||||
long: "dividend",
|
long: "dividend",
|
||||||
short: "n",
|
short: "n",
|
||||||
help: "the number to divide; corresponds to a numerator",
|
help: "the number to divide; corresponds to a numerator",
|
||||||
|
@ -18,7 +18,7 @@ main = Program.withArgs \args ->
|
||||||
)
|
)
|
||||||
|> Arg.withParser
|
|> Arg.withParser
|
||||||
(
|
(
|
||||||
Arg.i64 {
|
Arg.i64Option {
|
||||||
long: "divisor",
|
long: "divisor",
|
||||||
short: "d",
|
short: "d",
|
||||||
help: "the number to divide by; corresponds to a denominator",
|
help: "the number to divide by; corresponds to a denominator",
|
||||||
|
@ -30,7 +30,7 @@ main = Program.withArgs \args ->
|
||||||
Arg.succeed (\base -> \num -> Log (Num.toF64 base) (Num.toF64 num))
|
Arg.succeed (\base -> \num -> Log (Num.toF64 base) (Num.toF64 num))
|
||||||
|> Arg.withParser
|
|> Arg.withParser
|
||||||
(
|
(
|
||||||
Arg.i64 {
|
Arg.i64Option {
|
||||||
long: "base",
|
long: "base",
|
||||||
short: "b",
|
short: "b",
|
||||||
help: "base of the logarithm",
|
help: "base of the logarithm",
|
||||||
|
@ -38,7 +38,7 @@ main = Program.withArgs \args ->
|
||||||
)
|
)
|
||||||
|> Arg.withParser
|
|> Arg.withParser
|
||||||
(
|
(
|
||||||
Arg.i64 {
|
Arg.i64Option {
|
||||||
long: "num",
|
long: "num",
|
||||||
help: "the number to take the logarithm of",
|
help: "the number to take the logarithm of",
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,10 @@ interface Arg
|
||||||
toHelp,
|
toHelp,
|
||||||
parseFormatted,
|
parseFormatted,
|
||||||
succeed,
|
succeed,
|
||||||
bool,
|
boolOption,
|
||||||
|
strOption,
|
||||||
|
i64Option,
|
||||||
str,
|
str,
|
||||||
i64,
|
|
||||||
positional,
|
|
||||||
subCommand,
|
subCommand,
|
||||||
choice,
|
choice,
|
||||||
withParser,
|
withParser,
|
||||||
|
@ -32,7 +32,7 @@ NamedParser a := {
|
||||||
## needs, consider transforming it into a [NamedParser].
|
## needs, consider transforming it into a [NamedParser].
|
||||||
Parser a := [
|
Parser a := [
|
||||||
Succeed a,
|
Succeed a,
|
||||||
Arg ArgConfig (MarkedArgs -> Result { newlyTaken : Taken, val : a } (ParseError [])),
|
Option OptionConfig (MarkedArgs -> Result { newlyTaken : Taken, val : a } (ParseError [])),
|
||||||
Positional PositionalConfig (MarkedArgs -> Result { newlyTaken : Taken, val : a } (ParseError [])),
|
Positional PositionalConfig (MarkedArgs -> Result { newlyTaken : Taken, val : a } (ParseError [])),
|
||||||
# TODO: hiding the record behind an alias currently causes a panic
|
# TODO: hiding the record behind an alias currently causes a panic
|
||||||
SubCommand
|
SubCommand
|
||||||
|
@ -59,15 +59,15 @@ MarkedArgs : { args : List Str, taken : Taken }
|
||||||
ParseError a : [
|
ParseError a : [
|
||||||
## The program name was not found as the first argument to be parsed.
|
## The program name was not found as the first argument to be parsed.
|
||||||
ProgramNameNotProvided Str,
|
ProgramNameNotProvided Str,
|
||||||
## An argument is required, but it was not found.
|
## A positional argument (inherently required) was not found.
|
||||||
MissingRequiredArg Str,
|
MissingPositional Str,
|
||||||
## A positional argument is required, but it was not found.
|
## An option argument is required, but it was not found.
|
||||||
MissingPositionalArg Str,
|
MissingRequiredOption Str,
|
||||||
## An argument was found, but it didn't have the expected [Type].
|
## An argument was found, but it didn't have the expected [OptionType].
|
||||||
WrongType
|
WrongOptionType
|
||||||
{
|
{
|
||||||
arg : Str,
|
arg : Str,
|
||||||
expected : Type,
|
expected : OptionType,
|
||||||
},
|
},
|
||||||
## A subcommand is required, but it was not found.
|
## A subcommand is required, but it was not found.
|
||||||
SubCommandNotFound
|
SubCommandNotFound
|
||||||
|
@ -82,9 +82,9 @@ ParseError a : [
|
||||||
},
|
},
|
||||||
]a
|
]a
|
||||||
|
|
||||||
## Expected type of an argument, in an argument list being parsed.
|
## Expected type of an option, in an argument list being parsed.
|
||||||
## Describes how a string argument should be interpreted as a certain type.
|
## Describes how a string option should be interpreted as a certain type.
|
||||||
Type : [
|
OptionType : [
|
||||||
Str,
|
Str,
|
||||||
Bool,
|
Bool,
|
||||||
I64,
|
I64,
|
||||||
|
@ -96,11 +96,11 @@ Help : [
|
||||||
Config (List Config),
|
Config (List Config),
|
||||||
]
|
]
|
||||||
|
|
||||||
ArgConfig : {
|
OptionConfig : {
|
||||||
long : Str,
|
long : Str,
|
||||||
short : Str,
|
short : Str,
|
||||||
help : Str,
|
help : Str,
|
||||||
type : Type,
|
type : OptionType,
|
||||||
}
|
}
|
||||||
|
|
||||||
PositionalConfig : {
|
PositionalConfig : {
|
||||||
|
@ -108,7 +108,7 @@ PositionalConfig : {
|
||||||
help : Str,
|
help : Str,
|
||||||
}
|
}
|
||||||
|
|
||||||
Config : [Arg ArgConfig, Positional PositionalConfig]
|
Config : [Option OptionConfig, Positional PositionalConfig]
|
||||||
|
|
||||||
## Generates help metadata from a [Parser].
|
## Generates help metadata from a [Parser].
|
||||||
##
|
##
|
||||||
|
@ -133,8 +133,8 @@ toHelpHelper = \@Parser parser, configs ->
|
||||||
WithConfig innerParser config ->
|
WithConfig innerParser config ->
|
||||||
toHelpHelper innerParser (List.append configs config)
|
toHelpHelper innerParser (List.append configs config)
|
||||||
|
|
||||||
Arg config _ ->
|
Option config _ ->
|
||||||
List.append configs (Arg config)
|
List.append configs (Option config)
|
||||||
|> Config
|
|> Config
|
||||||
|
|
||||||
SubCommand commands ->
|
SubCommand commands ->
|
||||||
|
@ -165,7 +165,7 @@ findOneArg = \long, short, { args, taken } ->
|
||||||
if !found then
|
if !found then
|
||||||
Err NotFound
|
Err NotFound
|
||||||
else
|
else
|
||||||
# Return the next arg after the given one
|
# Return the next argument after the given one
|
||||||
List.get args (argIndex + 1)
|
List.get args (argIndex + 1)
|
||||||
|> Result.mapErr (\_ -> NotFound)
|
|> Result.mapErr (\_ -> NotFound)
|
||||||
|> Result.map
|
|> Result.map
|
||||||
|
@ -194,8 +194,8 @@ andMap = \@Parser parser, @Parser mapper ->
|
||||||
|> andMap (@Parser mapper)
|
|> andMap (@Parser mapper)
|
||||||
|> WithConfig config
|
|> WithConfig config
|
||||||
|
|
||||||
Arg config run ->
|
Option config run ->
|
||||||
Arg config \args ->
|
Option config \args ->
|
||||||
run args
|
run args
|
||||||
|> Result.map (\{ val, newlyTaken } -> { val: fn val, newlyTaken })
|
|> Result.map (\{ val, newlyTaken } -> { val: fn val, newlyTaken })
|
||||||
|
|
||||||
|
@ -211,16 +211,16 @@ andMap = \@Parser parser, @Parser mapper ->
|
||||||
List.map cmds mapSubParser
|
List.map cmds mapSubParser
|
||||||
|> SubCommand
|
|> SubCommand
|
||||||
|
|
||||||
Arg config run ->
|
Option config run ->
|
||||||
when parser is
|
when parser is
|
||||||
Succeed a ->
|
Succeed a ->
|
||||||
Arg config \args ->
|
Option config \args ->
|
||||||
when run args is
|
when run args is
|
||||||
Ok { val: fn, newlyTaken } -> Ok { val: fn a, newlyTaken }
|
Ok { val: fn, newlyTaken } -> Ok { val: fn a, newlyTaken }
|
||||||
Err err -> Err err
|
Err err -> Err err
|
||||||
|
|
||||||
Lazy thunk ->
|
Lazy thunk ->
|
||||||
Arg config \args ->
|
Option config \args ->
|
||||||
when run args is
|
when run args is
|
||||||
Ok { val: fn, newlyTaken } -> Ok { val: fn (thunk {}), newlyTaken }
|
Ok { val: fn, newlyTaken } -> Ok { val: fn (thunk {}), newlyTaken }
|
||||||
Err err -> Err err
|
Err err -> Err err
|
||||||
|
@ -230,9 +230,9 @@ andMap = \@Parser parser, @Parser mapper ->
|
||||||
|> andMap (@Parser mapper)
|
|> andMap (@Parser mapper)
|
||||||
|> WithConfig config2
|
|> WithConfig config2
|
||||||
|
|
||||||
Arg config2 run2 ->
|
Option config2 run2 ->
|
||||||
# Parse first the one and then the other.
|
# Parse first the one and then the other.
|
||||||
combinedParser = Arg config2 \args ->
|
combinedParser = Option config2 \args ->
|
||||||
when run args is
|
when run args is
|
||||||
Ok { val: fn, newlyTaken } ->
|
Ok { val: fn, newlyTaken } ->
|
||||||
run2 (updateTaken args newlyTaken)
|
run2 (updateTaken args newlyTaken)
|
||||||
|
@ -242,7 +242,7 @@ andMap = \@Parser parser, @Parser mapper ->
|
||||||
|
|
||||||
# Store the extra config.
|
# Store the extra config.
|
||||||
@Parser combinedParser
|
@Parser combinedParser
|
||||||
|> WithConfig (Arg config)
|
|> WithConfig (Option config)
|
||||||
|
|
||||||
Positional config2 run2 ->
|
Positional config2 run2 ->
|
||||||
combinedParser = Positional config2 \args ->
|
combinedParser = Positional config2 \args ->
|
||||||
|
@ -255,7 +255,7 @@ andMap = \@Parser parser, @Parser mapper ->
|
||||||
|
|
||||||
# Store the extra config.
|
# Store the extra config.
|
||||||
@Parser combinedParser
|
@Parser combinedParser
|
||||||
|> WithConfig (Arg config)
|
|> WithConfig (Option config)
|
||||||
|
|
||||||
SubCommand cmds ->
|
SubCommand cmds ->
|
||||||
# For each subcommand, first run the subcommand, then
|
# For each subcommand, first run the subcommand, then
|
||||||
|
@ -285,9 +285,9 @@ andMap = \@Parser parser, @Parser mapper ->
|
||||||
|> andMap (@Parser mapper)
|
|> andMap (@Parser mapper)
|
||||||
|> WithConfig config2
|
|> WithConfig config2
|
||||||
|
|
||||||
Arg config2 run2 ->
|
Option config2 run2 ->
|
||||||
# Parse first the one and then the other.
|
# Parse first the one and then the other.
|
||||||
combinedParser = Arg config2 \args ->
|
combinedParser = Option config2 \args ->
|
||||||
when run args is
|
when run args is
|
||||||
Ok { val: fn, newlyTaken } ->
|
Ok { val: fn, newlyTaken } ->
|
||||||
run2 (updateTaken args newlyTaken)
|
run2 (updateTaken args newlyTaken)
|
||||||
|
@ -336,8 +336,8 @@ andMap = \@Parser parser, @Parser mapper ->
|
||||||
|> andMap (@Parser mapper)
|
|> andMap (@Parser mapper)
|
||||||
|> WithConfig config
|
|> WithConfig config
|
||||||
|
|
||||||
Arg config run ->
|
Option config run ->
|
||||||
Arg config \args ->
|
Option config \args ->
|
||||||
run args
|
run args
|
||||||
|> Result.map (\{ val, newlyTaken } -> { val: fn val, newlyTaken })
|
|> Result.map (\{ val, newlyTaken } -> { val: fn val, newlyTaken })
|
||||||
|
|
||||||
|
@ -385,7 +385,7 @@ program = \parser, { name, help ? "" } ->
|
||||||
# TODO panics in alias analysis when this annotation is included
|
# TODO panics in alias analysis when this annotation is included
|
||||||
# parse : NamedParser a, List Str -> Result a (ParseError*)
|
# parse : NamedParser a, List Str -> Result a (ParseError*)
|
||||||
parse = \@NamedParser parser, args ->
|
parse = \@NamedParser parser, args ->
|
||||||
# By convention the first string in the arg list is the program name.
|
# By convention the first string in the argument list is the program name.
|
||||||
if
|
if
|
||||||
List.isEmpty args
|
List.isEmpty args
|
||||||
then
|
then
|
||||||
|
@ -399,7 +399,7 @@ parseHelp : Parser a, MarkedArgs -> Result a (ParseError [])
|
||||||
parseHelp = \@Parser parser, args ->
|
parseHelp = \@Parser parser, args ->
|
||||||
when parser is
|
when parser is
|
||||||
Succeed val -> Ok val
|
Succeed val -> Ok val
|
||||||
Arg _ run ->
|
Option _ run ->
|
||||||
run args
|
run args
|
||||||
|> Result.map .val
|
|> Result.map .val
|
||||||
|
|
||||||
|
@ -444,51 +444,51 @@ nextUnmarked = \marked ->
|
||||||
|
|
||||||
help 0
|
help 0
|
||||||
|
|
||||||
## Creates a parser for a boolean flag argument.
|
## Creates a parser for a boolean option argument.
|
||||||
## Flags of value "true" and "false" will be parsed as [Bool.true] and [Bool.false], respectively.
|
## Options of value "true" and "false" will be parsed as [Bool.true] and [Bool.false], respectively.
|
||||||
## All other values will result in a `WrongType` error.
|
## All other values will result in a `WrongOptionType` error.
|
||||||
bool : _ -> Parser Bool # TODO: panics if parameter annotation given
|
boolOption : _ -> Parser Bool # TODO: panics if parameter annotation given
|
||||||
bool = \{ long, short ? "", help ? "" } ->
|
boolOption = \{ long, short ? "", help ? "" } ->
|
||||||
fn = \args ->
|
fn = \args ->
|
||||||
when findOneArg long short args is
|
when findOneArg long short args is
|
||||||
Err NotFound -> Err (MissingRequiredArg long)
|
Err NotFound -> Err (MissingRequiredOption long)
|
||||||
Ok { val, newlyTaken } ->
|
Ok { val, newlyTaken } ->
|
||||||
when val is
|
when val is
|
||||||
"true" -> Ok { val: Bool.true, newlyTaken }
|
"true" -> Ok { val: Bool.true, newlyTaken }
|
||||||
"false" -> Ok { val: Bool.false, newlyTaken }
|
"false" -> Ok { val: Bool.false, newlyTaken }
|
||||||
_ -> Err (WrongType { arg: long, expected: Bool })
|
_ -> Err (WrongOptionType { arg: long, expected: Bool })
|
||||||
|
|
||||||
@Parser (Arg { long, short, help, type: Bool } fn)
|
@Parser (Option { long, short, help, type: Bool } fn)
|
||||||
|
|
||||||
## Creates a parser for a string flag argument.
|
## Creates a parser for a string option argument.
|
||||||
str : _ -> Parser Str # TODO: panics if parameter annotation given
|
strOption : _ -> Parser Str # TODO: panics if parameter annotation given
|
||||||
str = \{ long, short ? "", help ? "" } ->
|
strOption = \{ long, short ? "", help ? "" } ->
|
||||||
fn = \args ->
|
fn = \args ->
|
||||||
when findOneArg long short args is
|
when findOneArg long short args is
|
||||||
Err NotFound -> Err (MissingRequiredArg long)
|
Err NotFound -> Err (MissingRequiredOption long)
|
||||||
Ok { val, newlyTaken } -> Ok { val, newlyTaken }
|
Ok { val, newlyTaken } -> Ok { val, newlyTaken }
|
||||||
|
|
||||||
@Parser (Arg { long, short, help, type: Str } fn)
|
@Parser (Option { long, short, help, type: Str } fn)
|
||||||
|
|
||||||
## Creates a parser for a 64-bit signed integer ([I64]).
|
## Creates a parser for a 64-bit signed integer ([I64]) option argument.
|
||||||
i64 : _ -> Parser I64 # TODO: panics if parameter annotation given
|
i64Option : _ -> Parser I64 # TODO: panics if parameter annotation given
|
||||||
i64 = \{ long, short ? "", help ? "" } ->
|
i64Option = \{ long, short ? "", help ? "" } ->
|
||||||
fn = \args ->
|
fn = \args ->
|
||||||
when findOneArg long short args is
|
when findOneArg long short args is
|
||||||
Err NotFound -> Err (MissingRequiredArg long)
|
Err NotFound -> Err (MissingRequiredOption long)
|
||||||
Ok { val, newlyTaken } ->
|
Ok { val, newlyTaken } ->
|
||||||
Str.toI64 val
|
Str.toI64 val
|
||||||
|> Result.mapErr (\_ -> WrongType { arg: long, expected: I64 })
|
|> Result.mapErr (\_ -> WrongOptionType { arg: long, expected: I64 })
|
||||||
|> Result.map (\v -> { val: v, newlyTaken })
|
|> Result.map (\v -> { val: v, newlyTaken })
|
||||||
|
|
||||||
@Parser (Arg { long, short, help, type: I64 } fn)
|
@Parser (Option { long, short, help, type: I64 } fn)
|
||||||
|
|
||||||
## Parses a single positional argument as a string.
|
## Parses a single positional argument as a string.
|
||||||
positional : _ -> Parser Str
|
str : _ -> Parser Str
|
||||||
positional = \{ name, help ? "" } ->
|
str = \{ name, help ? "" } ->
|
||||||
fn = \args ->
|
fn = \args ->
|
||||||
nextUnmarked args
|
nextUnmarked args
|
||||||
|> Result.mapErr (\OutOfBounds -> MissingPositionalArg name)
|
|> Result.mapErr (\OutOfBounds -> MissingPositional name)
|
||||||
|> Result.map (\{ val, index } -> { val, newlyTaken: Set.insert args.taken index })
|
|> Result.map (\{ val, index } -> { val, newlyTaken: Set.insert args.taken index })
|
||||||
|
|
||||||
@Parser (Positional { name, help } fn)
|
@Parser (Positional { name, help } fn)
|
||||||
|
@ -573,12 +573,12 @@ formatHelpHelp = \n, cmdHelp ->
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Config configs ->
|
Config configs ->
|
||||||
argConfigs =
|
optionConfigs =
|
||||||
filterMap
|
filterMap
|
||||||
configs
|
configs
|
||||||
(\config ->
|
(\config ->
|
||||||
when config is
|
when config is
|
||||||
Arg c -> Some c
|
Option c -> Some c
|
||||||
_ -> None)
|
_ -> None)
|
||||||
|
|
||||||
positionalConfigs =
|
positionalConfigs =
|
||||||
|
@ -589,13 +589,13 @@ formatHelpHelp = \n, cmdHelp ->
|
||||||
Positional c -> Some c
|
Positional c -> Some c
|
||||||
_ -> None)
|
_ -> None)
|
||||||
|
|
||||||
fmtArgsHelp =
|
fmtOptionsHelp =
|
||||||
if List.isEmpty argConfigs then
|
if List.isEmpty optionConfigs then
|
||||||
""
|
""
|
||||||
else
|
else
|
||||||
helpStr =
|
helpStr =
|
||||||
argConfigs
|
optionConfigs
|
||||||
|> List.map (\c -> formatArgConfig (n + indentLevel) c)
|
|> List.map (\c -> formatOptionConfig (n + indentLevel) c)
|
||||||
|> Str.joinWith "\n"
|
|> Str.joinWith "\n"
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -615,11 +615,11 @@ formatHelpHelp = \n, cmdHelp ->
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
\(indented)POSITIONAL ARGUMENTS:
|
\(indented)ARGS:
|
||||||
\(helpStr)
|
\(helpStr)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Str.concat fmtArgsHelp fmtPositionalsHelp
|
Str.concat fmtPositionalsHelp fmtOptionsHelp
|
||||||
|
|
||||||
formatSubCommand = \n, { name, help } ->
|
formatSubCommand = \n, { name, help } ->
|
||||||
indented = indent n
|
indented = indent n
|
||||||
|
@ -628,14 +628,14 @@ formatSubCommand = \n, { name, help } ->
|
||||||
|
|
||||||
"\(indented)\(name)\(fmtHelp)"
|
"\(indented)\(name)\(fmtHelp)"
|
||||||
|
|
||||||
formatArgConfig : Nat, ArgConfig -> Str
|
formatOptionConfig : Nat, OptionConfig -> Str
|
||||||
formatArgConfig = \n, { long, short, help, type } ->
|
formatOptionConfig = \n, { long, short, help, type } ->
|
||||||
indented = indent n
|
indented = indent n
|
||||||
|
|
||||||
formattedShort =
|
formattedShort =
|
||||||
mapNonEmptyStr short \s -> ", -\(s)"
|
mapNonEmptyStr short \s -> ", -\(s)"
|
||||||
|
|
||||||
formattedType = formatType type
|
formattedType = formatOptionType type
|
||||||
|
|
||||||
formattedHelp =
|
formattedHelp =
|
||||||
mapNonEmptyStr help \h -> " \(h)"
|
mapNonEmptyStr help \h -> " \(h)"
|
||||||
|
@ -651,12 +651,12 @@ formatPositionalConfig = \n, { name, help } ->
|
||||||
|
|
||||||
"\(indented)\(name)\(formattedHelp)"
|
"\(indented)\(name)\(formattedHelp)"
|
||||||
|
|
||||||
formatType : Type -> Str
|
formatOptionType : OptionType -> Str
|
||||||
formatType = \type ->
|
formatOptionType = \type ->
|
||||||
when type is
|
when type is
|
||||||
Bool -> "bool"
|
Bool -> "boolean"
|
||||||
Str -> "string"
|
Str -> "string"
|
||||||
I64 -> "i64"
|
I64 -> "integer, 64-bit signed"
|
||||||
|
|
||||||
quote = \s -> "\"\(s)\""
|
quote = \s -> "\"\(s)\""
|
||||||
|
|
||||||
|
@ -664,18 +664,18 @@ formatError : ParseError [] -> Str
|
||||||
formatError = \err ->
|
formatError = \err ->
|
||||||
when err is
|
when err is
|
||||||
ProgramNameNotProvided programName ->
|
ProgramNameNotProvided programName ->
|
||||||
"The program name \"\(programName)\" was not probided as a first argument!"
|
"The program name \"\(programName)\" was not provided as a first argument!"
|
||||||
|
|
||||||
MissingRequiredArg arg ->
|
MissingPositional arg ->
|
||||||
"Argument `--\(arg)` is required but was not provided!"
|
"The argument `\(arg)` is required but was not provided!"
|
||||||
|
|
||||||
MissingPositionalArg arg ->
|
MissingRequiredOption arg ->
|
||||||
"A positional argument for `\(arg)` is required but was not provided!"
|
"The option `--\(arg)` is required but was not provided!"
|
||||||
|
|
||||||
WrongType { arg, expected } ->
|
WrongOptionType { arg, expected } ->
|
||||||
formattedType = formatType expected
|
formattedType = formatOptionType expected
|
||||||
|
|
||||||
"The argument `--\(arg)` expects a value of type \(formattedType)!"
|
"The option `--\(arg)` expects a value of type \(formattedType)!"
|
||||||
|
|
||||||
SubCommandNotFound { choices } ->
|
SubCommandNotFound { choices } ->
|
||||||
fmtChoices =
|
fmtChoices =
|
||||||
|
@ -708,117 +708,117 @@ formatError = \err ->
|
||||||
## the result of `parser` to `mapper`.
|
## the result of `parser` to `mapper`.
|
||||||
##
|
##
|
||||||
## This provides a way to chain the results of multiple parsers together. For
|
## This provides a way to chain the results of multiple parsers together. For
|
||||||
## example, to combine the results of two [str] arguments into a record, you
|
## example, to combine the results of two [strOption] arguments into a record,
|
||||||
## could use
|
## you could use
|
||||||
##
|
##
|
||||||
## ```
|
## ```
|
||||||
## succeed (\host -> \port -> { host, port })
|
## succeed (\host -> \port -> { host, port })
|
||||||
## |> withParser (str { long: "host" })
|
## |> withParser (strOption { long: "host" })
|
||||||
## |> withParser (str { long: "port" })
|
## |> withParser (strOption { long: "port" })
|
||||||
## ```
|
## ```
|
||||||
withParser = \arg1, arg2 -> andMap arg2 arg1
|
withParser = \arg1, arg2 -> andMap arg2 arg1
|
||||||
|
|
||||||
mark = \args -> { args, taken: Set.empty }
|
mark = \args -> { args, taken: Set.empty }
|
||||||
|
|
||||||
# bool undashed long argument is missing
|
# boolean undashed long optional is missing
|
||||||
expect
|
expect
|
||||||
parser = bool { long: "foo" }
|
parser = boolOption { long: "foo" }
|
||||||
|
|
||||||
parseHelp parser (mark ["foo"]) == Err (MissingRequiredArg "foo")
|
parseHelp parser (mark ["foo"]) == Err (MissingRequiredOption "foo")
|
||||||
|
|
||||||
# bool dashed long argument without value is missing
|
# boolean dashed long optional without value is missing
|
||||||
expect
|
expect
|
||||||
parser = bool { long: "foo" }
|
parser = boolOption { long: "foo" }
|
||||||
|
|
||||||
parseHelp parser (mark ["--foo"]) == Err (MissingRequiredArg "foo")
|
parseHelp parser (mark ["--foo"]) == Err (MissingRequiredOption "foo")
|
||||||
|
|
||||||
# bool dashed long argument with value is determined true
|
# boolean dashed long optional with value is determined true
|
||||||
expect
|
expect
|
||||||
parser = bool { long: "foo" }
|
parser = boolOption { long: "foo" }
|
||||||
|
|
||||||
parseHelp parser (mark ["--foo", "true"]) == Ok Bool.true
|
parseHelp parser (mark ["--foo", "true"]) == Ok Bool.true
|
||||||
|
|
||||||
# bool dashed long argument with value is determined false
|
# boolean dashed long optional with value is determined false
|
||||||
expect
|
expect
|
||||||
parser = bool { long: "foo" }
|
parser = boolOption { long: "foo" }
|
||||||
|
|
||||||
parseHelp parser (mark ["--foo", "false"]) == Ok Bool.false
|
parseHelp parser (mark ["--foo", "false"]) == Ok Bool.false
|
||||||
|
|
||||||
# bool dashed long argument with value is determined wrong type
|
# boolean dashed long optional with value is determined wrong type
|
||||||
expect
|
expect
|
||||||
parser = bool { long: "foo" }
|
parser = boolOption { long: "foo" }
|
||||||
|
|
||||||
parseHelp parser (mark ["--foo", "not-a-bool"]) == Err (WrongType { arg: "foo", expected: Bool })
|
parseHelp parser (mark ["--foo", "not-a-boolean"]) == Err (WrongOptionType { arg: "foo", expected: Bool })
|
||||||
|
|
||||||
# bool dashed short argument with value is determined true
|
# boolean dashed short optional with value is determined true
|
||||||
expect
|
expect
|
||||||
parser = bool { long: "foo", short: "F" }
|
parser = boolOption { long: "foo", short: "F" }
|
||||||
|
|
||||||
parseHelp parser (mark ["-F", "true"]) == Ok Bool.true
|
parseHelp parser (mark ["-F", "true"]) == Ok Bool.true
|
||||||
|
|
||||||
# bool dashed short argument with value is determined false
|
# boolean dashed short optional with value is determined false
|
||||||
expect
|
expect
|
||||||
parser = bool { long: "foo", short: "F" }
|
parser = boolOption { long: "foo", short: "F" }
|
||||||
|
|
||||||
parseHelp parser (mark ["-F", "false"]) == Ok Bool.false
|
parseHelp parser (mark ["-F", "false"]) == Ok Bool.false
|
||||||
|
|
||||||
# bool dashed short argument with value is determined wrong type
|
# boolean dashed short optional with value is determined wrong type
|
||||||
expect
|
expect
|
||||||
parser = bool { long: "foo", short: "F" }
|
parser = boolOption { long: "foo", short: "F" }
|
||||||
|
|
||||||
parseHelp parser (mark ["-F", "not-a-bool"]) == Err (WrongType { arg: "foo", expected: Bool })
|
parseHelp parser (mark ["-F", "not-a-boolean"]) == Err (WrongOptionType { arg: "foo", expected: Bool })
|
||||||
|
|
||||||
# string dashed long argument without value is missing
|
# string dashed long option without value is missing
|
||||||
expect
|
expect
|
||||||
parser = str { long: "foo" }
|
parser = strOption { long: "foo" }
|
||||||
|
|
||||||
parseHelp parser (mark ["--foo"]) == Err (MissingRequiredArg "foo")
|
parseHelp parser (mark ["--foo"]) == Err (MissingRequiredOption "foo")
|
||||||
|
|
||||||
# string dashed long argument with value is determined
|
# string dashed long option with value is determined
|
||||||
expect
|
expect
|
||||||
parser = str { long: "foo" }
|
parser = strOption { long: "foo" }
|
||||||
|
|
||||||
parseHelp parser (mark ["--foo", "itsme"]) == Ok "itsme"
|
parseHelp parser (mark ["--foo", "itsme"]) == Ok "itsme"
|
||||||
|
|
||||||
# string dashed short argument without value is missing
|
# string dashed short option without value is missing
|
||||||
expect
|
expect
|
||||||
parser = str { long: "foo", short: "F" }
|
parser = strOption { long: "foo", short: "F" }
|
||||||
|
|
||||||
parseHelp parser (mark ["-F"]) == Err (MissingRequiredArg "foo")
|
parseHelp parser (mark ["-F"]) == Err (MissingRequiredOption "foo")
|
||||||
|
|
||||||
# string dashed short argument with value is determined
|
# string dashed short option with value is determined
|
||||||
expect
|
expect
|
||||||
parser = str { long: "foo", short: "F" }
|
parser = strOption { long: "foo", short: "F" }
|
||||||
|
|
||||||
parseHelp parser (mark ["-F", "itsme"]) == Ok "itsme"
|
parseHelp parser (mark ["-F", "itsme"]) == Ok "itsme"
|
||||||
|
|
||||||
# i64 dashed long argument without value is missing
|
# i64 dashed long option without value is missing
|
||||||
expect
|
expect
|
||||||
parser = i64 { long: "foo" }
|
parser = i64Option { long: "foo" }
|
||||||
|
|
||||||
parseHelp parser (mark ["--foo"]) == Err (MissingRequiredArg "foo")
|
parseHelp parser (mark ["--foo"]) == Err (MissingRequiredOption "foo")
|
||||||
|
|
||||||
# i64 dashed long argument with value is determined positive
|
# i64 dashed long option with value is determined positive
|
||||||
expect
|
expect
|
||||||
parser = i64 { long: "foo" }
|
parser = i64Option { long: "foo" }
|
||||||
|
|
||||||
parseHelp parser (mark ["--foo", "1234"]) == Ok 1234
|
parseHelp parser (mark ["--foo", "1234"]) == Ok 1234
|
||||||
|
|
||||||
# i64 dashed long argument with value is determined negative
|
# i64 dashed long option with value is determined negative
|
||||||
expect
|
expect
|
||||||
parser = i64 { long: "foo" }
|
parser = i64Option { long: "foo" }
|
||||||
|
|
||||||
parseHelp parser (mark ["--foo", "-1234"]) == Ok -1234
|
parseHelp parser (mark ["--foo", "-1234"]) == Ok -1234
|
||||||
|
|
||||||
# i64 dashed short argument without value is missing
|
# i64 dashed short option without value is missing
|
||||||
expect
|
expect
|
||||||
parser = i64 { long: "foo", short: "F" }
|
parser = i64Option { long: "foo", short: "F" }
|
||||||
|
|
||||||
parseHelp parser (mark ["-F"]) == Err (MissingRequiredArg "foo")
|
parseHelp parser (mark ["-F"]) == Err (MissingRequiredOption "foo")
|
||||||
|
|
||||||
# i64 dashed short argument with value is determined
|
# i64 dashed short option with value is determined
|
||||||
expect
|
expect
|
||||||
parser = i64 { long: "foo", short: "F" }
|
parser = i64Option { long: "foo", short: "F" }
|
||||||
|
|
||||||
parseHelp parser (mark ["-F", "1234"]) == Ok 1234
|
parseHelp parser (mark ["-F", "1234"]) == Ok 1234
|
||||||
|
|
||||||
|
@ -826,8 +826,8 @@ expect
|
||||||
expect
|
expect
|
||||||
parser =
|
parser =
|
||||||
succeed (\foo -> \bar -> "foo: \(foo) bar: \(bar)")
|
succeed (\foo -> \bar -> "foo: \(foo) bar: \(bar)")
|
||||||
|> withParser (str { long: "foo" })
|
|> withParser (strOption { long: "foo" })
|
||||||
|> withParser (str { long: "bar" })
|
|> withParser (strOption { long: "bar" })
|
||||||
|
|
||||||
cases = [
|
cases = [
|
||||||
["--foo", "true", "--bar", "baz"],
|
["--foo", "true", "--bar", "baz"],
|
||||||
|
@ -841,61 +841,61 @@ expect
|
||||||
expect
|
expect
|
||||||
parser =
|
parser =
|
||||||
succeed (\foo -> \bar -> "foo: \(foo) bar: \(bar)")
|
succeed (\foo -> \bar -> "foo: \(foo) bar: \(bar)")
|
||||||
|> withParser (str { long: "foo" })
|
|> withParser (strOption { long: "foo" })
|
||||||
|> withParser (str { long: "bar" })
|
|> withParser (strOption { long: "bar" })
|
||||||
|
|
||||||
List.all
|
List.all
|
||||||
[
|
[
|
||||||
parseHelp parser (mark ["--foo", "zaz"]) == Err (MissingRequiredArg "bar"),
|
parseHelp parser (mark ["--foo", "zaz"]) == Err (MissingRequiredOption "bar"),
|
||||||
parseHelp parser (mark ["--bar", "zaz"]) == Err (MissingRequiredArg "foo"),
|
parseHelp parser (mark ["--bar", "zaz"]) == Err (MissingRequiredOption "foo"),
|
||||||
]
|
]
|
||||||
(\b -> b)
|
(\b -> b)
|
||||||
|
|
||||||
# string and bool parsers build help
|
# string and boolean parsers build help
|
||||||
expect
|
expect
|
||||||
parser =
|
parser =
|
||||||
succeed (\foo -> \bar -> \_bool -> "foo: \(foo) bar: \(bar)")
|
succeed (\foo -> \bar -> \_bool -> "foo: \(foo) bar: \(bar)")
|
||||||
|> withParser (str { long: "foo", help: "the foo flag" })
|
|> withParser (strOption { long: "foo", help: "the foo option" })
|
||||||
|> withParser (str { long: "bar", short: "B" })
|
|> withParser (strOption { long: "bar", short: "B" })
|
||||||
|> withParser (bool { long: "bool" })
|
|> withParser (boolOption { long: "boolean" })
|
||||||
|
|
||||||
toHelp parser
|
toHelp parser
|
||||||
== Config [
|
== Config [
|
||||||
Arg { long: "foo", short: "", help: "the foo flag", type: Str },
|
Option { long: "foo", short: "", help: "the foo option", type: Str },
|
||||||
Arg { long: "bar", short: "B", help: "", type: Str },
|
Option { long: "bar", short: "B", help: "", type: Str },
|
||||||
Arg { long: "bool", short: "", help: "", type: Bool },
|
Option { long: "boolean", short: "", help: "", type: Bool },
|
||||||
]
|
]
|
||||||
|
|
||||||
# format argument is missing
|
# format option is missing
|
||||||
expect
|
expect
|
||||||
parser = bool { long: "foo" }
|
parser = boolOption { long: "foo" }
|
||||||
|
|
||||||
when parseHelp parser (mark ["foo"]) is
|
when parseHelp parser (mark ["foo"]) is
|
||||||
Ok _ -> Bool.false
|
Ok _ -> Bool.false
|
||||||
Err e ->
|
Err e ->
|
||||||
err = formatError e
|
err = formatError e
|
||||||
|
|
||||||
err == "Argument `--foo` is required but was not provided!"
|
err == "The option `--foo` is required but was not provided!"
|
||||||
|
|
||||||
# format argument has wrong type
|
# format option has wrong type
|
||||||
expect
|
expect
|
||||||
parser = bool { long: "foo" }
|
parser = boolOption { long: "foo" }
|
||||||
|
|
||||||
when parseHelp parser (mark ["--foo", "12"]) is
|
when parseHelp parser (mark ["--foo", "12"]) is
|
||||||
Ok _ -> Bool.false
|
Ok _ -> Bool.false
|
||||||
Err e ->
|
Err e ->
|
||||||
err = formatError e
|
err = formatError e
|
||||||
|
|
||||||
err == "The argument `--foo` expects a value of type bool!"
|
err == "The option `--foo` expects a value of type boolean!"
|
||||||
|
|
||||||
# format help menu with only args
|
# format help menu with only options
|
||||||
expect
|
expect
|
||||||
parser =
|
parser =
|
||||||
succeed (\_foo -> \_bar -> \_baz -> \_bool -> "")
|
succeed (\_foo -> \_bar -> \_baz -> \_bool -> "")
|
||||||
|> withParser (str { long: "foo", help: "the foo flag" })
|
|> withParser (strOption { long: "foo", help: "the foo option" })
|
||||||
|> withParser (str { long: "bar", short: "B" })
|
|> withParser (strOption { long: "bar", short: "B" })
|
||||||
|> withParser (str { long: "baz", short: "z", help: "the baz flag" })
|
|> withParser (strOption { long: "baz", short: "z", help: "the baz option" })
|
||||||
|> withParser (bool { long: "bool" })
|
|> withParser (boolOption { long: "boolean" })
|
||||||
|> program { name: "test" }
|
|> program { name: "test" }
|
||||||
|
|
||||||
formatHelp parser
|
formatHelp parser
|
||||||
|
@ -904,10 +904,10 @@ expect
|
||||||
test
|
test
|
||||||
|
|
||||||
OPTIONS:
|
OPTIONS:
|
||||||
--foo the foo flag (string)
|
--foo the foo option (string)
|
||||||
--bar, -B (string)
|
--bar, -B (string)
|
||||||
--baz, -z the baz flag (string)
|
--baz, -z the baz option (string)
|
||||||
--bool (bool)
|
--boolean (boolean)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# format help menu with subcommands
|
# format help menu with subcommands
|
||||||
|
@ -915,12 +915,12 @@ expect
|
||||||
parser =
|
parser =
|
||||||
choice [
|
choice [
|
||||||
succeed (\user -> \pw -> "\(user)\(pw)")
|
succeed (\user -> \pw -> "\(user)\(pw)")
|
||||||
|> withParser (str { long: "user" })
|
|> withParser (strOption { long: "user" })
|
||||||
|> withParser (str { long: "pw" })
|
|> withParser (strOption { long: "pw" })
|
||||||
|> subCommand "login",
|
|> subCommand "login",
|
||||||
succeed (\file -> \url -> "\(file)\(url)")
|
succeed (\file -> \url -> "\(file)\(url)")
|
||||||
|> withParser (str { long: "file" })
|
|> withParser (strOption { long: "file" })
|
||||||
|> withParser (str { long: "url" })
|
|> withParser (strOption { long: "url" })
|
||||||
|> subCommand "publish",
|
|> subCommand "publish",
|
||||||
]
|
]
|
||||||
|> program { name: "test" }
|
|> program { name: "test" }
|
||||||
|
@ -963,12 +963,12 @@ expect
|
||||||
parser =
|
parser =
|
||||||
choice [
|
choice [
|
||||||
succeed (\user -> \pw -> "logging in \(user) with \(pw)")
|
succeed (\user -> \pw -> "logging in \(user) with \(pw)")
|
||||||
|> withParser (str { long: "user" })
|
|> withParser (strOption { long: "user" })
|
||||||
|> withParser (str { long: "pw" })
|
|> withParser (strOption { long: "pw" })
|
||||||
|> subCommand "login",
|
|> subCommand "login",
|
||||||
succeed (\file -> \url -> "\(file)\(url)")
|
succeed (\file -> \url -> "\(file)\(url)")
|
||||||
|> withParser (str { long: "file" })
|
|> withParser (strOption { long: "file" })
|
||||||
|> withParser (str { long: "url" })
|
|> withParser (strOption { long: "url" })
|
||||||
|> subCommand "publish",
|
|> subCommand "publish",
|
||||||
]
|
]
|
||||||
|> program { name: "test" }
|
|> program { name: "test" }
|
||||||
|
@ -983,8 +983,8 @@ expect
|
||||||
choice [
|
choice [
|
||||||
choice [
|
choice [
|
||||||
succeed (\user -> \pw -> "logging in \(user) with \(pw)")
|
succeed (\user -> \pw -> "logging in \(user) with \(pw)")
|
||||||
|> withParser (str { long: "user" })
|
|> withParser (strOption { long: "user" })
|
||||||
|> withParser (str { long: "pw" })
|
|> withParser (strOption { long: "pw" })
|
||||||
|> subCommand "login",
|
|> subCommand "login",
|
||||||
]
|
]
|
||||||
|> subCommand "auth",
|
|> subCommand "auth",
|
||||||
|
@ -1031,18 +1031,18 @@ expect
|
||||||
\t"auth", "publish"
|
\t"auth", "publish"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# parse positional argument
|
# parse positional
|
||||||
expect
|
expect
|
||||||
parser = positional { name: "foo" }
|
parser = str { name: "foo" }
|
||||||
|
|
||||||
parseHelp parser (mark ["myArg"]) == Ok "myArg"
|
parseHelp parser (mark ["myArg"]) == Ok "myArg"
|
||||||
|
|
||||||
# parse positional argument with argument flag
|
# parse positional with option
|
||||||
expect
|
expect
|
||||||
parser =
|
parser =
|
||||||
succeed (\foo -> \bar -> "foo: \(foo), bar: \(bar)")
|
succeed (\foo -> \bar -> "foo: \(foo), bar: \(bar)")
|
||||||
|> withParser (str { long: "foo" })
|
|> withParser (strOption { long: "foo" })
|
||||||
|> withParser (positional { name: "bar" })
|
|> withParser (str { name: "bar" })
|
||||||
|
|
||||||
cases = [
|
cases = [
|
||||||
["--foo", "true", "baz"],
|
["--foo", "true", "baz"],
|
||||||
|
@ -1051,17 +1051,17 @@ expect
|
||||||
|
|
||||||
List.all cases \args -> parseHelp parser (mark args) == Ok "foo: true, bar: baz"
|
List.all cases \args -> parseHelp parser (mark args) == Ok "foo: true, bar: baz"
|
||||||
|
|
||||||
# parse positional argument with subcommand
|
# parse positional with subcommand
|
||||||
expect
|
expect
|
||||||
parser = choice [
|
parser = choice [
|
||||||
positional { name: "bar" }
|
str { name: "bar" }
|
||||||
|> subCommand "hello",
|
|> subCommand "hello",
|
||||||
]
|
]
|
||||||
|
|
||||||
parseHelp parser (mark ["hello", "foo"]) == Ok "foo"
|
parseHelp parser (mark ["hello", "foo"]) == Ok "foo"
|
||||||
|
|
||||||
# missing positional argument
|
# missing positional
|
||||||
expect
|
expect
|
||||||
parser = positional { name: "bar" }
|
parser = str { name: "bar" }
|
||||||
|
|
||||||
parseHelp parser (mark []) == Err (MissingPositionalArg "bar")
|
parseHelp parser (mark []) == Err (MissingPositional "bar")
|
||||||
|
|
249
examples/cli/cli-platform/Cargo.lock
generated
249
examples/cli/cli-platform/Cargo.lock
generated
|
@ -2,6 +2,21 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "addr2line"
|
||||||
|
version = "0.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
|
||||||
|
dependencies = [
|
||||||
|
"gimli",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayvec"
|
name = "arrayvec"
|
||||||
version = "0.7.2"
|
version = "0.7.2"
|
||||||
|
@ -14,6 +29,21 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "backtrace"
|
||||||
|
version = "0.3.66"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7"
|
||||||
|
dependencies = [
|
||||||
|
"addr2line",
|
||||||
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"miniz_oxide",
|
||||||
|
"object",
|
||||||
|
"rustc-demangle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64"
|
name = "base64"
|
||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
|
@ -22,15 +52,15 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.10.0"
|
version = "3.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3"
|
checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.2.0"
|
version = "1.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f0b3de4a0c5e67e16066a0715723abd91edc2f9001d09c46e1dca929351e130e"
|
checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
|
@ -61,52 +91,51 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "form_urlencoded"
|
name = "form_urlencoded"
|
||||||
version = "1.0.1"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"
|
checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"matches",
|
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-channel"
|
name = "futures-channel"
|
||||||
version = "0.3.21"
|
version = "0.3.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
|
checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-core"
|
name = "futures-core"
|
||||||
version = "0.3.21"
|
version = "0.3.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
|
checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-io"
|
name = "futures-io"
|
||||||
version = "0.3.21"
|
version = "0.3.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
|
checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-sink"
|
name = "futures-sink"
|
||||||
version = "0.3.21"
|
version = "0.3.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868"
|
checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-task"
|
name = "futures-task"
|
||||||
version = "0.3.21"
|
version = "0.3.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a"
|
checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-util"
|
name = "futures-util"
|
||||||
version = "0.3.21"
|
version = "0.3.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
|
checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-io",
|
"futures-io",
|
||||||
|
@ -118,10 +147,16 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "h2"
|
name = "gimli"
|
||||||
version = "0.3.13"
|
version = "0.26.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57"
|
checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "h2"
|
||||||
|
version = "0.3.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"fnv",
|
"fnv",
|
||||||
|
@ -155,6 +190,7 @@ dependencies = [
|
||||||
name = "host"
|
name = "host"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"backtrace",
|
||||||
"libc",
|
"libc",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"roc_std",
|
"roc_std",
|
||||||
|
@ -184,9 +220,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "httparse"
|
name = "httparse"
|
||||||
version = "1.7.1"
|
version = "1.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c"
|
checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "httpdate"
|
name = "httpdate"
|
||||||
|
@ -233,11 +269,10 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "0.2.3"
|
version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
|
checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"matches",
|
|
||||||
"unicode-bidi",
|
"unicode-bidi",
|
||||||
"unicode-normalization",
|
"unicode-normalization",
|
||||||
]
|
]
|
||||||
|
@ -260,30 +295,24 @@ checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.2"
|
version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
|
checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.58"
|
version = "0.3.60"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27"
|
checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lazy_static"
|
|
||||||
version = "1.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.126"
|
version = "0.2.134"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
|
checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
|
@ -294,12 +323,6 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "matches"
|
|
||||||
version = "0.1.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
|
@ -312,6 +335,15 @@ version = "0.3.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
|
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"
|
||||||
|
dependencies = [
|
||||||
|
"adler",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "0.8.4"
|
version = "0.8.4"
|
||||||
|
@ -335,16 +367,25 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "object"
|
||||||
version = "1.13.0"
|
version = "0.29.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
|
checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.1.0"
|
version = "2.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
|
@ -360,27 +401,27 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.40"
|
version = "1.0.46"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7"
|
checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.20"
|
version = "1.0.21"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
|
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reqwest"
|
name = "reqwest"
|
||||||
version = "0.11.11"
|
version = "0.11.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92"
|
checksum = "431949c384f4e2ae07605ccaa56d1d9d2ecdb5cadd4f9577ccfab29f2e5149fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
@ -394,9 +435,9 @@ dependencies = [
|
||||||
"hyper-rustls",
|
"hyper-rustls",
|
||||||
"ipnet",
|
"ipnet",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"lazy_static",
|
|
||||||
"log",
|
"log",
|
||||||
"mime",
|
"mime",
|
||||||
|
"once_cell",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"rustls",
|
"rustls",
|
||||||
|
@ -438,6 +479,12 @@ dependencies = [
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-demangle"
|
||||||
|
version = "0.1.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls"
|
name = "rustls"
|
||||||
version = "0.20.6"
|
version = "0.20.6"
|
||||||
|
@ -452,18 +499,18 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls-pemfile"
|
name = "rustls-pemfile"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e7522c9de787ff061458fe9a829dc790a3f5b22dc571694fc5883f448b94d9a9"
|
checksum = "0864aeff53f8c05aa08d86e5ef839d3dfcf07aeba2db32f12db0ef716e87bd55"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.10"
|
version = "1.0.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695"
|
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sct"
|
name = "sct"
|
||||||
|
@ -477,15 +524,15 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.140"
|
version = "1.0.145"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fc855a42c7967b7c369eb5860f7164ef1f6f81c20c7cc1141f2a604e18723b03"
|
checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.82"
|
version = "1.0.85"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7"
|
checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
|
@ -515,9 +562,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.4.4"
|
version = "0.4.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
|
checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"winapi",
|
"winapi",
|
||||||
|
@ -537,9 +584,9 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.98"
|
version = "1.0.102"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
|
checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -563,9 +610,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.20.0"
|
version = "1.21.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "57aec3cfa4c296db7255446efb4928a6be304b431a806216105542a67b6ca82e"
|
checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
@ -573,7 +620,6 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
"mio",
|
"mio",
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
"once_cell",
|
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"socket2",
|
"socket2",
|
||||||
"winapi",
|
"winapi",
|
||||||
|
@ -592,9 +638,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-util"
|
name = "tokio-util"
|
||||||
version = "0.7.3"
|
version = "0.7.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45"
|
checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
@ -612,9 +658,9 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing"
|
name = "tracing"
|
||||||
version = "0.1.35"
|
version = "0.1.37"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160"
|
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
|
@ -623,9 +669,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-core"
|
name = "tracing-core"
|
||||||
version = "0.1.28"
|
version = "0.1.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7"
|
checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
@ -644,15 +690,15 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.1"
|
version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c"
|
checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-normalization"
|
name = "unicode-normalization"
|
||||||
version = "0.1.21"
|
version = "0.1.22"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6"
|
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"tinyvec",
|
"tinyvec",
|
||||||
]
|
]
|
||||||
|
@ -665,13 +711,12 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "url"
|
name = "url"
|
||||||
version = "2.2.2"
|
version = "2.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c"
|
checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"form_urlencoded",
|
"form_urlencoded",
|
||||||
"idna",
|
"idna",
|
||||||
"matches",
|
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -693,9 +738,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.81"
|
version = "0.2.83"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994"
|
checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"wasm-bindgen-macro",
|
"wasm-bindgen-macro",
|
||||||
|
@ -703,13 +748,13 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-backend"
|
name = "wasm-bindgen-backend"
|
||||||
version = "0.2.81"
|
version = "0.2.83"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a"
|
checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"lazy_static",
|
|
||||||
"log",
|
"log",
|
||||||
|
"once_cell",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
|
@ -718,9 +763,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-futures"
|
name = "wasm-bindgen-futures"
|
||||||
version = "0.4.31"
|
version = "0.4.33"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "de9a9cec1733468a8c657e57fa2413d2ae2c0129b95e87c5b72b8ace4d13f31f"
|
checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
|
@ -730,9 +775,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro"
|
name = "wasm-bindgen-macro"
|
||||||
version = "0.2.81"
|
version = "0.2.83"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa"
|
checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"wasm-bindgen-macro-support",
|
"wasm-bindgen-macro-support",
|
||||||
|
@ -740,9 +785,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro-support"
|
name = "wasm-bindgen-macro-support"
|
||||||
version = "0.2.81"
|
version = "0.2.83"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048"
|
checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -753,15 +798,15 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-shared"
|
name = "wasm-bindgen-shared"
|
||||||
version = "0.2.81"
|
version = "0.2.83"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be"
|
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "web-sys"
|
name = "web-sys"
|
||||||
version = "0.3.58"
|
version = "0.3.60"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90"
|
checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
|
@ -779,9 +824,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webpki-roots"
|
name = "webpki-roots"
|
||||||
version = "0.22.4"
|
version = "0.22.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f1c760f0d366a6c24a02ed7816e23e691f5d92291f94d15e836006fd11b04daf"
|
checksum = "368bfe657969fb01238bb756d351dcade285e0f6fcbd36dcb23359a5169975be"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"webpki",
|
"webpki",
|
||||||
]
|
]
|
||||||
|
|
|
@ -20,5 +20,6 @@ path = "src/main.rs"
|
||||||
roc_std = { path = "../../../crates/roc_std" }
|
roc_std = { path = "../../../crates/roc_std" }
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
reqwest = { version="0.11.11", default-features=false, features=["blocking", "rustls-tls"] }
|
reqwest = { version="0.11.11", default-features=false, features=["blocking", "rustls-tls"] }
|
||||||
|
backtrace = "0.3"
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
|
|
|
@ -14,7 +14,9 @@ hosted Effect
|
||||||
setCwd,
|
setCwd,
|
||||||
exePath,
|
exePath,
|
||||||
stdoutLine,
|
stdoutLine,
|
||||||
|
stdoutWrite,
|
||||||
stderrLine,
|
stderrLine,
|
||||||
|
stderrWrite,
|
||||||
stdinLine,
|
stdinLine,
|
||||||
sendRequest,
|
sendRequest,
|
||||||
fileReadBytes,
|
fileReadBytes,
|
||||||
|
@ -26,7 +28,9 @@ hosted Effect
|
||||||
generates Effect with [after, map, always, forever, loop]
|
generates Effect with [after, map, always, forever, loop]
|
||||||
|
|
||||||
stdoutLine : Str -> Effect {}
|
stdoutLine : Str -> Effect {}
|
||||||
|
stdoutWrite : Str -> Effect {}
|
||||||
stderrLine : Str -> Effect {}
|
stderrLine : Str -> Effect {}
|
||||||
|
stderrWrite : Str -> Effect {}
|
||||||
stdinLine : Effect Str
|
stdinLine : Effect Str
|
||||||
|
|
||||||
fileWriteBytes : List U8, List U8 -> Effect (Result {} InternalFile.WriteErr)
|
fileWriteBytes : List U8, List U8 -> Effect (Result {} InternalFile.WriteErr)
|
||||||
|
|
|
@ -1,8 +1,15 @@
|
||||||
interface Stderr
|
interface Stderr
|
||||||
exposes [line]
|
exposes [line, write]
|
||||||
imports [Effect, Task.{ Task }, InternalTask]
|
imports [Effect, Task.{ Task }, InternalTask]
|
||||||
|
|
||||||
line : Str -> Task {} * [Write [Stderr]*]*
|
line : Str -> Task {} * [Write [Stderr]*]*
|
||||||
line = \str ->
|
line = \str ->
|
||||||
Effect.map (Effect.stderrLine str) (\_ -> Ok {})
|
Effect.stderrLine str
|
||||||
|
|> Effect.map (\_ -> Ok {})
|
||||||
|
|> InternalTask.fromEffect
|
||||||
|
|
||||||
|
write : Str -> Task {} * [Write [Stderr]*]*
|
||||||
|
write = \str ->
|
||||||
|
Effect.stderrWrite str
|
||||||
|
|> Effect.map (\_ -> Ok {})
|
||||||
|> InternalTask.fromEffect
|
|> InternalTask.fromEffect
|
||||||
|
|
|
@ -1,8 +1,15 @@
|
||||||
interface Stdout
|
interface Stdout
|
||||||
exposes [line]
|
exposes [line, write]
|
||||||
imports [Effect, Task.{ Task }, InternalTask]
|
imports [Effect, Task.{ Task }, InternalTask]
|
||||||
|
|
||||||
line : Str -> Task {} * [Write [Stdout]*]*
|
line : Str -> Task {} * [Write [Stdout]*]*
|
||||||
line = \str ->
|
line = \str ->
|
||||||
Effect.map (Effect.stdoutLine str) (\_ -> Ok {})
|
Effect.stdoutLine str
|
||||||
|
|> Effect.map (\_ -> Ok {})
|
||||||
|
|> InternalTask.fromEffect
|
||||||
|
|
||||||
|
write : Str -> Task {} * [Write [Stdout]*]*
|
||||||
|
write = \str ->
|
||||||
|
Effect.stdoutWrite str
|
||||||
|
|> Effect.map (\_ -> Ok {})
|
||||||
|> InternalTask.fromEffect
|
|> InternalTask.fromEffect
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
interface Task
|
interface Task
|
||||||
exposes [Task, succeed, fail, await, map, mapFail, onFail, attempt, forever, loop]
|
exposes [Task, succeed, fail, await, map, mapFail, onFail, attempt, forever, loop, fromResult]
|
||||||
imports [Effect, InternalTask]
|
imports [Effect, InternalTask]
|
||||||
|
|
||||||
Task ok err fx : InternalTask.Task ok err fx
|
Task ok err fx : InternalTask.Task ok err fx
|
||||||
|
@ -93,3 +93,10 @@ mapFail = \task, transform ->
|
||||||
Err err -> Task.fail (transform err) |> InternalTask.toEffect
|
Err err -> Task.fail (transform err) |> InternalTask.toEffect
|
||||||
|
|
||||||
InternalTask.fromEffect effect
|
InternalTask.fromEffect effect
|
||||||
|
|
||||||
|
## Use a Result among other Tasks by converting it into a Task.
|
||||||
|
fromResult : Result ok err -> Task ok err *
|
||||||
|
fromResult = \result ->
|
||||||
|
when result is
|
||||||
|
Ok ok -> succeed ok
|
||||||
|
Err err -> fail err
|
||||||
|
|
|
@ -12,6 +12,7 @@ use roc_std::{RocDict, RocList, RocResult, RocStr};
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::ffi::{CStr, OsStr};
|
use std::ffi::{CStr, OsStr};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
use std::io::{self, Write};
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
@ -63,13 +64,110 @@ pub unsafe extern "C" fn roc_panic(c_ptr: *mut c_void, tag_id: u32) {
|
||||||
0 => {
|
0 => {
|
||||||
let slice = CStr::from_ptr(c_ptr as *const c_char);
|
let slice = CStr::from_ptr(c_ptr as *const c_char);
|
||||||
let string = slice.to_str().unwrap();
|
let string = slice.to_str().unwrap();
|
||||||
eprintln!("Roc hit a panic: {}", string);
|
eprintln!("Roc crashed with:\n\n\t{}\n", string);
|
||||||
|
|
||||||
|
print_backtrace();
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_backtrace() {
|
||||||
|
eprintln!("Here is the call stack that led to the crash:\n");
|
||||||
|
|
||||||
|
let mut entries = Vec::new();
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct Entry {
|
||||||
|
pub fn_name: String,
|
||||||
|
pub filename: Option<String>,
|
||||||
|
pub line: Option<u32>,
|
||||||
|
pub col: Option<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
backtrace::trace(|frame| {
|
||||||
|
backtrace::resolve_frame(frame, |symbol| {
|
||||||
|
if let Some(fn_name) = symbol.name() {
|
||||||
|
let fn_name = fn_name.to_string();
|
||||||
|
|
||||||
|
if should_show_in_backtrace(&fn_name) {
|
||||||
|
let mut entry: Entry = Default::default();
|
||||||
|
|
||||||
|
entry.fn_name = format_fn_name(&fn_name);
|
||||||
|
|
||||||
|
if let Some(path) = symbol.filename() {
|
||||||
|
entry.filename = Some(path.to_string_lossy().into_owned());
|
||||||
|
};
|
||||||
|
|
||||||
|
entry.line = symbol.lineno();
|
||||||
|
entry.col = symbol.colno();
|
||||||
|
|
||||||
|
entries.push(entry);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
entries.push(Entry {
|
||||||
|
fn_name: "???".to_string(),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
true // keep going to the next frame
|
||||||
|
});
|
||||||
|
|
||||||
|
for entry in entries {
|
||||||
|
eprintln!("\t{}", entry.fn_name);
|
||||||
|
|
||||||
|
if let Some(filename) = entry.filename {
|
||||||
|
eprintln!("\t\t{filename}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eprintln!("\nOptimizations can make this list inaccurate! If it looks wrong, try running without `--optimize` and with `--linker=legacy`\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn should_show_in_backtrace(fn_name: &str) -> bool {
|
||||||
|
let is_from_rust = fn_name.contains("::");
|
||||||
|
let is_host_fn = fn_name.starts_with("roc_panic")
|
||||||
|
|| fn_name.starts_with("_Effect_effect")
|
||||||
|
|| fn_name.starts_with("_roc__")
|
||||||
|
|| fn_name.starts_with("rust_main")
|
||||||
|
|| fn_name == "_main";
|
||||||
|
|
||||||
|
!is_from_rust && !is_host_fn
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_fn_name(fn_name: &str) -> String {
|
||||||
|
// e.g. convert "_Num_sub_a0c29024d3ec6e3a16e414af99885fbb44fa6182331a70ab4ca0886f93bad5"
|
||||||
|
// to ["Num", "sub", "a0c29024d3ec6e3a16e414af99885fbb44fa6182331a70ab4ca0886f93bad5"]
|
||||||
|
let mut pieces_iter = fn_name.split("_");
|
||||||
|
|
||||||
|
if let (_, Some(module_name), Some(name)) =
|
||||||
|
(pieces_iter.next(), pieces_iter.next(), pieces_iter.next())
|
||||||
|
{
|
||||||
|
display_roc_fn(module_name, name)
|
||||||
|
} else {
|
||||||
|
"???".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn display_roc_fn(module_name: &str, fn_name: &str) -> String {
|
||||||
|
let module_name = if module_name == "#UserApp" {
|
||||||
|
"app"
|
||||||
|
} else {
|
||||||
|
module_name
|
||||||
|
};
|
||||||
|
|
||||||
|
let fn_name = if fn_name.parse::<u64>().is_ok() {
|
||||||
|
"(anonymous function)"
|
||||||
|
} else {
|
||||||
|
fn_name
|
||||||
|
};
|
||||||
|
|
||||||
|
format!("\u{001B}[36m{module_name}\u{001B}[39m.{fn_name}")
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn roc_memcpy(dst: *mut c_void, src: *mut c_void, n: usize) -> *mut c_void {
|
pub unsafe extern "C" fn roc_memcpy(dst: *mut c_void, src: *mut c_void, n: usize) -> *mut c_void {
|
||||||
libc::memcpy(dst, src, n)
|
libc::memcpy(dst, src, n)
|
||||||
|
@ -179,12 +277,26 @@ pub extern "C" fn roc_fx_stdoutLine(line: &RocStr) {
|
||||||
println!("{}", string);
|
println!("{}", string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn roc_fx_stdoutWrite(text: &RocStr) {
|
||||||
|
let string = text.as_str();
|
||||||
|
print!("{}", string);
|
||||||
|
io::stdout().flush().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn roc_fx_stderrLine(line: &RocStr) {
|
pub extern "C" fn roc_fx_stderrLine(line: &RocStr) {
|
||||||
let string = line.as_str();
|
let string = line.as_str();
|
||||||
eprintln!("{}", string);
|
eprintln!("{}", string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn roc_fx_stderrWrite(text: &RocStr) {
|
||||||
|
let string = text.as_str();
|
||||||
|
eprint!("{}", string);
|
||||||
|
io::stderr().flush().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
// #[no_mangle]
|
// #[no_mangle]
|
||||||
// pub extern "C" fn roc_fx_fileWriteUtf8(
|
// pub extern "C" fn roc_fx_fileWriteUtf8(
|
||||||
// roc_path: &RocList<u8>,
|
// roc_path: &RocList<u8>,
|
||||||
|
|
1
examples/swiftui/.gitignore
vendored
Normal file
1
examples/swiftui/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
swiftui
|
|
@ -12,9 +12,9 @@ If you have a specific question, the [FAQ](../FAQ.md) might have an answer, alth
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
- [Linux x86](linux_x86.md)
|
- [Linux x86_64](linux_x86_64.md)
|
||||||
- [MacOS Apple Silicon](macos_apple_silicon.md)
|
- [MacOS Apple Silicon](macos_apple_silicon.md)
|
||||||
- [MacOS x86](macos_x86.md)
|
- [MacOS x86_64](macos_x86_64.md)
|
||||||
- [Windows](windows.md)
|
- [Windows](windows.md)
|
||||||
- [Other](other.md)
|
- [Other](other.md)
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Roc installation guide for x86 Linux systems
|
# Roc installation guide for x86_64 Linux systems
|
||||||
|
|
||||||
## How to install Roc
|
## How to install Roc
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Roc installation guide for x86 macOS systems
|
# Roc installation guide for x86_64 macOS systems
|
||||||
|
|
||||||
## How to install Roc
|
## How to install Roc
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue