Current section

Files

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

src/caffeine_lang@parser@blueprints.erl

-module(caffeine_lang@parser@blueprints).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/caffeine_lang/parser/blueprints.gleam").
-export([validate_blueprints/2, blueprints_from_json/2, parse_from_json_string/2, parse_from_json_file/2]).
-export_type([blueprint/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 blueprint() :: {blueprint,
binary(),
list(binary()),
gleam@dict:dict(binary(), caffeine_lang@common@accepted_types:accepted_types()),
gleam@dict:dict(binary(), gleam@dynamic:dynamic_())}.
-file("src/caffeine_lang/parser/blueprints.gleam", 148).
?DOC(" Map each blueprint to its list of referenced artifacts.\n").
-spec map_blueprints_to_artifacts(
list(blueprint()),
list(caffeine_lang@parser@artifacts:artifact())
) -> list({blueprint(), list(caffeine_lang@parser@artifacts:artifact())}).
map_blueprints_to_artifacts(Blueprints, Artifacts) ->
Artifact_map = begin
_pipe = Artifacts,
_pipe@1 = gleam@list:map(
_pipe,
fun(A) ->
{caffeine_lang@parser@artifacts:artifact_type_to_string(
erlang:element(2, A)
),
A}
end
),
maps:from_list(_pipe@1)
end,
_pipe@2 = Blueprints,
gleam@list:map(
_pipe@2,
fun(Blueprint) ->
Artifact_list = begin
_pipe@3 = erlang:element(3, Blueprint),
gleam@list:filter_map(
_pipe@3,
fun(Ref) -> gleam_stdlib:map_get(Artifact_map, Ref) end
)
end,
{Blueprint, Artifact_list}
end
).
-file("src/caffeine_lang/parser/blueprints.gleam", 167).
?DOC(" Merge params from multiple artifacts into a single dict.\n").
-spec merge_artifact_params(list(caffeine_lang@parser@artifacts:artifact())) -> gleam@dict:dict(binary(), caffeine_lang@common@accepted_types:accepted_types()).
merge_artifact_params(Artifact_list) ->
_pipe = Artifact_list,
gleam@list:fold(
_pipe,
maps:new(),
fun(Acc, Artifact) -> maps:merge(Acc, erlang:element(3, Artifact)) end
).
-file("src/caffeine_lang/parser/blueprints.gleam", 177).
?DOC(" Validate that no blueprint has duplicate artifact refs.\n").
-spec validate_no_duplicate_artifact_refs(list(blueprint())) -> {ok, boolean()} |
{error, caffeine_lang@common@errors:compilation_error()}.
validate_no_duplicate_artifact_refs(Blueprints) ->
Duplicates = begin
_pipe = Blueprints,
gleam@list:filter_map(
_pipe,
fun(Blueprint) ->
Refs = erlang:element(3, Blueprint),
Unique_refs = begin
_pipe@1 = Refs,
gleam@list:unique(_pipe@1)
end,
case erlang:length(Refs) =:= erlang:length(Unique_refs) of
true ->
{error, nil};
false ->
Duplicate_refs = begin
_pipe@2 = Refs,
_pipe@3 = gleam@list:group(_pipe@2, fun(R) -> R end),
_pipe@4 = gleam@dict:filter(
_pipe@3,
fun(_, V) -> erlang:length(V) > 1 end
),
_pipe@5 = maps:keys(_pipe@4),
gleam@string:join(_pipe@5, <<", "/utf8>>)
end,
{ok, Duplicate_refs}
end
end
)
end,
case Duplicates of
[] ->
{ok, true};
[First | _] ->
{error,
{parser_duplicate_error,
<<"Duplicate artifact references in blueprint: "/utf8,
First/binary>>}}
end.
-file("src/caffeine_lang/parser/blueprints.gleam", 230).
?DOC(" Find param names that have different types across artifacts.\n").
-spec find_conflicting_params(list(caffeine_lang@parser@artifacts:artifact())) -> {ok,
binary()} |
{error, nil}.
find_conflicting_params(Artifacts) ->
All_params = begin
_pipe = Artifacts,
gleam@list:flat_map(
_pipe,
fun(A) -> maps:to_list(erlang:element(3, A)) end
)
end,
Grouped = begin
_pipe@1 = All_params,
gleam@list:group(_pipe@1, fun(Pair) -> erlang:element(1, Pair) end)
end,
Conflicting_names = begin
_pipe@2 = Grouped,
_pipe@3 = maps:to_list(_pipe@2),
gleam@list:filter_map(
_pipe@3,
fun(Group) ->
{Name, Pairs} = Group,
Types = begin
_pipe@4 = Pairs,
gleam@list:map(_pipe@4, fun(P) -> erlang:element(2, P) end)
end,
Unique_types = begin
_pipe@5 = Types,
gleam@list:unique(_pipe@5)
end,
case erlang:length(Unique_types) > 1 of
true ->
{ok, Name};
false ->
{error, nil}
end
end
)
end,
case Conflicting_names of
[] ->
{error, nil};
[First | _] ->
{ok, First}
end.
-file("src/caffeine_lang/parser/blueprints.gleam", 210).
?DOC(" Validate that artifacts referenced by a blueprint don't have conflicting param types.\n").
-spec validate_no_conflicting_params(
list({blueprint(), list(caffeine_lang@parser@artifacts:artifact())})
) -> {ok, boolean()} | {error, caffeine_lang@common@errors:compilation_error()}.
validate_no_conflicting_params(Blueprint_artifacts_collection) ->
Conflicts = begin
_pipe = Blueprint_artifacts_collection,
gleam@list:filter_map(
_pipe,
fun(Pair) ->
{_, Artifact_list} = Pair,
find_conflicting_params(Artifact_list)
end
)
end,
case Conflicts of
[] ->
{ok, true};
[First | _] ->
{error,
{parser_duplicate_error,
<<"Conflicting param types across artifacts: "/utf8,
First/binary>>}}
end.
-file("src/caffeine_lang/parser/blueprints.gleam", 57).
?DOC(false).
-spec validate_blueprints(
list(blueprint()),
list(caffeine_lang@parser@artifacts:artifact())
) -> {ok, list(blueprint())} |
{error, caffeine_lang@common@errors:compilation_error()}.
validate_blueprints(Blueprints, Artifacts) ->
gleam@result:'try'(
caffeine_lang@common@validations:validate_relevant_uniqueness(
Blueprints,
fun(B) -> erlang:element(2, B) end,
<<"blueprint names"/utf8>>
),
fun(_) ->
gleam@result:'try'(
validate_no_duplicate_artifact_refs(Blueprints),
fun(_) ->
Blueprint_artifacts_collection = map_blueprints_to_artifacts(
Blueprints,
Artifacts
),
gleam@result:'try'(
validate_no_conflicting_params(
Blueprint_artifacts_collection
),
fun(_) ->
Blueprint_merged_artifact_collection = begin
_pipe = Blueprint_artifacts_collection,
gleam@list:map(
_pipe,
fun(Pair) ->
{Blueprint, Artifact_list} = Pair,
Merged_params = merge_artifact_params(
Artifact_list
),
{Blueprint,
{artifact, s_l_o, Merged_params}}
end
)
end,
gleam@result:'try'(
caffeine_lang@common@validations:validate_inputs_for_collection(
Blueprint_merged_artifact_collection,
fun(Blueprint@1) ->
erlang:element(5, Blueprint@1)
end,
fun(Artifact) ->
erlang:element(3, Artifact)
end,
true
),
fun(_) ->
Overshadow_params_error = begin
_pipe@1 = Blueprint_merged_artifact_collection,
_pipe@2 = gleam@list:filter_map(
_pipe@1,
fun(Blueprint_artifact_pair) ->
{Blueprint@2, Merged_artifact} = Blueprint_artifact_pair,
case caffeine_lang@common@validations:check_collection_key_overshadowing(
erlang:element(
4,
Blueprint@2
),
erlang:element(
3,
Merged_artifact
),
<<"Blueprint overshadowing inherited_params from artifact: "/utf8>>
) of
{ok, _} ->
{error, nil};
{error, Msg} ->
{ok, Msg}
end
end
),
gleam@string:join(
_pipe@2,
<<", "/utf8>>
)
end,
gleam@result:'try'(
case Overshadow_params_error of
<<""/utf8>> ->
{ok, true};
_ ->
{error,
{parser_duplicate_error,
<<"Overshadowed inherited_params in blueprint error: "/utf8,
Overshadow_params_error/binary>>}}
end,
fun(_) ->
Merged_param_blueprints = begin
_pipe@3 = Blueprint_artifacts_collection,
gleam@list:map(
_pipe@3,
fun(
Blueprint_artifacts_pair
) ->
{Blueprint@3,
Artifact_list@1} = Blueprint_artifacts_pair,
All_params = begin
_pipe@4 = merge_artifact_params(
Artifact_list@1
),
maps:merge(
_pipe@4,
erlang:element(
4,
Blueprint@3
)
)
end,
{blueprint,
erlang:element(
2,
Blueprint@3
),
erlang:element(
3,
Blueprint@3
),
All_params,
erlang:element(
5,
Blueprint@3
)}
end
)
end,
{ok, Merged_param_blueprints}
end
)
end
)
end
)
end
)
end
).
-file("src/caffeine_lang/parser/blueprints.gleam", 263).
?DOC(false).
-spec blueprints_from_json(
binary(),
list(caffeine_lang@parser@artifacts:artifact())
) -> {ok, list(blueprint())} | {error, gleam@json:decode_error()}.
blueprints_from_json(Json_string, Artifacts) ->
Blueprint_decoded = begin
gleam@dynamic@decode:field(
<<"name"/utf8>>,
caffeine_lang@common@decoders:non_empty_string_decoder(),
fun(Name) ->
gleam@dynamic@decode:field(
<<"artifact_refs"/utf8>>,
caffeine_lang@common@decoders:non_empty_named_reference_list_decoder(
Artifacts,
fun(A) ->
caffeine_lang@parser@artifacts:artifact_type_to_string(
erlang:element(2, A)
)
end
),
fun(Artifact_refs) ->
gleam@dynamic@decode:field(
<<"params"/utf8>>,
gleam@dynamic@decode:dict(
{decoder,
fun gleam@dynamic@decode:decode_string/1},
caffeine_lang@common@decoders:accepted_types_decoder(
)
),
fun(Params) ->
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(
{blueprint,
Name,
Artifact_refs,
Params,
Inputs}
)
end
)
end
)
end
)
end
)
end,
Blueprints_decoded = begin
gleam@dynamic@decode:field(
<<"blueprints"/utf8>>,
gleam@dynamic@decode:list(Blueprint_decoded),
fun(Blueprints) -> gleam@dynamic@decode:success(Blueprints) end
)
end,
gleam@json:parse(Json_string, Blueprints_decoded).
-file("src/caffeine_lang/parser/blueprints.gleam", 39).
?DOC(false).
-spec parse_from_json_string(
binary(),
list(caffeine_lang@parser@artifacts:artifact())
) -> {ok, list(blueprint())} |
{error, caffeine_lang@common@errors:compilation_error()}.
parse_from_json_string(Json_string, Artifacts) ->
gleam@result:'try'(case blueprints_from_json(Json_string, Artifacts) of
{ok, Blueprints} ->
{ok, Blueprints};
{error, Err} ->
{error,
caffeine_lang@common@errors:format_json_decode_error(Err)}
end, fun(Blueprints@1) ->
validate_blueprints(Blueprints@1, Artifacts)
end).
-file("src/caffeine_lang/parser/blueprints.gleam", 28).
?DOC(false).
-spec parse_from_json_file(
binary(),
list(caffeine_lang@parser@artifacts:artifact())
) -> {ok, list(blueprint())} |
{error, caffeine_lang@common@errors:compilation_error()}.
parse_from_json_file(File_path, Artifacts) ->
gleam@result:'try'(
caffeine_lang@common@helpers:json_from_file(File_path),
fun(Json_string) -> parse_from_json_string(Json_string, Artifacts) end
).