Current section
Files
Jump to
Current section
Files
src/glue.erl
-module(glue).
-compile([no_auto_import, nowarn_unused_vars]).
-export([generate_list_variants/2, generate_compare/2]).
-export_type([error/0]).
-type error() :: {parse_error, glance:error()} |
{type_not_found, binary()} |
{type_is_not_enum, binary(), binary()}.
-spec enum_variants(glance:custom_type()) -> {ok, list(binary())} |
{error, error()}.
enum_variants(Custom_type) ->
_pipe = erlang:element(5, Custom_type),
gleam@list:try_map(_pipe, fun(Variant) -> case erlang:element(3, Variant) of
[] ->
{ok, erlang:element(2, Variant)};
_ ->
{error,
{type_is_not_enum,
erlang:element(2, Custom_type),
erlang:element(2, Variant)}}
end end).
-spec parse(binary()) -> {ok, glance:module_()} | {error, error()}.
parse(Src) ->
_pipe = glance:module(Src),
gleam@result:map_error(_pipe, fun(Field@0) -> {parse_error, Field@0} end).
-spec find_custom_type(glance:module_(), binary()) -> {ok, glance:custom_type()} |
{error, error()}.
find_custom_type(Module, Type_name) ->
_pipe = erlang:element(3, Module),
_pipe@1 = gleam@list:find(
_pipe,
fun(T) -> erlang:element(2, T) =:= Type_name end
),
gleam@result:replace_error(_pipe@1, {type_not_found, Type_name}).
-spec snake_case(binary()) -> binary().
snake_case(Name) ->
Add = fun(Acc, Grapheme) ->
Lower = gleam@string:lowercase(Grapheme),
case Grapheme =:= Lower of
false when Acc =/= <<""/utf8>> ->
<<<<Acc/binary, "_"/utf8>>/binary, Lower/binary>>;
false ->
Lower;
true ->
<<Acc/binary, Lower/binary>>
end
end,
_pipe = Name,
_pipe@1 = gleam@string:to_graphemes(_pipe),
gleam@list:fold(_pipe@1, <<""/utf8>>, Add).
-spec generate_list_variants(binary(), binary()) -> {ok, binary()} |
{error, error()}.
generate_list_variants(Src, Type_name) ->
gleam@result:'try'(
parse(Src),
fun(Module) ->
gleam@result:'try'(
find_custom_type(Module, Type_name),
fun(Custom_type) ->
gleam@result:map(
enum_variants(Custom_type),
fun(Names) ->
_pipe = {function,
<<(snake_case(Type_name))/binary, "_list"/utf8>>,
[],
<<<<"List("/utf8, Type_name/binary>>/binary,
")"/utf8>>,
[{expression,
{list,
gleam@list:map(
Names,
fun(Field@0) -> {variable, Field@0} end
)}}]},
glue@internal@code:function_to_string(_pipe)
end
)
end
)
end
).
-spec generate_compare(binary(), binary()) -> {ok, binary()} | {error, error()}.
generate_compare(Src, Type_name) ->
gleam@result:'try'(
parse(Src),
fun(Module) ->
gleam@result:'try'(
find_custom_type(Module, Type_name),
fun(Custom_type) ->
gleam@result:map(
enum_variants(Custom_type),
fun(Names) ->
Clause = fun(I, Name) ->
{clause, {constructor, Name, []}, {int, I}}
end,
_pipe = {function,
<<"compare_"/utf8,
(snake_case(Type_name))/binary>>,
[{<<"a"/utf8>>, Type_name},
{<<"b"/utf8>>, Type_name}],
<<"Order"/utf8>>,
[{'let',
<<"to_int"/utf8>>,
{fn,
[<<"x"/utf8>>],
[{expression,
{'case',
{variable, <<"x"/utf8>>},
gleam@list:index_map(
Names,
Clause
)}}]}},
{expression,
{call,
{variable, <<"int.compare"/utf8>>},
[{call,
{variable,
<<"to_int"/utf8>>},
[{variable, <<"a"/utf8>>}]},
{call,
{variable,
<<"to_int"/utf8>>},
[{variable, <<"b"/utf8>>}]}]}}]},
glue@internal@code:function_to_string(_pipe)
end
)
end
)
end
).