Packages

Generate Gleam types, JSON codecs, and a typed XRPC client from atproto lexicon files.

Current section

Files

Jump to
atproto_codegen src atproto_codegen@emit@zero.erl
Raw

src/atproto_codegen@emit@zero.erl

-module(atproto_codegen@emit@zero).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/atproto_codegen/emit/zero.gleam").
-export([compute/1, needs_zero/2, choose_fallback/3]).
-export_type([zero_plan/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(
" Zero values for closed-union decode fallbacks; a required-ref cycle\n"
" fails codegen with a named reason.\n"
).
-opaque zero_plan() :: {zero_plan,
gleam@dict:dict({binary(), binary()}, atproto_codegen@lower:flat_def()),
gleam@dict:dict({binary(), binary()}, boolean())}.
-file("src/atproto_codegen/emit/zero.gleam", 63).
-spec key_of(binary(), binary()) -> {binary(), binary()}.
key_of(Current, Ref) ->
R = atproto_codegen@naming:parse_ref(Current, Ref),
{erlang:element(2, R), erlang:element(3, R)}.
-file("src/atproto_codegen/emit/zero.gleam", 182).
-spec def_nsid(atproto_codegen@lower:flat_def()) -> binary().
def_nsid(Def) ->
case Def of
{flat_record, Nsid, _} ->
Nsid;
{flat_object, Nsid@1, _, _} ->
Nsid@1;
_ ->
<<""/utf8>>
end.
-file("src/atproto_codegen/emit/zero.gleam", 166).
-spec field_resolvable(
gleam@dict:dict({binary(), binary()}, atproto_codegen@lower:flat_def()),
binary(),
atproto_codegen@lower:flat_type(),
gleam@set:set({binary(), binary()}),
gleam@dict:dict({binary(), binary()}, boolean())
) -> {boolean(), gleam@dict:dict({binary(), binary()}, boolean())}.
field_resolvable(Defs, Current, Ft, Visiting, Memo) ->
case Ft of
{t_ref, Ref} ->
resolve_key(Defs, key_of(Current, Ref), Visiting, Memo);
{t_union, Refs, true} ->
resolve_fallback(Defs, Current, Refs, Visiting, Memo);
{t_unsupported, _} ->
{false, Memo};
_ ->
{true, Memo}
end.
-file("src/atproto_codegen/emit/zero.gleam", 135).
-spec resolve_def(
gleam@dict:dict({binary(), binary()}, atproto_codegen@lower:flat_def()),
{binary(), binary()},
gleam@set:set({binary(), binary()}),
gleam@dict:dict({binary(), binary()}, boolean())
) -> {boolean(), gleam@dict:dict({binary(), binary()}, boolean())}.
resolve_def(Defs, Key, Visiting, Memo) ->
case gleam_stdlib:map_get(Defs, Key) of
{error, nil} ->
{false, gleam@dict:insert(Memo, Key, false)};
{ok, Def} ->
Visiting2 = gleam@set:insert(Visiting, Key),
Own_nsid = def_nsid(Def),
{Ok, Memo2} = gleam@list:fold(
atproto_codegen@lower:properties_of(Def),
{true, Memo},
fun(Acc, Field) ->
{Ok_acc, Memo_acc} = Acc,
case {Ok_acc, erlang:element(4, Field)} of
{false, _} ->
Acc;
{_, false} ->
Acc;
{true, true} ->
field_resolvable(
Defs,
Own_nsid,
erlang:element(3, Field),
Visiting2,
Memo_acc
)
end
end
),
{Ok, gleam@dict:insert(Memo2, Key, Ok)}
end.
-file("src/atproto_codegen/emit/zero.gleam", 119).
-spec resolve_key(
gleam@dict:dict({binary(), binary()}, atproto_codegen@lower:flat_def()),
{binary(), binary()},
gleam@set:set({binary(), binary()}),
gleam@dict:dict({binary(), binary()}, boolean())
) -> {boolean(), gleam@dict:dict({binary(), binary()}, boolean())}.
resolve_key(Defs, Key, Visiting, Memo) ->
case gleam_stdlib:map_get(Memo, Key) of
{ok, Known} ->
{Known, Memo};
{error, nil} ->
case gleam@set:contains(Visiting, Key) of
true ->
{false, Memo};
false ->
resolve_def(Defs, Key, Visiting, Memo)
end
end.
-file("src/atproto_codegen/emit/zero.gleam", 100).
-spec resolve_fallback(
gleam@dict:dict({binary(), binary()}, atproto_codegen@lower:flat_def()),
binary(),
list(binary()),
gleam@set:set({binary(), binary()}),
gleam@dict:dict({binary(), binary()}, boolean())
) -> {boolean(), gleam@dict:dict({binary(), binary()}, boolean())}.
resolve_fallback(Defs, Current, Refs, Visiting, Memo) ->
case Refs of
[] ->
{false, Memo};
[Ref | Rest] ->
{Ok, Memo2} = resolve_key(
Defs,
key_of(Current, Ref),
Visiting,
Memo
),
case Ok of
true ->
{true, Memo2};
false ->
resolve_fallback(Defs, Current, Rest, Visiting, Memo2)
end
end.
-file("src/atproto_codegen/emit/zero.gleam", 88).
-spec closed_unions(list(atproto_codegen@lower:flat_lexicon())) -> list({binary(),
list(binary())}).
closed_unions(Lexicons) ->
gleam@list:flat_map(
Lexicons,
fun(Lex) ->
_pipe = atproto_codegen@lower:codec_units(erlang:element(4, Lex)),
gleam@list:filter_map(_pipe, fun(Unit) -> case Unit of
{union_unit, _, _, Refs, true} ->
{ok, {erlang:element(2, Lex), Refs}};
_ ->
{error, nil}
end end)
end
).
-file("src/atproto_codegen/emit/zero.gleam", 68).
-spec key_of_def(atproto_codegen@lower:flat_def()) -> {ok, {binary(), binary()}} |
{error, nil}.
key_of_def(Def) ->
case Def of
{flat_record, Nsid, _} ->
{ok, {Nsid, <<"main"/utf8>>}};
{flat_object, Nsid@1, Name, _} ->
{ok, {Nsid@1, Name}};
_ ->
{error, nil}
end.
-file("src/atproto_codegen/emit/zero.gleam", 76).
-spec index_defs(list(atproto_codegen@lower:flat_lexicon())) -> gleam@dict:dict({binary(),
binary()}, atproto_codegen@lower:flat_def()).
index_defs(Lexicons) ->
_pipe = Lexicons,
_pipe@1 = gleam@list:flat_map(_pipe, fun(Lex) -> erlang:element(4, Lex) end),
_pipe@2 = gleam@list:filter_map(_pipe@1, fun(Def) -> case key_of_def(Def) of
{ok, Key} ->
{ok, {Key, Def}};
{error, nil} ->
{error, nil}
end end),
maps:from_list(_pipe@2).
-file("src/atproto_codegen/emit/zero.gleam", 23).
?DOC(" Fails naming a closed union with no zeroable member.\n").
-spec compute(list(atproto_codegen@lower:flat_lexicon())) -> {ok, zero_plan()} |
{error, binary()}.
compute(Lexicons) ->
Defs = index_defs(Lexicons),
gleam@result:'try'(
gleam@list:try_fold(
closed_unions(Lexicons),
maps:new(),
fun(Memo, U) ->
{Current, Refs} = U,
{Ok, Memo2} = resolve_fallback(
Defs,
Current,
Refs,
gleam@set:new(),
Memo
),
case Ok of
true ->
{ok, Memo2};
false ->
{error,
<<<<<<<<"closed union in "/utf8, Current/binary>>/binary,
" has no member with a constructible zero value (refs: "/utf8>>/binary,
(gleam@string:join(Refs, <<", "/utf8>>))/binary>>/binary,
")"/utf8>>}
end
end
),
fun(Resolvable) -> {ok, {zero_plan, Defs, Resolvable}} end
).
-file("src/atproto_codegen/emit/zero.gleam", 45).
-spec needs_zero(zero_plan(), atproto_codegen@lower:flat_def()) -> boolean().
needs_zero(Plan, Def) ->
case key_of_def(Def) of
{ok, Key} ->
gleam_stdlib:map_get(erlang:element(3, Plan), Key) =:= {ok, true};
{error, nil} ->
false
end.
-file("src/atproto_codegen/emit/zero.gleam", 53).
?DOC(" `compute` already proved a zeroable ref exists; `Error` is unreachable.\n").
-spec choose_fallback(zero_plan(), binary(), list(binary())) -> {ok, binary()} |
{error, nil}.
choose_fallback(Plan, Current, Refs) ->
gleam@list:find(
Refs,
fun(Ref) ->
gleam_stdlib:map_get(erlang:element(3, Plan), key_of(Current, Ref))
=:= {ok, true}
end
).