Packages
caffeine_lang
5.2.0
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@linker@ir_builder.erl
-module(caffeine_lang@linker@ir_builder).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/caffeine_lang/linker/ir_builder.gleam").
-export([reserved_labels/1, build_all/4]).
-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/linker/ir_builder.gleam", 28).
?DOC(false).
-spec reserved_labels(
gleam@dict:dict(binary(), caffeine_lang@linker@artifacts:param_info())
) -> gleam@set:set(binary()).
reserved_labels(Params) ->
_pipe = Params,
_pipe@1 = maps:keys(_pipe),
gleam@set:from_list(_pipe@1).
-file("src/caffeine_lang/linker/ir_builder.gleam", 323).
?DOC(
" Extract SLO-specific fields from an indexed Dict of ValueTuples.\n"
" Threshold defaults to the standard default when not present (e.g. unmeasured expectations).\n"
).
-spec build_slo_fields(
gleam@dict:dict(binary(), caffeine_lang@helpers:value_tuple())
) -> caffeine_lang@linker@ir:slo_fields().
build_slo_fields(Index) ->
Threshold = begin
_pipe = caffeine_lang@helpers:extract_value(
Index,
<<"threshold"/utf8>>,
fun caffeine_lang@value:extract_percentage/1
),
gleam@result:unwrap(_pipe, 99.9)
end,
Indicators = caffeine_lang@helpers:extract_indicators(Index),
Window_in_days = caffeine_lang@helpers:extract_window_in_days(Index),
Evaluation = begin
_pipe@1 = caffeine_lang@helpers:extract_value(
Index,
<<"evaluation"/utf8>>,
fun caffeine_lang@value:extract_string/1
),
gleam@option:from_result(_pipe@1)
end,
Tags = caffeine_lang@helpers:extract_tags(Index),
Runbook = begin
_pipe@2 = caffeine_lang@helpers:extract_value(
Index,
<<"runbook"/utf8>>,
fun(V) -> case V of
nil_value ->
{ok, none};
{string_value, S} ->
{ok, {some, S}};
_ ->
{error, nil}
end end
),
gleam@result:unwrap(_pipe@2, none)
end,
Relations = caffeine_lang@helpers:extract_depends_on(Index),
Depends_on = case gleam@dict:is_empty(Relations) of
true ->
none;
false ->
{some, Relations}
end,
{slo_fields,
Threshold,
Indicators,
Window_in_days,
Evaluation,
Tags,
Runbook,
Depends_on}.
-file("src/caffeine_lang/linker/ir_builder.gleam", 280).
?DOC(
" Resolves a value tuple to a list of strings for use as tags.\n"
" Primitives and refinements produce a single-element list.\n"
" Lists are exploded into multiple string values.\n"
" Dicts and type alias refs are unsupported.\n"
" Optional(None) produces an empty list (filtered out).\n"
" Defaulted(None) produces the default value.\n"
).
-spec resolve_values_for_tag(
caffeine_lang@types:accepted_types(),
caffeine_lang@value:value()
) -> {ok, list(binary())} | {error, nil}.
resolve_values_for_tag(Typ, Val) ->
case Typ of
{primitive_type, _} ->
{ok, [caffeine_lang@value:to_string(Val)]};
{refinement_type, Refinement} ->
case Refinement of
{one_of, Inner, _} ->
resolve_values_for_tag(Inner, Val);
{inclusive_range, Inner@1, _, _} ->
resolve_values_for_tag(Inner@1, Val)
end;
{collection_type, {list, Inner@2}} ->
case Val of
{list_value, Items} ->
_pipe = Items,
_pipe@2 = gleam@list:try_map(
_pipe,
fun(Item) ->
_pipe@1 = resolve_values_for_tag(Inner@2, Item),
gleam@result:map(
_pipe@1,
fun(Strings) -> Strings end
)
end
),
gleam@result:map(_pipe@2, fun lists:append/1);
_ ->
{error, nil}
end;
{collection_type, {dict, _, _}} ->
{error, nil};
{record_type, _} ->
{error, nil};
{modifier_type, {optional, Inner@3}} ->
case Val of
nil_value ->
{ok, []};
_ ->
resolve_values_for_tag(Inner@3, Val)
end;
{modifier_type, {defaulted, Inner@4, Default}} ->
case Val of
nil_value ->
{ok, [Default]};
_ ->
resolve_values_for_tag(Inner@4, Val)
end
end.
-file("src/caffeine_lang/linker/ir_builder.gleam", 255).
?DOC(
" Extract misc metadata from value tuples.\n"
" Filters out reserved labels (derived from artifact params) and unsupported types.\n"
" Each key maps to a list of string values (primitives become single-element\n"
" lists, collection lists are exploded, nulls are excluded).\n"
).
-spec extract_misc_metadata(
list(caffeine_lang@helpers:value_tuple()),
gleam@set:set(binary())
) -> gleam@dict:dict(binary(), list(binary())).
extract_misc_metadata(Value_tuples, Reserved_labels) ->
_pipe = Value_tuples,
_pipe@1 = gleam@list:filter_map(
_pipe,
fun(Value_tuple) ->
gleam@bool:guard(
gleam@set:contains(
Reserved_labels,
erlang:element(2, Value_tuple)
),
{error, nil},
fun() ->
case resolve_values_for_tag(
erlang:element(3, Value_tuple),
erlang:element(4, Value_tuple)
) of
{ok, []} ->
{error, nil};
{ok, Values} ->
{ok, {erlang:element(2, Value_tuple), Values}};
{error, _} ->
{error, nil}
end
end
)
end
),
maps:from_list(_pipe@1).
-file("src/caffeine_lang/linker/ir_builder.gleam", 232).
?DOC(
" Build value tuples for Optional/Defaulted params that weren't provided.\n"
" These need to be in value_tuples so the templatizer can resolve them.\n"
).
-spec build_unprovided_optional_value_tuples(
gleam@dict:dict(binary(), caffeine_lang@value:value()),
gleam@dict:dict(binary(), caffeine_lang@types:accepted_types())
) -> list(caffeine_lang@helpers:value_tuple()).
build_unprovided_optional_value_tuples(Merged_inputs, Params) ->
_pipe = Params,
_pipe@1 = maps:to_list(_pipe),
gleam@list:filter_map(
_pipe@1,
fun(Param) ->
{Label, Typ} = Param,
gleam@bool:guard(
gleam@dict:has_key(Merged_inputs, Label),
{error, nil},
fun() ->
case caffeine_lang@types:is_optional_or_defaulted(Typ) of
true ->
{ok, {value_tuple, Label, Typ, nil_value}};
false ->
{error, nil}
end
end
)
end
).
-file("src/caffeine_lang/linker/ir_builder.gleam", 215).
?DOC(" Build value tuples from provided inputs.\n").
-spec build_provided_value_tuples(
gleam@dict:dict(binary(), caffeine_lang@value:value()),
gleam@dict:dict(binary(), caffeine_lang@types:accepted_types())
) -> list(caffeine_lang@helpers:value_tuple()).
build_provided_value_tuples(Merged_inputs, Params) ->
_pipe = Merged_inputs,
_pipe@1 = maps:to_list(_pipe),
gleam@list:filter_map(
_pipe@1,
fun(Pair) ->
{Label, Val} = Pair,
case gleam_stdlib:map_get(Params, Label) of
{ok, Typ} ->
{ok, {value_tuple, Label, Typ, Val}};
{error, nil} ->
{error, nil}
end
end
).
-file("src/caffeine_lang/linker/ir_builder.gleam", 205).
?DOC(
" Build value tuples from merged inputs and params.\n"
" Includes both provided inputs and unprovided Optional/Defaulted params.\n"
).
-spec build_value_tuples(
gleam@dict:dict(binary(), caffeine_lang@value:value()),
gleam@dict:dict(binary(), caffeine_lang@types:accepted_types())
) -> list(caffeine_lang@helpers:value_tuple()).
build_value_tuples(Merged_inputs, Params) ->
Provided = build_provided_value_tuples(Merged_inputs, Params),
Unprovided = build_unprovided_optional_value_tuples(Merged_inputs, Params),
lists:append(Provided, Unprovided).
-file("src/caffeine_lang/linker/ir_builder.gleam", 162).
?DOC(
" Build an IR from an unmeasured expectation.\n"
" Uses restricted params (threshold, window_in_days, depends_on) and sets vendor to None.\n"
).
-spec build_unmeasured(
caffeine_lang@linker@expectations:expectation(),
binary(),
binary(),
binary(),
gleam@set:set(binary()),
gleam@dict:dict(binary(), caffeine_lang@types:accepted_types())
) -> caffeine_lang@linker@ir:intermediate_representation(caffeine_lang@linker@ir:linked()).
build_unmeasured(
Expectation,
Org,
Team,
Service,
Reserved_labels,
Unmeasured_params
) ->
Value_tuples = build_value_tuples(
erlang:element(4, Expectation),
Unmeasured_params
),
Index = caffeine_lang@helpers:index_value_tuples(Value_tuples),
Misc_metadata = extract_misc_metadata(Value_tuples, Reserved_labels),
Unique_name = <<<<<<<<Org/binary, "_"/utf8>>/binary, Service/binary>>/binary,
"_"/utf8>>/binary,
(erlang:element(2, Expectation))/binary>>,
Slo = build_slo_fields(Index),
{intermediate_representation,
{intermediate_representation_meta_data,
{expectation_label, erlang:element(2, Expectation)},
{org_name, Org},
{service_name, Service},
{measurement_name, <<"unmeasured"/utf8>>},
{team_name, Team},
Misc_metadata},
Unique_name,
Value_tuples,
Slo,
none}.
-file("src/caffeine_lang/linker/ir_builder.gleam", 105).
?DOC(" Build an IR from a measured expectation paired with its measurement.\n").
-spec build_measured(
caffeine_lang@linker@expectations:expectation(),
caffeine_lang@linker@measurements:measurement(caffeine_lang@linker@measurements:measurement_validated()),
binary(),
binary(),
binary(),
gleam@set:set(binary()),
gleam@dict:dict(binary(), caffeine_lang@analysis@vendor:vendor())
) -> {ok,
caffeine_lang@linker@ir:intermediate_representation(caffeine_lang@linker@ir:linked())} |
{error, caffeine_lang@errors:compilation_error()}.
build_measured(
Expectation,
Measurement,
Org,
Team,
Service,
Reserved_labels,
Vendor_lookup
) ->
Merged_inputs = maps:merge(
erlang:element(4, Measurement),
erlang:element(4, Expectation)
),
Value_tuples = build_value_tuples(
Merged_inputs,
erlang:element(3, Measurement)
),
Index = caffeine_lang@helpers:index_value_tuples(Value_tuples),
Misc_metadata = extract_misc_metadata(Value_tuples, Reserved_labels),
Unique_name = <<<<<<<<Org/binary, "_"/utf8>>/binary, Service/binary>>/binary,
"_"/utf8>>/binary,
(erlang:element(2, Expectation))/binary>>,
Slo = build_slo_fields(Index),
Resolved_vendor = case gleam_stdlib:map_get(
Vendor_lookup,
erlang:element(2, Measurement)
) of
{ok, V} ->
{ok, {some, V}};
{error, nil} ->
{error,
caffeine_lang@errors:linker_vendor_resolution_error(
<<<<<<<<<<<<<<<<<<<<"expectation '"/utf8, Org/binary>>/binary,
"."/utf8>>/binary,
Team/binary>>/binary,
"."/utf8>>/binary,
Service/binary>>/binary,
"."/utf8>>/binary,
(erlang:element(2, Expectation))/binary>>/binary,
"' - measurement '"/utf8>>/binary,
(erlang:element(2, Measurement))/binary>>/binary,
"' has no associated vendor"/utf8>>
)}
end,
gleam@result:'try'(
Resolved_vendor,
fun(Resolved_vendor@1) ->
{ok,
{intermediate_representation,
{intermediate_representation_meta_data,
{expectation_label, erlang:element(2, Expectation)},
{org_name, Org},
{service_name, Service},
{measurement_name, erlang:element(2, Measurement)},
{team_name, Team},
Misc_metadata},
Unique_name,
Value_tuples,
Slo,
Resolved_vendor@1}}
end
).
-file("src/caffeine_lang/linker/ir_builder.gleam", 65).
?DOC(" Build intermediate representations from validated expectations for a single file.\n").
-spec build(
list({caffeine_lang@linker@expectations:expectation(),
gleam@option:option(caffeine_lang@linker@measurements:measurement(caffeine_lang@linker@measurements:measurement_validated()))}),
binary(),
gleam@set:set(binary()),
gleam@dict:dict(binary(), caffeine_lang@analysis@vendor:vendor()),
gleam@dict:dict(binary(), caffeine_lang@types:accepted_types())
) -> {ok,
list(caffeine_lang@linker@ir:intermediate_representation(caffeine_lang@linker@ir:linked()))} |
{error, caffeine_lang@errors:compilation_error()}.
build(
Expectations_measurement_collection,
File_path,
Reserved_labels,
Vendor_lookup,
Unmeasured_params
) ->
{Org, Team, Service} = caffeine_lang@helpers:extract_path_prefix(File_path),
_pipe = Expectations_measurement_collection,
gleam@list:try_map(
_pipe,
fun(Expectation_and_measurement_pair) ->
{Expectation, Maybe_measurement} = Expectation_and_measurement_pair,
case Maybe_measurement of
{some, Measurement} ->
build_measured(
Expectation,
Measurement,
Org,
Team,
Service,
Reserved_labels,
Vendor_lookup
);
none ->
{ok,
build_unmeasured(
Expectation,
Org,
Team,
Service,
Reserved_labels,
Unmeasured_params
)}
end
end
).
-file("src/caffeine_lang/linker/ir_builder.gleam", 194).
?DOC(
" Derives the restricted param types for unmeasured expectations from SLO params.\n"
" Only includes threshold, window_in_days, and depends_on.\n"
).
-spec build_unmeasured_param_types(
gleam@dict:dict(binary(), caffeine_lang@linker@artifacts:param_info())
) -> gleam@dict:dict(binary(), caffeine_lang@types:accepted_types()).
build_unmeasured_param_types(Slo_params) ->
Allowed = gleam@set:from_list(
[<<"threshold"/utf8>>, <<"window_in_days"/utf8>>, <<"depends_on"/utf8>>]
),
_pipe = Slo_params,
_pipe@1 = gleam@dict:filter(
_pipe,
fun(Key, _) -> gleam@set:contains(Allowed, Key) end
),
caffeine_lang@linker@artifacts:params_to_types(_pipe@1).
-file("src/caffeine_lang/linker/ir_builder.gleam", 36).
?DOC(false).
-spec build_all(
list({list({caffeine_lang@linker@expectations:expectation(),
gleam@option:option(caffeine_lang@linker@measurements:measurement(caffeine_lang@linker@measurements:measurement_validated()))}),
binary()}),
gleam@set:set(binary()),
gleam@dict:dict(binary(), caffeine_lang@analysis@vendor:vendor()),
gleam@dict:dict(binary(), caffeine_lang@linker@artifacts:param_info())
) -> {ok,
list(caffeine_lang@linker@ir:intermediate_representation(caffeine_lang@linker@ir:linked()))} |
{error, caffeine_lang@errors:compilation_error()}.
build_all(Expectations_with_paths, Reserved_labels, Vendor_lookup, Slo_params) ->
Unmeasured_params = build_unmeasured_param_types(Slo_params),
_pipe = Expectations_with_paths,
_pipe@1 = gleam@list:map(
_pipe,
fun(Pair) ->
{Expectations_measurement_collection, File_path} = Pair,
build(
Expectations_measurement_collection,
File_path,
Reserved_labels,
Vendor_lookup,
Unmeasured_params
)
end
),
_pipe@2 = caffeine_lang@errors:from_results(_pipe@1),
gleam@result:map(_pipe@2, fun lists:append/1).