Packages
caffeine_lang
4.3.6
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", 59).
?DOC(false).
-spec build_expectation_index(
list(caffeine_lang@linker@ir:intermediate_representation())
) -> gleam@dict:dict(binary(), caffeine_lang@linker@ir:intermediate_representation()).
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", 105).
-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", 125).
-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,
{semantic_analysis_dependency_validation_error,
<<<<<<<<"Duplicate dependency reference '"/utf8,
Target/binary>>/binary,
"' in '"/utf8>>/binary,
Self_path/binary>>/binary,
"'"/utf8>>,
caffeine_lang@errors:empty_context()}},
fun() ->
do_check_for_duplicates(
Rest,
gleam@set:insert(Seen, Target),
Self_path
)
end
)
end.
-file("src/caffeine_lang/analysis/dependency_validator.gleam", 113).
-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", 198).
?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", 149).
-spec validate_dependency_target(
binary(),
binary(),
gleam@dict:dict(binary(), caffeine_lang@linker@ir:intermediate_representation())
) -> {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,
{semantic_analysis_dependency_validation_error,
<<<<<<<<"Invalid dependency reference '"/utf8,
Target/binary>>/binary,
"' in '"/utf8>>/binary,
Self_path/binary>>/binary,
"': expected format 'org.team.service.name'"/utf8>>,
caffeine_lang@errors:empty_context()}};
{ok, _} ->
gleam@bool:guard(
Target =:= Self_path,
{error,
{semantic_analysis_dependency_validation_error,
<<<<<<<<"Invalid dependency reference '"/utf8,
Target/binary>>/binary,
"' in '"/utf8>>/binary,
Self_path/binary>>/binary,
"': self-reference not allowed"/utf8>>,
caffeine_lang@errors:empty_context()}},
fun() -> case gleam_stdlib:map_get(Expectation_index, Target) of
{ok, _} ->
{ok, nil};
{error, nil} ->
{error,
{semantic_analysis_dependency_validation_error,
<<<<<<<<"Invalid dependency reference '"/utf8,
Target/binary>>/binary,
"' in '"/utf8>>/binary,
Self_path/binary>>/binary,
"': target does not exist"/utf8>>,
caffeine_lang@errors:empty_context()}}
end end
)
end.
-file("src/caffeine_lang/analysis/dependency_validator.gleam", 70).
-spec validate_ir_dependencies(
caffeine_lang@linker@ir:intermediate_representation(),
gleam@dict:dict(binary(), caffeine_lang@linker@ir:intermediate_representation())
) -> {ok, nil} | {error, caffeine_lang@errors:compilation_error()}.
validate_ir_dependencies(Ir, Expectation_index) ->
gleam@bool:guard(
not gleam@list:contains(erlang:element(4, Ir), dependency_relations),
{ok, nil},
fun() ->
Self_path = caffeine_lang@linker@ir:ir_to_identifier(Ir),
gleam@result:'try'(
begin
_pipe = caffeine_lang@linker@ir:get_dependency_fields(
erlang:element(6, Ir)
),
gleam@option:to_result(
_pipe,
{semantic_analysis_dependency_validation_error,
<<Self_path/binary,
" - missing dependency artifact data"/utf8>>,
caffeine_lang@errors:empty_context()}
)
end,
fun(Dep) ->
Relations = erlang:element(2, Dep),
gleam@result:'try'(
check_for_duplicates_per_relation(Relations, Self_path),
fun(_) ->
All_targets = get_all_dependency_targets(Relations),
_pipe@1 = All_targets,
gleam@list:try_each(
_pipe@1,
fun(Target) ->
validate_dependency_target(
Target,
Self_path,
Expectation_index
)
end
)
end
)
end
)
end
).
-file("src/caffeine_lang/analysis/dependency_validator.gleam", 212).
?DOC(" Builds a directed adjacency list from all IRs with DependencyRelations.\n").
-spec build_adjacency_list(
list(caffeine_lang@linker@ir:intermediate_representation())
) -> gleam@dict:dict(binary(), list(binary())).
build_adjacency_list(Irs) ->
_pipe = Irs,
_pipe@1 = gleam@list:filter(
_pipe,
fun(Ir) ->
gleam@list:contains(erlang:element(4, Ir), dependency_relations)
end
),
_pipe@2 = gleam@list:filter_map(
_pipe@1,
fun(Ir@1) ->
case caffeine_lang@linker@ir:get_dependency_fields(
erlang:element(6, Ir@1)
) of
{some, Dep} ->
Path = caffeine_lang@linker@ir:ir_to_identifier(Ir@1),
Targets = get_all_dependency_targets(erlang:element(2, Dep)),
{ok, {Path, Targets}};
none ->
{error, nil}
end
end
),
maps:from_list(_pipe@2).
-file("src/caffeine_lang/analysis/dependency_validator.gleam", 368).
-spec validate_single_hard_threshold(
binary(),
float(),
binary(),
gleam@dict:dict(binary(), caffeine_lang@linker@ir:intermediate_representation())
) -> {ok, nil} | {error, caffeine_lang@errors:compilation_error()}.
validate_single_hard_threshold(
Source_path,
Source_threshold,
Target_path,
Expectation_index
) ->
case gleam_stdlib:map_get(Expectation_index, Target_path) of
{error, nil} ->
{ok, nil};
{ok, Target_ir} ->
gleam@bool:guard(
not gleam@list:contains(erlang:element(4, Target_ir), s_l_o),
{ok, nil},
fun() ->
gleam@result:'try'(
begin
_pipe = caffeine_lang@linker@ir:get_slo_fields(
erlang:element(6, Target_ir)
),
gleam@option:to_result(
_pipe,
{semantic_analysis_dependency_validation_error,
<<Target_path/binary,
" - missing SLO artifact data"/utf8>>,
caffeine_lang@errors:empty_context()}
)
end,
fun(Target_slo) ->
Target_threshold = erlang:element(2, Target_slo),
case gleam@float:compare(
Source_threshold,
Target_threshold
) of
gt ->
{error,
{semantic_analysis_dependency_validation_error,
<<<<<<<<<<<<<<<<"Hard dependency threshold violation: '"/utf8,
Source_path/binary>>/binary,
"' (threshold: "/utf8>>/binary,
(gleam_stdlib:float_to_string(
Source_threshold
))/binary>>/binary,
") cannot exceed its hard dependency '"/utf8>>/binary,
Target_path/binary>>/binary,
"' (threshold: "/utf8>>/binary,
(gleam_stdlib:float_to_string(
Target_threshold
))/binary>>/binary,
")"/utf8>>,
caffeine_lang@errors:empty_context()}};
_ ->
{ok, nil}
end
end
)
end
)
end.
-file("src/caffeine_lang/analysis/dependency_validator.gleam", 336).
?DOC(
" Validates hard dependency thresholds for a single IR.\n"
" A source's threshold must not exceed its hard dependency's threshold.\n"
).
-spec validate_single_ir_hard_thresholds(
caffeine_lang@linker@ir:intermediate_representation(),
gleam@dict:dict(binary(), caffeine_lang@linker@ir:intermediate_representation())
) -> {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),
gleam@result:'try'(
case {caffeine_lang@linker@ir:get_slo_fields(erlang:element(6, Ir)),
caffeine_lang@linker@ir:get_dependency_fields(erlang:element(6, Ir))} of
{{some, Slo}, {some, Dep}} ->
{ok, {Slo, Dep}};
{_, _} ->
{error,
{semantic_analysis_dependency_validation_error,
<<Self_path/binary,
" - missing SLO or dependency artifact data"/utf8>>,
caffeine_lang@errors:empty_context()}}
end,
fun(_use0) ->
{Slo@1, Dep@1} = _use0,
Source_threshold = erlang:element(2, Slo@1),
Hard_targets = begin
_pipe = gleam_stdlib:map_get(erlang:element(2, Dep@1), hard),
gleam@result:unwrap(_pipe, [])
end,
_pipe@1 = Hard_targets,
gleam@list:try_each(
_pipe@1,
fun(Target) ->
validate_single_hard_threshold(
Self_path,
Source_threshold,
Target,
Expectation_index
)
end
)
end
).
-file("src/caffeine_lang/analysis/dependency_validator.gleam", 293).
-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,
{semantic_analysis_dependency_validation_error,
<<<<<<"Circular dependency detected: "/utf8,
(gleam@string:join(
lists:reverse(Path),
<<" -> "/utf8>>
))/binary>>/binary,
" -> "/utf8>>/binary,
Neighbor/binary>>,
caffeine_lang@errors:empty_context()}},
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", 269).
-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", 244).
-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", 231).
?DOC(" Detects circular dependencies in the dependency graph.\n").
-spec detect_cycles(list(caffeine_lang@linker@ir:intermediate_representation())) -> {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", 22).
?DOC(false).
-spec validate_dependency_relations(
list(caffeine_lang@linker@ir:intermediate_representation())
) -> {ok, list(caffeine_lang@linker@ir:intermediate_representation())} |
{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@list:contains(
erlang:element(4, Ir@1),
dependency_relations
)
andalso gleam@list:contains(
erlang:element(4, Ir@1),
s_l_o
)
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, Irs} end
)
end
)
end
).