Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move PNC apply to separate Expr/Pattern variant #7480

Merged
merged 5 commits into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 68 additions & 52 deletions crates/compiler/builtins/roc/Dict.roc
Original file line number Diff line number Diff line change
Expand Up @@ -133,22 +133,26 @@ hash_dict = \hasher, dict -> Hash.hash_unordered(hasher, to_list(dict), List.wal

to_inspector_dict : Dict k v -> Inspector f where k implements Inspect & Hash & Eq, v implements Inspect, f implements InspectFormatter
to_inspector_dict = \dict ->
Inspect.custom(\fmt ->
Inspect.apply(Inspect.dict(dict, walk, Inspect.to_inspector, Inspect.to_inspector), fmt))
Inspect.custom(
\fmt ->
Inspect.apply(Inspect.dict(dict, walk, Inspect.to_inspector, Inspect.to_inspector), fmt),
)

## Return an empty dictionary.
## ```roc
## empty_dict = Dict.empty({})
## ```
empty : {} -> Dict * *
empty = \{} ->
@Dict({
buckets: [],
data: [],
max_bucket_capacity: 0,
max_load_factor: default_max_load_factor,
shifts: initial_shifts,
})
@Dict(
{
buckets: [],
data: [],
max_bucket_capacity: 0,
max_load_factor: default_max_load_factor,
shifts: initial_shifts,
},
)

## Return a dictionary with space allocated for a number of entries. This
## may provide a performance optimization if you know how many entries will be
Expand All @@ -169,13 +173,15 @@ reserve = \@Dict({ buckets, data, max_bucket_capacity: original_max_bucket_capac
if List.is_empty(buckets) || requested_shifts > shifts then
(buckets0, max_bucket_capacity) = alloc_buckets_from_shift(requested_shifts, max_load_factor)
buckets1 = fill_buckets_from_data(buckets0, data, requested_shifts)
@Dict({
buckets: buckets1,
data: List.reserve(data, Num.sub_saturated(size, current_size)),
max_bucket_capacity,
max_load_factor,
shifts: requested_shifts,
})
@Dict(
{
buckets: buckets1,
data: List.reserve(data, Num.sub_saturated(size, current_size)),
max_bucket_capacity,
max_load_factor,
shifts: requested_shifts,
},
)
else
@Dict({ buckets, data, max_bucket_capacity: original_max_bucket_capacity, max_load_factor, shifts })

Expand All @@ -191,13 +197,15 @@ release_excess_capacity = \@Dict({ buckets, data, max_bucket_capacity: original_
if min_shifts < shifts then
(buckets0, max_bucket_capacity) = alloc_buckets_from_shift(min_shifts, max_load_factor)
buckets1 = fill_buckets_from_data(buckets0, data, min_shifts)
@Dict({
buckets: buckets1,
data: List.release_excess_capacity(data),
max_bucket_capacity,
max_load_factor,
shifts: min_shifts,
})
@Dict(
{
buckets: buckets1,
data: List.release_excess_capacity(data),
max_bucket_capacity,
max_load_factor,
shifts: min_shifts,
},
)
else
@Dict({ buckets, data, max_bucket_capacity: original_max_bucket_capacity, max_load_factor, shifts })

Expand Down Expand Up @@ -280,14 +288,16 @@ is_empty = \@Dict({ data }) ->
## ```
clear : Dict k v -> Dict k v
clear = \@Dict({ buckets, data, max_bucket_capacity, max_load_factor, shifts }) ->
@Dict({
buckets: List.map(buckets, \_ -> empty_bucket),
# use take_first to keep around the capacity
data: List.take_first(data, 0),
max_bucket_capacity,
max_load_factor,
shifts,
})
@Dict(
{
buckets: List.map(buckets, \_ -> empty_bucket),
# use take_first to keep around the capacity
data: List.take_first(data, 0),
max_bucket_capacity,
max_load_factor,
shifts,
},
)

## Convert each value in the dictionary to something new, by calling a conversion
## function on each of them which receives both the key and the old value. Then return a
Expand Down Expand Up @@ -822,21 +832,25 @@ remove_bucket = \@Dict({ buckets: buckets0, data: data0, max_bucket_capacity, ma
bucket_index3 = scan_for_index(buckets2, bucket_index2, Num.to_u32(last_data_index))
swap_bucket = list_get_unsafe(buckets2, bucket_index3)

@Dict({
buckets: List.set(buckets2, bucket_index3, { swap_bucket & data_index: data_index_to_remove }),
data: List.drop_last(data1, 1),
max_bucket_capacity,
max_load_factor,
shifts,
})
@Dict(
{
buckets: List.set(buckets2, bucket_index3, { swap_bucket & data_index: data_index_to_remove }),
data: List.drop_last(data1, 1),
max_bucket_capacity,
max_load_factor,
shifts,
},
)
else
@Dict({
buckets: buckets2,
data: List.drop_last(data0, 1),
max_bucket_capacity,
max_load_factor,
shifts,
})
@Dict(
{
buckets: buckets2,
data: List.drop_last(data0, 1),
max_bucket_capacity,
max_load_factor,
shifts,
},
)

scan_for_index : List Bucket, U64, U32 -> U64
scan_for_index = \buckets, bucket_index, data_index ->
Expand All @@ -863,13 +877,15 @@ increase_size = \@Dict({ data, max_bucket_capacity, max_load_factor, shifts }) -
new_shifts = shifts |> Num.sub_wrap(1)
(buckets0, new_max_bucket_capacity) = alloc_buckets_from_shift(new_shifts, max_load_factor)
buckets1 = fill_buckets_from_data(buckets0, data, new_shifts)
@Dict({
buckets: buckets1,
data,
max_bucket_capacity: new_max_bucket_capacity,
max_load_factor,
shifts: new_shifts,
})
@Dict(
{
buckets: buckets1,
data,
max_bucket_capacity: new_max_bucket_capacity,
max_load_factor,
shifts: new_shifts,
},
)
else
crash("Dict hit limit of $(Num.to_str(max_bucket_count)) elements. Unable to grow more.")

Expand Down
83 changes: 55 additions & 28 deletions crates/compiler/builtins/roc/List.roc
Original file line number Diff line number Diff line change
Expand Up @@ -1092,11 +1092,15 @@ min = \list ->

min_help : List (Num a), Num a -> Num a
min_help = \list, initial ->
List.walk(list, initial, \best_so_far, current ->
if current < best_so_far then
current
else
best_so_far)
List.walk(
list,
initial,
\best_so_far, current ->
if current < best_so_far then
current
else
best_so_far,
)

max : List (Num a) -> Result (Num a) [ListWasEmpty]
max = \list ->
Expand All @@ -1109,11 +1113,15 @@ max = \list ->

max_help : List (Num a), Num a -> Num a
max_help = \list, initial ->
List.walk(list, initial, \best_so_far, current ->
if current > best_so_far then
current
else
best_so_far)
List.walk(
list,
initial,
\best_so_far, current ->
if current > best_so_far then
current
else
best_so_far,
)

## Like [List.map], except the transformation function wraps the return value
## in a list. At the end, all the lists get joined together into one list.
Expand Down Expand Up @@ -1156,11 +1164,15 @@ find_last = \list, pred ->
## If no satisfying element is found, an `Err NotFound` is returned.
find_first_index : List elem, (elem -> Bool) -> Result U64 [NotFound]
find_first_index = \list, matcher ->
found_index = List.iterate(list, 0, \index, elem ->
if matcher(elem) then
Break(index)
else
Continue(Num.add_wrap(index, 1)))
found_index = List.iterate(
list,
0,
\index, elem ->
if matcher(elem) then
Break(index)
else
Continue(Num.add_wrap(index, 1)),
)

when found_index is
Break(index) -> Ok(index)
Expand All @@ -1171,13 +1183,17 @@ find_first_index = \list, matcher ->
## If no satisfying element is found, an `Err NotFound` is returned.
find_last_index : List elem, (elem -> Bool) -> Result U64 [NotFound]
find_last_index = \list, matches ->
found_index = List.iterate_backwards(list, List.len(list), \prev_index, elem ->
answer = Num.sub_wrap(prev_index, 1)
found_index = List.iterate_backwards(
list,
List.len(list),
\prev_index, elem ->
answer = Num.sub_wrap(prev_index, 1)

if matches(elem) then
Break(answer)
else
Continue(answer))
if matches(elem) then
Break(answer)
else
Continue(answer),
)

when found_index is
Break(index) -> Ok(index)
Expand Down Expand Up @@ -1214,10 +1230,14 @@ intersperse = \list, sep ->
capacity = 2 * List.len(list)
init = List.with_capacity(capacity)
new_list =
List.walk(list, init, \acc, elem ->
acc
|> List.append_unsafe(elem)
|> List.append_unsafe(sep))
List.walk(
list,
init,
\acc, elem ->
acc
|> List.append_unsafe(elem)
|> List.append_unsafe(sep),
)

List.drop_last(new_list, 1)

Expand Down Expand Up @@ -1359,9 +1379,16 @@ chunks_of_help = \list_rest, chunk_size, chunks ->
## If it returns `Ok` for every element, [map_try] returns `Ok` with the transformed list.
map_try : List elem, (elem -> Result ok err) -> Result (List ok) err
map_try = \list, to_result ->
walk_try(list, [], \state, elem ->
Result.map(to_result(elem), \ok ->
List.append(state, ok)))
walk_try(
list,
[],
\state, elem ->
Result.map(
to_result(elem),
\ok ->
List.append(state, ok),
),
)

## Same as [List.walk], except you can stop walking early by returning `Err`.
##
Expand Down
36 changes: 25 additions & 11 deletions crates/compiler/builtins/roc/Set.roc
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,25 @@ is_eq = \xs, ys ->
if len(xs) != len(ys) then
Bool.false
else
walk_until(xs, Bool.true, \_, elem ->
if contains(ys, elem) then
Continue(Bool.true)
else
Break(Bool.false))
walk_until(
xs,
Bool.true,
\_, elem ->
if contains(ys, elem) then
Continue(Bool.true)
else
Break(Bool.false),
)

hash_set : hasher, Set k -> hasher where hasher implements Hasher
hash_set = \hasher, @Set(inner) -> Hash.hash(hasher, inner)

to_inspector_set : Set k -> Inspector f where k implements Inspect & Hash & Eq, f implements InspectFormatter
to_inspector_set = \set ->
Inspect.custom(\fmt ->
Inspect.apply(Inspect.set(set, walk, Inspect.to_inspector), fmt))
Inspect.custom(
\fmt ->
Inspect.apply(Inspect.set(set, walk, Inspect.to_inspector), fmt),
)

## Creates a new empty `Set`.
## ```roc
Expand Down Expand Up @@ -326,8 +332,12 @@ map : Set a, (a -> b) -> Set b
map = \set, transform ->
init = with_capacity(capacity(set))

walk(set, init, \answer, k ->
insert(answer, transform(k)))
walk(
set,
init,
\answer, k ->
insert(answer, transform(k)),
)

## Like [Set.map], except the transformation function wraps the return value
## in a set. At the end, all the sets get joined together
Expand All @@ -338,8 +348,12 @@ join_map : Set a, (a -> Set b) -> Set b
join_map = \set, transform ->
init = with_capacity(capacity(set)) # Might be a pessimization

walk(set, init, \answer, k ->
union(answer, transform(k)))
walk(
set,
init,
\answer, k ->
union(answer, transform(k)),
)

## Iterate through the values of a given `Set` and build a value, can stop
## iterating part way through the collection.
Expand Down
18 changes: 10 additions & 8 deletions crates/compiler/builtins/roc/Str.roc
Original file line number Diff line number Diff line change
Expand Up @@ -940,14 +940,16 @@ matches_at = \haystack, haystack_index, needle ->
needle_length = Str.count_utf8_bytes(needle)
end_index = min(Num.add_saturated(haystack_index, needle_length), haystack_length)

matches_at_help({
haystack,
haystack_index,
needle,
needle_index: 0,
needle_length,
end_index,
})
matches_at_help(
{
gamebox marked this conversation as resolved.
Show resolved Hide resolved
haystack,
haystack_index,
needle,
needle_index: 0,
needle_length,
end_index,
},
)

matches_at_help = \state ->
{ haystack, haystack_index, needle, needle_index, needle_length, end_index } = state
Expand Down
Loading
Loading