-module(caffeine_lang@parser@expectations). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/caffeine_lang/parser/expectations.gleam"). -export([extract_path_prefix/1, build_ir/2, expectations_from_json/2, parse_from_string/3, parse_from_file/2]). -export_type([expectation/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. -type expectation() :: {expectation, binary(), binary(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_())}. -file("src/caffeine_lang/parser/expectations.gleam", 188). ?DOC(false). -spec extract_path_prefix(binary()) -> {binary(), binary(), binary()}. extract_path_prefix(Path) -> case begin _pipe = Path, _pipe@1 = gleam@string:split(_pipe, <<"/"/utf8>>), _pipe@2 = lists:reverse(_pipe@1), _pipe@3 = gleam@list:take(_pipe@2, 3), _pipe@4 = lists:reverse(_pipe@3), gleam@list:map( _pipe@4, fun(Segment) -> case gleam_stdlib:string_ends_with(Segment, <<".json"/utf8>>) of true -> gleam@string:drop_end(Segment, 5); false -> Segment end end ) end of [Org, Team, Service] -> {Org, Team, Service}; _ -> {<<"unknown"/utf8>>, <<"unknown"/utf8>>, <<"unknown"/utf8>>} end. -file("src/caffeine_lang/parser/expectations.gleam", 103). ?DOC(false). -spec build_ir( list({expectation(), caffeine_lang@parser@blueprints:blueprint()}), binary() ) -> {ok, list(caffeine_lang@middle_end@semantic_analyzer:intermediate_representation())} | {error, any()}. build_ir(Expectations_blueprint_collection, File_path) -> _pipe = Expectations_blueprint_collection, _pipe@9 = gleam@list:map( _pipe, fun(Expectation_and_blueprint_pair) -> {Expectation, Blueprint} = Expectation_and_blueprint_pair, Merged_inputs = maps:merge( erlang:element(5, Blueprint), erlang:element(4, Expectation) ), Provided_value_tuples = begin _pipe@1 = Merged_inputs, _pipe@2 = maps:keys(_pipe@1), gleam@list:map( _pipe@2, fun(Label) -> Value@1 = case begin _pipe@3 = Merged_inputs, gleam_stdlib:map_get(_pipe@3, Label) end of {ok, Value} -> Value; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"caffeine_lang/parser/expectations"/utf8>>, function => <<"build_ir"/utf8>>, line => 121, value => _assert_fail, start => 4075, 'end' => 4130, pattern_start => 4086, pattern_end => 4095}) end, Typ@1 = case begin _pipe@4 = erlang:element(4, Blueprint), gleam_stdlib:map_get(_pipe@4, Label) end of {ok, Typ} -> Typ; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"caffeine_lang/parser/expectations"/utf8>>, function => <<"build_ir"/utf8>>, line => 122, value => _assert_fail@1, start => 4139, 'end' => 4195, pattern_start => 4150, pattern_end => 4157}) end, {value_tuple, Label, Typ@1, Value@1} end ) end, Unprovided_optional_value_tuples = begin _pipe@5 = erlang:element(4, Blueprint), _pipe@6 = maps:to_list(_pipe@5), gleam@list:filter_map( _pipe@6, fun(Param) -> {Label@1, Typ@2} = Param, case gleam@dict:has_key(Merged_inputs, Label@1) of true -> {error, nil}; false -> case Typ@2 of {modifier, {optional, _}} -> {ok, {value_tuple, Label@1, Typ@2, gleam@dynamic:nil()}}; {modifier, {defaulted, _, _}} -> {ok, {value_tuple, Label@1, Typ@2, gleam@dynamic:nil()}}; _ -> {error, nil} end end end ) end, Value_tuples = lists:append( Provided_value_tuples, Unprovided_optional_value_tuples ), Misc_metadata = begin _pipe@7 = Value_tuples, _pipe@8 = gleam@list:filter_map( _pipe@7, fun(Value_tuple) -> case {erlang:element(2, Value_tuple), gleam@dynamic@decode:run( erlang:element(4, Value_tuple), {decoder, fun gleam@dynamic@decode:decode_string/1} )} of {_, {error, _}} -> {error, nil}; {<<"window_in_days"/utf8>>, _} -> {error, nil}; {<<"threshold"/utf8>>, _} -> {error, nil}; {<<"value"/utf8>>, _} -> {error, nil}; {_, {ok, Value_string}} -> {ok, {erlang:element(2, Value_tuple), Value_string}} end end ), maps:from_list(_pipe@8) end, {Org, Team, Service} = extract_path_prefix(File_path), Service_name = Service, Unique_name = <<<<<<<>/binary, Service_name/binary>>/binary, "_"/utf8>>/binary, (erlang:element(2, Expectation))/binary>>, {intermediate_representation, {intermediate_representation_meta_data, erlang:element(2, Expectation), Org, Service_name, erlang:element(2, Blueprint), Team, Misc_metadata}, Unique_name, erlang:element(3, Blueprint), Value_tuples, none} end ), {ok, _pipe@9}. -file("src/caffeine_lang/parser/expectations.gleam", 210). -spec check_input_overshadowing( list({expectation(), caffeine_lang@parser@blueprints:blueprint()}) ) -> {ok, boolean()} | {error, caffeine_lang@common@errors:compilation_error()}. check_input_overshadowing(Expectations_blueprint_collection) -> Overshadow_errors = begin _pipe = Expectations_blueprint_collection, _pipe@1 = gleam@list:filter_map( _pipe, fun(Pair) -> {Expectation, Blueprint} = Pair, case caffeine_lang@common@validations:check_collection_key_overshadowing( erlang:element(4, Expectation), erlang:element(5, Blueprint), <<<<"Expectation '"/utf8, (erlang:element(2, Expectation))/binary>>/binary, "' overshadowing inputs from blueprint: "/utf8>> ) of {ok, _} -> {error, nil}; {error, Msg} -> {ok, Msg} end end ), gleam@string:join(_pipe@1, <<", "/utf8>>) end, case Overshadow_errors of <<""/utf8>> -> {ok, true}; _ -> {error, {parser_duplicate_error, Overshadow_errors}} end. -file("src/caffeine_lang/parser/expectations.gleam", 58). ?DOC(" Validate expectations and build intermediate representations.\n"). -spec validate_and_build_irs( list(expectation()), list(caffeine_lang@parser@blueprints:blueprint()), binary() ) -> {ok, list(caffeine_lang@middle_end@semantic_analyzer:intermediate_representation())} | {error, caffeine_lang@common@errors:compilation_error()}. validate_and_build_irs(Expectations, Blueprints, File_path) -> Expectations_blueprint_collection = caffeine_lang@common@helpers:map_reference_to_referrer_over_collection( Blueprints, Expectations, fun(B) -> erlang:element(2, B) end, fun(E) -> erlang:element(3, E) end ), gleam@result:'try'( check_input_overshadowing(Expectations_blueprint_collection), fun(_) -> gleam@result:'try'( caffeine_lang@common@validations:validate_inputs_for_collection( Expectations_blueprint_collection, fun(Expectation) -> erlang:element(4, Expectation) end, fun(Blueprint) -> Blueprint_input_keys = begin _pipe = erlang:element(5, Blueprint), maps:keys(_pipe) end, _pipe@1 = erlang:element(4, Blueprint), gleam@dict:filter( _pipe@1, fun(Key, _) -> not gleam@list:contains( Blueprint_input_keys, Key ) end ) end ), fun(_) -> gleam@result:'try'( caffeine_lang@common@validations:validate_relevant_uniqueness( Expectations, fun(E@1) -> erlang:element(2, E@1) end, <<"expectation names"/utf8>> ), fun(_) -> build_ir( Expectations_blueprint_collection, File_path ) end ) end ) end ). -file("src/caffeine_lang/parser/expectations.gleam", 240). ?DOC( " Parse expectations from a JSON string.\n" " This is public so it can be used by browser.gleam for in-browser compilation.\n" ). -spec expectations_from_json( binary(), list(caffeine_lang@parser@blueprints:blueprint()) ) -> {ok, list(expectation())} | {error, gleam@json:decode_error()}. expectations_from_json(Json_string, Blueprints) -> Expectation_decoded = begin gleam@dynamic@decode:field( <<"name"/utf8>>, caffeine_lang@common@decoders:non_empty_string_decoder(), fun(Name) -> gleam@dynamic@decode:field( <<"blueprint_ref"/utf8>>, caffeine_lang@common@decoders:named_reference_decoder( Blueprints, fun(B) -> erlang:element(2, B) end ), fun(Blueprint_ref) -> gleam@dynamic@decode:field( <<"inputs"/utf8>>, gleam@dynamic@decode:dict( {decoder, fun gleam@dynamic@decode:decode_string/1}, {decoder, fun gleam@dynamic@decode:decode_dynamic/1} ), fun(Inputs) -> gleam@dynamic@decode:success( {expectation, Name, Blueprint_ref, Inputs} ) end ) end ) end ) end, Expectations_decoded = begin gleam@dynamic@decode:field( <<"expectations"/utf8>>, gleam@dynamic@decode:list(Expectation_decoded), fun(Expectations) -> gleam@dynamic@decode:success(Expectations) end ) end, gleam@json:parse(Json_string, Expectations_decoded). -file("src/caffeine_lang/parser/expectations.gleam", 41). ?DOC( " Parse expectations from a JSON string with a given path for metadata extraction.\n" " This is public so it can be used by browser.gleam for in-browser compilation.\n" " Furthermore, internally we use this as the base from which parse_from_file also\n" " uses to parse.\n" ). -spec parse_from_string( binary(), binary(), list(caffeine_lang@parser@blueprints:blueprint()) ) -> {ok, list(caffeine_lang@middle_end@semantic_analyzer:intermediate_representation())} | {error, caffeine_lang@common@errors:compilation_error()}. parse_from_string(Json_string, File_path, Blueprints) -> gleam@result:'try'(case expectations_from_json(Json_string, Blueprints) of {ok, Expectations} -> {ok, Expectations}; {error, Err} -> {error, caffeine_lang@common@errors:format_json_decode_error(Err)} end, fun(Expectations@1) -> validate_and_build_irs(Expectations@1, Blueprints, File_path) end). -file("src/caffeine_lang/parser/expectations.gleam", 28). ?DOC(" Parse expectations from a file, leveraging the given file path for metadata extraction.\n"). -spec parse_from_file( binary(), list(caffeine_lang@parser@blueprints:blueprint()) ) -> {ok, list(caffeine_lang@middle_end@semantic_analyzer:intermediate_representation())} | {error, caffeine_lang@common@errors:compilation_error()}. parse_from_file(File_path, Blueprints) -> gleam@result:'try'( caffeine_lang@common@helpers:json_from_file(File_path), fun(Json_string) -> parse_from_string(Json_string, File_path, Blueprints) end ).