Current section

Files

Jump to
graded src graded@internal@annotation.erl
Raw

src/graded@internal@annotation.erl

-module(graded@internal@annotation).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/graded/internal/annotation.gleam").
-export([parse_file/1, extract_annotations/1, parse/1, extract_returns/1, format_returns/1, extract_checks/1, format_annotation/1, split_qualified_name/1, format_type_field/1, extract_type_fields/1, format_effect_set/1, format_external/1, extract_externals/1, format_file/1, merge_inferred/3, format_sorted/1]).
-export_type([parse_error/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.
?MODULEDOC(false).
-type parse_error() :: {invalid_line, integer(), binary()}.
-file("src/graded/internal/annotation.gleam", 589).
?DOC(false).
-spec is_label_token(binary()) -> boolean().
is_label_token(Token) ->
graded@internal@types:is_upper_initial(Token).
-file("src/graded/internal/annotation.gleam", 665).
?DOC(false).
-spec split_top_level_commas(binary()) -> list(binary()).
split_top_level_commas(Input) ->
{Segments@1, Current@1, _} = gleam@list:fold(
gleam@string:to_graphemes(Input),
{[], <<""/utf8>>, 0},
fun(State, Char) ->
{Segments, Current, Depth} = State,
case Char of
<<","/utf8>> when Depth =:= 0 ->
{[Current | Segments], <<""/utf8>>, Depth};
<<"["/utf8>> ->
{Segments, <<Current/binary, Char/binary>>, Depth + 1};
<<"("/utf8>> ->
{Segments, <<Current/binary, Char/binary>>, Depth + 1};
<<"]"/utf8>> ->
{Segments, <<Current/binary, Char/binary>>, Depth - 1};
<<")"/utf8>> ->
{Segments, <<Current/binary, Char/binary>>, Depth - 1};
_ ->
{Segments, <<Current/binary, Char/binary>>, Depth}
end
end
),
lists:reverse([Current@1 | Segments@1]).
-file("src/graded/internal/annotation.gleam", 651).
?DOC(false).
-spec parse_application_args(binary()) -> {ok,
list(graded@internal@types:effect_term())} |
{error, nil}.
parse_application_args(Inner) ->
case gleam@string:trim(Inner) of
<<""/utf8>> ->
{ok, []};
Trimmed ->
_pipe = Trimmed,
_pipe@1 = split_top_level_commas(_pipe),
_pipe@2 = gleam@list:map(_pipe@1, fun gleam@string:trim/1),
gleam@list:try_map(_pipe@2, fun parse_effect_term/1)
end.
-file("src/graded/internal/annotation.gleam", 631).
?DOC(false).
-spec parse_atom(binary()) -> {ok, graded@internal@types:effect_term()} |
{error, nil}.
parse_atom(Token) ->
case gleam@string:split_once(Token, <<"("/utf8>>) of
{ok, {Name, Rest}} ->
gleam@bool:guard(
not gleam_stdlib:string_ends_with(Rest, <<")"/utf8>>),
{error, nil},
fun() ->
Callee = gleam@string:trim(Name),
gleam@bool:guard(
Callee =:= <<""/utf8>>,
{error, nil},
fun() ->
gleam@result:'try'(
parse_application_args(
gleam@string:drop_end(Rest, 1)
),
fun(Args) ->
{ok,
gleam@list:fold(
Args,
{t_var, Callee},
fun(Acc, Arg) ->
{t_app, Acc, Arg}
end
)}
end
)
end
)
end
);
{error, nil} ->
case is_label_token(Token) of
true ->
{ok, {t_labels, gleam@set:from_list([Token])}};
false ->
{ok, {t_var, Token}}
end
end.
-file("src/graded/internal/annotation.gleam", 618).
?DOC(false).
-spec parse_atoms(binary()) -> {ok, list(graded@internal@types:effect_term())} |
{error, nil}.
parse_atoms(Inner) ->
_pipe = Inner,
_pipe@1 = split_top_level_commas(_pipe),
_pipe@2 = gleam@list:map(_pipe@1, fun gleam@string:trim/1),
_pipe@3 = gleam@list:filter(_pipe@2, fun(Token) -> Token /= <<""/utf8>> end),
gleam@list:try_map(_pipe@3, fun parse_atom/1).
-file("src/graded/internal/annotation.gleam", 596).
?DOC(false).
-spec parse_effect_term(binary()) -> {ok, graded@internal@types:effect_term()} |
{error, nil}.
parse_effect_term(Input) ->
Trimmed = gleam@string:trim(Input),
gleam@bool:guard(
not (gleam_stdlib:string_starts_with(Trimmed, <<"["/utf8>>) andalso gleam_stdlib:string_ends_with(
Trimmed,
<<"]"/utf8>>
)),
{error, nil},
fun() ->
Inner = begin
_pipe = Trimmed,
_pipe@1 = gleam@string:drop_start(_pipe, 1),
_pipe@2 = gleam@string:drop_end(_pipe@1, 1),
gleam@string:trim(_pipe@2)
end,
case Inner of
<<"_"/utf8>> ->
{ok, t_top};
<<""/utf8>> ->
{ok, {t_labels, gleam@set:new()}};
_ ->
gleam@result:'try'(
parse_atoms(Inner),
fun(Atoms) ->
{ok,
graded@internal@effect_term:normalize(
{t_union, Atoms}
)}
end
)
end
end
).
-file("src/graded/internal/annotation.gleam", 681).
?DOC(false).
-spec parse_bound_effect(binary()) -> {ok, graded@internal@types:effect_term()} |
{error, nil}.
parse_bound_effect(Input) ->
Trimmed = gleam@string:trim(Input),
case gleam_stdlib:string_starts_with(Trimmed, <<"fn("/utf8>>) of
false ->
parse_effect_term(Trimmed);
true ->
gleam@result:'try'(
gleam@string:split_once(Trimmed, <<")"/utf8>>),
fun(_use0) ->
{Params_part, After} = _use0,
Params = begin
_pipe = Params_part,
_pipe@1 = gleam@string:drop_start(_pipe, 3),
_pipe@2 = split_top_level_commas(_pipe@1),
_pipe@3 = gleam@list:map(
_pipe@2,
fun gleam@string:trim/1
),
gleam@list:filter(
_pipe@3,
fun(Param) -> Param /= <<""/utf8>> end
)
end,
gleam@bool:guard(
Params =:= [],
{error, nil},
fun() ->
gleam@result:'try'(
gleam@string:split_once(After, <<"->"/utf8>>),
fun(_use0@1) ->
{_, Body_str} = _use0@1,
gleam@result:'try'(
parse_effect_term(
gleam@string:trim(Body_str)
),
fun(Body) ->
{ok,
gleam@list:fold_right(
Params,
Body,
fun(Acc, Param@1) ->
{t_abs, Param@1, Acc}
end
)}
end
)
end
)
end
)
end
)
end.
-file("src/graded/internal/annotation.gleam", 574).
?DOC(false).
-spec parse_name_colon_effects(binary()) -> {ok,
{binary(), graded@internal@types:effect_term()}} |
{error, nil}.
parse_name_colon_effects(Input) ->
gleam@result:'try'(
gleam@string:split_once(gleam@string:trim(Input), <<":"/utf8>>),
fun(_use0) ->
{Name_part, Effects_part} = _use0,
Name = gleam@string:trim(Name_part),
gleam@bool:guard(
Name =:= <<""/utf8>>,
{error, nil},
fun() ->
gleam@result:'try'(
parse_bound_effect(gleam@string:trim(Effects_part)),
fun(Effects) -> {ok, {Name, Effects}} end
)
end
)
end
).
-file("src/graded/internal/annotation.gleam", 400).
?DOC(false).
-spec parse_returns_line(binary()) -> {ok,
graded@internal@types:returns_annotation()} |
{error, nil}.
parse_returns_line(Rest) ->
gleam@result:'try'(
parse_name_colon_effects(Rest),
fun(_use0) ->
{Name, Operator} = _use0,
{ok, {returns_annotation, Name, Operator}}
end
).
-file("src/graded/internal/annotation.gleam", 538).
?DOC(false).
-spec parse_external_line(binary()) -> {ok,
graded@internal@types:external_annotation()} |
{error, nil}.
parse_external_line(Rest) ->
gleam@result:'try'(
parse_name_colon_effects(Rest),
fun(_use0) ->
{Qualified, Term} = _use0,
Effects = graded@internal@effect_term:to_effect_set(Term),
Segments = gleam@string:split(Qualified, <<"."/utf8>>),
Len = erlang:length(Segments),
case Len of
1 ->
{ok,
{external_annotation,
Qualified,
module_external,
Effects}};
_ ->
gleam@result:'try'(
gleam@list:last(Segments),
fun(Function) ->
Module = begin
_pipe = Segments,
_pipe@1 = gleam@list:take(_pipe, Len - 1),
gleam@string:join(_pipe@1, <<"."/utf8>>)
end,
{ok,
{external_annotation,
Module,
{function_external, Function},
Effects}}
end
)
end
end
).
-file("src/graded/internal/annotation.gleam", 507).
?DOC(false).
-spec parse_type_field_line(binary()) -> {ok,
graded@internal@types:type_field_annotation()} |
{error, nil}.
parse_type_field_line(Rest) ->
gleam@result:'try'(
parse_name_colon_effects(Rest),
fun(_use0) ->
{Qualified, Effects} = _use0,
case gleam@string:split(Qualified, <<"."/utf8>>) of
[Type_name, Field] when (Type_name =/= <<""/utf8>>) andalso (Field =/= <<""/utf8>>) ->
{ok,
{type_field_annotation, none, Type_name, Field, Effects}};
Segments ->
Count = erlang:length(Segments),
gleam@bool:guard(
Count < 3,
{error, nil},
fun() ->
Module_segments = gleam@list:take(
Segments,
Count - 2
),
Trailing = gleam@list:drop(Segments, Count - 2),
case Trailing of
[Type_name@1, Field@1] when (Type_name@1 =/= <<""/utf8>>) andalso (Field@1 =/= <<""/utf8>>) ->
Module = gleam@string:join(
Module_segments,
<<"."/utf8>>
),
gleam@bool:guard(
Module =:= <<""/utf8>>,
{error, nil},
fun() ->
{ok,
{type_field_annotation,
{some, Module},
Type_name@1,
Field@1,
Effects}}
end
);
_ ->
{error, nil}
end
end
)
end
end
).
-file("src/graded/internal/annotation.gleam", 566).
?DOC(false).
-spec parse_single_param(binary()) -> {ok, graded@internal@types:param_bound()} |
{error, nil}.
parse_single_param(Input) ->
gleam@result:'try'(
parse_name_colon_effects(Input),
fun(_use0) ->
{Name, Effects} = _use0,
{ok, {param_bound, Name, Effects}}
end
).
-file("src/graded/internal/annotation.gleam", 559).
?DOC(false).
-spec parse_params_section(binary()) -> {ok,
list(graded@internal@types:param_bound())} |
{error, nil}.
parse_params_section(Input) ->
case gleam@string:trim(Input) of
<<""/utf8>> ->
{ok, []};
Trimmed ->
gleam@list:try_map(
split_top_level_commas(Trimmed),
fun parse_single_param/1
)
end.
-file("src/graded/internal/annotation.gleam", 477).
?DOC(false).
-spec parse_params_suffix(
graded@internal@types:annotation_kind(),
binary(),
binary(),
binary()
) -> {ok, graded@internal@types:effect_annotation()} | {error, nil}.
parse_params_suffix(Kind, Name, Params_str, Suffix) ->
Suffix_trimmed = gleam@string:trim(Suffix),
case gleam_stdlib:string_starts_with(Suffix_trimmed, <<":"/utf8>>) of
false ->
{error, nil};
true ->
Effects_str = gleam@string:trim(
gleam@string:drop_start(Suffix_trimmed, 1)
),
case {parse_effect_term(Effects_str),
parse_params_section(Params_str)} of
{{ok, Effects}, {ok, Params}} ->
{ok, {effect_annotation, Kind, Name, Params, Effects}};
{_, _} ->
{error, nil}
end
end.
-file("src/graded/internal/annotation.gleam", 460).
?DOC(false).
-spec match_paren(list(binary()), integer(), list(binary())) -> {ok,
{binary(), binary()}} |
{error, nil}.
match_paren(Graphemes, Depth, Acc) ->
case Graphemes of
[] ->
{error, nil};
[<<")"/utf8>> | Rest] when Depth =:= 0 ->
_pipe@2 = {begin
_pipe = Acc,
_pipe@1 = lists:reverse(_pipe),
erlang:list_to_binary(_pipe@1)
end,
erlang:list_to_binary(Rest)},
{ok, _pipe@2};
[<<"("/utf8>> | Rest@1] ->
match_paren(Rest@1, Depth + 1, [<<"("/utf8>> | Acc]);
[<<")"/utf8>> | Rest@2] ->
match_paren(Rest@2, Depth - 1, [<<")"/utf8>> | Acc]);
[Grapheme | Rest@3] ->
match_paren(Rest@3, Depth, [Grapheme | Acc])
end.
-file("src/graded/internal/annotation.gleam", 449).
?DOC(false).
-spec split_call(binary()) -> {ok, {binary(), binary(), binary()}} |
{error, nil}.
split_call(S) ->
gleam@result:'try'(
gleam@string:split_once(S, <<"("/utf8>>),
fun(_use0) ->
{Before, Rest} = _use0,
gleam@bool:guard(
gleam_stdlib:contains_string(Before, <<"["/utf8>>),
{error, nil},
fun() ->
gleam@result:'try'(
match_paren(gleam@string:to_graphemes(Rest), 0, []),
fun(_use0@1) ->
{Params, Suffix} = _use0@1,
{ok, {Before, Params, Suffix}}
end
)
end
)
end
).
-file("src/graded/internal/annotation.gleam", 422).
?DOC(false).
-spec parse_annotation_rest(
graded@internal@types:annotation_kind(),
binary(),
integer(),
binary()
) -> {ok, graded@internal@types:effect_annotation()} | {error, parse_error()}.
parse_annotation_rest(Kind, Rest, Line_number, Original) ->
Err = {error, {invalid_line, Line_number, Original}},
case split_call(Rest) of
{error, nil} ->
case parse_name_colon_effects(Rest) of
{error, nil} ->
Err;
{ok, {Name, Effects}} ->
{ok, {effect_annotation, Kind, Name, [], Effects}}
end;
{ok, {Name@1, Params_str, Suffix}} ->
_pipe = parse_params_suffix(
Kind,
gleam@string:trim(Name@1),
Params_str,
Suffix
),
gleam@result:replace_error(
_pipe,
{invalid_line, Line_number, Original}
)
end.
-file("src/graded/internal/annotation.gleam", 405).
?DOC(false).
-spec parse_annotation_line(binary(), integer(), binary()) -> {ok,
graded@internal@types:effect_annotation()} |
{error, parse_error()}.
parse_annotation_line(Trimmed, Line_number, Original) ->
{Kind, Rest} = case Trimmed of
<<"effects "/utf8, Remaining/binary>> ->
{{ok, effects}, Remaining};
<<"check "/utf8, Remaining@1/binary>> ->
{{ok, check}, Remaining@1};
_ ->
{{error, nil}, <<""/utf8>>}
end,
case Kind of
{error, nil} ->
{error, {invalid_line, Line_number, Original}};
{ok, Parsed_kind} ->
parse_annotation_rest(Parsed_kind, Rest, Line_number, Original)
end.
-file("src/graded/internal/annotation.gleam", 366).
?DOC(false).
-spec parse_structured_line(binary(), integer()) -> {ok,
graded@internal@types:graded_line()} |
{error, parse_error()}.
parse_structured_line(Line, Line_number) ->
Trimmed = gleam@string:trim(Line),
case Trimmed of
<<""/utf8>> ->
{ok, blank_line};
<<"//"/utf8, _/binary>> ->
{ok, {comment_line, Line}};
<<"effects "/utf8, _/binary>> ->
case parse_annotation_line(Trimmed, Line_number, Line) of
{ok, Annotation} ->
{ok, {annotation_line, Annotation}};
{error, Parse_error} ->
{error, Parse_error}
end;
<<"check "/utf8, _/binary>> ->
case parse_annotation_line(Trimmed, Line_number, Line) of
{ok, Annotation} ->
{ok, {annotation_line, Annotation}};
{error, Parse_error} ->
{error, Parse_error}
end;
<<"type "/utf8, Rest/binary>> ->
case parse_type_field_line(Rest) of
{ok, Tf} ->
{ok, {type_field_line, Tf}};
{error, nil} ->
{error, {invalid_line, Line_number, Line}}
end;
<<"external effects "/utf8, Rest@1/binary>> ->
case parse_external_line(Rest@1) of
{ok, Ext} ->
{ok, {external_line, Ext}};
{error, nil} ->
{error, {invalid_line, Line_number, Line}}
end;
<<"returns "/utf8, Rest@2/binary>> ->
case parse_returns_line(Rest@2) of
{ok, Returns} ->
{ok, {returns_line, Returns}};
{error, nil} ->
{error, {invalid_line, Line_number, Line}}
end;
_ ->
{error, {invalid_line, Line_number, Line}}
end.
-file("src/graded/internal/annotation.gleam", 24).
?DOC(false).
-spec parse_file(binary()) -> {ok, graded@internal@types:graded_file()} |
{error, parse_error()}.
parse_file(Input) ->
_pipe = Input,
_pipe@1 = gleam@string:split(_pipe, <<"\n"/utf8>>),
_pipe@2 = gleam@list:index_map(
_pipe@1,
fun(Line, Index) -> {Index + 1, Line} end
),
_pipe@3 = gleam@list:try_map(
_pipe@2,
fun(Pair) ->
{Line_number, Line@1} = Pair,
parse_structured_line(Line@1, Line_number)
end
),
gleam@result:map(_pipe@3, fun(Lines) -> {graded_file, Lines} end).
-file("src/graded/internal/annotation.gleam", 42).
?DOC(false).
-spec extract_annotations(graded@internal@types:graded_file()) -> list(graded@internal@types:effect_annotation()).
extract_annotations(File) ->
gleam@list:filter_map(erlang:element(2, File), fun(Line) -> case Line of
{annotation_line, Annotation} ->
{ok, Annotation};
{type_field_line, _} ->
{error, nil};
{external_line, _} ->
{error, nil};
{returns_line, _} ->
{error, nil};
{comment_line, _} ->
{error, nil};
blank_line ->
{error, nil}
end end).
-file("src/graded/internal/annotation.gleam", 36).
?DOC(false).
-spec parse(binary()) -> {ok, list(graded@internal@types:effect_annotation())} |
{error, parse_error()}.
parse(Input) ->
gleam@result:'try'(
parse_file(Input),
fun(File) -> {ok, extract_annotations(File)} end
).
-file("src/graded/internal/annotation.gleam", 56).
?DOC(false).
-spec extract_returns(graded@internal@types:graded_file()) -> list(graded@internal@types:returns_annotation()).
extract_returns(File) ->
gleam@list:filter_map(erlang:element(2, File), fun(Line) -> case Line of
{returns_line, Returns} ->
{ok, Returns};
_ ->
{error, nil}
end end).
-file("src/graded/internal/annotation.gleam", 785).
?DOC(false).
-spec abstraction_spine(graded@internal@types:effect_term()) -> {list(binary()),
graded@internal@types:effect_term()}.
abstraction_spine(Term) ->
case Term of
{t_abs, Param, Body} ->
{Rest, Inner} = abstraction_spine(Body),
{[Param | Rest], Inner};
Other ->
{[], Other}
end.
-file("src/graded/internal/annotation.gleam", 766).
?DOC(false).
-spec application_spine(graded@internal@types:effect_term()) -> {graded@internal@types:effect_term(),
list(graded@internal@types:effect_term())}.
application_spine(Term) ->
case Term of
{t_app, Operator, Argument} ->
{Head, Args} = application_spine(Operator),
{Head, lists:append(Args, [Argument])};
Other ->
{Other, []}
end.
-file("src/graded/internal/annotation.gleam", 778).
?DOC(false).
-spec render_abstraction(graded@internal@types:effect_term()) -> binary().
render_abstraction(Term) ->
{Binders, Body} = abstraction_spine(Term),
<<<<<<"fn("/utf8, (gleam@string:join(Binders, <<", "/utf8>>))/binary>>/binary,
") -> "/utf8>>/binary,
(format_effect_term(Body))/binary>>.
-file("src/graded/internal/annotation.gleam", 752).
?DOC(false).
-spec render_application(graded@internal@types:effect_term()) -> binary().
render_application(Term) ->
{Head, Args} = application_spine(Term),
Callee = case Head of
{t_var, Name} ->
Name;
Other ->
gleam@string:join(
begin
_pipe = term_atoms(Other),
gleam@list:sort(_pipe, fun gleam@string:compare/2)
end,
<<" "/utf8>>
)
end,
<<<<<<Callee/binary, "("/utf8>>/binary,
(begin
_pipe@1 = Args,
_pipe@2 = gleam@list:map(_pipe@1, fun format_effect_term/1),
gleam@string:join(_pipe@2, <<", "/utf8>>)
end)/binary>>/binary,
")"/utf8>>.
-file("src/graded/internal/annotation.gleam", 737).
?DOC(false).
-spec term_atoms(graded@internal@types:effect_term()) -> list(binary()).
term_atoms(Term) ->
case Term of
{t_labels, Labels} ->
gleam@set:to_list(Labels);
{t_var, Name} ->
[Name];
t_top ->
[<<"_"/utf8>>];
{t_app, _, _} ->
[render_application(Term)];
{t_union, Members} ->
gleam@list:flat_map(Members, fun term_atoms/1);
{t_abs, _, _} ->
[render_abstraction(Term)]
end.
-file("src/graded/internal/annotation.gleam", 725).
?DOC(false).
-spec format_effect_term(graded@internal@types:effect_term()) -> binary().
format_effect_term(Term) ->
case graded@internal@effect_term:normalize(Term) of
t_top ->
<<"[_]"/utf8>>;
Normalized ->
<<<<"["/utf8,
(begin
_pipe = term_atoms(Normalized),
_pipe@1 = gleam@list:sort(
_pipe,
fun gleam@string:compare/2
),
gleam@string:join(_pipe@1, <<", "/utf8>>)
end)/binary>>/binary,
"]"/utf8>>
end.
-file("src/graded/internal/annotation.gleam", 72).
?DOC(false).
-spec format_operator(graded@internal@types:effect_term()) -> binary().
format_operator(Term) ->
case Term of
{t_abs, _, _} ->
render_abstraction(Term);
Other ->
format_effect_term(Other)
end.
-file("src/graded/internal/annotation.gleam", 66).
?DOC(false).
-spec format_returns(graded@internal@types:returns_annotation()) -> binary().
format_returns(Returns) ->
<<<<<<"returns "/utf8, (erlang:element(2, Returns))/binary>>/binary,
" : "/utf8>>/binary,
(format_operator(erlang:element(3, Returns)))/binary>>.
-file("src/graded/internal/annotation.gleam", 80).
?DOC(false).
-spec extract_checks(graded@internal@types:graded_file()) -> list(graded@internal@types:effect_annotation()).
extract_checks(File) ->
_pipe = extract_annotations(File),
gleam@list:filter(
_pipe,
fun(Annotation) -> erlang:element(2, Annotation) =:= check end
).
-file("src/graded/internal/annotation.gleam", 713).
?DOC(false).
-spec format_param_bound(graded@internal@types:param_bound()) -> binary().
format_param_bound(Param) ->
case erlang:element(3, Param) of
{t_abs, _, _} ->
<<<<(erlang:element(2, Param))/binary, ": "/utf8>>/binary,
(render_abstraction(erlang:element(3, Param)))/binary>>;
Other ->
<<<<(erlang:element(2, Param))/binary, ": "/utf8>>/binary,
(format_effect_term(Other))/binary>>
end.
-file("src/graded/internal/annotation.gleam", 86).
?DOC(false).
-spec format_annotation(graded@internal@types:effect_annotation()) -> binary().
format_annotation(Annotation) ->
Prefix = case erlang:element(2, Annotation) of
effects ->
<<"effects"/utf8>>;
check ->
<<"check"/utf8>>
end,
Params_string = case erlang:element(4, Annotation) of
[] ->
<<""/utf8>>;
Params ->
<<<<"("/utf8,
(gleam@string:join(
gleam@list:map(Params, fun format_param_bound/1),
<<", "/utf8>>
))/binary>>/binary,
")"/utf8>>
end,
Effects_string = format_effect_term(erlang:element(5, Annotation)),
<<<<<<<<<<Prefix/binary, " "/utf8>>/binary,
(erlang:element(3, Annotation))/binary>>/binary,
Params_string/binary>>/binary,
" : "/utf8>>/binary,
Effects_string/binary>>.
-file("src/graded/internal/annotation.gleam", 113).
?DOC(false).
-spec split_qualified_name(binary()) -> {ok, {binary(), binary()}} |
{error, nil}.
split_qualified_name(Qualified) ->
case lists:reverse(gleam@string:split(Qualified, <<"."/utf8>>)) of
[] ->
{error, nil};
[_] ->
{error, nil};
[Function | Rest_reversed] ->
Module = gleam@string:join(
lists:reverse(Rest_reversed),
<<"."/utf8>>
),
case (Module =:= <<""/utf8>>) orelse (Function =:= <<""/utf8>>) of
true ->
{error, nil};
false ->
{ok, {Module, Function}}
end
end.
-file("src/graded/internal/annotation.gleam", 132).
?DOC(false).
-spec format_type_field(graded@internal@types:type_field_annotation()) -> binary().
format_type_field(Tf) ->
Prefix = case erlang:element(2, Tf) of
{some, Module} ->
<<Module/binary, "."/utf8>>;
none ->
<<""/utf8>>
end,
<<<<<<<<<<<<"type "/utf8, Prefix/binary>>/binary,
(erlang:element(3, Tf))/binary>>/binary,
"."/utf8>>/binary,
(erlang:element(4, Tf))/binary>>/binary,
" : "/utf8>>/binary,
(format_effect_term(erlang:element(5, Tf)))/binary>>.
-file("src/graded/internal/annotation.gleam", 147).
?DOC(false).
-spec extract_type_fields(graded@internal@types:graded_file()) -> list(graded@internal@types:type_field_annotation()).
extract_type_fields(File) ->
gleam@list:filter_map(erlang:element(2, File), fun(Line) -> case Line of
{type_field_line, Tf} ->
{ok, Tf};
_ ->
{error, nil}
end end).
-file("src/graded/internal/annotation.gleam", 159).
?DOC(false).
-spec external_sort_key(graded@internal@types:external_annotation()) -> binary().
external_sort_key(External_annotation) ->
case erlang:element(3, External_annotation) of
module_external ->
erlang:element(2, External_annotation);
{function_external, Function} ->
<<<<(erlang:element(2, External_annotation))/binary, "."/utf8>>/binary,
Function/binary>>
end.
-file("src/graded/internal/annotation.gleam", 799).
?DOC(false).
-spec format_effect_set(graded@internal@types:effect_set()) -> binary().
format_effect_set(Effect_set) ->
case Effect_set of
wildcard ->
<<"[_]"/utf8>>;
{specific, Labels} ->
case begin
_pipe = gleam@set:to_list(Labels),
gleam@list:sort(_pipe, fun gleam@string:compare/2)
end of
[] ->
<<"[]"/utf8>>;
Sorted ->
<<<<"["/utf8,
(gleam@string:join(Sorted, <<", "/utf8>>))/binary>>/binary,
"]"/utf8>>
end;
{polymorphic, Labels@1, Variables} ->
Sorted_labels = begin
_pipe@1 = gleam@set:to_list(Labels@1),
gleam@list:sort(_pipe@1, fun gleam@string:compare/2)
end,
Sorted_variables = begin
_pipe@2 = gleam@set:to_list(Variables),
gleam@list:sort(_pipe@2, fun gleam@string:compare/2)
end,
<<<<"["/utf8,
(gleam@string:join(
lists:append(Sorted_labels, Sorted_variables),
<<", "/utf8>>
))/binary>>/binary,
"]"/utf8>>
end.
-file("src/graded/internal/annotation.gleam", 167).
?DOC(false).
-spec format_external(graded@internal@types:external_annotation()) -> binary().
format_external(External_annotation) ->
<<<<<<"external effects "/utf8,
(external_sort_key(External_annotation))/binary>>/binary,
" : "/utf8>>/binary,
(format_effect_set(erlang:element(4, External_annotation)))/binary>>.
-file("src/graded/internal/annotation.gleam", 175).
?DOC(false).
-spec extract_externals(graded@internal@types:graded_file()) -> list(graded@internal@types:external_annotation()).
extract_externals(File) ->
gleam@list:filter_map(erlang:element(2, File), fun(Line) -> case Line of
{external_line, External_annotation} ->
{ok, External_annotation};
_ ->
{error, nil}
end end).
-file("src/graded/internal/annotation.gleam", 185).
?DOC(false).
-spec format_file(graded@internal@types:graded_file()) -> binary().
format_file(File) ->
_pipe = erlang:element(2, File),
_pipe@1 = gleam@list:map(_pipe, fun(Line) -> case Line of
{annotation_line, Annotation} ->
format_annotation(Annotation);
{type_field_line, Tf} ->
format_type_field(Tf);
{external_line, Ext} ->
format_external(Ext);
{returns_line, Returns} ->
format_returns(Returns);
{comment_line, Text} ->
Text;
blank_line ->
<<""/utf8>>
end end),
gleam@string:join(_pipe@1, <<"\n"/utf8>>).
-file("src/graded/internal/annotation.gleam", 206).
?DOC(false).
-spec merge_inferred(
graded@internal@types:graded_file(),
list(graded@internal@types:effect_annotation()),
list(graded@internal@types:returns_annotation())
) -> graded@internal@types:graded_file().
merge_inferred(File, Inferred, Inferred_returns) ->
External_functions = begin
_pipe = gleam@list:filter_map(
erlang:element(2, File),
fun(Line) -> case Line of
{external_line, Ext} ->
case erlang:element(3, Ext) of
{function_external, Name} ->
{ok,
<<<<(erlang:element(2, Ext))/binary,
"."/utf8>>/binary,
Name/binary>>};
module_external ->
{error, nil}
end;
_ ->
{error, nil}
end end
),
gleam@set:from_list(_pipe)
end,
Inferred@1 = gleam@list:filter(
Inferred,
fun(Annotation) ->
not gleam@set:contains(
External_functions,
erlang:element(3, Annotation)
)
end
),
Inferred_map = begin
_pipe@1 = Inferred@1,
_pipe@2 = gleam@list:map(
_pipe@1,
fun(Annotation@1) ->
{erlang:element(3, Annotation@1), Annotation@1}
end
),
maps:from_list(_pipe@2)
end,
Returns_map = begin
_pipe@3 = Inferred_returns,
_pipe@4 = gleam@list:map(
_pipe@3,
fun(Returns) -> {erlang:element(2, Returns), Returns} end
),
maps:from_list(_pipe@4)
end,
{New_lines, Placed, Placed_returns} = gleam@list:fold(
erlang:element(2, File),
{[], gleam@set:new(), gleam@set:new()},
fun(State, Line@1) ->
{Lines, Placed_set, Placed_returns_set} = State,
case Line@1 of
{annotation_line, Annotation@2} ->
case erlang:element(2, Annotation@2) of
effects ->
case gleam_stdlib:map_get(
Inferred_map,
erlang:element(3, Annotation@2)
) of
{ok, New_annotation} ->
{[{annotation_line, New_annotation} | Lines],
gleam@set:insert(
Placed_set,
erlang:element(3, Annotation@2)
),
Placed_returns_set};
{error, nil} ->
{Lines, Placed_set, Placed_returns_set}
end;
check ->
{[Line@1 | Lines], Placed_set, Placed_returns_set}
end;
{returns_line, Returns@1} ->
case gleam_stdlib:map_get(
Returns_map,
erlang:element(2, Returns@1)
) of
{ok, New_returns} ->
{[{returns_line, New_returns} | Lines],
Placed_set,
gleam@set:insert(
Placed_returns_set,
erlang:element(2, Returns@1)
)};
{error, nil} ->
{Lines, Placed_set, Placed_returns_set}
end;
{type_field_line, _} ->
{[Line@1 | Lines], Placed_set, Placed_returns_set};
{external_line, _} ->
{[Line@1 | Lines], Placed_set, Placed_returns_set};
{comment_line, _} ->
{[Line@1 | Lines], Placed_set, Placed_returns_set};
blank_line ->
{[Line@1 | Lines], Placed_set, Placed_returns_set}
end
end
),
Remaining_effects = begin
_pipe@5 = Inferred@1,
_pipe@6 = gleam@list:filter(
_pipe@5,
fun(Annotation@3) ->
not gleam@set:contains(Placed, erlang:element(3, Annotation@3))
end
),
gleam@list:map(_pipe@6, fun(Field@0) -> {annotation_line, Field@0} end)
end,
Remaining_returns = begin
_pipe@7 = Inferred_returns,
_pipe@8 = gleam@list:filter(
_pipe@7,
fun(Returns@2) ->
not gleam@set:contains(
Placed_returns,
erlang:element(2, Returns@2)
)
end
),
gleam@list:map(_pipe@8, fun(Field@0) -> {returns_line, Field@0} end)
end,
{graded_file,
lists:append(
[lists:reverse(New_lines), Remaining_effects, Remaining_returns]
)}.
-file("src/graded/internal/annotation.gleam", 701).
?DOC(false).
-spec collect_comments(list(graded@internal@types:graded_line())) -> list(binary()).
collect_comments(Lines) ->
gleam@list:filter_map(Lines, fun(Line) -> case Line of
{comment_line, Text} ->
{ok, Text};
_ ->
{error, nil}
end end).
-file("src/graded/internal/annotation.gleam", 304).
?DOC(false).
-spec format_sorted(graded@internal@types:graded_file()) -> binary().
format_sorted(File) ->
Comments = collect_comments(erlang:element(2, File)),
Annotations = extract_annotations(File),
Check_lines = begin
_pipe = Annotations,
_pipe@1 = gleam@list:filter(
_pipe,
fun(Annotation) -> erlang:element(2, Annotation) =:= check end
),
_pipe@2 = gleam@list:sort(
_pipe@1,
fun(Left, Right) ->
gleam@string:compare(
erlang:element(3, Left),
erlang:element(3, Right)
)
end
),
gleam@list:map(_pipe@2, fun format_annotation/1)
end,
Effects_lines = begin
_pipe@3 = Annotations,
_pipe@4 = gleam@list:filter(
_pipe@3,
fun(Annotation@1) -> erlang:element(2, Annotation@1) =:= effects end
),
_pipe@5 = gleam@list:sort(
_pipe@4,
fun(Left@1, Right@1) ->
gleam@string:compare(
erlang:element(3, Left@1),
erlang:element(3, Right@1)
)
end
),
gleam@list:map(_pipe@5, fun format_annotation/1)
end,
Type_field_lines = begin
_pipe@6 = extract_type_fields(File),
_pipe@7 = gleam@list:sort(
_pipe@6,
fun(Left@2, Right@2) ->
gleam@string:compare(
<<<<(erlang:element(3, Left@2))/binary, "."/utf8>>/binary,
(erlang:element(4, Left@2))/binary>>,
<<<<(erlang:element(3, Right@2))/binary, "."/utf8>>/binary,
(erlang:element(4, Right@2))/binary>>
)
end
),
gleam@list:map(_pipe@7, fun format_type_field/1)
end,
External_lines = begin
_pipe@8 = extract_externals(File),
_pipe@9 = gleam@list:sort(
_pipe@8,
fun(Left@3, Right@3) ->
gleam@string:compare(
external_sort_key(Left@3),
external_sort_key(Right@3)
)
end
),
gleam@list:map(_pipe@9, fun format_external/1)
end,
Returns_lines = begin
_pipe@10 = extract_returns(File),
_pipe@11 = gleam@list:sort(
_pipe@10,
fun(Left@4, Right@4) ->
gleam@string:compare(
erlang:element(2, Left@4),
erlang:element(2, Right@4)
)
end
),
gleam@list:map(_pipe@11, fun format_returns/1)
end,
Sections = [Comments,
External_lines,
Type_field_lines,
Check_lines,
Effects_lines,
Returns_lines],
_pipe@12 = Sections,
_pipe@13 = gleam@list:filter(_pipe@12, fun(Section) -> Section /= [] end),
_pipe@14 = gleam@list:map(
_pipe@13,
fun(Section@1) -> gleam@string:join(Section@1, <<"\n"/utf8>>) end
),
_pipe@15 = gleam@string:join(_pipe@14, <<"\n\n"/utf8>>),
(fun(Content) -> <<Content/binary, "\n"/utf8>> end)(_pipe@15).