-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, <>, Depth + 1}; <<"("/utf8>> -> {Segments, <>, Depth + 1}; <<"]"/utf8>> -> {Segments, <>, Depth - 1}; <<")"/utf8>> -> {Segments, <>, Depth - 1}; _ -> {Segments, <>, 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", 789). ?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", 770). ?DOC(false). -spec spine_loop( graded@internal@types:effect_term(), list(graded@internal@types:effect_term()) ) -> {graded@internal@types:effect_term(), list(graded@internal@types:effect_term())}. spine_loop(Term, Args) -> case Term of {t_app, Operator, Argument} -> spine_loop(Operator, [Argument | Args]); Other -> {Other, Args} 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) -> spine_loop(Term, []). -file("src/graded/internal/annotation.gleam", 782). ?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, <<<<<>/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)), <<<<<<<<<>/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} -> <>; 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", 803). ?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) -> <> end)(_pipe@15).