Packages
caffeine_lang
5.0.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@analysis@dependency_validator.erl
-module(caffeine_lang@analysis@dependency_validator).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/caffeine_lang/analysis/dependency_validator.gleam").
-export([build_expectation_index/1, parse_dependency_path/1, validate_dependency_relations/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/analysis/dependency_validator.gleam", 18).
?DOC(" Extracts depends_on from an IR's SloFields.\n").
-spec get_depends_on(caffeine_lang@linker@ir:intermediate_representation(any())) -> gleam@option:option(gleam@dict:dict(caffeine_lang@linker@artifacts:dependency_relation_type(), list(binary()))).
get_depends_on(Ir) ->
erlang:element(8, erlang:element(5, Ir)).
-file("src/caffeine_lang/analysis/dependency_validator.gleam", 70).
?DOC(false).
-spec build_expectation_index(
list(caffeine_lang@linker@ir:intermediate_representation(HHM))
) -> gleam@dict:dict(binary(), caffeine_lang@linker@ir:intermediate_representation(HHM)).
build_expectation_index(Irs) ->
_pipe = Irs,
_pipe@1 = gleam@list:map(
_pipe,
fun(Ir) ->
Path = caffeine_lang@linker@ir:ir_to_identifier(Ir),
{Path, Ir}
end
),
maps:from_list(_pipe@1).
-file("src/caffeine_lang/analysis/dependency_validator.gleam", 107).
-spec get_all_dependency_targets(
gleam@dict:dict(caffeine_lang@linker@artifacts:dependency_relation_type(), list(binary()))
) -> list(binary()).
get_all_dependency_targets(Relations) ->
_pipe = Relations,
_pipe@1 = maps:values(_pipe),
lists:append(_pipe@1).
-file("src/caffeine_lang/analysis/dependency_validator.gleam", 127).
-spec do_check_for_duplicates(list(binary()), gleam@set:set(binary()), binary()) -> {ok,
nil} |
{error, caffeine_lang@errors:compilation_error()}.
do_check_for_duplicates(Targets, Seen, Self_path) ->
case Targets of
[] ->
{ok, nil};
[Target | Rest] ->
gleam@bool:guard(
gleam@set:contains(Seen, Target),
{error,
caffeine_lang@errors:semantic_analysis_dependency_validation_error(
<<<<<<<<"Duplicate dependency reference '"/utf8,
Target/binary>>/binary,
"' in '"/utf8>>/binary,
Self_path/binary>>/binary,
"'"/utf8>>
)},
fun() ->
do_check_for_duplicates(
Rest,
gleam@set:insert(Seen, Target),
Self_path
)
end
)
end.
-file("src/caffeine_lang/analysis/dependency_validator.gleam", 115).
-spec check_for_duplicates_per_relation(
gleam@dict:dict(caffeine_lang@linker@artifacts:dependency_relation_type(), list(binary())),
binary()
) -> {ok, nil} | {error, caffeine_lang@errors:compilation_error()}.
check_for_duplicates_per_relation(Relations, Self_path) ->
_pipe = Relations,
_pipe@1 = maps:to_list(_pipe),
gleam@list:try_each(
_pipe@1,
fun(Pair) ->
{_, Targets} = Pair,
do_check_for_duplicates(Targets, gleam@set:new(), Self_path)
end
).
-file("src/caffeine_lang/analysis/dependency_validator.gleam", 186).
?DOC(false).
-spec parse_dependency_path(binary()) -> {ok,
{binary(), binary(), binary(), binary()}} |
{error, nil}.
parse_dependency_path(Path) ->
case gleam@string:split(Path, <<"."/utf8>>) of
[Org, Team, Service, Name] when (((Org =/= <<""/utf8>>) andalso (Team =/= <<""/utf8>>)) andalso (Service =/= <<""/utf8>>)) andalso (Name =/= <<""/utf8>>) ->
{ok, {Org, Team, Service, Name}};
_ ->
{error, nil}
end.
-file("src/caffeine_lang/analysis/dependency_validator.gleam", 198).
?DOC(" Build a dependency reference error with a consistent message format.\n").
-spec dependency_ref_error(binary(), binary(), binary()) -> caffeine_lang@errors:compilation_error().
dependency_ref_error(Target, Self_path, Reason) ->
caffeine_lang@errors:semantic_analysis_dependency_validation_error(
<<<<<<<<<<"Invalid dependency reference '"/utf8, Target/binary>>/binary,
"' in '"/utf8>>/binary,
Self_path/binary>>/binary,
"': "/utf8>>/binary,
Reason/binary>>
).
-file("src/caffeine_lang/analysis/dependency_validator.gleam", 150).
-spec validate_dependency_target(
binary(),
binary(),
gleam@dict:dict(binary(), caffeine_lang@linker@ir:intermediate_representation(any()))
) -> {ok, nil} | {error, caffeine_lang@errors:compilation_error()}.
validate_dependency_target(Target, Self_path, Expectation_index) ->
case parse_dependency_path(Target) of
{error, nil} ->
{error,
dependency_ref_error(
Target,
Self_path,
<<"expected format 'org.team.service.name'"/utf8>>
)};
{ok, _} ->
gleam@bool:guard(
Target =:= Self_path,
{error,
dependency_ref_error(
Target,
Self_path,
<<"self-reference not allowed"/utf8>>
)},
fun() -> case gleam_stdlib:map_get(Expectation_index, Target) of
{ok, _} ->
{ok, nil};
{error, nil} ->
{error,
dependency_ref_error(
Target,
Self_path,
<<"target does not exist"/utf8>>
)}
end end
)
end.
-file("src/caffeine_lang/analysis/dependency_validator.gleam", 81).
-spec validate_ir_dependencies(
caffeine_lang@linker@ir:intermediate_representation(HHS),
gleam@dict:dict(binary(), caffeine_lang@linker@ir:intermediate_representation(HHS))
) -> {ok, nil} | {error, caffeine_lang@errors:compilation_error()}.
validate_ir_dependencies(Ir, Expectation_index) ->
Depends_on = get_depends_on(Ir),
gleam@bool:guard(
gleam@option:is_none(Depends_on),
{ok, nil},
fun() ->
Self_path = caffeine_lang@linker@ir:ir_to_identifier(Ir),
Relations@1 = case Depends_on of
{some, Relations} -> Relations;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"caffeine_lang/analysis/dependency_validator"/utf8>>,
function => <<"validate_ir_dependencies"/utf8>>,
line => 92,
value => _assert_fail,
start => 2813,
'end' => 2859,
pattern_start => 2824,
pattern_end => 2846})
end,
gleam@result:'try'(
check_for_duplicates_per_relation(Relations@1, Self_path),
fun(_) ->
All_targets = get_all_dependency_targets(Relations@1),
_pipe = All_targets,
gleam@list:try_each(
_pipe,
fun(Target) ->
validate_dependency_target(
Target,
Self_path,
Expectation_index
)
end
)
end
)
end
).
-file("src/caffeine_lang/analysis/dependency_validator.gleam", 216).
?DOC(" Builds a directed adjacency list from all IRs with depends_on.\n").
-spec build_adjacency_list(
list(caffeine_lang@linker@ir:intermediate_representation(any()))
) -> gleam@dict:dict(binary(), list(binary())).
build_adjacency_list(Irs) ->
_pipe = Irs,
_pipe@1 = gleam@list:filter_map(_pipe, fun(Ir) -> case get_depends_on(Ir) of
{some, Relations} ->
Path = caffeine_lang@linker@ir:ir_to_identifier(Ir),
Targets = get_all_dependency_targets(Relations),
{ok, {Path, Targets}};
none ->
{error, nil}
end end),
maps:from_list(_pipe@1).
-file("src/caffeine_lang/analysis/dependency_validator.gleam", 388).
?DOC(
" Collects thresholds from hard dependency targets.\n"
" Skips targets that don't exist in the index.\n"
).
-spec collect_hard_dep_thresholds(
list(binary()),
gleam@dict:dict(binary(), caffeine_lang@linker@ir:intermediate_representation(any()))
) -> list({binary(), float()}).
collect_hard_dep_thresholds(Targets, Expectation_index) ->
_pipe = Targets,
gleam@list:filter_map(
_pipe,
fun(Target_path) ->
case gleam_stdlib:map_get(Expectation_index, Target_path) of
{error, nil} ->
{error, nil};
{ok, Target_ir} ->
{ok,
{Target_path,
erlang:element(2, erlang:element(5, Target_ir))}}
end
end
).
-file("src/caffeine_lang/analysis/dependency_validator.gleam", 404).
?DOC(
" Computes the composite availability ceiling from a list of thresholds.\n"
" Each threshold is a percentage (e.g. 99.99). The composite ceiling is\n"
" the product of individual availabilities.\n"
).
-spec compute_composite_ceiling(list(float())) -> float().
compute_composite_ceiling(Thresholds) ->
gleam@list:fold(Thresholds, 1.0, fun(Acc, T) -> Acc * (T / 100.0) end) * 100.0.
-file("src/caffeine_lang/analysis/dependency_validator.gleam", 409).
?DOC(" Rounds a float to 4 decimal places for cleaner display.\n").
-spec round_to_4(float()) -> float().
round_to_4(F) ->
erlang:float(erlang:round(F * 10000.0)) / 10000.0.
-file("src/caffeine_lang/analysis/dependency_validator.gleam", 339).
?DOC(
" Validates hard dependency thresholds for a single IR using composite ceiling.\n"
" The composite ceiling is the product of all hard dependency thresholds,\n"
" representing the maximum achievable availability given those dependencies.\n"
).
-spec validate_single_ir_hard_thresholds(
caffeine_lang@linker@ir:intermediate_representation(HKJ),
gleam@dict:dict(binary(), caffeine_lang@linker@ir:intermediate_representation(HKJ))
) -> {ok, nil} | {error, caffeine_lang@errors:compilation_error()}.
validate_single_ir_hard_thresholds(Ir, Expectation_index) ->
Self_path = caffeine_lang@linker@ir:ir_to_identifier(Ir),
Slo = erlang:element(5, Ir),
Source_threshold = erlang:element(2, Slo),
Hard_targets = case erlang:element(8, Slo) of
{some, Relations} ->
_pipe = gleam_stdlib:map_get(Relations, hard),
gleam@result:unwrap(_pipe, []);
none ->
[]
end,
Dep_thresholds = collect_hard_dep_thresholds(
Hard_targets,
Expectation_index
),
gleam@bool:guard(
gleam@list:is_empty(Dep_thresholds),
{ok, nil},
fun() ->
Composite_ceiling = compute_composite_ceiling(
gleam@list:map(
Dep_thresholds,
fun(Pair) -> erlang:element(2, Pair) end
)
),
Display_ceiling = round_to_4(Composite_ceiling),
case gleam@float:compare(Source_threshold, Composite_ceiling) of
gt ->
Deps_description = begin
_pipe@1 = Dep_thresholds,
_pipe@2 = gleam@list:map(
_pipe@1,
fun(Pair@1) ->
<<<<<<<<"'"/utf8,
(erlang:element(1, Pair@1))/binary>>/binary,
"' ("/utf8>>/binary,
(gleam_stdlib:float_to_string(
erlang:element(2, Pair@1)
))/binary>>/binary,
")"/utf8>>
end
),
gleam@string:join(_pipe@2, <<", "/utf8>>)
end,
{error,
caffeine_lang@errors:semantic_analysis_dependency_validation_error(
<<<<<<<<<<<<<<"Composite hard dependency threshold violation: '"/utf8,
Self_path/binary>>/binary,
"' (threshold: "/utf8>>/binary,
(gleam_stdlib:float_to_string(
Source_threshold
))/binary>>/binary,
") exceeds the composite availability ceiling of "/utf8>>/binary,
(gleam_stdlib:float_to_string(
Display_ceiling
))/binary>>/binary,
" from its hard dependencies: "/utf8>>/binary,
Deps_description/binary>>
)};
_ ->
{ok, nil}
end
end
).
-file("src/caffeine_lang/analysis/dependency_validator.gleam", 296).
-spec explore_neighbors(
list(binary()),
gleam@dict:dict(binary(), list(binary())),
gleam@set:set(binary()),
gleam@set:set(binary()),
list(binary())
) -> {ok, {gleam@set:set(binary()), gleam@set:set(binary())}} |
{error, caffeine_lang@errors:compilation_error()}.
explore_neighbors(Neighbors, Adjacency, Visited, In_progress, Path) ->
case Neighbors of
[] ->
{ok, {Visited, In_progress}};
[Neighbor | Rest] ->
gleam@bool:guard(
gleam@set:contains(In_progress, Neighbor),
{error,
caffeine_lang@errors:semantic_analysis_dependency_validation_error(
<<<<<<"Circular dependency detected: "/utf8,
(gleam@string:join(
lists:reverse(Path),
<<" -> "/utf8>>
))/binary>>/binary,
" -> "/utf8>>/binary,
Neighbor/binary>>
)},
fun() ->
gleam@bool:guard(
gleam@set:contains(Visited, Neighbor),
explore_neighbors(
Rest,
Adjacency,
Visited,
In_progress,
Path
),
fun() ->
gleam@result:'try'(
explore_node(
Neighbor,
Adjacency,
Visited,
In_progress,
[Neighbor | Path]
),
fun(_use0) ->
{Visited@1, In_progress@1} = _use0,
explore_neighbors(
Rest,
Adjacency,
Visited@1,
In_progress@1,
Path
)
end
)
end
)
end
)
end.
-file("src/caffeine_lang/analysis/dependency_validator.gleam", 272).
-spec explore_node(
binary(),
gleam@dict:dict(binary(), list(binary())),
gleam@set:set(binary()),
gleam@set:set(binary()),
list(binary())
) -> {ok, {gleam@set:set(binary()), gleam@set:set(binary())}} |
{error, caffeine_lang@errors:compilation_error()}.
explore_node(Node, Adjacency, Visited, In_progress, Path) ->
In_progress@1 = gleam@set:insert(In_progress, Node),
Neighbors = begin
_pipe = gleam_stdlib:map_get(Adjacency, Node),
gleam@result:unwrap(_pipe, [])
end,
gleam@result:'try'(
explore_neighbors(Neighbors, Adjacency, Visited, In_progress@1, Path),
fun(_use0) ->
{Visited@1, In_progress@2} = _use0,
Visited@2 = gleam@set:insert(Visited@1, Node),
In_progress@3 = gleam@set:delete(In_progress@2, Node),
{ok, {Visited@2, In_progress@3}}
end
).
-file("src/caffeine_lang/analysis/dependency_validator.gleam", 247).
-spec detect_cycles_loop(
list(binary()),
gleam@dict:dict(binary(), list(binary())),
gleam@set:set(binary()),
gleam@set:set(binary())
) -> {ok, gleam@set:set(binary())} |
{error, caffeine_lang@errors:compilation_error()}.
detect_cycles_loop(Nodes, Adjacency, Visited, In_progress) ->
case Nodes of
[] ->
{ok, Visited};
[Node | Rest] ->
gleam@bool:guard(
gleam@set:contains(Visited, Node),
detect_cycles_loop(Rest, Adjacency, Visited, In_progress),
fun() ->
gleam@result:'try'(
explore_node(
Node,
Adjacency,
Visited,
In_progress,
[Node]
),
fun(_use0) ->
{Visited@1, In_progress@1} = _use0,
detect_cycles_loop(
Rest,
Adjacency,
Visited@1,
In_progress@1
)
end
)
end
)
end.
-file("src/caffeine_lang/analysis/dependency_validator.gleam", 234).
?DOC(" Detects circular dependencies in the dependency graph.\n").
-spec detect_cycles(
list(caffeine_lang@linker@ir:intermediate_representation(any()))
) -> {ok, nil} | {error, caffeine_lang@errors:compilation_error()}.
detect_cycles(Irs) ->
Adjacency = build_adjacency_list(Irs),
Nodes = begin
_pipe = Adjacency,
_pipe@1 = maps:keys(_pipe),
gleam@list:sort(_pipe@1, fun gleam@string:compare/2)
end,
_pipe@2 = detect_cycles_loop(
Nodes,
Adjacency,
gleam@set:new(),
gleam@set:new()
),
gleam@result:map(_pipe@2, fun(_) -> nil end).
-file("src/caffeine_lang/analysis/dependency_validator.gleam", 32).
?DOC(false).
-spec validate_dependency_relations(
list(caffeine_lang@linker@ir:intermediate_representation(caffeine_lang@linker@ir:linked()))
) -> {ok,
list(caffeine_lang@linker@ir:intermediate_representation(caffeine_lang@linker@ir:deps_validated()))} |
{error, caffeine_lang@errors:compilation_error()}.
validate_dependency_relations(Irs) ->
Expectation_index = build_expectation_index(Irs),
gleam@result:'try'(
begin
_pipe = Irs,
_pipe@1 = gleam@list:map(
_pipe,
fun(Ir) -> validate_ir_dependencies(Ir, Expectation_index) end
),
_pipe@2 = caffeine_lang@errors:from_results(_pipe@1),
gleam@result:map(_pipe@2, fun(_) -> nil end)
end,
fun(_) ->
gleam@result:'try'(
detect_cycles(Irs),
fun(_) ->
gleam@result:'try'(
begin
_pipe@3 = Irs,
_pipe@4 = gleam@list:filter(
_pipe@3,
fun(Ir@1) ->
gleam@option:is_some(get_depends_on(Ir@1))
end
),
_pipe@5 = gleam@list:map(
_pipe@4,
fun(Ir@2) ->
validate_single_ir_hard_thresholds(
Ir@2,
Expectation_index
)
end
),
_pipe@6 = caffeine_lang@errors:from_results(_pipe@5),
gleam@result:map(_pipe@6, fun(_) -> nil end)
end,
fun(_) ->
{ok,
gleam@list:map(
Irs,
fun caffeine_lang@linker@ir:promote/1
)}
end
)
end
)
end
).