-module(molt@internal@cst@query). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/molt/internal/cst/query.gleam"). -export([collect_key_prefix/1, get_cursor_where/3, get_cursor/2, get/2]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC(false). -file("src/molt/internal/cst/query.gleam", 459). ?DOC(false). -spec is_kv_named(greenwood:node_(molt@types:toml_kind()), binary()) -> boolean(). is_kv_named(Node, Key) -> (erlang:element(2, Node) =:= key_value) andalso (molt@internal@cst@elements:key_name( erlang:element(3, Node) ) =:= {some, Key}). -file("src/molt/internal/cst/query.gleam", 490). ?DOC(false). -spec is_table_at(greenwood:node_(molt@types:toml_kind()), list(binary())) -> boolean(). is_table_at(Node, Path) -> ((erlang:element(2, Node) =:= table) orelse (erlang:element(2, Node) =:= array_of_tables)) andalso (molt@internal@cst@elements:extract_key_segments( erlang:element(3, Node) ) =:= Path). -file("src/molt/internal/cst/query.gleam", 468). ?DOC(false). -spec kv_key_segments(list(greenwood:element(molt@types:toml_kind()))) -> list(binary()). kv_key_segments(Children) -> case Children of [] -> []; [{token_element, {token, equals, _}} | _] -> []; [{node_element, N} | _] when erlang:element(2, N) =:= key -> molt@internal@cst@elements:extract_key_segments( erlang:element(3, N) ); [{token_element, {token, bare_key, Text}} | Rest] -> [Text | kv_key_segments(Rest)]; [{token_element, {token, basic_string, Text@1}} | Rest@1] -> [molt@internal@utils:unescape_basic_string(Text@1) | kv_key_segments(Rest@1)]; [{token_element, {token, literal_string, Text@2}} | Rest@2] -> [Text@2 | kv_key_segments(Rest@2)]; [_ | Rest@3] -> kv_key_segments(Rest@3) end. -file("src/molt/internal/cst/query.gleam", 463). ?DOC(false). -spec is_kv_with_path(greenwood:node_(molt@types:toml_kind()), list(binary())) -> boolean(). is_kv_with_path(Node, Path) -> (erlang:element(2, Node) =:= key_value) andalso (kv_key_segments( erlang:element(3, Node) ) =:= Path). -file("src/molt/internal/cst/query.gleam", 411). ?DOC(false). -spec try_shorter_table_prefix( greenwood:zipper(molt@types:toml_kind()), list(binary()), list(binary()), fun((greenwood:node_(molt@types:toml_kind())) -> boolean()) ) -> {ok, greenwood:zipper(molt@types:toml_kind())} | {error, list(binary())}. try_shorter_table_prefix(Cursor, Prefix, Full_prefix, Filter) -> case gleam@list:take(Prefix, erlang:length(Prefix) - 1) of [] -> {error, []}; Init -> case greenwood@zipper:down_where( Cursor, fun(_capture) -> is_table_at(_capture, Init) end ) of {some, Inner_cursor} -> Rest = gleam@list:drop(Full_prefix, erlang:length(Init)), case resolve_over_key(Inner_cursor, Rest, Filter) of {ok, Cursor@1} -> {ok, Cursor@1}; {error, _} -> {error, Init} end; none -> try_shorter_table_prefix(Cursor, Init, Full_prefix, Filter) end end. -file("src/molt/internal/cst/query.gleam", 329). ?DOC(false). -spec resolve_over_key( greenwood:zipper(molt@types:toml_kind()), list(binary()), fun((greenwood:node_(molt@types:toml_kind())) -> boolean()) ) -> {ok, greenwood:zipper(molt@types:toml_kind())} | {error, list(binary())}. resolve_over_key(Cursor, Prefix, Filter) -> case greenwood@zipper:down_where( Cursor, fun(N) -> is_table_at(N, Prefix) andalso Filter(N) end ) of {some, Cursor@1} -> {ok, Cursor@1}; none -> case Prefix of [] -> {error, []}; [Key] -> _pipe = greenwood@zipper:down_where( Cursor, fun(N@1) -> is_kv_named(N@1, Key) andalso Filter(N@1) end ), gleam@option:to_result(_pipe, []); _ -> case greenwood@zipper:down_where( Cursor, fun(N@2) -> is_kv_with_path(N@2, Prefix) andalso Filter(N@2) end ) of {some, Cursor@2} -> {ok, Cursor@2}; none -> try_shorter_table_prefix( Cursor, Prefix, Prefix, Filter ) end end end. -file("src/molt/internal/cst/query.gleam", 495). ?DOC(false). -spec is_array_of_tables_at( greenwood:node_(molt@types:toml_kind()), list(binary()) ) -> boolean(). is_array_of_tables_at(Node, Path) -> (erlang:element(2, Node) =:= array_of_tables) andalso (molt@internal@cst@elements:extract_key_segments( erlang:element(3, Node) ) =:= Path). -file("src/molt/internal/cst/query.gleam", 41). ?DOC(false). -spec collect_key_prefix(list(molt@types:path_segment())) -> list(binary()). collect_key_prefix(Path) -> case Path of [{key_segment, K} | Rest] -> [K | collect_key_prefix(Rest)]; _ -> [] end. -file("src/molt/internal/cst/query.gleam", 600). ?DOC(false). -spec count_right_matches( greenwood:zipper(molt@types:toml_kind()), list(binary()) ) -> integer(). count_right_matches(Cursor, Segments) -> case greenwood@zipper:right_where( Cursor, fun(_capture) -> is_array_of_tables_at(_capture, Segments) end ) of {some, Cursor@1} -> 1 + count_right_matches(Cursor@1, Segments); none -> 0 end. -file("src/molt/internal/cst/query.gleam", 500). ?DOC(false). -spec resolve_to_nth_match( greenwood:zipper(molt@types:toml_kind()), integer(), list(binary()) ) -> {ok, greenwood:zipper(molt@types:toml_kind())} | {error, nil}. resolve_to_nth_match(Cursor, Index, Segments) -> Count = count_right_matches(Cursor, Segments) + 1, Resolved = molt@internal@utils:resolve_index(Index, Count), case Resolved of 0 -> {ok, Cursor}; N when N > 0 -> _pipe = greenwood@zipper:right_n_where( Cursor, N, fun(_capture) -> is_array_of_tables_at(_capture, Segments) end ), gleam@option:to_result(_pipe, nil); _ -> {error, nil} end. -file("src/molt/internal/cst/query.gleam", 438). ?DOC(false). -spec resolve_into_array_of_tables( greenwood:zipper(molt@types:toml_kind()), list(binary()), integer() ) -> {ok, greenwood:zipper(molt@types:toml_kind())} | {error, nil}. resolve_into_array_of_tables(Cursor, Prefix, Index) -> case greenwood@zipper:down_where( Cursor, fun(_capture) -> is_array_of_tables_at(_capture, Prefix) end ) of {some, Cursor@1} -> resolve_to_nth_match(Cursor@1, Index, Prefix); none -> case Prefix of [Key | Rest] when Rest =/= [] -> gleam@result:'try'( begin _pipe = greenwood@zipper:down_where( Cursor, fun(_capture@1) -> is_table_at(_capture@1, [Key]) end ), gleam@option:to_result(_pipe, nil) end, fun(Cursor@2) -> resolve_into_array_of_tables(Cursor@2, Rest, Index) end ); _ -> {error, nil} end end. -file("src/molt/internal/cst/query.gleam", 163). ?DOC(false). -spec resolve_into_array_element_value(greenwood:zipper(molt@types:toml_kind())) -> {ok, greenwood:zipper(molt@types:toml_kind())} | {error, nil}. resolve_into_array_element_value(Cursor) -> _pipe = greenwood@zipper:down_where( Cursor, fun(N) -> (erlang:element(2, N) =:= inline_table) orelse (erlang:element(2, N) =:= array) end ), gleam@option:to_result(_pipe, nil). -file("src/molt/internal/cst/query.gleam", 152). ?DOC(false). -spec resolve_into_kv_value(greenwood:zipper(molt@types:toml_kind())) -> {ok, greenwood:zipper(molt@types:toml_kind())} | {error, nil}. resolve_into_kv_value(Cursor) -> _pipe = greenwood@zipper:down_where( Cursor, fun(N) -> (erlang:element(2, N) =:= array) orelse (erlang:element(2, N) =:= inline_table) end ), gleam@option:to_result(_pipe, nil). -file("src/molt/internal/cst/query.gleam", 586). ?DOC(false). -spec is_array_element(greenwood:node_(molt@types:toml_kind())) -> boolean(). is_array_element(N) -> erlang:element(2, N) =:= array_element. -file("src/molt/internal/cst/query.gleam", 590). ?DOC(false). -spec is_node( greenwood:element(molt@types:toml_kind()), fun((greenwood:node_(molt@types:toml_kind())) -> boolean()) ) -> boolean(). is_node(El, Predicate) -> case El of {node_element, N} -> Predicate(N); _ -> false end. -file("src/molt/internal/cst/query.gleam", 173). ?DOC(false). -spec resolve_into_nth_array_element( greenwood:zipper(molt@types:toml_kind()), integer() ) -> {ok, greenwood:zipper(molt@types:toml_kind())} | {error, nil}. resolve_into_nth_array_element(Cursor, Index) -> case greenwood@zipper:down_where(Cursor, fun is_array_element/1) of none -> {error, nil}; {some, Child_cursor} -> Count = gleam@list:count( erlang:element(3, erlang:element(2, Cursor)), fun(_capture) -> is_node(_capture, fun is_array_element/1) end ), Offset = molt@internal@utils:resolve_index(Index, Count), gleam@bool:guard( Offset < 0, {error, nil}, fun() -> _pipe = greenwood@zipper:right_n_where( Child_cursor, Offset, fun is_array_element/1 ), gleam@option:to_result(_pipe, nil) end ) end. -file("src/molt/internal/cst/query.gleam", 368). ?DOC(false). -spec resolve_under_key( greenwood:zipper(molt@types:toml_kind()), list(molt@types:path_segment()), list(binary()), list(molt@types:path_segment()), list(molt@types:path_segment()), list(binary()), fun((greenwood:node_(molt@types:toml_kind())) -> boolean()) ) -> {ok, greenwood:zipper(molt@types:toml_kind())} | {error, molt@error:molt_error()}. resolve_under_key( Cursor, After, Prefix, Segments, Visited, Resolved_prefix, Predicate ) -> case Prefix of [First_key | Rest_keys] -> case greenwood@zipper:down_where( Cursor, fun(_capture) -> is_kv_named(_capture, First_key) end ) of {some, Kv_cursor} -> Rest_path = lists:append( gleam@list:map( Rest_keys, fun(Field@0) -> {key_segment, Field@0} end ), After ), Kv_visited = [{key_segment, First_key} | Visited], resolve_path(Kv_cursor, Rest_path, Kv_visited, Predicate); none -> Visited@1 = lists:append( lists:reverse( gleam@list:map( Resolved_prefix, fun(Field@0) -> {key_segment, Field@0} end ) ), Visited ), {error, molt@error:not_found_path2(Segments, Visited@1)} end; _ -> Visited@2 = lists:append( lists:reverse( gleam@list:map( Resolved_prefix, fun(Field@0) -> {key_segment, Field@0} end ) ), Visited ), {error, molt@error:not_found_path2(Segments, Visited@2)} end. -file("src/molt/internal/cst/query.gleam", 529). ?DOC(false). -spec resolve_aot_scoped_path( greenwood:zipper(molt@types:toml_kind()), list(binary()), list(binary()), list(binary()), list(molt@types:path_segment()), list(molt@types:path_segment()), list(molt@types:path_segment()), fun((greenwood:node_(molt@types:toml_kind())) -> boolean()) ) -> {ok, greenwood:zipper(molt@types:toml_kind())} | {error, molt@error:molt_error()}. resolve_aot_scoped_path( Cursor, Aot_prefix, Sub_prefix, Full_sub_prefix, After, Segments, Visited, Predicate ) -> case Sub_prefix of [] -> {error, molt@error:not_found_path2(Segments, Visited)}; _ -> Full_table_path = lists:append(Aot_prefix, Sub_prefix), Remaining = lists:append( gleam@list:map( gleam@list:drop(Full_sub_prefix, erlang:length(Sub_prefix)), fun(Field@0) -> {key_segment, Field@0} end ), After ), Filter = case Remaining of [] -> Predicate; _ -> fun(_) -> true end end, Stop = fun(_capture) -> is_array_of_tables_at(_capture, Aot_prefix) end, case greenwood@zipper:right_until( Cursor, fun(N) -> is_table_at(N, Full_table_path) andalso Filter(N) end, Stop ) of {some, Sub_cursor} -> resolve_path(Sub_cursor, Remaining, Visited, Predicate); none -> resolve_aot_scoped_path( Cursor, Aot_prefix, gleam@list:take( Sub_prefix, erlang:length(Sub_prefix) - 1 ), Full_sub_prefix, After, Segments, Visited, Predicate ) end end. -file("src/molt/internal/cst/query.gleam", 281). ?DOC(false). -spec resolve_into_index_after_key( greenwood:zipper(molt@types:toml_kind()), integer(), list(binary()), list(molt@types:path_segment()), list(molt@types:path_segment()), list(molt@types:path_segment()), list(molt@types:path_segment()), fun((greenwood:node_(molt@types:toml_kind())) -> boolean()) ) -> {ok, greenwood:zipper(molt@types:toml_kind())} | {error, molt@error:molt_error()}. resolve_into_index_after_key( Cursor, Index, Prefix, Segments, Rest, Visited, New_visited, Predicate ) -> case resolve_into_array_of_tables(Cursor, Prefix, Index) of {ok, Found} -> Sub_prefix = collect_key_prefix(Rest), After = gleam@list:drop(Rest, erlang:length(Sub_prefix)), _pipe = resolve_path(Found, Rest, New_visited, Predicate), gleam@result:lazy_or( _pipe, fun() -> resolve_aot_scoped_path( Found, Prefix, Sub_prefix, Sub_prefix, After, Segments, New_visited, Predicate ) end ); {error, nil} -> case Prefix of [Key] -> case greenwood@zipper:down_where( Cursor, fun(_capture) -> is_kv_named(_capture, Key) end ) of {some, Kv_cursor} -> resolve_path( Kv_cursor, [{index_segment, Index} | Rest], [{key_segment, Key} | Visited], Predicate ); none -> {error, molt@error:not_found_path2(Segments, Visited)} end; _ -> {error, molt@error:not_found_path2(Segments, Visited)} end end. -file("src/molt/internal/cst/query.gleam", 226). ?DOC(false). -spec resolve_into_key( greenwood:zipper(molt@types:toml_kind()), list(molt@types:path_segment()), list(molt@types:path_segment()), fun((greenwood:node_(molt@types:toml_kind())) -> boolean()) ) -> {ok, greenwood:zipper(molt@types:toml_kind())} | {error, molt@error:molt_error()}. resolve_into_key(Cursor, Segments, Visited, Predicate) -> Prefix = collect_key_prefix(Segments), After = gleam@list:drop(Segments, erlang:length(Prefix)), New_visited = lists:append( lists:reverse( gleam@list:map(Prefix, fun(Field@0) -> {key_segment, Field@0} end) ), Visited ), case After of [{index_segment, Index} | Rest] -> resolve_into_index_after_key( Cursor, Index, Prefix, Segments, Rest, Visited, New_visited, Predicate ); _ -> Filter = case After =:= [] of true -> Predicate; false -> fun(_) -> true end end, case resolve_over_key(Cursor, Prefix, Filter) of {ok, Found} -> resolve_path(Found, After, New_visited, Predicate); {error, Resolved_prefix} -> resolve_under_key( Cursor, After, Prefix, Segments, Visited, Resolved_prefix, Predicate ) end end. -file("src/molt/internal/cst/query.gleam", 197). ?DOC(false). -spec resolve_into_inline_table( greenwood:zipper(molt@types:toml_kind()), list(molt@types:path_segment()), list(molt@types:path_segment()), fun((greenwood:node_(molt@types:toml_kind())) -> boolean()) ) -> {ok, greenwood:zipper(molt@types:toml_kind())} | {error, molt@error:molt_error()}. resolve_into_inline_table(Cursor, Segments, Visited, Predicate) -> case Segments of [] -> {ok, Cursor}; [{key_segment, Key} | Rest] -> gleam@result:'try'( begin _pipe = greenwood@zipper:down_where( Cursor, fun(_capture) -> is_kv_named(_capture, Key) end ), gleam@option:to_result( _pipe, molt@error:not_found_path3(Segments, Rest, Visited) ) end, fun(Cursor@1) -> case Rest of [] -> gleam@bool:guard( Predicate(erlang:element(2, Cursor@1)), {ok, Cursor@1}, fun() -> {error, molt@error:not_found_path2( Segments, Visited )} end ); _ -> Visited@1 = [{key_segment, Key} | Visited], resolve_path(Cursor@1, Rest, Visited@1, Predicate) end end ); _ -> {error, molt@error:not_found_path2(Segments, Visited)} end. -file("src/molt/internal/cst/query.gleam", 118). ?DOC(false). -spec resolve_path_by_key( greenwood:zipper(molt@types:toml_kind()), list(molt@types:path_segment()), list(molt@types:path_segment()), fun((greenwood:node_(molt@types:toml_kind())) -> boolean()) ) -> {ok, greenwood:zipper(molt@types:toml_kind())} | {error, molt@error:molt_error()}. resolve_path_by_key(Cursor, Segments, Visited, Predicate) -> case erlang:element(2, erlang:element(2, Cursor)) of inline_table -> resolve_into_inline_table(Cursor, Segments, Visited, Predicate); key_value -> gleam@result:'try'( begin _pipe = resolve_into_kv_value(Cursor), gleam@result:replace_error( _pipe, molt@error:not_found_path2(Segments, Visited) ) end, fun(Cursor@1) -> resolve_path(Cursor@1, Segments, Visited, Predicate) end ); array_element -> gleam@result:'try'( begin _pipe@1 = resolve_into_array_element_value(Cursor), gleam@result:replace_error( _pipe@1, molt@error:not_found_path2(Segments, Visited) ) end, fun(Cursor@2) -> resolve_path(Cursor@2, Segments, Visited, Predicate) end ); _ -> resolve_into_key(Cursor, Segments, Visited, Predicate) end. -file("src/molt/internal/cst/query.gleam", 72). ?DOC(false). -spec resolve_path_by_index( greenwood:zipper(molt@types:toml_kind()), integer(), list(molt@types:path_segment()), list(molt@types:path_segment()), list(molt@types:path_segment()), fun((greenwood:node_(molt@types:toml_kind())) -> boolean()) ) -> {ok, greenwood:zipper(molt@types:toml_kind())} | {error, molt@error:molt_error()}. resolve_path_by_index(Cursor, Index, Segments, Rest, Visited, Predicate) -> case erlang:element(2, erlang:element(2, Cursor)) of array -> gleam@result:'try'( begin _pipe = resolve_into_nth_array_element(Cursor, Index), gleam@result:replace_error( _pipe, molt@error:not_found_path3(Segments, Rest, Visited) ) end, fun(Cursor@1) -> resolve_path( Cursor@1, Rest, [{index_segment, Index} | Visited], Predicate ) end ); key_value -> gleam@result:'try'( begin _pipe@1 = resolve_into_kv_value(Cursor), gleam@result:replace_error( _pipe@1, molt@error:not_found_path3(Segments, Rest, Visited) ) end, fun(Cursor@2) -> resolve_path(Cursor@2, Segments, Visited, Predicate) end ); array_element -> gleam@result:'try'( begin _pipe@2 = resolve_into_array_element_value(Cursor), gleam@result:replace_error( _pipe@2, molt@error:not_found_path3(Segments, Rest, Visited) ) end, fun(Cursor@3) -> resolve_path(Cursor@3, Segments, Visited, Predicate) end ); _ -> {error, molt@error:not_found_path2(Segments, Visited)} end. -file("src/molt/internal/cst/query.gleam", 48). ?DOC(false). -spec resolve_path( greenwood:zipper(molt@types:toml_kind()), list(molt@types:path_segment()), list(molt@types:path_segment()), fun((greenwood:node_(molt@types:toml_kind())) -> boolean()) ) -> {ok, greenwood:zipper(molt@types:toml_kind())} | {error, molt@error:molt_error()}. resolve_path(Cursor, Segments, Visited, Predicate) -> case Segments of [] -> {ok, Cursor}; [{index_segment, Index} | Rest] -> resolve_path_by_index( Cursor, Index, Segments, Rest, Visited, Predicate ); [{key_segment, _} | _] -> resolve_path_by_key(Cursor, Segments, Visited, Predicate) end. -file("src/molt/internal/cst/query.gleam", 30). ?DOC(false). -spec get_cursor_where( greenwood:node_(molt@types:toml_kind()), list(molt@types:path_segment()), fun((greenwood:node_(molt@types:toml_kind())) -> boolean()) ) -> {ok, greenwood:zipper(molt@types:toml_kind())} | {error, molt@error:molt_error()}. get_cursor_where(Node, Segments, Predicate) -> _pipe = Node, _pipe@1 = greenwood@zipper:zip(_pipe), resolve_path(_pipe@1, Segments, [], Predicate). -file("src/molt/internal/cst/query.gleam", 23). ?DOC(false). -spec get_cursor( greenwood:node_(molt@types:toml_kind()), list(molt@types:path_segment()) ) -> {ok, greenwood:zipper(molt@types:toml_kind())} | {error, molt@error:molt_error()}. get_cursor(Node, Segments) -> get_cursor_where(Node, Segments, fun(_) -> true end). -file("src/molt/internal/cst/query.gleam", 15). ?DOC(false). -spec get( greenwood:node_(molt@types:toml_kind()), list(molt@types:path_segment()) ) -> {ok, greenwood:node_(molt@types:toml_kind())} | {error, molt@error:molt_error()}. get(Node, Segments) -> _pipe = get_cursor(Node, Segments), gleam@result:map(_pipe, fun(Cursor) -> erlang:element(2, Cursor) end).