-module(caffeine_lang@phase_4@slo_resolver). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/caffeine_lang/phase_4/slo_resolver.gleam"). -export([convert_list_to_or_expression/2, parse_list_value/2, inner_parse_string/1, inner_parse_int/1, resolve_sli/3, resolve_slo/3, resolve_slos/1]). -file("src/caffeine_lang/phase_4/slo_resolver.gleam", 217). -spec cleanup_empty_optionals(binary()) -> binary(). cleanup_empty_optionals(Query) -> _pipe = Query, _pipe@1 = gleam@string:replace(_pipe, <<", , , "/utf8>>, <<", "/utf8>>), _pipe@2 = gleam@string:replace(_pipe@1, <<", , "/utf8>>, <<", "/utf8>>), _pipe@3 = gleam@string:replace(_pipe@2, <<"{, "/utf8>>, <<"{"/utf8>>), _pipe@4 = gleam@string:replace(_pipe@3, <<", }"/utf8>>, <<"}"/utf8>>), _pipe@5 = gleam@string:replace(_pipe@4, <<", )"/utf8>>, <<")"/utf8>>), gleam@string:replace(_pipe@5, <<"{,}"/utf8>>, <<"{}"/utf8>>). -file("src/caffeine_lang/phase_4/slo_resolver.gleam", 244). -spec convert_commas_in_braces(binary(), binary(), boolean()) -> binary(). convert_commas_in_braces(Remaining, Acc, Inside_braces) -> case gleam_stdlib:string_pop_grapheme(Remaining) of {ok, {<<"{"/utf8>>, Rest}} -> convert_commas_in_braces(Rest, <>, true); {ok, {<<"}"/utf8>>, Rest@1}} -> convert_commas_in_braces(Rest@1, <>, false); {ok, {<<","/utf8>>, Rest@2}} -> case Inside_braces of true -> case gleam_stdlib:string_pop_grapheme(Rest@2) of {ok, {<<" "/utf8>>, Rest2}} -> convert_commas_in_braces( Rest2, <>, true ); _ -> convert_commas_in_braces( Rest@2, <>, true ) end; false -> convert_commas_in_braces( Rest@2, <>, false ) end; {ok, {Char, Rest@3}} -> convert_commas_in_braces( Rest@3, <>, Inside_braces ); {error, _} -> Acc end. -file("src/caffeine_lang/phase_4/slo_resolver.gleam", 234). -spec convert_commas_to_and(binary()) -> binary(). convert_commas_to_and(Query) -> case gleam_stdlib:contains_string(Query, <<" OR "/utf8>>) of true -> convert_commas_in_braces(Query, <<""/utf8>>, false); false -> Query end. -file("src/caffeine_lang/phase_4/slo_resolver.gleam", 354). -spec parse_template_variable(binary()) -> {ok, {binary(), binary(), boolean()}} | {error, binary()}. parse_template_variable(Template_var) -> Content = begin _pipe = Template_var, gleam@string:replace(_pipe, <<"$$"/utf8>>, <<""/utf8>>) end, {Content@1, Is_negated} = case gleam_stdlib:string_starts_with( Content, <<"NOT["/utf8>> ) of true -> Inner = begin _pipe@1 = Content, _pipe@2 = gleam@string:replace( _pipe@1, <<"NOT["/utf8>>, <<""/utf8>> ), gleam@string:replace(_pipe@2, <<"]"/utf8>>, <<""/utf8>>) end, {Inner, true}; false -> {Content, false} end, case gleam@string:split(Content@1, <<"->"/utf8>>) of [Field_name, Var_name] -> {ok, {Field_name, Var_name, Is_negated}}; _ -> {error, <<<<"Invalid template variable format: "/utf8, Template_var/binary>>/binary, ". Expected $$field->var$$ or $$NOT[field->var]$$"/utf8>>} end. -file("src/caffeine_lang/phase_4/slo_resolver.gleam", 477). -spec convert_list_to_or_expression(list(binary()), binary()) -> binary(). convert_list_to_or_expression(Items, Field_name) -> case Items of [] -> <<"[]"/utf8>>; [Single] -> Value = <<<>/binary, Single/binary>>, case ((gleam_stdlib:contains_string(Single, <<"*"/utf8>>) orelse gleam_stdlib:contains_string( Single, <<"+"/utf8>> )) orelse gleam_stdlib:contains_string(Single, <<"-"/utf8>>)) orelse gleam_stdlib:contains_string(Single, <<"/"/utf8>>) of true -> <<<<"("/utf8, Value/binary>>/binary, ")"/utf8>>; false -> Value end; _ -> Or_parts = gleam@list:map( Items, fun(Item) -> <<<>/binary, Item/binary>> end ), <<<<"("/utf8, (gleam@string:join(Or_parts, <<" OR "/utf8>>))/binary>>/binary, ")"/utf8>> end. -file("src/caffeine_lang/phase_4/slo_resolver.gleam", 496). -spec parse_list_value( binary(), fun((binary()) -> {ok, PRC} | {error, binary()}) ) -> {ok, list(PRC)} | {error, binary()}. parse_list_value(Value, Inner_parse) -> Splitted = gleam@string:split(Value, <<"]"/utf8>>), Splitted@1 = gleam@string:split( gleam@string:join(Splitted, <<""/utf8>>), <<"["/utf8>> ), Content = begin _pipe = gleam@string:join(Splitted@1, <<""/utf8>>), gleam@string:trim(_pipe) end, case Content of <<""/utf8>> -> {error, <<"Empty list not allowed: list must contain at least one value"/utf8>>}; _ -> Parse_result = begin _pipe@1 = Content, _pipe@2 = gleam@string:split(_pipe@1, <<","/utf8>>), _pipe@3 = gleam@list:map(_pipe@2, Inner_parse), gleam@result:all(_pipe@3) end, case Parse_result of {error, Parse_error} -> {error, <<"Failed to parse list values: "/utf8, Parse_error/binary>>}; {ok, Parsed_list} -> {ok, Parsed_list} end end. -file("src/caffeine_lang/phase_4/slo_resolver.gleam", 523). -spec inner_parse_string(binary()) -> {ok, binary()} | {error, binary()}. inner_parse_string(Value) -> Splitted = gleam@string:split(Value, <<"\""/utf8>>), Result = begin _pipe = gleam@string:join(Splitted, <<""/utf8>>), gleam@string:trim(_pipe) end, {ok, Result}. -file("src/caffeine_lang/phase_4/slo_resolver.gleam", 532). -spec inner_parse_int(binary()) -> {ok, integer()} | {error, binary()}. inner_parse_int(Value) -> case gleam_stdlib:parse_int(gleam@string:trim(Value)) of {ok, Int_value} -> {ok, Int_value}; {error, _} -> {error, <<"Invalid integer value: "/utf8, Value/binary>>} end. -file("src/caffeine_lang/phase_4/slo_resolver.gleam", 539). -spec find_filter_type(caffeine_lang@types@ast@sli_type:sli_type(), binary()) -> {ok, caffeine_lang@types@common@accepted_types:accepted_types()} | {error, binary()}. find_filter_type(Sli_type, Filter_name) -> _pipe = erlang:element(5, Sli_type), _pipe@1 = gleam@list:find( _pipe, fun(Basic_type) -> erlang:element(2, Basic_type) =:= Filter_name end ), _pipe@2 = gleam@result:map( _pipe@1, fun(Basic_type@1) -> erlang:element(3, Basic_type@1) end ), gleam@result:replace_error(_pipe@2, <<"Filter type not found"/utf8>>). -file("src/caffeine_lang/phase_4/slo_resolver.gleam", 384). -spec process_filter_value( binary(), caffeine_lang@types@ast@sli_type:sli_type(), binary(), binary() ) -> {ok, binary()} | {error, binary()}. process_filter_value(Value, Sli_type, Filter_name, Field_name) -> case find_filter_type(Sli_type, Filter_name) of {ok, {non_empty_list, Inner_type}} -> case Inner_type of string -> case parse_list_value(Value, fun inner_parse_string/1) of {ok, Parsed_list} -> case Parsed_list of [] -> {error, <<<<"Empty list not allowed for NonEmptyList field '"/utf8, Filter_name/binary>>/binary, "': must contain at least one value"/utf8>>}; _ -> {ok, convert_list_to_or_expression( Parsed_list, Field_name )} end; {error, Err} -> {error, <<<<<<"Error parsing NonEmptyList field '"/utf8, Filter_name/binary>>/binary, "': "/utf8>>/binary, Err/binary>>} end; integer -> case parse_list_value(Value, fun inner_parse_int/1) of {ok, Parsed_list@1} -> case Parsed_list@1 of [] -> {error, <<<<"Empty list not allowed for NonEmptyList field '"/utf8, Filter_name/binary>>/binary, "': must contain at least one value"/utf8>>}; _ -> {ok, convert_list_to_or_expression( gleam@list:map( Parsed_list@1, fun erlang:integer_to_binary/1 ), Field_name )} end; {error, Err@1} -> {error, <<<<<<"Error parsing NonEmptyList field '"/utf8, Filter_name/binary>>/binary, "': "/utf8>>/binary, Err@1/binary>>} end; _ -> {ok, <<<>/binary, Value/binary>>} end; {ok, {optional, Inner_type@1}} -> case Inner_type@1 of {non_empty_list, List_inner_type} -> case List_inner_type of string -> case parse_list_value( Value, fun inner_parse_string/1 ) of {ok, Parsed_list@2} -> case Parsed_list@2 of [] -> {error, <<<<"Empty list not allowed for NonEmptyList field '"/utf8, Filter_name/binary>>/binary, "': must contain at least one value"/utf8>>}; _ -> {ok, convert_list_to_or_expression( Parsed_list@2, Field_name )} end; {error, Err@2} -> {error, <<<<<<"Error parsing NonEmptyList field '"/utf8, Filter_name/binary>>/binary, "': "/utf8>>/binary, Err@2/binary>>} end; integer -> case parse_list_value(Value, fun inner_parse_int/1) of {ok, Parsed_list@3} -> case Parsed_list@3 of [] -> {error, <<<<"Empty list not allowed for NonEmptyList field '"/utf8, Filter_name/binary>>/binary, "': must contain at least one value"/utf8>>}; _ -> {ok, convert_list_to_or_expression( gleam@list:map( Parsed_list@3, fun erlang:integer_to_binary/1 ), Field_name )} end; {error, Err@3} -> {error, <<<<<<"Error parsing NonEmptyList field '"/utf8, Filter_name/binary>>/binary, "': "/utf8>>/binary, Err@3/binary>>} end; _ -> {ok, <<<>/binary, Value/binary>>} end; string -> {ok, <<<>/binary, Value/binary>>}; integer -> {ok, <<<>/binary, Value/binary>>}; boolean -> {ok, <<<>/binary, Value/binary>>}; decimal -> {ok, <<<>/binary, Value/binary>>}; _ -> {ok, <<<>/binary, Value/binary>>} end; _ -> {ok, <<<>/binary, Value/binary>>} end. -file("src/caffeine_lang/phase_4/slo_resolver.gleam", 292). -spec process_template_variable( binary(), gleam@dict:dict(binary(), binary()), caffeine_lang@types@ast@sli_type:sli_type() ) -> {ok, binary()} | {error, binary()}. process_template_variable(Template_var, Filters, Sli_type) -> gleam@result:'try'( parse_template_variable(Template_var), fun(_use0) -> {Field_name, Var_name, Is_negated} = _use0, case find_filter_type(Sli_type, Var_name) of {ok, {optional, _}} -> case gleam_stdlib:map_get(Filters, Var_name) of {ok, Value} -> gleam@result:'try'( process_filter_value( Value, Sli_type, Var_name, Field_name ), fun(Processed_value) -> case Is_negated of true -> {ok, <<<<"NOT ("/utf8, Processed_value/binary>>/binary, ")"/utf8>>}; false -> {ok, Processed_value} end end ); {error, _} -> {ok, <<""/utf8>>} end; _ -> case gleam_stdlib:map_get(Filters, Var_name) of {ok, Value@1} -> gleam@result:'try'( process_filter_value( Value@1, Sli_type, Var_name, Field_name ), fun(Processed_value@1) -> case Is_negated of true -> {ok, <<<<"NOT ("/utf8, Processed_value@1/binary>>/binary, ")"/utf8>>}; false -> {ok, Processed_value@1} end end ); {error, _} -> {error, <<<<"Template variable '"/utf8, Var_name/binary>>/binary, "' not found in filters"/utf8>>} end end end ). -file("src/caffeine_lang/phase_4/slo_resolver.gleam", 186). -spec process_template_parts( list(binary()), list(binary()), gleam@dict:dict(binary(), binary()), caffeine_lang@types@ast@sli_type:sli_type(), boolean() ) -> {ok, binary()} | {error, binary()}. process_template_parts(Parts, Acc, Filters, Sli_type, Is_variable) -> case Parts of [] -> {ok, gleam@string:join(lists:reverse(Acc), <<""/utf8>>)}; [Part | Rest] -> case Is_variable of false -> process_template_parts( Rest, [Part | Acc], Filters, Sli_type, true ); true -> gleam@result:'try'( process_template_variable(Part, Filters, Sli_type), fun(Replacement) -> process_template_parts( Rest, [Replacement | Acc], Filters, Sli_type, false ) end ) end end. -file("src/caffeine_lang/phase_4/slo_resolver.gleam", 169). -spec process_template_string( binary(), gleam@dict:dict(binary(), binary()), caffeine_lang@types@ast@sli_type:sli_type() ) -> {ok, binary()} | {error, binary()}. process_template_string(Template, Filters, Sli_type) -> Parts = gleam@string:split(Template, <<"$$"/utf8>>), gleam@result:'try'( process_template_parts(Parts, [], Filters, Sli_type, false), fun(Result) -> Cleaned = cleanup_empty_optionals(Result), {ok, convert_commas_to_and(Cleaned)} end ). -file("src/caffeine_lang/phase_4/slo_resolver.gleam", 130). -spec resolve_primary( caffeine_lang@cql@parser:primary(), gleam@dict:dict(binary(), binary()) ) -> {ok, caffeine_lang@cql@parser:primary()} | {error, binary()}. resolve_primary(Primary, Resolved_queries) -> case Primary of {primary_word, Word} -> case Word of {word, Word_value} -> case gleam_stdlib:map_get(Resolved_queries, Word_value) of {ok, Resolved_value} -> case caffeine_lang@cql@parser:parse_expr( Resolved_value ) of {ok, Parsed_exp} -> case Parsed_exp of {exp_container, Exp} -> {ok, {primary_exp, Exp}} end; {error, _} -> {ok, {primary_word, {word, Resolved_value}}} end; {error, _} -> {ok, {primary_word, Word}} end end; {primary_exp, Exp@1} -> gleam@result:'try'( resolve_exp(Exp@1, Resolved_queries), fun(Resolved_exp) -> {ok, {primary_exp, Resolved_exp}} end ) end. -file("src/caffeine_lang/phase_4/slo_resolver.gleam", 110). -spec resolve_exp( caffeine_lang@cql@parser:exp(), gleam@dict:dict(binary(), binary()) ) -> {ok, caffeine_lang@cql@parser:exp()} | {error, binary()}. resolve_exp(Exp, Resolved_queries) -> case Exp of {operator_expr, Left, Right, Op} -> gleam@result:'try'( resolve_exp(Left, Resolved_queries), fun(Resolved_left) -> gleam@result:'try'( resolve_exp(Right, Resolved_queries), fun(Resolved_right) -> {ok, {operator_expr, Resolved_left, Resolved_right, Op}} end ) end ); {primary, Primary} -> gleam@result:'try'( resolve_primary(Primary, Resolved_queries), fun(Resolved_primary) -> {ok, {primary, Resolved_primary}} end ) end. -file("src/caffeine_lang/phase_4/slo_resolver.gleam", 98). -spec resolve_cql_query( caffeine_lang@cql@parser:exp_container(), gleam@dict:dict(binary(), binary()) ) -> {ok, caffeine_lang@cql@parser:exp_container()} | {error, binary()}. resolve_cql_query(Query, Resolved_queries) -> case Query of {exp_container, Exp} -> gleam@result:'try'( resolve_exp(Exp, Resolved_queries), fun(Resolved_exp) -> {ok, {exp_container, Resolved_exp}} end ) end. -file("src/caffeine_lang/phase_4/slo_resolver.gleam", 61). -spec resolve_sli( gleam@dict:dict(binary(), binary()), caffeine_lang@types@ast@sli_type:sli_type(), binary() ) -> {ok, caffeine_lang@types@resolved@resolved_sli:sli()} | {error, binary()}. resolve_sli(Filters, Sli_type, Slo_name) -> gleam@result:'try'( begin _pipe = erlang:element(4, Sli_type), _pipe@1 = caffeine_lang@types@common@generic_dictionary:to_string_dict( _pipe ), _pipe@2 = maps:to_list(_pipe@1), _pipe@3 = gleam@list:try_map( _pipe@2, fun(Pair) -> {Metric_attribute, Template} = Pair, gleam@result:'try'( process_template_string(Template, Filters, Sli_type), fun(Processed) -> {ok, {Metric_attribute, Processed}} end ) end ), gleam@result:map(_pipe@3, fun maps:from_list/1) end, fun(Resolved_queries) -> gleam@result:'try'( resolve_cql_query( erlang:element(4, erlang:element(3, Sli_type)), Resolved_queries ), fun(Resolved_query) -> {ok, {sli, Slo_name, erlang:element(3, Sli_type), Resolved_queries, Resolved_query}} end ) end ). -file("src/caffeine_lang/phase_4/slo_resolver.gleam", 35). -spec resolve_slo( caffeine_lang@types@ast@slo:slo(), binary(), list(caffeine_lang@types@ast@sli_type:sli_type()) ) -> {ok, caffeine_lang@types@resolved@resolved_slo:slo()} | {error, binary()}. resolve_slo(Slo, Team_name, Sli_types) -> Sli_type@2 = case begin _pipe = Sli_types, gleam@list:find( _pipe, fun(Sli_type) -> erlang:element(2, Sli_type) =:= erlang:element(5, Slo) end ) end of {ok, Sli_type@1} -> Sli_type@1; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"caffeine_lang/phase_4/slo_resolver"/utf8>>, function => <<"resolve_slo"/utf8>>, line => 40, value => _assert_fail, start => 1064, 'end' => 1168, pattern_start => 1075, pattern_end => 1087}) end, Filters_dict = caffeine_lang@types@common@generic_dictionary:to_string_dict( erlang:element(3, Slo) ), gleam@result:'try'( resolve_sli(Filters_dict, Sli_type@2, erlang:element(2, Slo)), fun(Resolve_sli) -> {ok, {slo, erlang:element(7, Slo), erlang:element(4, Slo), erlang:element(6, Slo), Team_name, Resolve_sli}} end ). -file("src/caffeine_lang/phase_4/slo_resolver.gleam", 15). -spec resolve_slos(caffeine_lang@types@ast@organization:organization()) -> {ok, list(caffeine_lang@types@resolved@resolved_slo:slo())} | {error, binary()}. resolve_slos(Organization) -> Sli_types = begin _pipe = erlang:element(3, Organization), _pipe@1 = gleam@list:flat_map( _pipe, fun(Service_definition) -> erlang:element(3, Service_definition) end ), gleam@list:unique(_pipe@1) end, _pipe@2 = erlang:element(2, Organization), _pipe@5 = gleam@list:map( _pipe@2, fun(Team) -> _pipe@3 = erlang:element(3, Team), _pipe@4 = gleam@list:map( _pipe@3, fun(Slo) -> resolve_slo(Slo, erlang:element(2, Team), Sli_types) end ), gleam@result:all(_pipe@4) end ), _pipe@6 = gleam@result:all(_pipe@5), gleam@result:map(_pipe@6, fun lists:append/1).