-module(glyph_codegen@codegen). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([generate/1, main/0]). -export_type([field_decoder/0, args/0]). -type field_decoder() :: {field, binary(), binary()} | {optional_field, binary(), binary()}. -type args() :: {args, list(binary()), binary(), binary(), gleam@dict:dict(binary(), binary())}. -spec parse_args(list(binary())) -> args(). parse_args(Arguments) -> case Arguments of [<<"--import-module"/utf8>> | Rest] -> _assert_subject = gleam@list:split(Rest, 1), {[Val], Rest@1} = case _assert_subject of {[_], _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"glyph_codegen/codegen"/utf8>>, function => <<"parse_args"/utf8>>, line => 300}) end, _assert_subject@1 = parse_args(Rest@1), {args, _, _, _, _} = Args = case _assert_subject@1 of {args, _, _, _, _} -> _assert_subject@1; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@1, module => <<"glyph_codegen/codegen"/utf8>>, function => <<"parse_args"/utf8>>, line => 301}) end, erlang:setelement(4, Args, Val); [<<"--type"/utf8>> | Rest@2] -> _assert_subject@2 = gleam@list:split(Rest@2, 1), {[Val@1], Rest@3} = case _assert_subject@2 of {[_], _} -> _assert_subject@2; _assert_fail@2 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@2, module => <<"glyph_codegen/codegen"/utf8>>, function => <<"parse_args"/utf8>>, line => 305}) end, _assert_subject@3 = parse_args(Rest@3), {args, _, _, _, _} = Args@1 = case _assert_subject@3 of {args, _, _, _, _} -> _assert_subject@3; _assert_fail@3 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@3, module => <<"glyph_codegen/codegen"/utf8>>, function => <<"parse_args"/utf8>>, line => 306}) end, erlang:setelement( 2, Args@1, begin _pipe = erlang:element(2, Args@1), gleam@list:prepend(_pipe, Val@1) end ); [<<"--out-file"/utf8>> | Rest@4] -> _assert_subject@4 = gleam@list:split(Rest@4, 1), {[Val@2], Rest@5} = case _assert_subject@4 of {[_], _} -> _assert_subject@4; _assert_fail@4 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@4, module => <<"glyph_codegen/codegen"/utf8>>, function => <<"parse_args"/utf8>>, line => 314}) end, _assert_subject@5 = parse_args(Rest@5), {args, _, _, _, _} = Args@2 = case _assert_subject@5 of {args, _, _, _, _} -> _assert_subject@5; _assert_fail@5 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@5, module => <<"glyph_codegen/codegen"/utf8>>, function => <<"parse_args"/utf8>>, line => 315}) end, erlang:setelement(3, Args@2, Val@2); [<<"--rename"/utf8>> | Rest@6] -> _assert_subject@6 = gleam@list:split(Rest@6, 2), {[V1, V2], Rest@7} = case _assert_subject@6 of {[_, _], _} -> _assert_subject@6; _assert_fail@6 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@6, module => <<"glyph_codegen/codegen"/utf8>>, function => <<"parse_args"/utf8>>, line => 319}) end, _assert_subject@7 = parse_args(Rest@7), {args, _, _, _, _} = Args@3 = case _assert_subject@7 of {args, _, _, _, _} -> _assert_subject@7; _assert_fail@7 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@7, module => <<"glyph_codegen/codegen"/utf8>>, function => <<"parse_args"/utf8>>, line => 320}) end, erlang:setelement( 5, Args@3, begin _pipe@1 = erlang:element(5, Args@3), gleam@dict:insert(_pipe@1, V1, V2) end ); [] -> {args, [], <<""/utf8>>, <<""/utf8>>, gleam@dict:new()}; _ -> erlang:error(#{gleam_error => panic, message => <<"parsing error"/utf8>>, module => <<"glyph_codegen/codegen"/utf8>>, function => <<"parse_args"/utf8>>, line => 330}) end. -spec do_template(binary(), list({binary(), gleam@bbmustache:argument()})) -> binary(). do_template(Templ, Args) -> _assert_subject = gleam@bbmustache:compile(Templ), {ok, Compiled} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"glyph_codegen/codegen"/utf8>>, function => <<"do_template"/utf8>>, line => 377}) end, gleam@bbmustache:render(Compiled, Args). -spec format(binary(), list(binary())) -> binary(). format(Fmt, Args) -> case gleam@string:split_once(Fmt, <<"%"/utf8>>) of {ok, {Left, Right}} -> case Args of [] -> <<""/utf8>>; [E1] -> <<<>/binary, Right/binary>>; [E1@1 | Rest] -> <<<>/binary, (format(Right, Rest))/binary>> end; {error, _} -> <<""/utf8>> end. -spec convert_type_to_decoder(glance:field(glance:type())) -> field_decoder(). convert_type_to_decoder(Field) -> Id@1 = case erlang:element(2, Field) of {some, Id} -> Id; _ -> erlang:error(#{gleam_error => panic, message => <<"unknown id"/utf8>>, module => <<"glyph_codegen/codegen"/utf8>>, function => <<"convert_type_to_decoder"/utf8>>, line => 119}) end, gleam@io:debug(<<"parsing field: "/utf8, Id@1/binary>>), gleam@io:debug(Field), case erlang:element(3, Field) of {named_type, <<"List"/utf8>>, _, [{named_type, <<"String"/utf8>>, _, []}]} -> {field, Id@1, <<"dynamic.list(dynamic.string)"/utf8>>}; {named_type, <<"List"/utf8>>, _, [{named_type, <<"Int"/utf8>>, _, []}]} -> {field, Id@1, <<"dynamic.list(dynamic.int)"/utf8>>}; {named_type, <<"List"/utf8>>, _, [{named_type, <<"Snowflake"/utf8>>, _, []}]} -> {field, Id@1, <<"dynamic.list(dynamic.string)"/utf8>>}; {named_type, <<"List"/utf8>>, _, [{named_type, Name, _, []}]} when ((Name =/= <<"String"/utf8>>) andalso (Name =/= <<"Int"/utf8>>)) andalso (Name =/= <<"Bool"/utf8>>) -> {field, Id@1, format( <<"dynamic.list(decode_%)"/utf8>>, [justin:snake_case(Name)] )}; {named_type, <<"Option"/utf8>>, _, [{named_type, <<"Float"/utf8>>, _, []}]} -> {optional_field, Id@1, <<"dynamic.float"/utf8>>}; {named_type, <<"Option"/utf8>>, _, [{named_type, <<"Nil"/utf8>>, _, []}]} -> {optional_field, Id@1, <<"dynamic.string"/utf8>>}; {named_type, <<"Option"/utf8>>, _, [{named_type, <<"Snowflake"/utf8>>, _, []}]} -> {optional_field, Id@1, <<"dynamic.string"/utf8>>}; {named_type, <<"Option"/utf8>>, _, [{named_type, <<"String"/utf8>>, _, []}]} -> {optional_field, Id@1, <<"dynamic.string"/utf8>>}; {named_type, <<"Option"/utf8>>, _, [{named_type, <<"Int"/utf8>>, _, []}]} -> {optional_field, Id@1, <<"dynamic.int"/utf8>>}; {named_type, <<"Option"/utf8>>, _, [{named_type, <<"Bool"/utf8>>, _, []}]} -> {optional_field, Id@1, <<"dynamic.bool"/utf8>>}; {named_type, <<"Option"/utf8>>, _, [{named_type, Name@1, _, []}]} when ((Name@1 =/= <<"String"/utf8>>) andalso (Name@1 =/= <<"Int"/utf8>>)) andalso (Name@1 =/= <<"Bool"/utf8>>) -> {optional_field, Id@1, format(<<"decode_%"/utf8>>, [justin:snake_case(Name@1)])}; {named_type, <<"Option"/utf8>>, _, [{named_type, <<"Dict"/utf8>>, _, [{named_type, <<"Snowflake"/utf8>>, _, []}, {named_type, P2, _, []}]}]} -> {optional_field, Id@1, format( <<"dynamic.dict(dynamic.string, decode_%)"/utf8>>, [justin:snake_case(P2)] )}; {named_type, <<"Option"/utf8>>, _, [{named_type, <<"List"/utf8>>, _, [{named_type, <<"Snowflake"/utf8>>, _, []}]}]} -> {optional_field, Id@1, <<"dynamic.list(dynamic.string)"/utf8>>}; {named_type, <<"Option"/utf8>>, _, [{named_type, <<"List"/utf8>>, _, [{named_type, Name@2, _, []}]}]} when ((Name@2 =/= <<"String"/utf8>>) andalso (Name@2 =/= <<"Int"/utf8>>)) andalso (Name@2 =/= <<"Bool"/utf8>>) -> {optional_field, Id@1, format( <<"dynamic.list(decode_%)"/utf8>>, [justin:snake_case(Name@2)] )}; {named_type, <<"Option"/utf8>>, _, [{named_type, <<"List"/utf8>>, _, [{named_type, <<"Int"/utf8>>, _, []}]}]} -> {optional_field, Id@1, <<"dynamic.list(dynamic.int)"/utf8>>}; {named_type, <<"Option"/utf8>>, _, [{named_type, <<"List"/utf8>>, _, [{named_type, <<"String"/utf8>>, _, []}]}]} -> {optional_field, Id@1, <<"dynamic.list(dynamic.string)"/utf8>>}; {named_type, <<"dynamic.Dynamic"/utf8>>, _, []} -> {field, Id@1, <<"dynamic.dynamic"/utf8>>}; {named_type, Name@3, _, []} when (Name@3 =:= <<"Snowflake"/utf8>>) orelse (Name@3 =:= <<"String"/utf8>>) -> {field, Id@1, <<"dynamic.string"/utf8>>}; {named_type, <<"Int"/utf8>>, _, []} -> {field, Id@1, <<"dynamic.int"/utf8>>}; {named_type, <<"Dynamic"/utf8>>, _, []} -> {field, Id@1, <<"dynamic.dynamic"/utf8>>}; {named_type, <<"Bool"/utf8>>, _, []} -> {field, Id@1, <<"dynamic.bool"/utf8>>}; {named_type, Name@4, _, []} -> {field, Id@1, format(<<"decode_%"/utf8>>, [justin:snake_case(Name@4)])}; {named_type, <<"Dict"/utf8>>, _, [{named_type, P1, _, []}, {named_type, P2@1, _, []}]} -> {field, Id@1, format( <<"dynamic.dict(dynamic.%, dynamic.%)"/utf8>>, [justin:snake_case(P1), justin:snake_case(P2@1)] )}; _ -> erlang:error(#{gleam_error => panic, message => <<"unsupported type"/utf8>>, module => <<"glyph_codegen/codegen"/utf8>>, function => <<"convert_type_to_decoder"/utf8>>, line => 284}) end. -spec get_fields(list(glance:field(glance:type()))) -> list(field_decoder()). get_fields(Fields) -> case Fields of [Field | Fields@1] -> [convert_type_to_decoder(Field) | get_fields(Fields@1)]; [] -> [] end. -spec render_template(args(), binary(), list(field_decoder())) -> binary(). render_template(Args, Type_name, Fields) -> Fields@1 = begin _pipe = Fields, gleam@list:index_map( _pipe, fun(X, Idx) -> Comma = case (Idx + 1) =:= gleam@list:length(Fields) of true -> <<""/utf8>>; _ -> <<","/utf8>> end, {Func_name, Name@2, Arg@2} = case X of {field, Name, Arg} -> {<<"dynamic.field"/utf8>>, Name, Arg}; {optional_field, Name@1, Arg@1} -> {<<"dynamic.optional_field"/utf8>>, Name@1, Arg@1} end, Name@3 = case gleam@dict:get(erlang:element(5, Args), Name@2) of {ok, Renamed} -> Renamed; {error, _} -> Name@2 end, gleam_bbmustache_native:argument( [{<<"index"/utf8>>, gleam_bbmustache_native:argument( <<"a"/utf8, (begin _pipe@1 = Idx + 1, gleam@int:to_string(_pipe@1) end)/binary>> )}, {<<"func_name"/utf8>>, gleam_bbmustache_native:argument(Func_name)}, {<<"key"/utf8>>, gleam_bbmustache_native:argument(Name@3)}, {<<"value"/utf8>>, gleam_bbmustache_native:argument(Arg@2)}, {<<"comma"/utf8>>, gleam_bbmustache_native:argument(Comma)}] ) end ) end, do_template( <<" pub fn decode_{{type_snake_case}}( dyn: dynamic.Dynamic, ) -> Result(discord.{{type_name}}, dynamic.DecodeErrors) { case {{#fields}}{{func_name}}(\"{{key}}\", {{value}})(dyn){{comma}}{{/fields}} { {{#fields}}Ok({{index}}){{comma}}{{/fields}} -> Ok(discord.{{type_name}}({{#fields}}{{index}}{{comma}}{{/fields}} )) {{#fields}}{{index}}{{comma}}{{/fields}} -> Error(list.concat([ {{#fields}}all_errors({{index}}){{comma}}{{/fields}} ])) } } "/utf8>>, [{<<"fields"/utf8>>, gleam_bbmustache_native:argument(Fields@1)}, {<<"type_name"/utf8>>, gleam_bbmustache_native:argument(Type_name)}, {<<"type_snake_case"/utf8>>, gleam_bbmustache_native:argument(justin:snake_case(Type_name))}] ). -spec codegen(args()) -> {ok, binary()} | {error, {integer(), binary()}}. codegen(Args) -> gleam@io:debug(simplifile:read_directory(<<"."/utf8>>)), _assert_subject = simplifile:read( <<<<"./src/"/utf8, (erlang:element(4, Args))/binary>>/binary, ".gleam"/utf8>> ), {ok, Source} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"glyph_codegen/codegen"/utf8>>, function => <<"codegen"/utf8>>, line => 61}) end, _assert_subject@1 = glance:module(Source), {ok, Module} = case _assert_subject@1 of {ok, _} -> _assert_subject@1; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@1, module => <<"glyph_codegen/codegen"/utf8>>, function => <<"codegen"/utf8>>, line => 63}) end, Output_path = erlang:element(3, Args), case simplifile:delete(Output_path) of {ok, _} -> nil; {error, enoent} -> nil; _ -> erlang:error(#{gleam_error => panic, message => <<"cannot delete a old file"/utf8>>, module => <<"glyph_codegen/codegen"/utf8>>, function => <<"codegen"/utf8>>, line => 70}) end, Rendered = do_template( <<" import gleam/dynamic import gleam/list import {{module}} fn all_errors(result: Result(a, dynamic.DecodeErrors)) -> dynamic.DecodeErrors { case result { Ok(_) -> [] Error(errors) -> errors } } "/utf8>>, [{<<"module"/utf8>>, gleam_bbmustache_native:argument(erlang:element(4, Args))}] ), _assert_subject@2 = simplifile:write(Output_path, Rendered), {ok, _} = case _assert_subject@2 of {ok, _} -> _assert_subject@2; _assert_fail@2 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@2, module => <<"glyph_codegen/codegen"/utf8>>, function => <<"codegen"/utf8>>, line => 77}) end, gleam@list:each( erlang:element(2, Args), fun(Type_name) -> gleam@io:debug(<<"looking for the type: "/utf8, Type_name/binary>>), _assert_subject@3 = begin _pipe = erlang:element(3, Module), gleam@list:find( _pipe, fun(X) -> erlang:element(2, erlang:element(3, X)) =:= Type_name end ) end, {ok, Found} = case _assert_subject@3 of {ok, _} -> _assert_subject@3; _assert_fail@3 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@3, module => <<"glyph_codegen/codegen"/utf8>>, function => <<"codegen"/utf8>>, line => 81}) end, _assert_subject@4 = begin _pipe@1 = erlang:element(6, erlang:element(3, Found)), gleam@list:at(_pipe@1, 0) end, {ok, First_variant} = case _assert_subject@4 of {ok, _} -> _assert_subject@4; _assert_fail@4 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@4, module => <<"glyph_codegen/codegen"/utf8>>, function => <<"codegen"/utf8>>, line => 84}) end, Fields_decoders = get_fields(erlang:element(3, First_variant)), Rendered@1 = render_template(Args, Type_name, Fields_decoders), _assert_subject@5 = simplifile:append(Output_path, Rendered@1), {ok, _} = case _assert_subject@5 of {ok, _} -> _assert_subject@5; _assert_fail@5 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@5, module => <<"glyph_codegen/codegen"/utf8>>, function => <<"codegen"/utf8>>, line => 91}) end end ), gleam@io:debug(<<"formatting..."/utf8>>), _assert_subject@6 = shellout:command( <<"gleam"/utf8>>, [<<"format"/utf8>>, Output_path], <<"."/utf8>>, [let_be_stdout] ), {ok, _} = case _assert_subject@6 of {ok, _} -> _assert_subject@6; _assert_fail@6 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@6, module => <<"glyph_codegen/codegen"/utf8>>, function => <<"codegen"/utf8>>, line => 96}) end. -spec generate(args()) -> {ok, binary()} | {error, {integer(), binary()}}. generate(Args) -> codegen(Args). -spec main() -> {ok, binary()} | {error, {integer(), binary()}}. main() -> case simplifile:verify_is_file(<<"./gleam.toml"/utf8>>) of {ok, Exists} when Exists =:= true -> nil; _ -> erlang:error(#{gleam_error => panic, message => <<"not in project root"/utf8>>, module => <<"glyph_codegen/codegen"/utf8>>, function => <<"main"/utf8>>, line => 52}) end, _assert_subject = parse_args(erlang:element(4, argv:load())), {args, _, _, _, _} = Args = case _assert_subject of {args, _, _, _, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"glyph_codegen/codegen"/utf8>>, function => <<"main"/utf8>>, line => 55}) end, codegen(Args).