Skip to main content

src/girard@internal@printer.erl

-module(girard@internal@printer).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/girard/internal/printer.gleam").
-export([new_names/0, print/2, to_string/1]).
-export_type([names/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 names() :: {names, gleam@dict:dict(integer(), binary()), integer()}.

-file("src/girard/internal/printer.gleam", 16).
?DOC(false).
-spec new_names() -> names().
new_names() ->
    {names, maps:new(), 0}.

-file("src/girard/internal/printer.gleam", 81).
?DOC(false).
-spec is_reserved(binary()) -> boolean().
is_reserved(Name) ->
    case Name of
        <<"as"/utf8>> ->
            true;

        <<"assert"/utf8>> ->
            true;

        <<"case"/utf8>> ->
            true;

        <<"const"/utf8>> ->
            true;

        <<"echo"/utf8>> ->
            true;

        <<"fn"/utf8>> ->
            true;

        <<"if"/utf8>> ->
            true;

        <<"import"/utf8>> ->
            true;

        <<"let"/utf8>> ->
            true;

        <<"opaque"/utf8>> ->
            true;

        <<"panic"/utf8>> ->
            true;

        <<"pub"/utf8>> ->
            true;

        <<"todo"/utf8>> ->
            true;

        <<"type"/utf8>> ->
            true;

        <<"use"/utf8>> ->
            true;

        _ ->
            false
    end.

-file("src/girard/internal/printer.gleam", 103).
?DOC(false).
-spec letters(integer()) -> binary().
letters(N) ->
    Letter = gleam@string:utf_codepoint(97 + (N rem 26)),
    Prefix = case N div 26 of
        0 ->
            <<""/utf8>>;

        Higher ->
            letters(Higher - 1)
    end,
    case Letter of
        {ok, Codepoint} ->
            <<Prefix/binary,
                (gleam_stdlib:utf_codepoint_list_to_string([Codepoint]))/binary>>;

        {error, _} ->
            <<"t"/utf8, (erlang:integer_to_binary(N))/binary>>
    end.

-file("src/girard/internal/printer.gleam", 73).
?DOC(false).
-spec next_name(integer()) -> {binary(), integer()}.
next_name(N) ->
    Name = letters(N),
    case is_reserved(Name) of
        true ->
            next_name(N + 1);

        false ->
            {Name, N + 1}
    end.

-file("src/girard/internal/printer.gleam", 61).
?DOC(false).
-spec var_name(names(), integer()) -> {binary(), names()}.
var_name(Names, Id) ->
    case gleam_stdlib:map_get(erlang:element(2, Names), Id) of
        {ok, Name} ->
            {Name, Names};

        {error, _} ->
            {Name@1, Next} = next_name(erlang:element(3, Names)),
            {Name@1,
                {names,
                    gleam@dict:insert(erlang:element(2, Names), Id, Name@1),
                    Next}}
    end.

-file("src/girard/internal/printer.gleam", 51).
?DOC(false).
-spec print_list(names(), list(girard@types:type())) -> {binary(), names()}.
print_list(Names, Types_) ->
    {Rev, Names@3} = gleam@list:fold(
        Types_,
        {[], Names},
        fun(Acc, T) ->
            {Rendered, Names@1} = Acc,
            {S, Names@2} = print(Names@1, T),
            {[S | Rendered], Names@2}
        end
    ),
    {gleam@string:join(lists:reverse(Rev), <<", "/utf8>>), Names@3}.

-file("src/girard/internal/printer.gleam", 22).
?DOC(false).
-spec print(names(), girard@types:type()) -> {binary(), names()}.
print(Names, Type_) ->
    case Type_ of
        {named, _, Name, []} ->
            {Name, Names};

        {named, _, Name@1, Args} ->
            {Rendered, Names@1} = print_list(Names, Args),
            {<<<<<<Name@1/binary, "("/utf8>>/binary, Rendered/binary>>/binary,
                    ")"/utf8>>,
                Names@1};

        {fn, Args@1, Ret} ->
            {Rendered_args, Names@2} = print_list(Names, Args@1),
            {Rendered_ret, Names@3} = print(Names@2, Ret),
            {<<<<<<"fn("/utf8, Rendered_args/binary>>/binary, ") -> "/utf8>>/binary,
                    Rendered_ret/binary>>,
                Names@3};

        {tuple, Elements} ->
            {Rendered@1, Names@4} = print_list(Names, Elements),
            {<<<<"#("/utf8, Rendered@1/binary>>/binary, ")"/utf8>>, Names@4};

        {var, Id} ->
            var_name(Names, Id)
    end.

-file("src/girard/internal/printer.gleam", 47).
?DOC(false).
-spec to_string(girard@types:type()) -> binary().
to_string(Type_) ->
    erlang:element(1, print(new_names(), Type_)).