Packages

A `FingerTree` implementation for general purpose functional programming in Gleam!

Current section

Files

Jump to
shine_tree src shine_tree.erl
Raw

src/shine_tree.erl

-module(shine_tree).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([single/1, size/1, first/1, last/1, fold_r_until/3, try_foldr/3, any/2, contains/2, all/2, reverse/1, append/2, prepend/2, concat/1, fold_l_until/3, try_foldl/3, find/2, find_map/2, get/2, from_list/1, range/2, shift/1, to_iterator/1, equals/2, pop/1, unshift/2, push/2, from_iterator/1, map/2, fold_r/3, filter/2, to_list/1, fold_l/3, count/2, each/2, filter_map/2, sort/2, group/2]).
-export_type([shine_tree/1, node_/1]).
-opaque shine_tree(ISR) :: empty |
{single, ISR} |
{deep, integer(), node_(ISR), shine_tree(node_(ISR)), node_(ISR)}.
-type node_(ISS) :: {one, ISS} |
{two, ISS, ISS} |
{three, ISS, ISS, ISS} |
{four, ISS, ISS, ISS, ISS}.
-spec fold_l_node(ITA, node_(ISY), fun((ITA, ISY) -> ITA)) -> ITA.
fold_l_node(V, Node, F) ->
case Node of
{one, W} ->
F(V, W);
{two, W@1, X} ->
_pipe = V,
_pipe@1 = F(_pipe, W@1),
F(_pipe@1, X);
{three, W@2, X@1, Y} ->
_pipe@2 = V,
_pipe@3 = F(_pipe@2, W@2),
_pipe@4 = F(_pipe@3, X@1),
F(_pipe@4, Y);
{four, W@3, X@2, Y@1, Z} ->
_pipe@5 = V,
_pipe@6 = F(_pipe@5, W@3),
_pipe@7 = F(_pipe@6, X@2),
_pipe@8 = F(_pipe@7, Y@1),
F(_pipe@8, Z)
end.
-spec fold_r_node(ITM, node_(ITK), fun((ITM, ITK) -> ITM)) -> ITM.
fold_r_node(V, Node, F) ->
case Node of
{one, W} ->
F(V, W);
{two, W@1, X} ->
_pipe = V,
_pipe@1 = F(_pipe, X),
F(_pipe@1, W@1);
{three, W@2, X@1, Y} ->
_pipe@2 = V,
_pipe@3 = F(_pipe@2, Y),
_pipe@4 = F(_pipe@3, X@1),
F(_pipe@4, W@2);
{four, W@3, X@2, Y@1, Z} ->
_pipe@5 = V,
_pipe@6 = F(_pipe@5, Z),
_pipe@7 = F(_pipe@6, Y@1),
_pipe@8 = F(_pipe@7, X@2),
F(_pipe@8, W@3)
end.
-spec map_node(node_(ITV), fun((ITV) -> ITX)) -> node_(ITX).
map_node(Node, F) ->
case Node of
{one, W} ->
{one, F(W)};
{two, W@1, X} ->
{two, F(W@1), F(X)};
{three, W@2, X@1, Y} ->
{three, F(W@2), F(X@1), F(Y)};
{four, W@3, X@2, Y@1, Z} ->
{four, F(W@3), F(X@2), F(Y@1), F(Z)}
end.
-spec pop_node(node_(IUQ)) -> {ok, {IUQ, node_(IUQ)}} | {error, nil}.
pop_node(Node) ->
case Node of
{two, U, V} ->
{ok, {V, {one, U}}};
{three, U@1, V@1, W} ->
{ok, {W, {two, U@1, V@1}}};
{four, U@2, V@2, W@1, X} ->
{ok, {X, {three, U@2, V@2, W@1}}};
_ ->
{error, nil}
end.
-spec shift_node(node_(IUY)) -> {ok, {IUY, node_(IUY)}} | {error, nil}.
shift_node(Node) ->
case Node of
{two, U, V} ->
{ok, {U, {one, V}}};
{three, U@1, V@1, W} ->
{ok, {U@1, {two, V@1, W}}};
{four, U@2, V@2, W@1, X} ->
{ok, {U@2, {three, V@2, W@1, X}}};
_ ->
{error, nil}
end.
-spec do_chunk_values(list(IWA), list(node_(IWA)), integer()) -> {node_(IWA),
list(node_(IWA)),
integer()}.
do_chunk_values(Values, Acc, Count) ->
case Values of
[] ->
erlang:error(#{gleam_error => panic,
message => <<"This is impossible!"/utf8>>,
module => <<"shine_tree"/utf8>>,
function => <<"do_chunk_values"/utf8>>,
line => 461});
[A] ->
{{one, A}, Acc, Count + 1};
[A@1, B] ->
{{two, A@1, B}, Acc, Count + 2};
[A@2, B@1, C] ->
{{three, A@2, B@1, C}, Acc, Count + 3};
[A@3, B@2, C@1, D] ->
{{four, A@3, B@2, C@1, D}, Acc, Count + 4};
[A@4, B@3, C@2, D@1 | Rest] ->
do_chunk_values(Rest, [{four, A@4, B@3, C@2, D@1} | Acc], Count + 4)
end.
-spec do_chunk_values_reverse(list(IWK), list(node_(IWK)), integer()) -> {node_(IWK),
list(node_(IWK)),
integer()}.
do_chunk_values_reverse(Items, Acc, Count) ->
case Items of
[] ->
erlang:error(#{gleam_error => panic,
message => <<"This is impossible!"/utf8>>,
module => <<"shine_tree"/utf8>>,
function => <<"do_chunk_values_reverse"/utf8>>,
line => 510});
[A] ->
{{one, A}, Acc, Count + 1};
[A@1, B] ->
{{two, B, A@1}, Acc, Count + 2};
[A@2, B@1, C] ->
{{three, C, B@1, A@2}, Acc, Count + 3};
[A@3, B@2, C@1, D] ->
{{four, D, C@1, B@2, A@3}, Acc, Count + 4};
[A@4, B@3, C@2, D@1 | Rest] ->
do_chunk_values_reverse(
Rest,
[{four, D@1, C@2, B@3, A@4} | Acc],
Count + 4
)
end.
-spec to_node(list(IWS)) -> node_(IWS).
to_node(Val) ->
case Val of
[A] ->
{one, A};
[A@1, B] ->
{two, A@1, B};
[A@2, B@1, C] ->
{three, A@2, B@1, C};
[A@3, B@2, C@1, D] ->
{four, A@3, B@2, C@1, D};
_ ->
erlang:error(#{gleam_error => panic,
message => <<"This is impossible!"/utf8>>,
module => <<"shine_tree"/utf8>>,
function => <<"to_node"/utf8>>,
line => 543})
end.
-spec reverse_node(node_(IYD)) -> node_(IYD).
reverse_node(Node) ->
case Node of
{two, A, B} ->
{two, B, A};
{three, A@1, B@1, C} ->
{three, C, B@1, A@1};
{four, A@2, B@2, C@1, D} ->
{four, D, C@1, B@2, A@2};
Node@1 ->
Node@1
end.
-spec single(IYG) -> shine_tree(IYG).
single(U) ->
{single, U}.
-spec size(shine_tree(any())) -> integer().
size(Tree) ->
case Tree of
empty ->
0;
{single, _} ->
1;
{deep, A, _, _, _} ->
A
end.
-spec all_node(node_(IYO), fun((IYO) -> boolean())) -> boolean().
all_node(Node, F) ->
case Node of
{one, A} ->
F(A);
{two, A@1, B} ->
F(A@1) andalso F(B);
{three, A@2, B@1, C} ->
(F(A@2) andalso F(B@1)) andalso F(C);
{four, A@3, B@2, C@1, D} ->
((F(A@3) andalso F(B@2)) andalso F(C@1)) andalso F(D)
end.
-spec any_node(node_(IYU), fun((IYU) -> boolean())) -> boolean().
any_node(Node, F) ->
case Node of
{one, A} ->
F(A);
{two, A@1, B} ->
F(A@1) orelse F(B);
{three, A@2, B@1, C} ->
(F(A@2) orelse F(B@1)) orelse F(C);
{four, A@3, B@2, C@1, D} ->
((F(A@3) orelse F(B@2)) orelse F(C@1)) orelse F(D)
end.
-spec unwrap_fold_until(gleam@list:continue_or_stop(IZH)) -> IZH.
unwrap_fold_until(V) ->
case V of
{stop, V@1} ->
V@1;
{continue, V@1} ->
V@1
end.
-spec try_continue(
gleam@list:continue_or_stop(JAQ),
fun((JAQ) -> gleam@list:continue_or_stop(JAQ))
) -> gleam@list:continue_or_stop(JAQ).
try_continue(V, F) ->
case V of
{continue, V@1} ->
F(V@1);
V@2 ->
V@2
end.
-spec do_fold_node_l_until(
node_(JAU),
JAX,
fun((JAX, JAU) -> gleam@list:continue_or_stop(JAX))
) -> gleam@list:continue_or_stop(JAX).
do_fold_node_l_until(Node, V, F) ->
case Node of
{one, A} ->
F(V, A);
{two, A@1, B} ->
try_continue(F(V, A@1), fun(V@1) -> F(V@1, B) end);
{three, A@2, B@1, C} ->
try_continue(
F(V, A@2),
fun(V@2) ->
try_continue(F(V@2, B@1), fun(V@3) -> F(V@3, C) end)
end
);
{four, A@3, B@2, C@1, D} ->
try_continue(
F(V, A@3),
fun(V@4) ->
try_continue(
F(V@4, B@2),
fun(V@5) ->
try_continue(F(V@5, C@1), fun(V@6) -> F(V@6, D) end)
end
)
end
)
end.
-spec do_fold_node_r_until(
node_(JBA),
JBD,
fun((JBD, JBA) -> gleam@list:continue_or_stop(JBD))
) -> gleam@list:continue_or_stop(JBD).
do_fold_node_r_until(Node, V, F) ->
case Node of
{one, A} ->
F(V, A);
{two, B, A@1} ->
try_continue(F(V, A@1), fun(V@1) -> F(V@1, B) end);
{three, C, B@1, A@2} ->
try_continue(
F(V, A@2),
fun(V@2) ->
try_continue(F(V@2, B@1), fun(V@3) -> F(V@3, C) end)
end
);
{four, D, C@1, B@2, A@3} ->
try_continue(
F(V, A@3),
fun(V@4) ->
try_continue(
F(V@4, B@2),
fun(V@5) ->
try_continue(F(V@5, C@1), fun(V@6) -> F(V@6, D) end)
end
)
end
)
end.
-spec range_4(integer()) -> node_(integer()).
range_4(Start) ->
{four, Start, Start + 1, Start + 2, Start + 3}.
-spec range_3(integer()) -> node_(integer()).
range_3(Start) ->
{three, Start, Start + 1, Start + 2}.
-spec range_2(integer()) -> node_(integer()).
range_2(Start) ->
{two, Start, Start + 1}.
-spec first(shine_tree(JBY)) -> {ok, JBY} | {error, nil}.
first(Tree) ->
case Tree of
{deep, _, {one, U}, _, _} ->
{ok, U};
{deep, _, {two, U@1, _}, _, _} ->
{ok, U@1};
{deep, _, {three, U@2, _, _}, _, _} ->
{ok, U@2};
{deep, _, {four, U@3, _, _, _}, _, _} ->
{ok, U@3};
{single, U@4} ->
{ok, U@4};
_ ->
{error, nil}
end.
-spec last(shine_tree(JCC)) -> {ok, JCC} | {error, nil}.
last(Tree) ->
case Tree of
{deep, _, _, _, {one, U}} ->
{ok, U};
{deep, _, _, _, {two, _, U@1}} ->
{ok, U@1};
{deep, _, _, _, {three, _, _, U@2}} ->
{ok, U@2};
{deep, _, _, _, {four, _, _, _, U@3}} ->
{ok, U@3};
{single, U@4} ->
{ok, U@4};
_ ->
{error, nil}
end.
-spec do_group_by_node(
gleam@dict:dict(JCM, list(JCN)),
node_(JCN),
fun((JCN) -> JCM)
) -> gleam@dict:dict(JCM, list(JCN)).
do_group_by_node(Final_dict, Item, F) ->
case Item of
{one, U} ->
U_key = F(U),
U_list = [U |
begin
_pipe = gleam@dict:get(Final_dict, U_key),
gleam@result:unwrap(_pipe, [])
end],
gleam@dict:insert(Final_dict, U_key, U_list);
{two, U@1, V} ->
U_key@1 = F(U@1),
V_key = F(V),
U_list@1 = [U@1 |
begin
_pipe@1 = gleam@dict:get(Final_dict, U_key@1),
gleam@result:unwrap(_pipe@1, [])
end],
gleam@dict:insert(Final_dict, U_key@1, U_list@1),
V_list = [V |
begin
_pipe@2 = gleam@dict:get(Final_dict, V_key),
gleam@result:unwrap(_pipe@2, [])
end],
gleam@dict:insert(Final_dict, V_key, V_list);
{three, U@2, V@1, W} ->
U_key@2 = F(U@2),
V_key@1 = F(V@1),
W_key = F(W),
U_list@2 = [U@2 |
begin
_pipe@3 = gleam@dict:get(Final_dict, U_key@2),
gleam@result:unwrap(_pipe@3, [])
end],
gleam@dict:insert(Final_dict, U_key@2, U_list@2),
V_list@1 = [V@1 |
begin
_pipe@4 = gleam@dict:get(Final_dict, V_key@1),
gleam@result:unwrap(_pipe@4, [])
end],
gleam@dict:insert(Final_dict, V_key@1, V_list@1),
W_list = [W |
begin
_pipe@5 = gleam@dict:get(Final_dict, W_key),
gleam@result:unwrap(_pipe@5, [])
end],
gleam@dict:insert(Final_dict, W_key, W_list);
{four, U@3, V@2, W@1, X} ->
U_key@3 = F(U@3),
V_key@2 = F(V@2),
W_key@1 = F(W@1),
X_key = F(X),
U_list@3 = [U@3 |
begin
_pipe@6 = gleam@dict:get(Final_dict, U_key@3),
gleam@result:unwrap(_pipe@6, [])
end],
gleam@dict:insert(Final_dict, U_key@3, U_list@3),
V_list@2 = [V@2 |
begin
_pipe@7 = gleam@dict:get(Final_dict, V_key@2),
gleam@result:unwrap(_pipe@7, [])
end],
gleam@dict:insert(Final_dict, V_key@2, V_list@2),
W_list@1 = [W@1 |
begin
_pipe@8 = gleam@dict:get(Final_dict, W_key@1),
gleam@result:unwrap(_pipe@8, [])
end],
gleam@dict:insert(Final_dict, W_key@1, W_list@1),
X_list = [X |
begin
_pipe@9 = gleam@dict:get(Final_dict, X_key),
gleam@result:unwrap(_pipe@9, [])
end],
gleam@dict:insert(Final_dict, X_key, X_list)
end.
-spec node_size(node_(any())) -> integer().
node_size(Node) ->
case Node of
{one, _} ->
1;
{two, _, _} ->
2;
{three, _, _, _} ->
3;
{four, _, _, _, _} ->
4
end.
-spec get_node(integer(), node_(JDJ)) -> gleam@list:continue_or_stop({ok, JDJ} |
{error, integer()}).
get_node(Index, Node) ->
case {Node, Index} of
{{one, U}, 0} ->
{stop, {ok, U}};
{{two, U@1, _}, 0} ->
{stop, {ok, U@1}};
{{two, _, V}, 1} ->
{stop, {ok, V}};
{{three, U@2, _, _}, 0} ->
{stop, {ok, U@2}};
{{three, _, V@1, _}, 1} ->
{stop, {ok, V@1}};
{{three, _, _, W}, 2} ->
{stop, {ok, W}};
{{four, U@3, _, _, _}, 0} ->
{stop, {ok, U@3}};
{{four, _, V@2, _, _}, 1} ->
{stop, {ok, V@2}};
{{four, _, _, W@1, _}, 2} ->
{stop, {ok, W@1}};
{{four, _, _, _, X}, 3} ->
{stop, {ok, X}};
{Node@1, _} ->
{continue, {error, Index - node_size(Node@1)}}
end.
-spec do_fold_r_until(
shine_tree(JAK),
JAN,
fun((JAN, JAK) -> gleam@list:continue_or_stop(JAN))
) -> gleam@list:continue_or_stop(JAN).
do_fold_r_until(Tree, V, F) ->
case Tree of
empty ->
{continue, V};
{single, U} ->
F(V, U);
{deep, _, Pf, Root, Sf} ->
try_continue(
do_fold_node_r_until(Sf, V, F),
fun(V@1) ->
try_continue(
(do_fold_r_until(
Root,
V@1,
fun(V@2, Node) ->
do_fold_node_r_until(Node, V@2, F)
end
)),
fun(V@3) -> do_fold_node_r_until(Pf, V@3, F) end
)
end
)
end.
-spec fold_r_until(
shine_tree(IZZ),
JAC,
fun((JAC, IZZ) -> gleam@list:continue_or_stop(JAC))
) -> JAC.
fold_r_until(Tree, V, F) ->
_pipe = do_fold_r_until(Tree, V, F),
unwrap_fold_until(_pipe).
-spec try_foldr(
shine_tree(JDX),
JEA,
fun((JEA, JDX) -> {ok, JEA} | {error, JEB})
) -> {ok, JEA} | {error, JEB}.
try_foldr(Tree, Acc, F) ->
fold_r_until(
Tree,
{ok, Acc},
fun(Acc@1, U) ->
{ok, Acc@2} = case Acc@1 of
{ok, _} -> Acc@1;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"shine_tree"/utf8>>,
function => <<"try_foldr"/utf8>>,
line => 1266})
end,
case F(Acc@2, U) of
{ok, Acc@3} ->
{continue, {ok, Acc@3}};
{error, Err} ->
{stop, {error, Err}}
end
end
).
-spec any_rec(shine_tree(IYX), fun((IYX) -> boolean())) -> boolean().
any_rec(Tree, F) ->
any(Tree, F).
-spec any(shine_tree(IYR), fun((IYR) -> boolean())) -> boolean().
any(Tree, F) ->
case Tree of
empty ->
false;
{single, U} ->
F(U);
{deep, _, Pf, Root, Sf} ->
case {any_node(Pf, F), any_node(Sf, F)} of
{false, false} ->
any_rec(Root, fun(_capture) -> any_node(_capture, F) end);
{_, _} ->
true
end
end.
-spec contains(shine_tree(IZA), IZA) -> boolean().
contains(Tree, U) ->
any(Tree, fun(V) -> V =:= U end).
-spec all(shine_tree(IYL), fun((IYL) -> boolean())) -> boolean().
all(Tree, F) ->
case Tree of
empty ->
true;
{single, U} ->
F(U);
{deep, _, Pf, Root, Sf} ->
case {all_node(Pf, F), all_node(Sf, F)} of
{true, true} ->
all(Root, fun(_capture) -> all_node(_capture, F) end);
{_, _} ->
false
end
end.
-spec reverse_rec(shine_tree(node_(IXZ))) -> shine_tree(node_(IXZ)).
reverse_rec(Tree) ->
_pipe = Tree,
_pipe@1 = map(_pipe, fun reverse_node/1),
reverse(_pipe@1).
-spec reverse(shine_tree(IXW)) -> shine_tree(IXW).
reverse(Tree) ->
case Tree of
{deep, Count, Pf, Root, Sf} ->
{deep,
Count,
begin
_pipe = Sf,
reverse_node(_pipe)
end,
begin
_pipe@1 = Root,
reverse_rec(_pipe@1)
end,
begin
_pipe@2 = Pf,
reverse_node(_pipe@2)
end};
Tree@1 ->
Tree@1
end.
-spec append_rec(shine_tree(node_(IXM)), shine_tree(node_(IXM))) -> shine_tree(node_(IXM)).
append_rec(Tree_1, Tree_2) ->
_pipe = Tree_1,
append(_pipe, Tree_2).
-spec append(shine_tree(IXI), shine_tree(IXI)) -> shine_tree(IXI).
append(Tree_1, Tree_2) ->
case {Tree_1, Tree_2} of
{T1, empty} ->
T1;
{empty, T2} ->
T2;
{T1@1, {single, A}} ->
_pipe = T1@1,
push(_pipe, A);
{{single, A@1}, T2@1} ->
_pipe@1 = T2@1,
unshift(_pipe@1, A@1);
{{deep, Count1, Pf1, Root1, Sf1}, {deep, Count2, Pf2, Root2, Sf2}} ->
{deep,
Count1 + Count2,
Pf1,
begin
_pipe@2 = Root1,
_pipe@3 = push(_pipe@2, Sf1),
append_rec(
_pipe@3,
begin
_pipe@4 = Root2,
unshift(_pipe@4, Pf2)
end
)
end,
Sf2}
end.
-spec prepend(shine_tree(IXE), shine_tree(IXE)) -> shine_tree(IXE).
prepend(Tree_1, Tree_2) ->
append(Tree_2, Tree_1).
-spec concat(list(shine_tree(IXS))) -> shine_tree(IXS).
concat(Trees) ->
case Trees of
[] ->
empty;
[A] ->
A;
[A@1 | Rest] ->
append(A@1, concat(Rest))
end.
-spec do_fold_l_until(
shine_tree(JAE),
JAH,
fun((JAH, JAE) -> gleam@list:continue_or_stop(JAH))
) -> gleam@list:continue_or_stop(JAH).
do_fold_l_until(Tree, V, F) ->
case Tree of
empty ->
{continue, V};
{single, U} ->
F(V, U);
{deep, _, Pf, Root, Sf} ->
try_continue(
do_fold_node_l_until(Pf, V, F),
fun(V@1) ->
try_continue(
(do_fold_l_until(
Root,
V@1,
fun(V@2, Node) ->
do_fold_node_l_until(Node, V@2, F)
end
)),
fun(V@3) -> do_fold_node_l_until(Sf, V@3, F) end
)
end
)
end.
-spec fold_l_until(
shine_tree(IZU),
IZX,
fun((IZX, IZU) -> gleam@list:continue_or_stop(IZX))
) -> IZX.
fold_l_until(Tree, V, F) ->
_pipe = do_fold_l_until(Tree, V, F),
unwrap_fold_until(_pipe).
-spec try_foldl(
shine_tree(JDO),
JDR,
fun((JDR, JDO) -> {ok, JDR} | {error, JDS})
) -> {ok, JDR} | {error, JDS}.
try_foldl(Tree, Acc, F) ->
fold_l_until(
Tree,
{ok, Acc},
fun(Acc@1, U) ->
{ok, Acc@2} = case Acc@1 of
{ok, _} -> Acc@1;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"shine_tree"/utf8>>,
function => <<"try_foldl"/utf8>>,
line => 1248})
end,
case F(Acc@2, U) of
{ok, U@1} ->
{continue, {ok, U@1}};
{error, Err} ->
{stop, {error, Err}}
end
end
).
-spec find(shine_tree(IVQ), fun((IVQ) -> boolean())) -> {ok, IVQ} | {error, nil}.
find(Tree, F) ->
_pipe = (fold_l_until(Tree, none, fun(_, Item) -> case F(Item) of
true ->
{stop, {some, Item}};
false ->
{continue, none}
end end)),
gleam@option:to_result(_pipe, nil).
-spec find_map(shine_tree(IVT), fun((IVT) -> {ok, IVV} | {error, any()})) -> {ok,
IVV} |
{error, nil}.
find_map(Tree, F) ->
_pipe = (fold_l_until(Tree, none, fun(_, Item) -> case F(Item) of
{ok, Val} ->
{stop, {some, Val}};
_ ->
{continue, none}
end end)),
gleam@option:to_result(_pipe, nil).
-spec do_get_root(shine_tree(node_(JDF)), integer()) -> {ok, JDF} | {error, nil}.
do_get_root(Node, Index) ->
_pipe = (fold_l_until(
Node,
{error, Index},
fun(Index@1, Node@1) ->
{error, Index@2} = case Index@1 of
{error, _} -> Index@1;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"shine_tree"/utf8>>,
function => <<"do_get_root"/utf8>>,
line => 1209})
end,
get_node(Index@2, Node@1)
end
)),
gleam@result:nil_error(_pipe).
-spec get(shine_tree(JDB), integer()) -> {ok, JDB} | {error, nil}.
get(Tree, Index) ->
case {Tree, Index} of
{empty, _} ->
{error, nil};
{{single, U}, 0} ->
{ok, U};
{{single, _}, _} ->
{error, nil};
{{deep, Count, _, _, _}, Index@1} when (Index@1 >= Count) orelse (Index@1 < 0) ->
{error, nil};
{{deep, _, {one, U@1}, _, _}, 0} ->
{ok, U@1};
{{deep, _, {two, U@2, _}, _, _}, 0} ->
{ok, U@2};
{{deep, _, {three, U@3, _, _}, _, _}, 0} ->
{ok, U@3};
{{deep, _, {four, U@4, _, _, _}, _, _}, 0} ->
{ok, U@4};
{{deep, _, {two, _, V}, _, _}, 1} ->
{ok, V};
{{deep, _, {three, _, V@1, _}, _, _}, 1} ->
{ok, V@1};
{{deep, _, {four, _, V@2, _, _}, _, _}, 1} ->
{ok, V@2};
{{deep, _, {three, _, _, W}, _, _}, 2} ->
{ok, W};
{{deep, _, {four, _, _, W@1, _}, _, _}, 2} ->
{ok, W@1};
{{deep, _, {four, _, _, _, X}, _, _}, 3} ->
{ok, X};
{{deep, Count@1, _, _, {one, U@5}}, Index@2} when Index@2 =:= (Count@1 - 1) ->
{ok, U@5};
{{deep, Count@2, _, _, {two, _, U@6}}, Index@3} when Index@3 =:= (Count@2 - 1) ->
{ok, U@6};
{{deep, Count@3, _, _, {three, _, _, U@7}}, Index@4} when Index@4 =:= (Count@3 - 1) ->
{ok, U@7};
{{deep, Count@4, _, _, {four, _, _, _, U@8}}, Index@5} when Index@5 =:= (Count@4 - 1) ->
{ok, U@8};
{{deep, Count@5, _, _, {two, V@3, _}}, Index@6} when Index@6 =:= (Count@5 - 2) ->
{ok, V@3};
{{deep, Count@6, _, _, {three, _, V@4, _}}, Index@7} when Index@7 =:= (Count@6 - 2) ->
{ok, V@4};
{{deep, Count@7, _, _, {four, _, _, V@5, _}}, Index@8} when Index@8 =:= (Count@7 - 2) ->
{ok, V@5};
{{deep, Count@8, _, _, {three, W@2, _, _}}, Index@9} when Index@9 =:= (Count@8 - 3) ->
{ok, W@2};
{{deep, Count@9, _, _, {four, _, W@3, _, _}}, Index@10} when Index@10 =:= (Count@9 - 3) ->
{ok, W@3};
{{deep, Count@10, _, _, {four, X@1, _, _, _}}, Index@11} when Index@11 =:= (Count@10 - 4) ->
{ok, X@1};
{{deep, _, Pf, Root, _}, Index@12} ->
Index@13 = Index@12 - node_size(Pf),
do_get_root(Root, Index@13)
end.
-spec do_from_list_reverse(list(IWH)) -> shine_tree(IWH).
do_from_list_reverse(Value) ->
case Value of
[] ->
empty;
[A] ->
{single, A};
[A@1, B] ->
{deep, 2, {one, B}, empty, {one, A@1}};
[A@2, B@1, C] ->
{deep, 3, {two, C, B@1}, empty, {one, A@2}};
[A@3, B@2, C@1, D] ->
{deep, 4, {two, D, C@1}, empty, {two, B@2, A@3}};
[A@4, B@3, C@2, D@1, E] ->
{deep, 5, {three, E, D@1, C@2}, empty, {two, B@3, A@4}};
[A@5, B@4, C@3, D@2, E@1, F] ->
{deep, 6, {three, F, E@1, D@2}, empty, {three, C@3, B@4, A@5}};
[A@6, B@5, C@4, D@3, E@2, F@1, G] ->
{deep, 7, {four, G, F@1, E@2, D@3}, empty, {three, C@4, B@5, A@6}};
[A@7, B@6, C@5, D@4, E@3, F@2, G@1, H] ->
{deep,
8,
{four, H, G@1, F@2, E@3},
empty,
{four, D@4, C@5, B@6, A@7}};
[A@8, B@7, C@6, D@5, E@4, F@3, G@2, H@1, I] ->
{deep,
9,
{four, I, H@1, G@2, F@3},
{single, {one, E@4}},
{four, D@5, C@6, B@7, A@8}};
[A@9, B@8, C@7, D@6, E@5, F@4, G@3, H@2, I@1, J] ->
{deep,
10,
{four, J, I@1, H@2, G@3},
{single, {two, F@4, E@5}},
{four, D@6, C@7, B@8, A@9}};
[A@10, B@9, C@8, D@7, E@6, F@5, G@4, H@3, I@2, J@1, K] ->
{deep,
11,
{four, K, J@1, I@2, H@3},
{single, {three, G@4, F@5, E@6}},
{four, D@7, C@8, B@9, A@10}};
[A@11, B@10, C@9, D@8, E@7, F@6, G@5, H@4, I@3, J@2, K@1, L] ->
{deep,
12,
{four, L, K@1, J@2, I@3},
{single, {four, H@4, G@5, F@6, E@7}},
{four, D@8, C@9, B@10, A@11}};
[A@12, B@11, C@10, D@9 | Rest] ->
Tail = {four, D@9, C@10, B@11, A@12},
{Head, Nodes, Count} = do_chunk_values_reverse(Rest, [], 4),
{deep, Count, Head, do_from_list(Nodes), Tail}
end.
-spec do_from_list(list(IVN)) -> shine_tree(IVN).
do_from_list(Values) ->
case Values of
[] ->
empty;
[A] ->
{single, A};
[A@1, B] ->
{deep, 2, {one, A@1}, empty, {one, B}};
[A@2, B@1, C] ->
{deep, 3, {two, A@2, B@1}, empty, {one, C}};
[A@3, B@2, C@1, D] ->
{deep, 4, {two, A@3, B@2}, empty, {two, C@1, D}};
[A@4, B@3, C@2, D@1, E] ->
{deep, 5, {three, A@4, B@3, C@2}, empty, {two, D@1, E}};
[A@5, B@4, C@3, D@2, E@1, F] ->
{deep, 6, {three, A@5, B@4, C@3}, empty, {three, D@2, E@1, F}};
[A@6, B@5, C@4, D@3, E@2, F@1, G] ->
{deep, 7, {four, A@6, B@5, C@4, D@3}, empty, {three, E@2, F@1, G}};
[A@7, B@6, C@5, D@4, E@3, F@2, G@1, H] ->
{deep,
8,
{four, A@7, B@6, C@5, D@4},
empty,
{four, E@3, F@2, G@1, H}};
[A@8, B@7, C@6, D@5, E@4, F@3, G@2, H@1, I] ->
{deep,
9,
{four, A@8, B@7, C@6, D@5},
{single, {one, E@4}},
{four, F@3, G@2, H@1, I}};
[A@9, B@8, C@7, D@6, E@5, F@4, G@3, H@2, I@1, J] ->
{deep,
10,
{four, A@9, B@8, C@7, D@6},
{single, {two, E@5, F@4}},
{four, G@3, H@2, I@1, J}};
[A@10, B@9, C@8, D@7, E@6, F@5, G@4, H@3, I@2, J@1, K] ->
{deep,
11,
{four, A@10, B@9, C@8, D@7},
{single, {three, E@6, F@5, G@4}},
{four, H@3, I@2, J@1, K}};
[A@11, B@10, C@9, D@8, E@7, F@6, G@5, H@4, I@3, J@2, K@1, L] ->
{deep,
12,
{four, A@11, B@10, C@9, D@8},
{single, {four, E@7, F@6, G@5, H@4}},
{four, I@3, J@2, K@1, L}};
[A@12, B@11, C@10, D@9 | Rest] ->
{Tail, Rest@1, Count} = do_chunk_values(Rest, [], 4),
{deep,
Count,
{four, A@12, B@11, C@10, D@9},
do_from_list_reverse(Rest@1),
Tail}
end.
-spec from_list(list(IVK)) -> shine_tree(IVK).
from_list(Values) ->
do_from_list(Values).
-spec do_deep_range(integer(), integer(), list(node_(integer()))) -> shine_tree(node_(integer())).
do_deep_range(Start, Finish, Acc) ->
case Finish - Start of
0 ->
_pipe = [{one, Start} | Acc],
do_from_list_reverse(_pipe);
1 ->
_pipe@1 = [range_2(Start) | Acc],
do_from_list_reverse(_pipe@1);
2 ->
_pipe@2 = [range_3(Start) | Acc],
do_from_list_reverse(_pipe@2);
3 ->
_pipe@3 = [range_4(Start) | Acc],
do_from_list_reverse(_pipe@3);
4 ->
_pipe@4 = [{one, Finish}, range_4(Finish - 4) | Acc],
do_from_list_reverse(_pipe@4);
_ ->
do_deep_range(Start + 4, Finish, [range_4(Start) | Acc])
end.
-spec range(integer(), integer()) -> shine_tree(integer()).
range(Start, Finish) ->
case Finish - Start of
Val when Val < 0 ->
_pipe = range(Finish, Start),
reverse(_pipe);
0 ->
{single, Start};
1 ->
{deep, 2, {one, Start}, empty, {one, Finish}};
2 ->
{deep, 3, range_2(Start), empty, {one, Finish}};
3 ->
{deep, 4, {two, Start, Start + 1}, empty, {two, Start + 2, Finish}};
4 ->
{deep,
5,
{three, Start, Start + 1, Start + 2},
empty,
{two, Start + 3, Finish}};
5 ->
{deep,
6,
{three, Start, Start + 1, Start + 2},
empty,
{three, Start + 3, Start + 4, Finish}};
6 ->
{deep,
7,
{four, Start, Start + 1, Start + 2, Start + 3},
empty,
{three, Start + 4, Start + 5, Finish}};
7 ->
{deep,
8,
{four, Start, Start + 1, Start + 2, Start + 3},
empty,
{four, Start + 4, Start + 5, Start + 6, Finish}};
8 ->
{deep,
9,
{four, Start, Start + 1, Start + 2, Start + 3},
{single, {one, Start + 4}},
{four, Start + 5, Start + 6, Start + 7, Finish}};
9 ->
{deep,
10,
{four, Start, Start + 1, Start + 2, Start + 3},
{single, {two, Start + 4, Start + 5}},
{four, Start + 6, Start + 7, Start + 8, Finish}};
10 ->
{deep,
11,
{four, Start, Start + 1, Start + 2, Start + 3},
{single, {three, Start + 4, Start + 5, Start + 6}},
{four, Start + 7, Start + 8, Start + 9, Finish}};
11 ->
{deep,
12,
{four, Start, Start + 1, Start + 2, Start + 3},
{single, {four, Start + 4, Start + 5, Start + 6, Start + 7}},
{four, Start + 8, Start + 9, Start + 10, Finish}};
N ->
{deep,
N + 1,
range_4(Start),
do_deep_range(Start + 4, Finish - 4, []),
range_4(Finish - 3)}
end.
-spec shift(shine_tree(IUT)) -> {ok, {IUT, shine_tree(IUT)}} | {error, nil}.
shift(Tree) ->
case Tree of
empty ->
{error, nil};
{single, U} ->
{ok, {U, empty}};
{deep, _, {one, U@1}, empty, {one, V}} ->
{ok, {U@1, {single, V}}};
{deep, Count, {one, U@2}, empty, {two, V@1, W}} ->
{ok, {U@2, {deep, Count - 1, {one, V@1}, empty, {one, W}}}};
{deep, Count@1, {one, U@3}, empty, {three, V@2, W@1, X}} ->
{ok, {U@3, {deep, Count@1 - 1, {two, V@2, W@1}, empty, {one, X}}}};
{deep, Count@2, {one, U@4}, empty, {four, V@3, W@2, X@1, Y}} ->
{ok,
{U@4,
{deep, Count@2 - 1, {two, V@3, W@2}, empty, {two, X@1, Y}}}};
{deep, Count@3, {one, U@5}, Root, Sf} ->
_assert_subject = shift(Root),
{ok, {Pf, Root@1}} = case _assert_subject of
{ok, {_, _}} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"shine_tree"/utf8>>,
function => <<"shift"/utf8>>,
line => 293})
end,
{ok, {U@5, {deep, Count@3 - 1, Pf, Root@1, Sf}}};
{deep, Count@4, Pf@1, Root@2, Sf@1} ->
_assert_subject@1 = shift_node(Pf@1),
{ok, {U@6, Pf@2}} = case _assert_subject@1 of
{ok, {_, _}} -> _assert_subject@1;
_assert_fail@1 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail@1,
module => <<"shine_tree"/utf8>>,
function => <<"shift"/utf8>>,
line => 297})
end,
{ok, {U@6, {deep, Count@4 - 1, Pf@2, Root@2, Sf@1}}}
end.
-spec to_iterator(shine_tree(IVB)) -> gleam@iterator:iterator(IVB).
to_iterator(Tree) ->
gleam@iterator:unfold(Tree, fun(State) -> case shift(State) of
{ok, {Item, Next}} ->
{next, Item, Next};
{error, nil} ->
done
end end).
-spec equals(shine_tree(JBO), shine_tree(JBO)) -> boolean().
equals(A, B) ->
case {A, B} of
{A@1, B@1} when A@1 =:= B@1 ->
true;
{A@2, B@2} ->
case {shift(A@2), shift(B@2)} of
{{ok, {Item_a, A@3}}, {ok, {Item_b, B@3}}} when Item_a =:= Item_b ->
equals(A@3, B@3);
{_, _} ->
false
end
end.
-spec pop(shine_tree(IUL)) -> {ok, {IUL, shine_tree(IUL)}} | {error, nil}.
pop(Tree) ->
case Tree of
empty ->
{error, nil};
{single, U} ->
{ok, {U, empty}};
{deep, _, {one, V}, empty, {one, U@1}} ->
{ok, {U@1, {single, V}}};
{deep, Count, {two, V@1, W}, empty, {one, U@2}} ->
{ok, {U@2, {deep, Count - 1, {one, V@1}, empty, {one, W}}}};
{deep, Count@1, {three, V@2, W@1, X}, empty, {one, U@3}} ->
{ok, {U@3, {deep, Count@1 - 1, {two, V@2, W@1}, empty, {one, X}}}};
{deep, Count@2, {four, V@3, W@2, X@1, Y}, empty, {one, U@4}} ->
{ok,
{U@4,
{deep, Count@2 - 1, {two, V@3, W@2}, empty, {two, X@1, Y}}}};
{deep, Count@3, Pf, Root, {one, U@5}} ->
_assert_subject = pop(Root),
{ok, {Sf, Root@1}} = case _assert_subject of
{ok, {_, _}} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"shine_tree"/utf8>>,
function => <<"pop"/utf8>>,
line => 244})
end,
{ok, {U@5, {deep, Count@3 - 1, Pf, Root@1, Sf}}};
{deep, Count@4, Pf@1, Root@2, Sf@1} ->
_assert_subject@1 = pop_node(Sf@1),
{ok, {U@6, Sf@2}} = case _assert_subject@1 of
{ok, {_, _}} -> _assert_subject@1;
_assert_fail@1 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail@1,
module => <<"shine_tree"/utf8>>,
function => <<"pop"/utf8>>,
line => 248})
end,
{ok, {U@6, {deep, Count@4 - 1, Pf@1, Root@2, Sf@2}}}
end.
-spec unshift(shine_tree(IUI), IUI) -> shine_tree(IUI).
unshift(Tree, Value) ->
case Tree of
empty ->
{single, Value};
{single, V} ->
{deep, 2, {one, Value}, empty, {one, V}};
{deep, Count, {one, V@1}, Root, Sf} ->
{deep, Count + 1, {two, Value, V@1}, Root, Sf};
{deep, Count@1, {two, V@2, W}, Root@1, Sf@1} ->
{deep, Count@1 + 1, {three, Value, V@2, W}, Root@1, Sf@1};
{deep, Count@2, {three, V@3, W@1, X}, Root@2, Sf@2} ->
{deep, Count@2 + 1, {four, Value, V@3, W@1, X}, Root@2, Sf@2};
{deep, Count@3, Pf, Root@3, Sf@3} ->
{deep, Count@3 + 1, {one, Value}, unshift(Root@3, Pf), Sf@3}
end.
-spec push(shine_tree(IUF), IUF) -> shine_tree(IUF).
push(Tree, Value) ->
case Tree of
empty ->
{single, Value};
{single, V} ->
{deep, 2, {one, V}, empty, {one, Value}};
{deep, Count, Pf, Root, {one, V@1}} ->
{deep, Count + 1, Pf, Root, {two, V@1, Value}};
{deep, Count@1, Pf@1, Root@1, {two, V@2, W}} ->
{deep, Count@1 + 1, Pf@1, Root@1, {three, V@2, W, Value}};
{deep, Count@2, Pf@2, Root@2, {three, V@3, W@1, X}} ->
{deep, Count@2 + 1, Pf@2, Root@2, {four, V@3, W@1, X, Value}};
{deep, Count@3, Pf@3, Root@3, Sf} ->
{deep, Count@3 + 1, Pf@3, push(Root@3, Sf), {one, Value}}
end.
-spec push_node(shine_tree(IWV), node_(IWV)) -> shine_tree(IWV).
push_node(Tree, Node) ->
case {Tree, Node} of
{empty, {one, A}} ->
{single, A};
{empty, {two, A@1, B}} ->
{deep, 2, {one, A@1}, empty, {one, B}};
{empty, {three, A@2, B@1, C}} ->
{deep, 3, {one, A@2}, empty, {two, B@1, C}};
{empty, {four, A@3, B@2, C@1, D}} ->
{deep, 4, {two, A@3, B@2}, empty, {two, C@1, D}};
{{single, Node@1}, {one, A@4}} ->
{deep, 2, {one, Node@1}, empty, {one, A@4}};
{{single, Node@2}, {two, A@5, B@3}} ->
{deep, 3, {two, Node@2, A@5}, empty, {one, B@3}};
{{single, Node@3}, {three, A@6, B@4, C@2}} ->
{deep, 4, {two, Node@3, A@6}, empty, {two, B@4, C@2}};
{{single, Node@4}, {four, A@7, B@5, C@3, D@1}} ->
{deep, 5, {three, Node@4, A@7, B@5}, empty, {two, C@3, D@1}};
{{deep, Count, Pr, Body, Sf}, {one, A@8}} ->
{deep,
Count + 1,
Pr,
begin
_pipe = Body,
push(_pipe, Sf)
end,
{one, A@8}};
{{deep, Count@1, Pr@1, Body@1, Sf@1}, {two, A@9, B@6}} ->
{deep,
Count@1 + 2,
Pr@1,
begin
_pipe@1 = Body@1,
push(_pipe@1, Sf@1)
end,
{two, A@9, B@6}};
{{deep, Count@2, Pr@2, Body@2, Sf@2}, {three, A@10, B@7, C@4}} ->
{deep,
Count@2 + 3,
Pr@2,
begin
_pipe@2 = Body@2,
push(_pipe@2, Sf@2)
end,
{three, A@10, B@7, C@4}};
{{deep, Count@3, Pr@3, Body@3, Sf@3}, {four, A@11, B@8, C@5, D@2}} ->
{deep,
Count@3 + 4,
Pr@3,
begin
_pipe@3 = Body@3,
push(_pipe@3, Sf@3)
end,
{four, A@11, B@8, C@5, D@2}}
end.
-spec do_from_iterator(shine_tree(IWZ), gleam@iterator:iterator(node_(IWZ))) -> shine_tree(IWZ).
do_from_iterator(Acc, Rest) ->
case gleam@iterator:step(Rest) of
done ->
Acc;
{next, Node, Rest@1} ->
do_from_iterator(
begin
_pipe = Acc,
push_node(_pipe, Node)
end,
Rest@1
)
end.
-spec from_iterator(gleam@iterator:iterator(IWP)) -> shine_tree(IWP).
from_iterator(Iterable) ->
Node_iterator = begin
_pipe = gleam@iterator:sized_chunk(Iterable, 4),
gleam@iterator:map(_pipe, fun to_node/1)
end,
case gleam@iterator:step(Node_iterator) of
done ->
empty;
{next, {one, A}, Node_iterator@1} ->
do_from_iterator({single, A}, Node_iterator@1);
{next, {two, A@1, B}, Node_iterator@2} ->
do_from_iterator(
{deep, 2, {one, A@1}, empty, {one, B}},
Node_iterator@2
);
{next, {three, A@2, B@1, C}, Node_iterator@3} ->
do_from_iterator(
{deep, 3, {two, A@2, B@1}, empty, {one, C}},
Node_iterator@3
);
{next, {four, A@3, B@2, C@1, D}, Node_iterator@4} ->
do_from_iterator(
{deep, 4, {two, A@3, B@2}, empty, {two, C@1, D}},
Node_iterator@4
)
end.
-spec map_root(shine_tree(node_(ITZ)), fun((ITZ) -> IUC)) -> shine_tree(node_(IUC)).
map_root(Root, F) ->
map(Root, fun(Node) -> map_node(Node, F) end).
-spec map(shine_tree(ITR), fun((ITR) -> ITT)) -> shine_tree(ITT).
map(Tree, F) ->
case Tree of
empty ->
empty;
{single, U} ->
{single, F(U)};
{deep, Count, Pf, Root, Sf} ->
Pf@1 = map_node(Pf, F),
Root@1 = map_root(Root, F),
Sf@1 = map_node(Sf, F),
{deep, Count, Pf@1, Root@1, Sf@1}
end.
-spec fold_r_root(ITN, shine_tree(node_(ITO)), fun((ITN, ITO) -> ITN)) -> ITN.
fold_r_root(Acc, Root, F) ->
fold_r(Root, Acc, fun(Acc@1, Node) -> fold_r_node(Acc@1, Node, F) end).
-spec fold_r(shine_tree(ITF), any(), fun((ITI, ITF) -> ITI)) -> ITI.
fold_r(Tree, V, F) ->
case Tree of
empty ->
V;
{single, U} ->
F(V, U);
{deep, _, Pf, Root, Sf} ->
_pipe = V,
_pipe@1 = fold_r_node(_pipe, Sf, F),
_pipe@2 = fold_r_root(_pipe@1, Root, F),
fold_r_node(_pipe@2, Pf, F)
end.
-spec filter(shine_tree(IVE), fun((IVE) -> boolean())) -> shine_tree(IVE).
filter(Tree, F) ->
_pipe = (fold_r(Tree, [], fun(Acc, U) -> case F(U) of
true ->
[U | Acc];
false ->
Acc
end end)),
do_from_list(_pipe).
-spec to_list(shine_tree(IVH)) -> list(IVH).
to_list(Tree) ->
fold_r(Tree, [], fun(Acc, U) -> [U | Acc] end).
-spec fold_l_root(ITB, shine_tree(node_(ITC)), fun((ITB, ITC) -> ITB)) -> ITB.
fold_l_root(Acc, Root, F) ->
fold_l(Root, Acc, fun(Acc@1, Node) -> fold_l_node(Acc@1, Node, F) end).
-spec fold_l(shine_tree(IST), any(), fun((ISW, IST) -> ISW)) -> ISW.
fold_l(Tree, V, F) ->
case Tree of
empty ->
V;
{single, U} ->
F(V, U);
{deep, _, Pf, Root, Sf} ->
_pipe = V,
_pipe@1 = fold_l_node(_pipe, Pf, F),
_pipe@2 = fold_l_root(_pipe@1, Root, F),
fold_l_node(_pipe@2, Sf, F)
end.
-spec count(shine_tree(IZE), fun((IZE) -> boolean())) -> integer().
count(Tree, F) ->
fold_l(Tree, 0, fun(Acc, U) -> case F(U) of
true ->
Acc + 1;
false ->
Acc
end end).
-spec each(shine_tree(IZK), fun((IZK) -> any())) -> nil.
each(Tree, F) ->
fold_l(
Tree,
nil,
fun(_, Item) ->
F(Item),
nil
end
).
-spec filter_map(shine_tree(IZN), fun((IZN) -> {ok, IZP} | {error, any()})) -> shine_tree(IZP).
filter_map(Tree, F) ->
_pipe = (fold_l(Tree, [], fun(Acc, Item) -> case F(Item) of
{ok, B} ->
[B | Acc];
_ ->
Acc
end end)),
do_from_list_reverse(_pipe).
-spec partition(shine_tree(JBV), JBV, fun((JBV, JBV) -> gleam@order:order())) -> {list(JBV),
list(JBV)}.
partition(Tree, Pivot, Compare) ->
fold_l(
Tree,
{[], []},
fun(_use0, Item) ->
{Left, Right} = _use0,
case Compare(Item, Pivot) of
gt ->
{Left, [Item | Right]};
_ ->
{[Item | Left], Right}
end
end
).
-spec sort(shine_tree(JBS), fun((JBS, JBS) -> gleam@order:order())) -> shine_tree(JBS).
sort(Tree, Compare) ->
case Tree of
empty ->
empty;
{single, U} ->
{single, U};
_ ->
_assert_subject = shift(Tree),
{ok, {Pivot, Tree@1}} = case _assert_subject of
{ok, {_, _}} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"shine_tree"/utf8>>,
function => <<"sort"/utf8>>,
line => 1052})
end,
{Left, Right} = partition(Tree@1, Pivot, Compare),
Left@1 = gleam@list:sort(Left, Compare),
Right@1 = [Pivot | gleam@list:sort(Right, Compare)],
_pipe = lists:append(Left@1, Right@1),
from_list(_pipe)
end.
-spec do_group_by(
gleam@dict:dict(JCT, list(JCU)),
shine_tree(node_(JCU)),
fun((JCU) -> JCT)
) -> gleam@dict:dict(JCT, list(JCU)).
do_group_by(Dict, Tree, F) ->
fold_l(
Tree,
Dict,
fun(Final_dict, Item) -> do_group_by_node(Final_dict, Item, F) end
).
-spec group(shine_tree(JCG), fun((JCG) -> JCI)) -> gleam@dict:dict(JCI, shine_tree(JCG)).
group(Tree, F) ->
case Tree of
empty ->
gleam@dict:new();
{single, U} ->
gleam@dict:insert(gleam@dict:new(), F(U), {single, U});
{deep, _, Pf, Root, Sf} ->
_pipe = gleam@dict:new(),
_pipe@1 = do_group_by_node(_pipe, Pf, F),
_pipe@2 = do_group_by(_pipe@1, Root, F),
_pipe@3 = do_group_by_node(_pipe@2, Sf, F),
gleam@dict:map_values(
_pipe@3,
fun(_, Value) -> from_list(Value) end
)
end.