Packages
caffeine_lang
6.2.1
6.3.1
6.3.0
6.2.2
6.2.1
6.2.0
6.1.2
6.1.1
6.1.0
6.0.0
5.6.0
5.5.0
5.4.4
5.4.3
5.4.2
5.4.1
5.4.0
5.3.0
5.2.0
5.1.1
5.1.0
5.0.12
5.0.11
5.0.10
5.0.8
5.0.7
5.0.6
5.0.5
5.0.4
5.0.1
5.0.0
4.10.0
4.9.0
4.8.3
4.8.2
4.8.1
4.8.0
4.7.9
4.7.8
4.7.7
4.7.6
4.7.5
4.6.7
4.6.6
4.6.5
4.6.4
4.6.3
4.6.2
4.6.0
4.5.1
4.5.0
4.4.4
4.4.3
4.4.1
4.4.0
4.3.7
4.3.6
3.0.6
3.0.5
3.0.4
3.0.3
3.0.2
3.0.1
3.0.0
2.0.5
2.0.4
2.0.3
2.0.2
2.0.1
2.0.0
1.0.2
1.0.1
0.1.0
0.0.24
0.0.23
0.0.22
0.0.21
0.0.20
0.0.19
0.0.18
0.0.17
0.0.16
0.0.15
0.0.14
0.0.13
0.0.12
0.0.11
0.0.10
0.0.9
0.0.8
0.0.7
0.0.6
0.0.5
0.0.4
0.0.2
0.0.1
A compiler for generating reliability artifacts from service expectation definitions.
Current section
Files
Jump to
Current section
Files
src/caffeine_lang@frontend@lowering.erl
-module(caffeine_lang@frontend@lowering).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/caffeine_lang/frontend/lowering.gleam").
-export([literal_to_value/1, lower_measurements/1, lower_expectations/1]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-file("src/caffeine_lang/frontend/lowering.gleam", 426).
?DOC(" Resolves inner types of a refinement.\n").
-spec resolve_refinement(
caffeine_lang@types:refinement_types(caffeine_lang@types:parsed_type()),
gleam@dict:dict(binary(), caffeine_lang@types:parsed_type())
) -> caffeine_lang@types:refinement_types(caffeine_lang@types:accepted_types()).
resolve_refinement(Refinement, Aliases) ->
case Refinement of
{one_of, Inner, Values} ->
{one_of, resolve_type_aliases(Inner, Aliases), Values};
{inclusive_range, Inner@1, Low, High} ->
{inclusive_range, resolve_type_aliases(Inner@1, Aliases), Low, High}
end.
-file("src/caffeine_lang/frontend/lowering.gleam", 414).
?DOC(" Resolves inner types of a modifier.\n").
-spec resolve_modifier(
caffeine_lang@types:modifier_types(caffeine_lang@types:parsed_type()),
gleam@dict:dict(binary(), caffeine_lang@types:parsed_type())
) -> caffeine_lang@types:modifier_types(caffeine_lang@types:accepted_types()).
resolve_modifier(Modifier, Aliases) ->
case Modifier of
{optional, Inner} ->
{optional, resolve_type_aliases(Inner, Aliases)};
{defaulted, Inner@1, Default} ->
{defaulted, resolve_type_aliases(Inner@1, Aliases), Default}
end.
-file("src/caffeine_lang/frontend/lowering.gleam", 399).
?DOC(" Resolves inner types of a collection.\n").
-spec resolve_collection(
caffeine_lang@types:collection_types(caffeine_lang@types:parsed_type()),
gleam@dict:dict(binary(), caffeine_lang@types:parsed_type())
) -> caffeine_lang@types:collection_types(caffeine_lang@types:accepted_types()).
resolve_collection(Collection, Aliases) ->
case Collection of
{list, Inner} ->
{list, resolve_type_aliases(Inner, Aliases)};
{dict, Key, Value} ->
{dict,
resolve_type_aliases(Key, Aliases),
resolve_type_aliases(Value, Aliases)}
end.
-file("src/caffeine_lang/frontend/lowering.gleam", 373).
?DOC(
" Resolves all ParsedTypeAliasRef instances, converting ParsedType to AcceptedTypes.\n"
" This is the resolution boundary where parsed types become fully resolved types.\n"
).
-spec resolve_type_aliases(
caffeine_lang@types:parsed_type(),
gleam@dict:dict(binary(), caffeine_lang@types:parsed_type())
) -> caffeine_lang@types:accepted_types().
resolve_type_aliases(T, Aliases) ->
case T of
{parsed_primitive, P} ->
{primitive_type, P};
{parsed_type_alias_ref, Name} ->
case gleam_stdlib:map_get(Aliases, Name) of
{ok, Resolved} ->
resolve_type_aliases(Resolved, Aliases);
{error, _} ->
{primitive_type, string}
end;
{parsed_collection, Collection} ->
{collection_type, resolve_collection(Collection, Aliases)};
{parsed_modifier, Modifier} ->
{modifier_type, resolve_modifier(Modifier, Aliases)};
{parsed_refinement, Refinement} ->
{refinement_type, resolve_refinement(Refinement, Aliases)};
{parsed_record, Fields} ->
{record_type,
gleam@dict:map_values(
Fields,
fun(_, V) -> resolve_type_aliases(V, Aliases) end
)}
end.
-file("src/caffeine_lang/frontend/lowering.gleam", 95).
?DOC(
" Walks a measurement's `Provides` struct looking for an `indicators:` field\n"
" whose value is a `LiteralStruct` of indicator-name -> indicator-value\n"
" entries. For each entry whose value is a `LiteralExternalIndicator` with a\n"
" `value_extraction.type_`, resolve the parsed type through the same\n"
" type-alias resolver used for `Requires` fields and stash the result keyed\n"
" by indicator name. This is the only place the AST-level type info from the\n"
" `value:` clause is recovered for downstream IR construction.\n"
).
-spec collect_external_indicator_types(
caffeine_lang@frontend@ast:struct(),
gleam@dict:dict(binary(), caffeine_lang@types:parsed_type())
) -> gleam@dict:dict(binary(), caffeine_lang@types:accepted_types()).
collect_external_indicator_types(Provides, Type_aliases) ->
Indicators_field = begin
_pipe = erlang:element(2, Provides),
gleam@list:find(
_pipe,
fun(F) -> erlang:element(2, F) =:= <<"indicators"/utf8>> end
)
end,
case Indicators_field of
{error, _} ->
maps:new();
{ok, Field} ->
case erlang:element(3, Field) of
{literal_value, {literal_struct, Inner_fields, _}} ->
_pipe@1 = Inner_fields,
_pipe@2 = gleam@list:filter_map(
_pipe@1,
fun(Inner_field) ->
case erlang:element(3, Inner_field) of
{literal_value,
{literal_external_indicator,
_,
_,
{some,
{value_extraction, _, Parsed_type}}}} ->
Resolved = resolve_type_aliases(
Parsed_type,
Type_aliases
),
{ok,
{erlang:element(2, Inner_field),
Resolved}};
_ ->
{error, nil}
end
end
),
maps:from_list(_pipe@2);
_ ->
maps:new()
end
end.
-file("src/caffeine_lang/frontend/lowering.gleam", 502).
-spec transform_template_vars_loop(binary(), list(binary())) -> binary().
transform_template_vars_loop(Remaining, Acc) ->
case gleam@string:split_once(Remaining, <<"$"/utf8>>) of
{ok, {Before, After}} ->
case gleam_stdlib:string_starts_with(After, <<"$"/utf8>>) of
true ->
transform_template_vars_loop(
gleam@string:drop_start(After, 1),
[<<"$$"/utf8>>, Before | Acc]
);
false ->
case gleam@string:split_once(After, <<"$"/utf8>>) of
{ok, {Var_content, Rest}} ->
Transformed = gleam@string:replace(
Var_content,
<<".not"/utf8>>,
<<":not"/utf8>>
),
transform_template_vars_loop(
Rest,
[<<"$$"/utf8>>,
Transformed,
<<"$$"/utf8>>,
Before |
Acc]
);
{error, nil} ->
erlang:list_to_binary(
lists:reverse(
[After, <<"$"/utf8>>, Before | Acc]
)
)
end
end;
{error, nil} ->
erlang:list_to_binary(lists:reverse([Remaining | Acc]))
end.
-file("src/caffeine_lang/frontend/lowering.gleam", 498).
?DOC(
" Transforms template variables from $var->attr$ to $$var->attr$$ format.\n"
" Also handles $var->attr.not$ to $$var->attr:not$$ format.\n"
).
-spec transform_template_vars(binary()) -> binary().
transform_template_vars(S) ->
transform_template_vars_loop(S, []).
-file("src/caffeine_lang/frontend/lowering.gleam", 451).
?DOC(false).
-spec literal_to_value(caffeine_lang@frontend@ast:literal()) -> caffeine_lang@value:value().
literal_to_value(Lit) ->
case Lit of
{literal_string, S} ->
{string_value, transform_template_vars(S)};
{literal_integer, I} ->
{int_value, I};
{literal_float, F} ->
{float_value, F};
{literal_percentage, F@1} ->
{percentage_value, F@1};
{literal_duration, Amount, Unit} ->
case caffeine_lang@value:duration_unit_from_string(Unit) of
{ok, Parsed_unit} ->
{duration_value, Amount, Parsed_unit};
{error, nil} ->
nil_value
end;
literal_true ->
{bool_value, true};
literal_false ->
{bool_value, false};
{literal_list, Elements} ->
{list_value, gleam@list:map(Elements, fun literal_to_value/1)};
{literal_struct, Fields, _} ->
_pipe = Fields,
_pipe@1 = gleam@list:filter_map(
_pipe,
fun(Field) -> case erlang:element(3, Field) of
{literal_value, Inner} ->
{ok,
{erlang:element(2, Field),
literal_to_value(Inner)}};
{type_value, _} ->
{error, nil}
end end
),
_pipe@2 = maps:from_list(_pipe@1),
{dict_value, _pipe@2};
{literal_external_indicator, Source, Match, Value_extraction} ->
Match_dict = begin
_pipe@3 = Match,
_pipe@4 = gleam@list:map(
_pipe@3,
fun(Clause) ->
{match_clause, Field@1, Val} = Clause,
{Field@1, literal_to_value(Val)}
end
),
maps:from_list(_pipe@4)
end,
Value_path = gleam@option:map(
Value_extraction,
fun(Ve) ->
{value_extraction, Path, _} = Ve,
Path
end
),
{external_indicator_value, Source, Match_dict, Value_path}
end.
-file("src/caffeine_lang/frontend/lowering.gleam", 438).
?DOC(" Converts a struct's literal-valued fields to an inputs dict.\n").
-spec struct_to_inputs(caffeine_lang@frontend@ast:struct()) -> gleam@dict:dict(binary(), caffeine_lang@value:value()).
struct_to_inputs(S) ->
_pipe = erlang:element(2, S),
_pipe@1 = gleam@list:filter_map(
_pipe,
fun(Field) -> case erlang:element(3, Field) of
{literal_value, Lit} ->
{ok, {erlang:element(2, Field), literal_to_value(Lit)}};
{type_value, _} ->
{error, nil}
end end
),
maps:from_list(_pipe@1).
-file("src/caffeine_lang/frontend/lowering.gleam", 354).
?DOC(
" Converts a struct's type-valued fields to a params dict.\n"
" Resolves type alias references before storing.\n"
).
-spec struct_to_params(
caffeine_lang@frontend@ast:struct(),
gleam@dict:dict(binary(), caffeine_lang@types:parsed_type())
) -> gleam@dict:dict(binary(), caffeine_lang@types:accepted_types()).
struct_to_params(S, Type_aliases) ->
_pipe = erlang:element(2, S),
_pipe@1 = gleam@list:filter_map(
_pipe,
fun(Field) -> case erlang:element(3, Field) of
{type_value, T} ->
Resolved = resolve_type_aliases(T, Type_aliases),
{ok, {erlang:element(2, Field), Resolved}};
{literal_value, _} ->
{error, nil}
end end
),
maps:from_list(_pipe@1).
-file("src/caffeine_lang/frontend/lowering.gleam", 342).
?DOC(
" Removes duplicate field names, keeping the last occurrence (allows overrides).\n"
" Returns fields sorted by name for consistent output.\n"
).
-spec dedupe_fields(list(caffeine_lang@frontend@ast:field())) -> list(caffeine_lang@frontend@ast:field()).
dedupe_fields(Fields) ->
_pipe = Fields,
_pipe@1 = gleam@list:fold(
_pipe,
maps:new(),
fun(Acc, Field) ->
gleam@dict:insert(Acc, erlang:element(2, Field), Field)
end
),
_pipe@2 = maps:to_list(_pipe@1),
_pipe@3 = gleam@list:sort(
_pipe@2,
fun(A, B) ->
gleam@string:compare(erlang:element(1, A), erlang:element(1, B))
end
),
gleam@list:map(_pipe@3, fun(Pair) -> erlang:element(2, Pair) end).
-file("src/caffeine_lang/frontend/lowering.gleam", 284).
?DOC(" Collects fields from extended extendables matching a given kind.\n").
-spec collect_extended_fields(
list(binary()),
gleam@dict:dict(binary(), caffeine_lang@frontend@ast:extendable()),
caffeine_lang@frontend@ast:extendable_kind()
) -> list(caffeine_lang@frontend@ast:field()).
collect_extended_fields(Extends, Extendables, Kind) ->
_pipe = Extends,
gleam@list:flat_map(
_pipe,
fun(Name) -> case gleam_stdlib:map_get(Extendables, Name) of
{ok, Ext} when erlang:element(3, Ext) =:= Kind ->
erlang:element(2, erlang:element(4, Ext));
_ ->
[]
end end
).
-file("src/caffeine_lang/frontend/lowering.gleam", 300).
?DOC(
" Merges extended fields into a measurement item's requires and provides.\n"
" Order: extended extendables left-to-right, then item's own fields (can override).\n"
).
-spec merge_measurement_extends(
caffeine_lang@frontend@ast:measurement_item(),
gleam@dict:dict(binary(), caffeine_lang@frontend@ast:extendable())
) -> {caffeine_lang@frontend@ast:struct(), caffeine_lang@frontend@ast:struct()}.
merge_measurement_extends(Item, Extendables) ->
Requires_fields = begin
_pipe = collect_extended_fields(
erlang:element(4, Item),
Extendables,
extendable_requires
),
_pipe@1 = lists:append(
_pipe,
erlang:element(2, erlang:element(5, Item))
),
dedupe_fields(_pipe@1)
end,
Provides_fields = begin
_pipe@2 = collect_extended_fields(
erlang:element(4, Item),
Extendables,
extendable_provides
),
_pipe@3 = lists:append(
_pipe@2,
erlang:element(2, erlang:element(6, Item))
),
dedupe_fields(_pipe@3)
end,
{{struct, Requires_fields, []}, {struct, Provides_fields, []}}.
-file("src/caffeine_lang/frontend/lowering.gleam", 66).
?DOC(" Generates a single measurement from an AST item.\n").
-spec generate_measurement_item(
caffeine_lang@frontend@ast:measurement_item(),
gleam@dict:dict(binary(), caffeine_lang@frontend@ast:extendable()),
gleam@dict:dict(binary(), caffeine_lang@types:parsed_type())
) -> caffeine_lang@linker@measurements:measurement(caffeine_lang@linker@measurements:raw()).
generate_measurement_item(Item, Extendables, Type_aliases) ->
{Merged_requires, Merged_provides} = merge_measurement_extends(
Item,
Extendables
),
Params = struct_to_params(Merged_requires, Type_aliases),
Inputs = struct_to_inputs(Merged_provides),
External_indicator_types = collect_external_indicator_types(
Merged_provides,
Type_aliases
),
{measurement,
erlang:element(2, Item),
Params,
Inputs,
External_indicator_types,
erlang:element(3, Item)}.
-file("src/caffeine_lang/frontend/lowering.gleam", 49).
?DOC(" Builds a map of extendable name to extendable for quick lookup.\n").
-spec build_extendable_map(list(caffeine_lang@frontend@ast:extendable())) -> gleam@dict:dict(binary(), caffeine_lang@frontend@ast:extendable()).
build_extendable_map(Extendables) ->
_pipe = Extendables,
_pipe@1 = gleam@list:map(_pipe, fun(E) -> {erlang:element(2, E), E} end),
maps:from_list(_pipe@1).
-file("src/caffeine_lang/frontend/lowering.gleam", 58).
?DOC(" Builds a map of type alias name to its parsed type for quick lookup.\n").
-spec build_type_alias_map(list(caffeine_lang@frontend@ast:type_alias())) -> gleam@dict:dict(binary(), caffeine_lang@types:parsed_type()).
build_type_alias_map(Type_aliases) ->
_pipe = caffeine_lang@frontend@ast:build_type_alias_pairs(Type_aliases),
maps:from_list(_pipe).
-file("src/caffeine_lang/frontend/lowering.gleam", 27).
?DOC(false).
-spec lower_measurements(
caffeine_lang@frontend@ast:measurements_file(caffeine_lang@frontend@ast:validated())
) -> list(caffeine_lang@linker@measurements:measurement(caffeine_lang@linker@measurements:raw())).
lower_measurements(File) ->
Type_aliases = build_type_alias_map(erlang:element(2, File)),
Extendables = build_extendable_map(erlang:element(3, File)),
_pipe = erlang:element(4, File),
gleam@list:map(
_pipe,
fun(Item) ->
generate_measurement_item(Item, Extendables, Type_aliases)
end
).
-file("src/caffeine_lang/frontend/lowering.gleam", 275).
-spec strip_doc_comment_text(binary()) -> binary().
strip_doc_comment_text(Text) ->
Stripped = case gleam_stdlib:string_starts_with(Text, <<" "/utf8>>) of
true ->
gleam@string:drop_start(Text, 1);
false ->
Text
end,
gleam@string:trim_end(Stripped).
-file("src/caffeine_lang/frontend/lowering.gleam", 260).
?DOC(
" Extracts `###` doc-comment text from a node's leading comments and joins\n"
" the lines with `\\n`. Returns `None` when no doc comments are present.\n"
" Each line drops a single leading space (the universal `### ` form) and\n"
" rstrips trailing whitespace. `#` and `##` comments are ignored — they're\n"
" treated as section headers / inline notes, not SLO descriptions.\n"
).
-spec extract_doc_description(list(caffeine_lang@frontend@ast:comment())) -> gleam@option:option(binary()).
extract_doc_description(Comments) ->
Lines = begin
_pipe = Comments,
gleam@list:filter_map(_pipe, fun(C) -> case C of
{doc_comment, Text} ->
{ok, strip_doc_comment_text(Text)};
_ ->
{error, nil}
end end)
end,
case Lines of
[] ->
none;
_ ->
{some, gleam@string:join(Lines, <<"\n"/utf8>>)}
end.
-file("src/caffeine_lang/frontend/lowering.gleam", 233).
-spec deps_to_value(list(caffeine_lang@frontend@ast:dependency())) -> caffeine_lang@value:value().
deps_to_value(Deps) ->
{Hard, Soft} = gleam@list:partition(
Deps,
fun(D) -> case erlang:element(2, D) of
hard_dep ->
true;
soft_dep ->
false
end end
),
Hard_list = begin
_pipe = Hard,
_pipe@1 = gleam@list:map(
_pipe,
fun(D@1) -> {string_value, erlang:element(3, D@1)} end
),
{list_value, _pipe@1}
end,
Soft_list = begin
_pipe@2 = Soft,
_pipe@3 = gleam@list:map(
_pipe@2,
fun(D@2) -> {string_value, erlang:element(3, D@2)} end
),
{list_value, _pipe@3}
end,
_pipe@4 = maps:new(),
_pipe@5 = gleam@dict:insert(_pipe@4, <<"hard"/utf8>>, Hard_list),
_pipe@6 = gleam@dict:insert(_pipe@5, <<"soft"/utf8>>, Soft_list),
{dict_value, _pipe@6}.
-file("src/caffeine_lang/frontend/lowering.gleam", 219).
-spec maybe_insert_depends_on(
gleam@dict:dict(binary(), caffeine_lang@value:value()),
gleam@option:option(caffeine_lang@frontend@ast:assumes())
) -> gleam@dict:dict(binary(), caffeine_lang@value:value()).
maybe_insert_depends_on(Inputs, Assumes) ->
case Assumes of
none ->
Inputs;
{some, A} ->
case erlang:element(2, A) of
[] ->
Inputs;
_ ->
gleam@dict:insert(
Inputs,
<<"depends_on"/utf8>>,
deps_to_value(erlang:element(2, A))
)
end
end.
-file("src/caffeine_lang/frontend/lowering.gleam", 199).
-spec maybe_insert_below_ms(
gleam@dict:dict(binary(), caffeine_lang@value:value()),
gleam@option:option(caffeine_lang@frontend@ast:duration_literal())
) -> gleam@dict:dict(binary(), caffeine_lang@value:value()).
maybe_insert_below_ms(Inputs, Below) ->
case Below of
none ->
Inputs;
{some, D} ->
case caffeine_lang@value:duration_unit_from_string(
erlang:element(3, D)
) of
{ok, Unit} ->
gleam@dict:insert(
Inputs,
<<"below_ms"/utf8>>,
{float_value,
caffeine_lang@value:duration_to_milliseconds(
erlang:element(2, D),
Unit
)}
);
{error, nil} ->
Inputs
end
end.
-file("src/caffeine_lang/frontend/lowering.gleam", 191).
-spec float_floor_to_int(float()) -> integer().
float_floor_to_int(F) ->
Rounded = erlang:round(F - 0.5),
case Rounded < 0 of
true ->
0;
false ->
Rounded
end.
-file("src/caffeine_lang/frontend/lowering.gleam", 176).
?DOC(
" Converts a duration literal to whole days. Non-day units are normalized\n"
" through `value.duration_to_milliseconds` and divided down. Floors fractional\n"
" days (e.g. `1h` -> 0 days, `25h` -> 1 day) since the IR currently carries\n"
" `window_in_days` as an integer. Negative values clamp to 0.\n"
).
-spec duration_to_days(caffeine_lang@frontend@ast:duration_literal()) -> integer().
duration_to_days(D) ->
case caffeine_lang@value:duration_unit_from_string(erlang:element(3, D)) of
{ok, Unit} ->
Ms = caffeine_lang@value:duration_to_milliseconds(
erlang:element(2, D),
Unit
),
Days_float = Ms / 86400000.0,
case Days_float < +0.0 of
true ->
0;
false ->
float_floor_to_int(Days_float)
end;
{error, nil} ->
0
end.
-file("src/caffeine_lang/frontend/lowering.gleam", 324).
?DOC(
" Merges extended fields into an expect item's `with: {...}` args.\n"
" Order: extended extendables left-to-right, then the item's own with-fields\n"
" (can override). Unmeasured expectations have no `with:`; for them only the\n"
" extendable fields contribute.\n"
).
-spec merge_expect_with_args(
caffeine_lang@frontend@ast:expect_item(),
gleam@dict:dict(binary(), caffeine_lang@frontend@ast:extendable())
) -> caffeine_lang@frontend@ast:struct().
merge_expect_with_args(Item, Extendables) ->
Item_fields = case erlang:element(5, erlang:element(5, Item)) of
{some, Mb} ->
erlang:element(2, erlang:element(3, Mb));
none ->
[]
end,
Merged = begin
_pipe = collect_extended_fields(
erlang:element(3, Item),
Extendables,
extendable_provides
),
_pipe@1 = lists:append(_pipe, Item_fields),
dedupe_fields(_pipe@1)
end,
{struct, Merged, []}.
-file("src/caffeine_lang/frontend/lowering.gleam", 137).
?DOC(
" Generates a single expectation from a new-envelope AST item.\n"
"\n"
" Flattens the structured envelope (Assumes section, Guarantees clause,\n"
" optional `as measured by ... with: {...}`) into the flat `inputs` dict the\n"
" linker IR builder expects. Keys produced:\n"
" - \"threshold\": PercentageValue from `Guarantees N%`\n"
" - \"window_in_days\": IntValue from `over <dur> window` (any unit normalized to days)\n"
" - \"depends_on\": DictValue with \"hard\"/\"soft\" -> ListValue(StringValue) from `Assumes:`\n"
" - <each `with:` field>: literal value (after extendable merge)\n"
).
-spec generate_expect_item(
caffeine_lang@frontend@ast:expect_item(),
gleam@dict:dict(binary(), caffeine_lang@frontend@ast:extendable())
) -> caffeine_lang@linker@expectations:expectation().
generate_expect_item(Item, Extendables) ->
With_args = merge_expect_with_args(Item, Extendables),
Base_inputs = struct_to_inputs(With_args),
Inputs = begin
_pipe = Base_inputs,
_pipe@1 = gleam@dict:insert(
_pipe,
<<"threshold"/utf8>>,
{percentage_value, erlang:element(2, erlang:element(5, Item))}
),
_pipe@2 = gleam@dict:insert(
_pipe@1,
<<"window_in_days"/utf8>>,
{int_value,
duration_to_days(erlang:element(4, erlang:element(5, Item)))}
),
_pipe@3 = maybe_insert_below_ms(
_pipe@2,
erlang:element(3, erlang:element(5, Item))
),
maybe_insert_depends_on(_pipe@3, erlang:element(4, Item))
end,
Measurement_ref = case erlang:element(5, erlang:element(5, Item)) of
{some, Mb} ->
{some, erlang:element(2, Mb)};
none ->
none
end,
Description = extract_doc_description(erlang:element(6, Item)),
{expectation, erlang:element(2, Item), Measurement_ref, Inputs, Description}.
-file("src/caffeine_lang/frontend/lowering.gleam", 41).
?DOC(false).
-spec lower_expectations(
caffeine_lang@frontend@ast:expects_file(caffeine_lang@frontend@ast:validated())
) -> list(caffeine_lang@linker@expectations:expectation()).
lower_expectations(File) ->
Extendables = build_extendable_map(erlang:element(2, File)),
_pipe = erlang:element(3, File),
gleam@list:map(
_pipe,
fun(Item) -> generate_expect_item(Item, Extendables) end
).