-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 ).