Current section

Files

Jump to
caffeine_lang src caffeine_lang@parser@expectations.erl
Raw

src/caffeine_lang@parser@expectations.erl

-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 => <<?FILEPATH/utf8>>,
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 => <<?FILEPATH/utf8>>,
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 = <<<<<<<<Org/binary, "_"/utf8>>/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
).