mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-20 15:27:45 +03:00
Merge branch 'trunk' into gen-dev/quicksort
This commit is contained in:
commit
865e789966
63
Cargo.lock
generated
63
Cargo.lock
generated
@ -2105,6 +2105,22 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mach_object"
|
||||
version = "0.1.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b6f2d7176b94027af58085a2c9d27c4e416586caba409c314569213901d6068"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"byteorder",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"log",
|
||||
"thiserror",
|
||||
"time 0.3.11",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "malloc_buf"
|
||||
version = "0.0.6"
|
||||
@ -2460,6 +2476,15 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_threads"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc"
|
||||
version = "0.2.7"
|
||||
@ -2499,6 +2524,18 @@ dependencies = [
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.26.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"flate2",
|
||||
"indexmap",
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.28.4"
|
||||
@ -3733,10 +3770,12 @@ dependencies = [
|
||||
"bumpalo",
|
||||
"clap 3.2.8",
|
||||
"iced-x86",
|
||||
"mach_object",
|
||||
"memmap2 0.5.4",
|
||||
"object 0.29.0",
|
||||
"object 0.26.2",
|
||||
"roc_build",
|
||||
"roc_collections",
|
||||
"roc_error_macros",
|
||||
"roc_mono",
|
||||
"serde",
|
||||
"target-lexicon",
|
||||
@ -4852,11 +4891,23 @@ dependencies = [
|
||||
"libc",
|
||||
"standback",
|
||||
"stdweb 0.4.20",
|
||||
"time-macros",
|
||||
"time-macros 0.1.1",
|
||||
"version_check",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72c91f41dcb2f096c05f0873d667dceec1087ce5bcf984ec8ffb19acddbb3217"
|
||||
dependencies = [
|
||||
"itoa 1.0.2",
|
||||
"libc",
|
||||
"num_threads",
|
||||
"time-macros 0.2.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.1.1"
|
||||
@ -4867,6 +4918,12 @@ dependencies = [
|
||||
"time-macros-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros-impl"
|
||||
version = "0.1.2"
|
||||
@ -5478,7 +5535,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22dc83aadbdf97388de3211cb6f105374f245a3cf2a5c65a16776e7a087a8468"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"time",
|
||||
"time 0.2.27",
|
||||
"wasmer-types",
|
||||
]
|
||||
|
||||
|
@ -287,13 +287,7 @@ pub fn build_file<'a>(
|
||||
let link_start = SystemTime::now();
|
||||
let problems = match (linking_strategy, link_type) {
|
||||
(LinkingStrategy::Surgical, _) => {
|
||||
roc_linker::link_preprocessed_host(target, &host_input_path, app_o_file, &binary_path)
|
||||
.map_err(|err| {
|
||||
todo!(
|
||||
"gracefully handle failing to surgically link with error: {:?}",
|
||||
err
|
||||
);
|
||||
})?;
|
||||
roc_linker::link_preprocessed_host(target, &host_input_path, app_o_file, &binary_path);
|
||||
problems
|
||||
}
|
||||
(LinkingStrategy::Additive, _) | (LinkingStrategy::Legacy, LinkType::None) => {
|
||||
@ -399,8 +393,7 @@ fn spawn_rebuild_thread(
|
||||
exported_symbols,
|
||||
exported_closure_types,
|
||||
target_valgrind,
|
||||
)
|
||||
.unwrap();
|
||||
);
|
||||
}
|
||||
LinkingStrategy::Legacy => {
|
||||
rebuild_host(
|
||||
|
@ -488,7 +488,7 @@ pub fn build(
|
||||
|
||||
let linking_strategy = if wasm_dev_backend {
|
||||
LinkingStrategy::Additive
|
||||
} else if !roc_linker::supported(&link_type, &triple)
|
||||
} else if !roc_linker::supported(link_type, &triple)
|
||||
|| matches.value_of(FLAG_LINKER) == Some("legacy")
|
||||
{
|
||||
LinkingStrategy::Legacy
|
||||
|
@ -34,11 +34,11 @@ interface Dict
|
||||
##
|
||||
## populationByCity =
|
||||
## Dict.empty
|
||||
## |> Dict.insert "London" 8_961_989
|
||||
## |> Dict.insert "Philadelphia" 1_603_797
|
||||
## |> Dict.insert "Shanghai" 24_870_895
|
||||
## |> Dict.insert "Delhi" 16_787_941
|
||||
## |> Dict.insert "Amsterdam" 872_680
|
||||
## |> Dict.insert "London" 8_961_989
|
||||
## |> Dict.insert "Philadelphia" 1_603_797
|
||||
## |> Dict.insert "Shanghai" 24_870_895
|
||||
## |> Dict.insert "Delhi" 16_787_941
|
||||
## |> Dict.insert "Amsterdam" 872_680
|
||||
##
|
||||
## ### Accessing keys or values
|
||||
##
|
||||
@ -100,8 +100,8 @@ insert = \@Dict list, k, v ->
|
||||
|
||||
Ok index ->
|
||||
list
|
||||
|> List.set index (Pair k v)
|
||||
|> @Dict
|
||||
|> List.set index (Pair k v)
|
||||
|> @Dict
|
||||
|
||||
len : Dict k v -> Nat
|
||||
len = \@Dict list ->
|
||||
@ -117,9 +117,9 @@ remove = \@Dict list, key ->
|
||||
lastIndex = List.len list - 1
|
||||
|
||||
list
|
||||
|> List.swap index lastIndex
|
||||
|> List.dropLast
|
||||
|> @Dict
|
||||
|> List.swap index lastIndex
|
||||
|> List.dropLast
|
||||
|> @Dict
|
||||
|
||||
contains : Dict k v, k -> Bool
|
||||
contains = \@Dict list, needle ->
|
||||
@ -156,7 +156,7 @@ insertAll = \xs, @Dict ys ->
|
||||
keepShared : Dict k v, Dict k v -> Dict k v
|
||||
keepShared = \@Dict xs, ys ->
|
||||
List.keepIf xs (\Pair k _ -> Dict.contains ys k)
|
||||
|> @Dict
|
||||
|> @Dict
|
||||
|
||||
# difference : Dict k v, Dict k v -> Dict k v
|
||||
removeAll : Dict k v, Dict k v -> Dict k v
|
||||
@ -169,8 +169,8 @@ removeAll = \xs, @Dict ys ->
|
||||
insertFresh : Dict k v, k, v -> Dict k v
|
||||
insertFresh = \@Dict list, k, v ->
|
||||
list
|
||||
|> List.append (Pair k v)
|
||||
|> @Dict
|
||||
|> List.append (Pair k v)
|
||||
|> @Dict
|
||||
|
||||
insertIfVacant : Dict k v, k, v -> Dict k v
|
||||
insertIfVacant = \dict, key, value ->
|
||||
|
@ -75,8 +75,8 @@ bool = \b -> custom \bytes, @Json {} ->
|
||||
|
||||
string = \s -> custom \bytes, @Json {} ->
|
||||
List.append bytes (Num.toU8 '"')
|
||||
|> List.concat (Str.toUtf8 s)
|
||||
|> List.append (Num.toU8 '"')
|
||||
|> List.concat (Str.toUtf8 s)
|
||||
|> List.append (Num.toU8 '"')
|
||||
|
||||
list = \lst, encodeElem ->
|
||||
custom \bytes, @Json {} ->
|
||||
@ -90,10 +90,10 @@ record = \fields ->
|
||||
writeRecord = \{ buffer, fieldsLeft }, { key, value } ->
|
||||
bufferWithKeyValue =
|
||||
List.append buffer (Num.toU8 '"')
|
||||
|> List.concat (Str.toUtf8 key)
|
||||
|> List.append (Num.toU8 '"')
|
||||
|> List.append (Num.toU8 ':')
|
||||
|> appendWith value (@Json {})
|
||||
|> List.concat (Str.toUtf8 key)
|
||||
|> List.append (Num.toU8 '"')
|
||||
|> List.append (Num.toU8 ':')
|
||||
|> appendWith value (@Json {})
|
||||
|
||||
bufferWithSuffix =
|
||||
if fieldsLeft > 0 then
|
||||
@ -123,13 +123,13 @@ tag = \name, payload ->
|
||||
|
||||
bytesHead =
|
||||
List.append bytes (Num.toU8 '{')
|
||||
|> List.append (Num.toU8 '"')
|
||||
|> List.concat (Str.toUtf8 name)
|
||||
|> List.append (Num.toU8 '"')
|
||||
|> List.append (Num.toU8 ':')
|
||||
|> List.append (Num.toU8 '[')
|
||||
|> List.append (Num.toU8 '"')
|
||||
|> List.concat (Str.toUtf8 name)
|
||||
|> List.append (Num.toU8 '"')
|
||||
|> List.append (Num.toU8 ':')
|
||||
|> List.append (Num.toU8 '[')
|
||||
|
||||
{ buffer: bytesWithPayload } = List.walk payload { buffer: bytesHead, itemsLeft: List.len payload } writePayload
|
||||
|
||||
List.append bytesWithPayload (Num.toU8 ']')
|
||||
|> List.append (Num.toU8 '}')
|
||||
|> List.append (Num.toU8 '}')
|
||||
|
@ -246,8 +246,8 @@ set = \list, index, value ->
|
||||
append : List a, a -> List a
|
||||
append = \list, element ->
|
||||
list
|
||||
|> List.reserve 1
|
||||
|> List.appendUnsafe element
|
||||
|> List.reserve 1
|
||||
|> List.appendUnsafe element
|
||||
|
||||
## Writes the element after the current last element unconditionally.
|
||||
## In other words, it is assumed that
|
||||
@ -837,8 +837,8 @@ intersperse = \list, sep ->
|
||||
newList =
|
||||
List.walk list init \acc, elem ->
|
||||
acc
|
||||
|> List.appendUnsafe elem
|
||||
|> List.appendUnsafe sep
|
||||
|> List.appendUnsafe elem
|
||||
|> List.appendUnsafe sep
|
||||
|
||||
List.dropLast newList
|
||||
|
||||
|
@ -38,8 +38,8 @@ single = \key ->
|
||||
insert : Set k, k -> Set k
|
||||
insert = \@Set dict, key ->
|
||||
dict
|
||||
|> Dict.insert key {}
|
||||
|> @Set
|
||||
|> Dict.insert key {}
|
||||
|> @Set
|
||||
|
||||
len : Set k -> Nat
|
||||
len = \@Set dict ->
|
||||
@ -53,8 +53,8 @@ remove = \@Set dict, key ->
|
||||
contains : Set k, k -> Bool
|
||||
contains = \set, key ->
|
||||
set
|
||||
|> Set.toDict
|
||||
|> Dict.contains key
|
||||
|> Set.toDict
|
||||
|> Dict.contains key
|
||||
|
||||
toList : Set k -> List k
|
||||
toList = \@Set dict ->
|
||||
|
@ -322,6 +322,7 @@ pub fn fmt_body<'a, 'buf>(
|
||||
) {
|
||||
pattern.format_with_options(buf, Parens::InApply, Newlines::No, indent);
|
||||
buf.push_str(" =");
|
||||
|
||||
if body.is_multiline() {
|
||||
match body {
|
||||
Expr::SpaceBefore(sub_def, spaces) => {
|
||||
@ -345,6 +346,22 @@ pub fn fmt_body<'a, 'buf>(
|
||||
);
|
||||
}
|
||||
}
|
||||
Expr::BinOps(_, _) => {
|
||||
// Binop chains always get a newline. Otherwise you can have things like:
|
||||
//
|
||||
// something = foo
|
||||
// |> bar baz
|
||||
//
|
||||
// By always inserting a newline, this becomes:
|
||||
//
|
||||
// something =
|
||||
// foo
|
||||
// |> bar baz
|
||||
//
|
||||
// This makes it clear what the binop is applying to!
|
||||
buf.newline();
|
||||
body.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent + INDENT);
|
||||
}
|
||||
_ => {
|
||||
buf.spaces(1);
|
||||
body.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent);
|
||||
|
@ -532,17 +532,14 @@ fn fmt_binops<'a, 'buf>(
|
||||
|| (&loc_right_side.value).is_multiline()
|
||||
|| lefts.iter().any(|(expr, _)| expr.value.is_multiline());
|
||||
|
||||
let mut curr_indent = indent;
|
||||
|
||||
for (loc_left_side, loc_binop) in lefts {
|
||||
let binop = loc_binop.value;
|
||||
|
||||
loc_left_side.format_with_options(buf, apply_needs_parens, Newlines::No, curr_indent);
|
||||
loc_left_side.format_with_options(buf, apply_needs_parens, Newlines::No, indent);
|
||||
|
||||
if is_multiline {
|
||||
buf.ensure_ends_with_newline();
|
||||
curr_indent = indent + INDENT;
|
||||
buf.indent(curr_indent);
|
||||
buf.indent(indent);
|
||||
} else {
|
||||
buf.spaces(1);
|
||||
}
|
||||
@ -552,13 +549,7 @@ fn fmt_binops<'a, 'buf>(
|
||||
buf.spaces(1);
|
||||
}
|
||||
|
||||
let next_indent = if is_multiline {
|
||||
indent + INDENT
|
||||
} else {
|
||||
indent
|
||||
};
|
||||
|
||||
loc_right_side.format_with_options(buf, apply_needs_parens, Newlines::Yes, next_indent);
|
||||
loc_right_side.format_with_options(buf, apply_needs_parens, Newlines::Yes, indent);
|
||||
}
|
||||
|
||||
fn format_spaces<'a, 'buf>(
|
||||
@ -760,10 +751,7 @@ fn fmt_when<'a, 'buf>(
|
||||
} else {
|
||||
if is_multiline_patterns {
|
||||
buf.ensure_ends_with_newline();
|
||||
// Indent an extra level for the `|`;
|
||||
// otherwise it'll be at the start of the line,
|
||||
// and will be incorrectly parsed as a pattern
|
||||
buf.indent(indent + INDENT + INDENT);
|
||||
buf.indent(indent + INDENT);
|
||||
buf.push('|');
|
||||
} else {
|
||||
buf.push_str(" |");
|
||||
|
@ -3108,7 +3108,7 @@ mod test_fmt {
|
||||
r#"
|
||||
if
|
||||
1
|
||||
== 2
|
||||
== 2
|
||||
then
|
||||
"yes"
|
||||
else
|
||||
@ -3385,8 +3385,7 @@ mod test_fmt {
|
||||
r#"
|
||||
when b is
|
||||
# look at cases
|
||||
1 ->
|
||||
# when 1
|
||||
1 -> # when 1
|
||||
1
|
||||
|
||||
# important
|
||||
@ -3406,7 +3405,7 @@ mod test_fmt {
|
||||
r#"
|
||||
when 0 is
|
||||
1 # comment
|
||||
| 2 -> "a"
|
||||
| 2 -> "a"
|
||||
|
||||
_ -> "b"
|
||||
"#
|
||||
@ -3506,21 +3505,21 @@ mod test_fmt {
|
||||
r#"
|
||||
when b is
|
||||
1
|
||||
| 2
|
||||
| 3 ->
|
||||
| 2
|
||||
| 3 ->
|
||||
4
|
||||
|
||||
5 | 6 | 7 ->
|
||||
8
|
||||
|
||||
9
|
||||
| 10 -> 11
|
||||
| 10 -> 11
|
||||
|
||||
12 | 13 ->
|
||||
when c is
|
||||
14 | 15 -> 16
|
||||
17
|
||||
| 18 -> 19
|
||||
| 18 -> 19
|
||||
|
||||
20 -> 21
|
||||
"#
|
||||
@ -3543,7 +3542,7 @@ mod test_fmt {
|
||||
when b is
|
||||
3 -> 4
|
||||
9
|
||||
| 8 -> 9
|
||||
| 8 -> 9
|
||||
"#
|
||||
),
|
||||
);
|
||||
@ -3607,7 +3606,7 @@ mod test_fmt {
|
||||
|
||||
when
|
||||
1
|
||||
+ 1
|
||||
+ 1
|
||||
is
|
||||
2 ->
|
||||
x
|
||||
@ -3644,7 +3643,7 @@ mod test_fmt {
|
||||
|
||||
when
|
||||
2
|
||||
+ 2
|
||||
+ 2
|
||||
is
|
||||
4 ->
|
||||
x
|
||||
@ -3656,6 +3655,31 @@ mod test_fmt {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multi_line_when_branch() {
|
||||
expr_formats_to(
|
||||
indoc!(
|
||||
r#"
|
||||
when x is
|
||||
Foo -> bar
|
||||
"arg1" "arg2"
|
||||
Bar -> 2
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
when x is
|
||||
Foo ->
|
||||
bar
|
||||
"arg1"
|
||||
"arg2"
|
||||
|
||||
Bar -> 2
|
||||
"#
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn single_line_when_patterns() {
|
||||
expr_formats_same(indoc!(
|
||||
@ -3874,8 +3898,8 @@ mod test_fmt {
|
||||
r#"
|
||||
if
|
||||
True
|
||||
== False
|
||||
== True
|
||||
== False
|
||||
== True
|
||||
then
|
||||
False
|
||||
else
|
||||
@ -3901,8 +3925,8 @@ mod test_fmt {
|
||||
r#"
|
||||
if
|
||||
False
|
||||
== False
|
||||
== False
|
||||
== False
|
||||
== False
|
||||
then
|
||||
"true"
|
||||
else
|
||||
@ -3960,8 +3984,8 @@ mod test_fmt {
|
||||
r#"
|
||||
if
|
||||
(1 == 1)
|
||||
&& (2 == 1)
|
||||
&& (3 == 2)
|
||||
&& (2 == 1)
|
||||
&& (3 == 2)
|
||||
then
|
||||
"true"
|
||||
else
|
||||
@ -3973,8 +3997,9 @@ mod test_fmt {
|
||||
|
||||
#[test]
|
||||
fn multiline_binop_with_comments() {
|
||||
expr_formats_same(indoc!(
|
||||
r#"
|
||||
expr_formats_to(
|
||||
indoc!(
|
||||
r#"
|
||||
x = 1
|
||||
+ 1 # comment 1
|
||||
- 1 # comment 2
|
||||
@ -3982,39 +4007,87 @@ mod test_fmt {
|
||||
|
||||
x
|
||||
"#
|
||||
));
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
x =
|
||||
1
|
||||
+ 1 # comment 1
|
||||
- 1 # comment 2
|
||||
* 1 # comment 3
|
||||
|
||||
expr_formats_same(indoc!(
|
||||
r#"
|
||||
x
|
||||
"#
|
||||
),
|
||||
);
|
||||
|
||||
expr_formats_to(
|
||||
indoc!(
|
||||
r#"
|
||||
x = 1
|
||||
+ 1 # comment 1
|
||||
* 1 # comment 2
|
||||
|
||||
x
|
||||
"#
|
||||
));
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
x =
|
||||
1
|
||||
+ 1 # comment 1
|
||||
* 1 # comment 2
|
||||
|
||||
expr_formats_same(indoc!(
|
||||
r#"
|
||||
x
|
||||
"#
|
||||
),
|
||||
);
|
||||
|
||||
expr_formats_to(
|
||||
indoc!(
|
||||
r#"
|
||||
x = 1
|
||||
+ 1 # comment
|
||||
|
||||
x
|
||||
"#
|
||||
));
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
x =
|
||||
1
|
||||
+ 1 # comment
|
||||
|
||||
expr_formats_same(indoc!(
|
||||
r#"
|
||||
x
|
||||
"#
|
||||
),
|
||||
);
|
||||
|
||||
expr_formats_to(
|
||||
indoc!(
|
||||
r#"
|
||||
x = 1
|
||||
* 1
|
||||
+ 1 # comment
|
||||
|
||||
x
|
||||
"#
|
||||
));
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
x =
|
||||
1
|
||||
* 1
|
||||
+ 1 # comment
|
||||
|
||||
expr_formats_same(indoc!(
|
||||
r#"
|
||||
x
|
||||
"#
|
||||
),
|
||||
);
|
||||
|
||||
expr_formats_to(
|
||||
indoc!(
|
||||
r#"
|
||||
x = 1
|
||||
- 1
|
||||
* 1
|
||||
@ -4022,7 +4095,19 @@ mod test_fmt {
|
||||
|
||||
x
|
||||
"#
|
||||
));
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
x =
|
||||
1
|
||||
- 1
|
||||
* 1
|
||||
+ 1
|
||||
|
||||
x
|
||||
"#
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -4031,12 +4116,12 @@ mod test_fmt {
|
||||
r#"
|
||||
if
|
||||
x
|
||||
+ 1 # comment 1
|
||||
> 0 # comment 2
|
||||
+ 1 # comment 1
|
||||
> 0 # comment 2
|
||||
then
|
||||
y
|
||||
* 2 # comment 3
|
||||
< 1 # comment 4
|
||||
* 2 # comment 3
|
||||
< 1 # comment 4
|
||||
else
|
||||
42
|
||||
"#
|
||||
@ -4045,35 +4130,66 @@ mod test_fmt {
|
||||
|
||||
#[test]
|
||||
fn multiline_binop_when_with_comments() {
|
||||
expr_formats_same(indoc!(
|
||||
r#"
|
||||
expr_formats_to(
|
||||
indoc!(
|
||||
r#"
|
||||
when
|
||||
x
|
||||
+ 1 # comment 1
|
||||
> 0 # comment 2
|
||||
+ 1 # comment 1
|
||||
> 0 # comment 2
|
||||
is
|
||||
y ->
|
||||
3
|
||||
* 2 # comment 3
|
||||
< 1 # comment 4
|
||||
* 2 # comment 3
|
||||
< 1 # comment 4
|
||||
|
||||
z ->
|
||||
4
|
||||
/ 5 # comment 5
|
||||
< 1 # comment 6
|
||||
/ 5 # comment 5
|
||||
< 1 # comment 6
|
||||
|
||||
46 # first pattern comment
|
||||
| 95 # alternative comment 1
|
||||
| 126 # alternative comment 2
|
||||
| 150 -> # This comment goes after the ->
|
||||
| 95 # alternative comment 1
|
||||
| 126 # alternative comment 2
|
||||
| 150 -> # This comment came after the ->
|
||||
# This comment is for the expr
|
||||
foo bar
|
||||
|> Result.withDefault "" # one last comment
|
||||
foo bar
|
||||
|> Result.withDefault "" # one last comment
|
||||
|
||||
_ ->
|
||||
42
|
||||
"#
|
||||
));
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
when
|
||||
x
|
||||
+ 1 # comment 1
|
||||
> 0 # comment 2
|
||||
is
|
||||
y ->
|
||||
3
|
||||
* 2 # comment 3
|
||||
< 1 # comment 4
|
||||
|
||||
z ->
|
||||
4
|
||||
/ 5 # comment 5
|
||||
< 1 # comment 6
|
||||
|
||||
46 # first pattern comment
|
||||
| 95 # alternative comment 1
|
||||
| 126 # alternative comment 2
|
||||
| 150 -> # This comment came after the ->
|
||||
# This comment is for the expr
|
||||
foo bar
|
||||
|> Result.withDefault "" # one last comment
|
||||
|
||||
_ ->
|
||||
42
|
||||
"#
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -4167,22 +4283,33 @@ mod test_fmt {
|
||||
expr_formats_same(indoc!(
|
||||
r#"
|
||||
isLast
|
||||
&& isEmpty
|
||||
&& isLoaded
|
||||
&& isEmpty
|
||||
&& isLoaded
|
||||
"#
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multi_line_binary_op_2() {
|
||||
expr_formats_same(indoc!(
|
||||
r#"
|
||||
expr_formats_to(
|
||||
indoc!(
|
||||
r#"
|
||||
x = 1
|
||||
< 2
|
||||
|
||||
f x
|
||||
"#
|
||||
));
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
x =
|
||||
1
|
||||
< 2
|
||||
|
||||
f x
|
||||
"#
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -4199,9 +4326,9 @@ mod test_fmt {
|
||||
indoc!(
|
||||
r#"
|
||||
1
|
||||
* 2
|
||||
/ 3
|
||||
// 4
|
||||
* 2
|
||||
/ 3
|
||||
// 4
|
||||
"#
|
||||
),
|
||||
);
|
||||
@ -4220,9 +4347,9 @@ mod test_fmt {
|
||||
indoc!(
|
||||
r#"
|
||||
2
|
||||
% 3
|
||||
// 5
|
||||
+ 7
|
||||
% 3
|
||||
// 5
|
||||
+ 7
|
||||
"#
|
||||
),
|
||||
);
|
||||
@ -4240,8 +4367,8 @@ mod test_fmt {
|
||||
indoc!(
|
||||
r#"
|
||||
isGreenLight
|
||||
&& isRedLight
|
||||
&& isYellowLight
|
||||
&& isRedLight
|
||||
&& isYellowLight
|
||||
"#
|
||||
),
|
||||
);
|
||||
@ -4252,8 +4379,8 @@ mod test_fmt {
|
||||
expr_formats_same(indoc!(
|
||||
r#"
|
||||
output
|
||||
|> List.set (offset + 0) b
|
||||
|> List.set (offset + 1) a
|
||||
|> List.set (offset + 0) b
|
||||
|> List.set (offset + 1) a
|
||||
"#
|
||||
));
|
||||
}
|
||||
@ -4275,9 +4402,9 @@ mod test_fmt {
|
||||
expr_formats_same(indoc!(
|
||||
r#"
|
||||
shout
|
||||
|> List.map
|
||||
xs
|
||||
(\i -> i)
|
||||
|> List.map
|
||||
xs
|
||||
(\i -> i)
|
||||
"#
|
||||
));
|
||||
}
|
||||
@ -4287,10 +4414,10 @@ mod test_fmt {
|
||||
expr_formats_same(indoc!(
|
||||
r#"
|
||||
shout
|
||||
|> List.map
|
||||
xs
|
||||
(\i -> i)
|
||||
|> List.join
|
||||
|> List.map
|
||||
xs
|
||||
(\i -> i)
|
||||
|> List.join
|
||||
"#
|
||||
));
|
||||
}
|
||||
@ -4316,15 +4443,15 @@ mod test_fmt {
|
||||
r#"
|
||||
example = \model ->
|
||||
model
|
||||
|> withModel
|
||||
(\result ->
|
||||
when result is
|
||||
Err _ ->
|
||||
Err {}
|
||||
|> withModel
|
||||
(\result ->
|
||||
when result is
|
||||
Err _ ->
|
||||
Err {}
|
||||
|
||||
Ok val ->
|
||||
Ok {}
|
||||
)
|
||||
Ok val ->
|
||||
Ok {}
|
||||
)
|
||||
|
||||
example
|
||||
"#
|
||||
@ -4352,15 +4479,15 @@ mod test_fmt {
|
||||
r#"
|
||||
example = \model ->
|
||||
model
|
||||
|> withModel
|
||||
(\result ->
|
||||
when result is
|
||||
Err _ ->
|
||||
Err {}
|
||||
|> withModel
|
||||
(\result ->
|
||||
when result is
|
||||
Err _ ->
|
||||
Err {}
|
||||
|
||||
Ok val ->
|
||||
Ok {}
|
||||
)
|
||||
Ok val ->
|
||||
Ok {}
|
||||
)
|
||||
|
||||
example
|
||||
"#
|
||||
|
@ -5,8 +5,8 @@ quicksort = \list, low, high ->
|
||||
when partition low high list is
|
||||
Pair partitionIndex partitioned ->
|
||||
partitioned
|
||||
|> quicksort low (partitionIndex - 1)
|
||||
|> quicksort (partitionIndex + 1) high
|
||||
|> quicksort low (partitionIndex - 1)
|
||||
|> quicksort (partitionIndex + 1) high
|
||||
|
||||
|
||||
swap : Nat, Nat, List a -> List a
|
||||
@ -14,8 +14,8 @@ swap = \i, j, list ->
|
||||
when Pair (List.get list i) (List.get list j) is
|
||||
Pair (Ok atI) (Ok atJ) ->
|
||||
list
|
||||
|> List.set i atJ
|
||||
|> List.set j atI
|
||||
|> List.set i atJ
|
||||
|> List.set j atI
|
||||
|
||||
_ ->
|
||||
[]
|
||||
|
@ -7,8 +7,8 @@ quicksort = \originalList ->
|
||||
when partition low high list is
|
||||
Pair partitionIndex partitioned ->
|
||||
partitioned
|
||||
|> quicksortHelp low (partitionIndex - 1)
|
||||
|> quicksortHelp (partitionIndex + 1) high
|
||||
|> quicksortHelp low (partitionIndex - 1)
|
||||
|> quicksortHelp (partitionIndex + 1) high
|
||||
else
|
||||
list
|
||||
|
||||
@ -18,8 +18,8 @@ quicksort = \originalList ->
|
||||
when Pair (List.get list i) (List.get list j) is
|
||||
Pair (Ok atI) (Ok atJ) ->
|
||||
list
|
||||
|> List.set i atJ
|
||||
|> List.set j atI
|
||||
|> List.set i atJ
|
||||
|> List.set j atI
|
||||
|
||||
_ ->
|
||||
[]
|
||||
|
@ -2085,7 +2085,7 @@ mod when {
|
||||
}
|
||||
}
|
||||
|
||||
/// Parsing alternative patterns in when branches.
|
||||
/// Parsing alternative patterns in `when` branches.
|
||||
fn branch_alternatives<'a>(
|
||||
min_indent: u32,
|
||||
options: ExprParseOptions,
|
||||
@ -2180,7 +2180,7 @@ mod when {
|
||||
|
||||
let parser = sep_by1(
|
||||
word1(b'|', EWhen::Bar),
|
||||
branch_single_alternative(pattern_indent + 1),
|
||||
branch_single_alternative(pattern_indent),
|
||||
);
|
||||
|
||||
match parser.parse(arena, state) {
|
||||
|
@ -40,9 +40,37 @@ When(
|
||||
],
|
||||
),
|
||||
@43-48 SpaceBefore(
|
||||
SpaceAfter(
|
||||
StrLiteral(
|
||||
PlainLine(
|
||||
"bar",
|
||||
),
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
@51-56 StrLiteral(
|
||||
PlainLine(
|
||||
"baz",
|
||||
),
|
||||
),
|
||||
],
|
||||
value: @60-61 Num(
|
||||
"2",
|
||||
),
|
||||
guard: None,
|
||||
},
|
||||
WhenBranch {
|
||||
patterns: [
|
||||
@63-70 SpaceBefore(
|
||||
StrLiteral(
|
||||
PlainLine(
|
||||
"bar",
|
||||
"stuff",
|
||||
),
|
||||
),
|
||||
[
|
||||
@ -50,8 +78,8 @@ When(
|
||||
],
|
||||
),
|
||||
],
|
||||
value: @52-53 Num(
|
||||
"2",
|
||||
value: @74-75 Num(
|
||||
"4",
|
||||
),
|
||||
guard: None,
|
||||
},
|
||||
|
@ -1,4 +1,6 @@
|
||||
when x is
|
||||
"blah" | "blop" -> 1
|
||||
"foo" |
|
||||
"bar" -> 2
|
||||
"bar"
|
||||
|"baz" -> 2
|
||||
"stuff" -> 4
|
||||
|
@ -25,8 +25,8 @@ const ROC_LIST_MAP: &str = indoc::indoc!(
|
||||
r#"
|
||||
app "bench" provides [main] to "./platform"
|
||||
|
||||
main : List I64 -> Nat
|
||||
main = \list ->
|
||||
main : List I64 -> Nat
|
||||
main = \list ->
|
||||
list
|
||||
|> List.map (\x -> x + 2)
|
||||
|> List.len
|
||||
@ -37,11 +37,11 @@ const ROC_LIST_MAP_WITH_INDEX: &str = indoc::indoc!(
|
||||
r#"
|
||||
app "bench" provides [main] to "./platform"
|
||||
|
||||
main : List I64 -> Nat
|
||||
main = \list ->
|
||||
main : List I64 -> Nat
|
||||
main = \list ->
|
||||
list
|
||||
|> List.mapWithIndex (\x, _ -> x + 2)
|
||||
|> List.len
|
||||
|> List.mapWithIndex (\x, _ -> x + 2)
|
||||
|> List.len
|
||||
"#
|
||||
);
|
||||
|
||||
|
@ -572,8 +572,8 @@ fn quicksort_help() {
|
||||
(Pair partitionIndex partitioned) = Pair 0 []
|
||||
|
||||
partitioned
|
||||
|> quicksortHelp low (partitionIndex - 1)
|
||||
|> quicksortHelp (partitionIndex + 1) high
|
||||
|> quicksortHelp low (partitionIndex - 1)
|
||||
|> quicksortHelp (partitionIndex + 1) high
|
||||
else
|
||||
list
|
||||
|
||||
@ -591,8 +591,8 @@ fn quicksort_swap() {
|
||||
when Pair (List.get list 0) (List.get list 0) is
|
||||
Pair (Ok atI) (Ok atJ) ->
|
||||
list
|
||||
|> List.set 0 atJ
|
||||
|> List.set 0 atI
|
||||
|> List.set 0 atJ
|
||||
|> List.set 0 atI
|
||||
|
||||
_ ->
|
||||
[]
|
||||
|
@ -11,21 +11,17 @@ description = "A surgical linker for Roc"
|
||||
name = "roc_linker"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "link"
|
||||
path = "src/main.rs"
|
||||
test = false
|
||||
bench = false
|
||||
|
||||
[dependencies]
|
||||
roc_mono = { path = "../compiler/mono" }
|
||||
roc_build = { path = "../compiler/build" }
|
||||
roc_collections = { path = "../compiler/collections" }
|
||||
roc_error_macros = { path = "../error_macros" }
|
||||
bumpalo = { version = "3.8.0", features = ["collections"] }
|
||||
clap = { version = "3.1.15", default-features = false, features = ["std", "color", "suggestions"] }
|
||||
iced-x86 = { version = "1.15.0", default-features = false, features = ["std", "decoder", "op_code_info", "instr_info"] }
|
||||
memmap2 = "0.5.3"
|
||||
object = { version = "0.29.0", features = ["read", "write"] }
|
||||
object = { version = "0.26.2", features = ["read", "write"] }
|
||||
mach_object = "0.1"
|
||||
serde = { version = "1.0.130", features = ["derive"] }
|
||||
bincode = "1.3.3"
|
||||
target-lexicon = "0.12.3"
|
||||
|
@ -39,7 +39,7 @@ This linker is run in 2 phases: preprocessing and surigical linking.
|
||||
- As a prereq, we need roc building on Windows (I'm not sure it does currently).
|
||||
- Definitely a solid bit different than elf, but hopefully after refactoring for Macho, won't be that crazy to add.
|
||||
- Look at enabling completely in memory linking that could be used with `roc run` and/or `roc repl`
|
||||
- Look more into roc hosts and keeping certain functions. Currently I just disabled linker garbage collection.
|
||||
- Look more into rust hosts and keeping certain functions. Currently I just disabled linker garbage collection.
|
||||
This works but adds 1.2MB (40%) to even a tiny app. It may be a size issue for large rust hosts.
|
||||
Roc, for reference, adds 13MB (20%) when linked without garbage collection.
|
||||
- Add a feature to the compiler to make this linker optional.
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,14 +0,0 @@
|
||||
use roc_linker::{build_app, preprocess, surgery, CMD_PREPROCESS, CMD_SURGERY};
|
||||
use std::io;
|
||||
|
||||
fn main() -> io::Result<()> {
|
||||
let matches = build_app().get_matches();
|
||||
|
||||
let exit_code = match matches.subcommand() {
|
||||
None => Ok::<i32, io::Error>(-1),
|
||||
Some((CMD_PREPROCESS, sub_matches)) => preprocess(sub_matches),
|
||||
Some((CMD_SURGERY, sub_matches)) => surgery(sub_matches),
|
||||
_ => unreachable!(),
|
||||
}?;
|
||||
std::process::exit(exit_code);
|
||||
}
|
@ -34,4 +34,5 @@ pub struct Metadata {
|
||||
pub dynamic_symbol_table_section_offset: u64,
|
||||
pub symbol_table_section_offset: u64,
|
||||
pub symbol_table_size: u64,
|
||||
pub macho_cmd_loc: u64,
|
||||
}
|
||||
|
@ -14,8 +14,8 @@ quicksortHelp = \list, low, high ->
|
||||
when partition low high list is
|
||||
Pair partitionIndex partitioned ->
|
||||
partitioned
|
||||
|> quicksortHelp low (partitionIndex - 1)
|
||||
|> quicksortHelp (partitionIndex + 1) high
|
||||
|> quicksortHelp low (partitionIndex - 1)
|
||||
|> quicksortHelp (partitionIndex + 1) high
|
||||
else
|
||||
list
|
||||
|
||||
@ -50,8 +50,8 @@ swap = \i, j, list ->
|
||||
when Pair (List.get list i) (List.get list j) is
|
||||
Pair (Ok atI) (Ok atJ) ->
|
||||
list
|
||||
|> List.set i atJ
|
||||
|> List.set j atI
|
||||
|> List.set i atJ
|
||||
|> List.set j atI
|
||||
|
||||
_ ->
|
||||
# to prevent a decrement on list
|
||||
|
@ -23,17 +23,17 @@ initialModel = \start -> {
|
||||
cheapestOpen : (position -> F64), Model position -> Result position {}
|
||||
cheapestOpen = \costFn, model ->
|
||||
model.openSet
|
||||
|> Set.toList
|
||||
|> List.keepOks
|
||||
(\position ->
|
||||
when Dict.get model.costs position is
|
||||
Err _ -> Err {}
|
||||
Ok cost -> Ok { cost: cost + costFn position, position }
|
||||
)
|
||||
|> Quicksort.sortBy .cost
|
||||
|> List.first
|
||||
|> Result.map .position
|
||||
|> Result.mapErr (\_ -> {})
|
||||
|> Set.toList
|
||||
|> List.keepOks
|
||||
(\position ->
|
||||
when Dict.get model.costs position is
|
||||
Err _ -> Err {}
|
||||
Ok cost -> Ok { cost: cost + costFn position, position }
|
||||
)
|
||||
|> Quicksort.sortBy .cost
|
||||
|> List.first
|
||||
|> Result.map .position
|
||||
|> Result.mapErr (\_ -> {})
|
||||
|
||||
reconstructPath : Dict position position, position -> List position
|
||||
reconstructPath = \cameFrom, goal ->
|
||||
@ -51,8 +51,8 @@ updateCost = \current, neighbor, model ->
|
||||
|
||||
distanceTo =
|
||||
reconstructPath newCameFrom neighbor
|
||||
|> List.len
|
||||
|> Num.toFrac
|
||||
|> List.len
|
||||
|> Num.toFrac
|
||||
|
||||
newModel =
|
||||
{ model &
|
||||
|
@ -63,23 +63,23 @@ bitsToCharsHelp = \bits, missing ->
|
||||
# any 6-bit number is a valid base64 digit, so this is actually safe
|
||||
p =
|
||||
Num.shiftRightZfBy 18 bits
|
||||
|> Num.intCast
|
||||
|> unsafeToChar
|
||||
|> Num.intCast
|
||||
|> unsafeToChar
|
||||
|
||||
q =
|
||||
Num.bitwiseAnd (Num.shiftRightZfBy 12 bits) lowest6BitsMask
|
||||
|> Num.intCast
|
||||
|> unsafeToChar
|
||||
|> Num.intCast
|
||||
|> unsafeToChar
|
||||
|
||||
r =
|
||||
Num.bitwiseAnd (Num.shiftRightZfBy 6 bits) lowest6BitsMask
|
||||
|> Num.intCast
|
||||
|> unsafeToChar
|
||||
|> Num.intCast
|
||||
|> unsafeToChar
|
||||
|
||||
s =
|
||||
Num.bitwiseAnd bits lowest6BitsMask
|
||||
|> Num.intCast
|
||||
|> unsafeToChar
|
||||
|> Num.intCast
|
||||
|> unsafeToChar
|
||||
|
||||
equals : U8
|
||||
equals = 61
|
||||
|
@ -8,15 +8,15 @@ InvalidChar : U8
|
||||
toBytes : Str -> List U8
|
||||
toBytes = \str ->
|
||||
str
|
||||
|> Str.toUtf8
|
||||
|> encodeChunks
|
||||
|> Bytes.Encode.sequence
|
||||
|> Bytes.Encode.encode
|
||||
|> Str.toUtf8
|
||||
|> encodeChunks
|
||||
|> Bytes.Encode.sequence
|
||||
|> Bytes.Encode.encode
|
||||
|
||||
encodeChunks : List U8 -> List Encoder
|
||||
encodeChunks = \bytes ->
|
||||
List.walk bytes { output: [], accum: None } folder
|
||||
|> encodeResidual
|
||||
|> encodeResidual
|
||||
|
||||
coerce : Nat, a -> a
|
||||
coerce = \_, x -> x
|
||||
|
@ -49,7 +49,7 @@ encode = \encoder ->
|
||||
output = List.repeat 0 (getWidth encoder)
|
||||
|
||||
encodeHelp encoder 0 output
|
||||
|> .output
|
||||
|> .output
|
||||
|
||||
encodeHelp : Encoder, Nat, List U8 -> { output : List U8, offset : Nat }
|
||||
encodeHelp = \encoder, offset, output ->
|
||||
@ -80,13 +80,13 @@ encodeHelp = \encoder, offset, output ->
|
||||
when endianness is
|
||||
BE ->
|
||||
output
|
||||
|> List.set (offset + 0) a
|
||||
|> List.set (offset + 1) b
|
||||
|> List.set (offset + 0) a
|
||||
|> List.set (offset + 1) b
|
||||
|
||||
LE ->
|
||||
output
|
||||
|> List.set (offset + 0) b
|
||||
|> List.set (offset + 1) a
|
||||
|> List.set (offset + 0) b
|
||||
|> List.set (offset + 1) a
|
||||
|
||||
{
|
||||
output: newOutput,
|
||||
@ -104,13 +104,13 @@ encodeHelp = \encoder, offset, output ->
|
||||
when endianness is
|
||||
BE ->
|
||||
output
|
||||
|> List.set (offset + 0) a
|
||||
|> List.set (offset + 1) b
|
||||
|> List.set (offset + 0) a
|
||||
|> List.set (offset + 1) b
|
||||
|
||||
LE ->
|
||||
output
|
||||
|> List.set (offset + 0) b
|
||||
|> List.set (offset + 1) a
|
||||
|> List.set (offset + 0) b
|
||||
|> List.set (offset + 1) a
|
||||
|
||||
{
|
||||
output: newOutput,
|
||||
|
@ -14,10 +14,10 @@ main =
|
||||
optimized = eval (constFolding (reassoc e))
|
||||
|
||||
unoptimized
|
||||
|> Num.toStr
|
||||
|> Str.concat " & "
|
||||
|> Str.concat (Num.toStr optimized)
|
||||
|> Task.putLine
|
||||
|> Num.toStr
|
||||
|> Str.concat " & "
|
||||
|> Str.concat (Num.toStr optimized)
|
||||
|> Task.putLine
|
||||
|
||||
Expr : [
|
||||
Add Expr Expr,
|
||||
|
@ -13,7 +13,7 @@ main = closure1 {}
|
||||
closure1 : {} -> Task.Task {} []
|
||||
closure1 = \_ ->
|
||||
Task.succeed (foo toUnitBorrowed "a long string such that it's malloced")
|
||||
|> Task.map (\_ -> {})
|
||||
|> Task.map \_ -> {}
|
||||
|
||||
toUnitBorrowed = \x -> Str.countGraphemes x
|
||||
|
||||
|
@ -18,7 +18,7 @@ main =
|
||||
f = pow x x
|
||||
|
||||
nest deriv n f # original koka n = 10
|
||||
|> Task.map (\_ -> {})
|
||||
|> Task.map \_ -> {}
|
||||
|
||||
nest : (I64, Expr -> IO Expr), I64, Expr -> IO Expr
|
||||
nest = \f, n, e -> Task.loop { s: n, f, m: n, x: e } nestHelp
|
||||
@ -160,8 +160,8 @@ deriv = \i, f ->
|
||||
fprime = d "x" f
|
||||
line =
|
||||
Num.toStr (i + 1)
|
||||
|> Str.concat " count: "
|
||||
|> Str.concat (Num.toStr (count fprime))
|
||||
|> Str.concat " count: "
|
||||
|> Str.concat (Num.toStr (count fprime))
|
||||
|
||||
Task.putLine line
|
||||
|> Task.after \_ -> Task.succeed fprime
|
||||
|> Task.after \_ -> Task.succeed fprime
|
||||
|
@ -9,8 +9,8 @@ main =
|
||||
Task.getInt
|
||||
\n ->
|
||||
queens n # original koka 13
|
||||
|> Num.toStr
|
||||
|> Task.putLine
|
||||
|> Num.toStr
|
||||
|> Task.putLine
|
||||
|
||||
ConsList a : [Nil, Cons a (ConsList a)]
|
||||
|
||||
|
@ -7,8 +7,8 @@ show = \list ->
|
||||
else
|
||||
content =
|
||||
list
|
||||
|> List.map Num.toStr
|
||||
|> Str.joinWith ", "
|
||||
|> List.map Num.toStr
|
||||
|> Str.joinWith ", "
|
||||
|
||||
"[\(content)]"
|
||||
|
||||
@ -30,8 +30,8 @@ quicksortHelp = \list, order, low, high ->
|
||||
when partition low high list order is
|
||||
Pair partitionIndex partitioned ->
|
||||
partitioned
|
||||
|> quicksortHelp order low (Num.subSaturated partitionIndex 1)
|
||||
|> quicksortHelp order (partitionIndex + 1) high
|
||||
|> quicksortHelp order low (Num.subSaturated partitionIndex 1)
|
||||
|> quicksortHelp order (partitionIndex + 1) high
|
||||
else
|
||||
list
|
||||
|
||||
@ -68,8 +68,8 @@ swap = \i, j, list ->
|
||||
when Pair (List.get list i) (List.get list j) is
|
||||
Pair (Ok atI) (Ok atJ) ->
|
||||
list
|
||||
|> List.set i atJ
|
||||
|> List.set j atI
|
||||
|> List.set i atJ
|
||||
|> List.set j atI
|
||||
|
||||
_ ->
|
||||
[]
|
||||
|
File diff suppressed because one or more lines are too long
@ -52,8 +52,8 @@ main =
|
||||
val = fold (\_, v, r -> if v then r + 1 else r) head 0
|
||||
|
||||
val
|
||||
|> Num.toStr
|
||||
|> Task.putLine
|
||||
|> Num.toStr
|
||||
|> Task.putLine
|
||||
|
||||
Nil ->
|
||||
Task.putLine "fail"
|
||||
|
@ -20,8 +20,8 @@ main =
|
||||
val = fold (\_, v, r -> if v then r + 1 else r) m 0
|
||||
|
||||
val
|
||||
|> Num.toStr
|
||||
|> Task.putLine
|
||||
|> Num.toStr
|
||||
|> Task.putLine
|
||||
|
||||
boom : Str -> a
|
||||
boom = \_ -> boom ""
|
||||
|
@ -9,8 +9,8 @@ main =
|
||||
tree = insert 0 {} Empty
|
||||
|
||||
tree
|
||||
|> show
|
||||
|> Task.putLine
|
||||
|> show
|
||||
|> Task.putLine
|
||||
|
||||
show : RedBlackTree I64 {} -> Str
|
||||
show = \tree -> showRBTree tree Num.toStr (\{} -> "{}")
|
||||
|
@ -8,11 +8,11 @@ forever : Task val err -> Task * err
|
||||
forever = \task ->
|
||||
looper = \{} ->
|
||||
task
|
||||
|> Effect.map
|
||||
\res ->
|
||||
when res is
|
||||
Ok _ -> Step {}
|
||||
Err e -> Done (Err e)
|
||||
|> Effect.map
|
||||
\res ->
|
||||
when res is
|
||||
Ok _ -> Step {}
|
||||
Err e -> Done (Err e)
|
||||
|
||||
Effect.loop {} looper
|
||||
|
||||
@ -20,12 +20,12 @@ loop : state, (state -> Task [Step state, Done done] err) -> Task done err
|
||||
loop = \state, step ->
|
||||
looper = \current ->
|
||||
step current
|
||||
|> Effect.map
|
||||
\res ->
|
||||
when res is
|
||||
Ok (Step newState) -> Step newState
|
||||
Ok (Done result) -> Done (Ok result)
|
||||
Err e -> Done (Err e)
|
||||
|> Effect.map
|
||||
\res ->
|
||||
when res is
|
||||
Ok (Step newState) -> Step newState
|
||||
Ok (Done result) -> Done (Ok result)
|
||||
Err e -> Done (Err e)
|
||||
|
||||
Effect.loop state looper
|
||||
|
||||
|
@ -64,7 +64,7 @@ update = \model, event ->
|
||||
tick : Model -> Model
|
||||
tick = \model ->
|
||||
model
|
||||
|> moveBall
|
||||
|> moveBall
|
||||
|
||||
moveBall : Model -> Model
|
||||
moveBall = \model ->
|
||||
@ -99,12 +99,12 @@ render = \model ->
|
||||
\index ->
|
||||
col =
|
||||
Num.rem index numCols
|
||||
|> Num.toF32
|
||||
|> Num.toF32
|
||||
|
||||
row =
|
||||
index
|
||||
// numCols
|
||||
|> Num.toF32
|
||||
// numCols
|
||||
|> Num.toF32
|
||||
|
||||
red = col / Num.toF32 numCols
|
||||
green = row / Num.toF32 numRows
|
||||
|
@ -90,8 +90,8 @@ translate = \child, toChild, toParent ->
|
||||
Button config label ->
|
||||
onPress = \parentState, event ->
|
||||
toChild parentState
|
||||
|> config.onPress event
|
||||
|> Action.map \c -> toParent parentState c
|
||||
|> config.onPress event
|
||||
|> Action.map \c -> toParent parentState c
|
||||
|
||||
Button { onPress } (translate label toChild toParent)
|
||||
|
||||
@ -136,8 +136,8 @@ list = \renderChild, parent, toChildren, toParent ->
|
||||
toChild
|
||||
\par, ch ->
|
||||
toChildren par
|
||||
|> List.set ch index
|
||||
|> toParent
|
||||
|> List.set ch index
|
||||
|> toParent
|
||||
|
||||
renderChild newChild
|
||||
|
||||
@ -165,8 +165,8 @@ translateOrDrop = \child, toChild, toParent ->
|
||||
when toChild parentState is
|
||||
Ok newChild ->
|
||||
newChild
|
||||
|> config.onPress event
|
||||
|> Action.map \c -> toParent parentState c
|
||||
|> config.onPress event
|
||||
|> Action.map \c -> toParent parentState c
|
||||
|
||||
Err _ ->
|
||||
# The child was removed from the list before this onPress handler resolved.
|
||||
@ -182,7 +182,7 @@ translateOrDrop = \child, toChild, toParent ->
|
||||
when toChild parentState is
|
||||
Ok newChild ->
|
||||
renderChild newChild
|
||||
|> translateOrDrop toChild toParent
|
||||
|> translateOrDrop toChild toParent
|
||||
|
||||
Err _ ->
|
||||
None
|
||||
|
@ -21,7 +21,7 @@ InterpreterErrors : [BadUtf8, DivByZero, EmptyStack, InvalidBooleanValue, Invali
|
||||
main : Str -> Task {} []
|
||||
main = \filename ->
|
||||
interpretFile filename
|
||||
|> Task.onFail (\StringErr e -> Stdout.line "Ran into problem:\n\(e)\n")
|
||||
|> Task.onFail \StringErr e -> Stdout.line "Ran into problem:\n\(e)\n"
|
||||
|
||||
interpretFile : Str -> Task {} [StringErr Str]
|
||||
interpretFile = \filename ->
|
||||
@ -70,19 +70,19 @@ interpretFile = \filename ->
|
||||
isDigit : U8 -> Bool
|
||||
isDigit = \char ->
|
||||
char
|
||||
>= 0x30 # `0`
|
||||
&& char
|
||||
<= 0x39 # `0`
|
||||
>= 0x30 # `0`
|
||||
&& char
|
||||
<= 0x39 # `0`
|
||||
isWhitespace : U8 -> Bool
|
||||
isWhitespace = \char ->
|
||||
char
|
||||
== 0xA # new line
|
||||
|| char
|
||||
== 0xB # carriage return
|
||||
|| char
|
||||
== 0x20 # space
|
||||
|| char
|
||||
== 0x9 # tab
|
||||
== 0xA # new line
|
||||
|| char
|
||||
== 0xB # carriage return
|
||||
|| char
|
||||
== 0x20 # space
|
||||
|| char
|
||||
== 0x9 # tab
|
||||
interpretCtx : Context -> Task Context InterpreterErrors
|
||||
interpretCtx = \ctx ->
|
||||
Task.loop ctx interpretCtxLoop
|
||||
|
@ -9,8 +9,8 @@ Variable := U8
|
||||
totalCount : Nat
|
||||
totalCount =
|
||||
0x7A # "z"
|
||||
- 0x61 # "a"
|
||||
+ 1
|
||||
- 0x61 # "a"
|
||||
+ 1
|
||||
|
||||
toStr : Variable -> Str
|
||||
toStr = \@Variable char ->
|
||||
@ -22,10 +22,9 @@ fromUtf8 : U8 -> Result Variable [InvalidVariableUtf8]
|
||||
fromUtf8 = \char ->
|
||||
if
|
||||
char
|
||||
>= 0x61 # "a"
|
||||
&& char
|
||||
<= 0x7A
|
||||
# "z"
|
||||
>= 0x61 # "a"
|
||||
&& char
|
||||
<= 0x7A # "z"
|
||||
then
|
||||
Ok (@Variable char)
|
||||
else
|
||||
|
@ -13,8 +13,8 @@ chunk = \@Handle handle -> Effect.after (Effect.getFileBytes handle) Task.succee
|
||||
open : Str -> Task.Task Handle *
|
||||
open = \path ->
|
||||
Effect.openFile path
|
||||
|> Effect.map (\id -> @Handle id)
|
||||
|> Effect.after Task.succeed
|
||||
|> Effect.map (\id -> @Handle id)
|
||||
|> Effect.after Task.succeed
|
||||
|
||||
close : Handle -> Task.Task {} *
|
||||
close = \@Handle handle -> Effect.after (Effect.closeFile handle) Task.succeed
|
||||
|
@ -8,12 +8,12 @@ loop : state, (state -> Task [Step state, Done done] err) -> Task done err
|
||||
loop = \state, step ->
|
||||
looper = \current ->
|
||||
step current
|
||||
|> Effect.map
|
||||
\res ->
|
||||
when res is
|
||||
Ok (Step newState) -> Step newState
|
||||
Ok (Done result) -> Done (Ok result)
|
||||
Err e -> Done (Err e)
|
||||
|> Effect.map
|
||||
\res ->
|
||||
when res is
|
||||
Ok (Step newState) -> Step newState
|
||||
Ok (Done result) -> Done (Ok result)
|
||||
Err e -> Done (Err e)
|
||||
|
||||
Effect.loop state looper
|
||||
|
||||
|
@ -90,8 +90,8 @@ translate = \child, toChild, toParent ->
|
||||
Button config label ->
|
||||
onPress = \parentState, event ->
|
||||
toChild parentState
|
||||
|> config.onPress event
|
||||
|> Action.map \c -> toParent parentState c
|
||||
|> config.onPress event
|
||||
|> Action.map \c -> toParent parentState c
|
||||
|
||||
Button { onPress } (translate label toChild toParent)
|
||||
|
||||
@ -136,8 +136,8 @@ list = \renderChild, parent, toChildren, toParent ->
|
||||
toChild
|
||||
\par, ch ->
|
||||
toChildren par
|
||||
|> List.set ch index
|
||||
|> toParent
|
||||
|> List.set ch index
|
||||
|> toParent
|
||||
|
||||
renderChild newChild
|
||||
|
||||
@ -165,8 +165,8 @@ translateOrDrop = \child, toChild, toParent ->
|
||||
when toChild parentState is
|
||||
Ok newChild ->
|
||||
newChild
|
||||
|> config.onPress event
|
||||
|> Action.map \c -> toParent parentState c
|
||||
|> config.onPress event
|
||||
|> Action.map \c -> toParent parentState c
|
||||
|
||||
Err _ ->
|
||||
# The child was removed from the list before this onPress handler resolved.
|
||||
@ -182,7 +182,7 @@ translateOrDrop = \child, toChild, toParent ->
|
||||
when toChild parentState is
|
||||
Ok newChild ->
|
||||
renderChild newChild
|
||||
|> translateOrDrop toChild toParent
|
||||
|> translateOrDrop toChild toParent
|
||||
|
||||
Err _ ->
|
||||
None
|
||||
|
@ -226,37 +226,37 @@ append = \@Path prefix, @Path suffix ->
|
||||
NoInteriorNul suffixBytes ->
|
||||
# Neither prefix nor suffix had interior nuls, so the answer won't either
|
||||
List.append prefixBytes suffixBytes
|
||||
|> NoInteriorNul
|
||||
|> NoInteriorNul
|
||||
|
||||
ArbitraryBytes suffixBytes ->
|
||||
List.append prefixBytes suffixBytes
|
||||
|> ArbitraryBytes
|
||||
|> ArbitraryBytes
|
||||
|
||||
FromStr suffixStr ->
|
||||
# Append suffixStr by writing it to the end of prefixBytes
|
||||
Str.writeUtf8 suffixStr prefixBytes (List.len prefixBytes)
|
||||
|> ArbitraryBytes
|
||||
|> ArbitraryBytes
|
||||
|
||||
ArbitraryBytes prefixBytes ->
|
||||
when suffix is
|
||||
ArbitraryBytes suffixBytes | NoInteriorNul suffixBytes ->
|
||||
List.append prefixBytes suffixBytes
|
||||
|> ArbitraryBytes
|
||||
|> ArbitraryBytes
|
||||
|
||||
FromStr suffixStr ->
|
||||
# Append suffixStr by writing it to the end of prefixBytes
|
||||
Str.writeUtf8 suffixStr prefixBytes (List.len prefixBytes)
|
||||
|> ArbitraryBytes
|
||||
|> ArbitraryBytes
|
||||
|
||||
FromStr prefixStr ->
|
||||
when suffix is
|
||||
ArbitraryBytes suffixBytes | NoInteriorNul suffixBytes ->
|
||||
List.append (Str.toUtf8 prefixStr) suffixBytes
|
||||
|> ArbitraryBytes
|
||||
|> ArbitraryBytes
|
||||
|
||||
FromStr suffixStr ->
|
||||
Str.append prefixStr suffixStr
|
||||
|> FromStr
|
||||
|> FromStr
|
||||
|
||||
@Path content
|
||||
|
||||
@ -267,11 +267,11 @@ appendStr = \@Path prefix, suffixStr ->
|
||||
NoInteriorNul prefixBytes | ArbitraryBytes prefixBytes ->
|
||||
# Append suffixStr by writing it to the end of prefixBytes
|
||||
Str.writeUtf8 suffixStr prefixBytes (List.len prefixBytes)
|
||||
|> ArbitraryBytes
|
||||
|> ArbitraryBytes
|
||||
|
||||
FromStr prefixStr ->
|
||||
Str.append prefixStr suffixStr
|
||||
|> FromStr
|
||||
|> FromStr
|
||||
|
||||
@Path content
|
||||
|
||||
@ -354,9 +354,9 @@ withExtension = \@Path path, extension ->
|
||||
Err NotFound -> list
|
||||
|
||||
beforeDot
|
||||
|> List.reserve (1 + List.len bytes)
|
||||
|> List.append '.'
|
||||
|> List.concat bytes
|
||||
|> List.reserve (1 + List.len bytes)
|
||||
|> List.append '.'
|
||||
|> List.concat bytes
|
||||
|
||||
FromStr str ->
|
||||
beforeDot =
|
||||
@ -365,9 +365,9 @@ withExtension = \@Path path, extension ->
|
||||
Err NotFound -> str
|
||||
|
||||
beforeDot
|
||||
|> Str.reserve (1 + Str.byteCount str)
|
||||
|> Str.append "."
|
||||
|> Str.concat str
|
||||
|> Str.reserve (1 + Str.byteCount str)
|
||||
|> Str.append "."
|
||||
|> Str.concat str
|
||||
|
||||
# NOTE: no withExtensionBytes because it's too narrow. If you really need to get some
|
||||
# non-Unicode in there, do it with
|
||||
|
@ -5,5 +5,5 @@ interface Stdin
|
||||
line : Task Str * [Read [Stdin]*]*
|
||||
line =
|
||||
Effect.getLine
|
||||
|> Effect.map Ok
|
||||
|> InternalTask.fromEffect
|
||||
|> Effect.map Ok
|
||||
|> InternalTask.fromEffect
|
||||
|
@ -5,4 +5,4 @@ interface Stdout
|
||||
line : Str -> Task {} * [Write [Stdout]*]*
|
||||
line = \str ->
|
||||
Effect.map (Effect.putLine str) (\_ -> Ok {})
|
||||
|> InternalTask.fromEffect
|
||||
|> InternalTask.fromEffect
|
||||
|
@ -8,40 +8,40 @@ forever : Task val err fx -> Task * err fx
|
||||
forever = \task ->
|
||||
looper = \{} ->
|
||||
task
|
||||
|> InternalTask.toEffect
|
||||
|> Effect.map
|
||||
\res ->
|
||||
when res is
|
||||
Ok _ -> Step {}
|
||||
Err e -> Done (Err e)
|
||||
|> InternalTask.toEffect
|
||||
|> Effect.map
|
||||
\res ->
|
||||
when res is
|
||||
Ok _ -> Step {}
|
||||
Err e -> Done (Err e)
|
||||
|
||||
Effect.loop {} looper
|
||||
|> InternalTask.fromEffect
|
||||
|> InternalTask.fromEffect
|
||||
|
||||
loop : state, (state -> Task [Step state, Done done] err fx) -> Task done err fx
|
||||
loop = \state, step ->
|
||||
looper = \current ->
|
||||
step current
|
||||
|> InternalTask.toEffect
|
||||
|> Effect.map
|
||||
\res ->
|
||||
when res is
|
||||
Ok (Step newState) -> Step newState
|
||||
Ok (Done result) -> Done (Ok result)
|
||||
Err e -> Done (Err e)
|
||||
|> InternalTask.toEffect
|
||||
|> Effect.map
|
||||
\res ->
|
||||
when res is
|
||||
Ok (Step newState) -> Step newState
|
||||
Ok (Done result) -> Done (Ok result)
|
||||
Err e -> Done (Err e)
|
||||
|
||||
Effect.loop state looper
|
||||
|> InternalTask.fromEffect
|
||||
|> InternalTask.fromEffect
|
||||
|
||||
succeed : val -> Task val * *
|
||||
succeed = \val ->
|
||||
Effect.always (Ok val)
|
||||
|> InternalTask.fromEffect
|
||||
|> InternalTask.fromEffect
|
||||
|
||||
fail : err -> Task * err *
|
||||
fail = \val ->
|
||||
Effect.always (Err val)
|
||||
|> InternalTask.fromEffect
|
||||
|> InternalTask.fromEffect
|
||||
|
||||
attempt : Task a b fx, (Result a b -> Task c d fx) -> Task c d fx
|
||||
attempt = \task, transform ->
|
||||
|
@ -104,17 +104,17 @@ append = \@Url urlStr, suffixUnencoded ->
|
||||
Ok { before, after } ->
|
||||
bytes =
|
||||
Str.countUtf8Bytes before
|
||||
+ 1 # for "/"
|
||||
+ Str.countUtf8Bytes suffix
|
||||
+ 1 # for "?"
|
||||
+ Str.countUtf8Bytes after
|
||||
+ 1 # for "/"
|
||||
+ Str.countUtf8Bytes suffix
|
||||
+ 1 # for "?"
|
||||
+ Str.countUtf8Bytes after
|
||||
|
||||
before
|
||||
|> Str.reserve bytes
|
||||
|> appendHelp suffix
|
||||
|> Str.concat "?"
|
||||
|> Str.concat after
|
||||
|> @Url
|
||||
|> Str.reserve bytes
|
||||
|> appendHelp suffix
|
||||
|> Str.concat "?"
|
||||
|> Str.concat after
|
||||
|> @Url
|
||||
|
||||
Err NotFound ->
|
||||
# There wasn't a query, but there might still be a fragment
|
||||
@ -122,17 +122,17 @@ append = \@Url urlStr, suffixUnencoded ->
|
||||
Ok { before, after } ->
|
||||
bytes =
|
||||
Str.countUtf8Bytes before
|
||||
+ 1 # for "/"
|
||||
+ Str.countUtf8Bytes suffix
|
||||
+ 1 # for "#"
|
||||
+ Str.countUtf8Bytes after
|
||||
+ 1 # for "/"
|
||||
+ Str.countUtf8Bytes suffix
|
||||
+ 1 # for "#"
|
||||
+ Str.countUtf8Bytes after
|
||||
|
||||
before
|
||||
|> Str.reserve bytes
|
||||
|> appendHelp suffix
|
||||
|> Str.concat "#"
|
||||
|> Str.concat after
|
||||
|> @Url
|
||||
|> Str.reserve bytes
|
||||
|> appendHelp suffix
|
||||
|> Str.concat "#"
|
||||
|> Str.concat after
|
||||
|> @Url
|
||||
|
||||
Err NotFound ->
|
||||
# No query and no fragment, so just append it
|
||||
@ -169,8 +169,8 @@ appendHelp = \prefix, suffix ->
|
||||
else
|
||||
# Neither is empty, but neither has a "/", so add one in between.
|
||||
prefix
|
||||
|> Str.concat "/"
|
||||
|> Str.concat suffix
|
||||
|> Str.concat "/"
|
||||
|> Str.concat suffix
|
||||
|
||||
## Internal helper. This is intentionally unexposed so that you don't accidentally
|
||||
## double-encode things. If you really want to percent-encode an arbitrary string,
|
||||
@ -194,30 +194,30 @@ percentEncode = \input ->
|
||||
# Spec for percent-encoding: https://www.ietf.org/rfc/rfc3986.txt
|
||||
if
|
||||
(byte >= 97 && byte <= 122) # lowercase ASCII
|
||||
|| (byte >= 65 && byte <= 90) # uppercase ASCII
|
||||
|| (byte >= 48 && byte <= 57) # digit
|
||||
|| (byte >= 65 && byte <= 90) # uppercase ASCII
|
||||
|| (byte >= 48 && byte <= 57) # digit
|
||||
then
|
||||
# This is the most common case: an unreserved character,
|
||||
# which needs no encoding in a path
|
||||
Str.appendScalar output (Num.toU32 byte)
|
||||
|> Result.withDefault "" # this will never fail
|
||||
|> Result.withDefault "" # this will never fail
|
||||
else
|
||||
when byte is
|
||||
46 # '.'
|
||||
| 95 # '_'
|
||||
| 126 # '~'
|
||||
| 150 -> # '-'
|
||||
| 95 # '_'
|
||||
| 126 # '~'
|
||||
| 150 -> # '-'
|
||||
# These special characters can all be unescaped in paths
|
||||
Str.appendScalar output (Num.toU32 byte)
|
||||
|> Result.withDefault "" # this will never fail
|
||||
|> Result.withDefault "" # this will never fail
|
||||
|
||||
_ ->
|
||||
# This needs encoding in a path
|
||||
suffix =
|
||||
Str.toUtf8 percentEncoded
|
||||
|> List.sublist { len: 3, start: 3 * Num.toNat byte }
|
||||
|> Str.fromUtf8
|
||||
|> Result.withDefault "" # This will never fail
|
||||
|> List.sublist { len: 3, start: 3 * Num.toNat byte }
|
||||
|> Str.fromUtf8
|
||||
|> Result.withDefault "" # This will never fail
|
||||
|
||||
Str.concat output suffix
|
||||
|
||||
@ -251,20 +251,20 @@ appendParam = \@Url urlStr, key, value ->
|
||||
|
||||
bytes =
|
||||
Str.countUtf8Bytes withoutFragment
|
||||
+ 1 # for "?" or "&"
|
||||
+ Str.countUtf8Bytes encodedKey
|
||||
+ 1 # for "="
|
||||
+ Str.countUtf8Bytes encodedValue
|
||||
+ Str.countUtf8Bytes afterQuery
|
||||
+ 1 # for "?" or "&"
|
||||
+ Str.countUtf8Bytes encodedKey
|
||||
+ 1 # for "="
|
||||
+ Str.countUtf8Bytes encodedValue
|
||||
+ Str.countUtf8Bytes afterQuery
|
||||
|
||||
withoutFragment
|
||||
|> Str.reserve bytes
|
||||
|> Str.concat (if hasQuery (@Url withoutFragment) then "&" else "?")
|
||||
|> Str.concat encodedKey
|
||||
|> Str.concat "="
|
||||
|> Str.concat encodedValue
|
||||
|> Str.concat afterQuery
|
||||
|> @Url
|
||||
|> Str.reserve bytes
|
||||
|> Str.concat (if hasQuery (@Url withoutFragment) then "&" else "?")
|
||||
|> Str.concat encodedKey
|
||||
|> Str.concat "="
|
||||
|> Str.concat encodedValue
|
||||
|> Str.concat afterQuery
|
||||
|> @Url
|
||||
|
||||
## Replaces the URL's [query](https://en.wikipedia.org/wiki/URL#Syntax)—the part after
|
||||
## the `?`, if it has one, but before any `#` it might have.
|
||||
@ -300,16 +300,16 @@ withQuery = \@Url urlStr, queryStr ->
|
||||
else
|
||||
bytes =
|
||||
Str.countUtf8Bytes beforeQuery
|
||||
+ 1 # for "?"
|
||||
+ Str.countUtf8Bytes queryStr
|
||||
+ Str.countUtf8Bytes afterQuery
|
||||
+ 1 # for "?"
|
||||
+ Str.countUtf8Bytes queryStr
|
||||
+ Str.countUtf8Bytes afterQuery
|
||||
|
||||
beforeQuery
|
||||
|> Str.reserve bytes
|
||||
|> Str.concat "?"
|
||||
|> Str.concat queryStr
|
||||
|> Str.concat afterQuery
|
||||
|> @Url
|
||||
|> Str.reserve bytes
|
||||
|> Str.concat "?"
|
||||
|> Str.concat queryStr
|
||||
|> Str.concat afterQuery
|
||||
|> @Url
|
||||
|
||||
## Returns the URL's [query](https://en.wikipedia.org/wiki/URL#Syntax)—the part after
|
||||
## the `?`, if it has one, but before any `#` it might have.
|
||||
@ -348,7 +348,7 @@ hasQuery = \@Url urlStr ->
|
||||
# TODO use Str.contains once it exists. It should have a "fast path"
|
||||
# with SIMD iteration if the string is small enough to fit in a SIMD register.
|
||||
Str.toUtf8 urlStr
|
||||
|> List.contains (Num.toU8 '?')
|
||||
|> List.contains (Num.toU8 '?')
|
||||
|
||||
## Returns the URL's [fragment](https://en.wikipedia.org/wiki/URL#Syntax)—the part after
|
||||
## the `#`, if it has one.
|
||||
@ -418,7 +418,7 @@ hasFragment = \@Url urlStr ->
|
||||
# TODO use Str.contains once it exists. It should have a "fast path"
|
||||
# with SIMD iteration if the string is small enough to fit in a SIMD register.
|
||||
Str.toUtf8 urlStr
|
||||
|> List.contains (Num.toU8 '#')
|
||||
|> List.contains (Num.toU8 '#')
|
||||
|
||||
strWithCapacity : Nat -> Str
|
||||
strWithCapacity = \cap ->
|
||||
|
@ -21,13 +21,13 @@ echo = \shout ->
|
||||
List.repeat spaceInUtf8 length
|
||||
|
||||
shout
|
||||
|> Str.toUtf8
|
||||
|> List.mapWithIndex
|
||||
(\_, i ->
|
||||
length = (List.len (Str.toUtf8 shout) - i)
|
||||
phrase = (List.split (Str.toUtf8 shout) length).before
|
||||
|> Str.toUtf8
|
||||
|> List.mapWithIndex
|
||||
(\_, i ->
|
||||
length = (List.len (Str.toUtf8 shout) - i)
|
||||
phrase = (List.split (Str.toUtf8 shout) length).before
|
||||
|
||||
List.concat (silence (if i == 0 then 2 * length else length)) phrase)
|
||||
|> List.join
|
||||
|> Str.fromUtf8
|
||||
|> Result.withDefault ""
|
||||
List.concat (silence (if i == 0 then 2 * length else length)) phrase)
|
||||
|> List.join
|
||||
|> Str.fromUtf8
|
||||
|> Result.withDefault ""
|
||||
|
Loading…
Reference in New Issue
Block a user