aboutsummaryrefslogtreecommitdiff
path: root/aoc2023/build/packages/gleam_otp/src/gleam@otp@actor.erl
diff options
context:
space:
mode:
Diffstat (limited to 'aoc2023/build/packages/gleam_otp/src/gleam@otp@actor.erl')
-rw-r--r--aoc2023/build/packages/gleam_otp/src/gleam@otp@actor.erl273
1 files changed, 273 insertions, 0 deletions
diff --git a/aoc2023/build/packages/gleam_otp/src/gleam@otp@actor.erl b/aoc2023/build/packages/gleam_otp/src/gleam@otp@actor.erl
new file mode 100644
index 0000000..0606147
--- /dev/null
+++ b/aoc2023/build/packages/gleam_otp/src/gleam@otp@actor.erl
@@ -0,0 +1,273 @@
+-module(gleam@otp@actor).
+-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]).
+
+-export([continue/1, with_selector/2, to_erlang_start_result/1, start_spec/1, start/2, send/2, call/3]).
+-export_type([message/1, next/2, init_result/2, self/2, spec/2, start_error/0, start_init_message/1]).
+
+-type message(GAS) :: {message, GAS} |
+ {system, gleam@otp@system:system_message()} |
+ {unexpected, gleam@dynamic:dynamic_()}.
+
+-type next(GAT, GAU) :: {continue,
+ GAU,
+ gleam@option:option(gleam@erlang@process:selector(GAT))} |
+ {stop, gleam@erlang@process:exit_reason()}.
+
+-type init_result(GAV, GAW) :: {ready, GAV, gleam@erlang@process:selector(GAW)} |
+ {failed, binary()}.
+
+-type self(GAX, GAY) :: {self,
+ gleam@otp@system:mode(),
+ gleam@erlang@process:pid_(),
+ GAX,
+ gleam@erlang@process:subject(GAY),
+ gleam@erlang@process:selector(message(GAY)),
+ gleam@otp@system:debug_state(),
+ fun((GAY, GAX) -> next(GAY, GAX))}.
+
+-type spec(GAZ, GBA) :: {spec,
+ fun(() -> init_result(GAZ, GBA)),
+ integer(),
+ fun((GBA, GAZ) -> next(GBA, GAZ))}.
+
+-type start_error() :: init_timeout |
+ {init_failed, gleam@erlang@process:exit_reason()} |
+ {init_crashed, gleam@dynamic:dynamic_()}.
+
+-type start_init_message(GBB) :: {ack,
+ {ok, gleam@erlang@process:subject(GBB)} |
+ {error, gleam@erlang@process:exit_reason()}} |
+ {mon, gleam@erlang@process:process_down()}.
+
+-spec continue(GBI) -> next(any(), GBI).
+continue(State) ->
+ {continue, State, none}.
+
+-spec with_selector(next(GBM, GBN), gleam@erlang@process:selector(GBM)) -> next(GBM, GBN).
+with_selector(Value, Selector) ->
+ case Value of
+ {continue, State, _} ->
+ {continue, State, {some, Selector}};
+
+ _ ->
+ Value
+ end.
+
+-spec exit_process(gleam@erlang@process:exit_reason()) -> gleam@erlang@process:exit_reason().
+exit_process(Reason) ->
+ Reason.
+
+-spec selecting_system_messages(gleam@erlang@process:selector(message(GBY))) -> gleam@erlang@process:selector(message(GBY)).
+selecting_system_messages(Selector) ->
+ _pipe = Selector,
+ gleam@erlang@process:selecting_record3(
+ _pipe,
+ erlang:binary_to_atom(<<"system"/utf8>>),
+ fun gleam_otp_external:convert_system_message/2
+ ).
+
+-spec receive_message(self(any(), GBU)) -> message(GBU).
+receive_message(Self) ->
+ Selector = case erlang:element(2, Self) of
+ suspended ->
+ _pipe = gleam_erlang_ffi:new_selector(),
+ selecting_system_messages(_pipe);
+
+ running ->
+ _pipe@1 = gleam_erlang_ffi:new_selector(),
+ _pipe@2 = gleam@erlang@process:selecting_anything(
+ _pipe@1,
+ fun(Field@0) -> {unexpected, Field@0} end
+ ),
+ _pipe@3 = gleam_erlang_ffi:merge_selector(
+ _pipe@2,
+ erlang:element(6, Self)
+ ),
+ selecting_system_messages(_pipe@3)
+ end,
+ gleam_erlang_ffi:select(Selector).
+
+-spec process_status_info(self(any(), any())) -> gleam@otp@system:status_info().
+process_status_info(Self) ->
+ {status_info,
+ erlang:binary_to_atom(<<"gleam@otp@actor"/utf8>>),
+ erlang:element(3, Self),
+ erlang:element(2, Self),
+ erlang:element(7, Self),
+ gleam@dynamic:from(erlang:element(4, Self))}.
+
+-spec init_selector(
+ gleam@erlang@process:subject(GGN),
+ gleam@erlang@process:selector(GGN)
+) -> gleam@erlang@process:selector(message(GGN)).
+init_selector(Subject, Selector) ->
+ _pipe = gleam_erlang_ffi:new_selector(),
+ _pipe@1 = gleam@erlang@process:selecting(
+ _pipe,
+ Subject,
+ fun(Field@0) -> {message, Field@0} end
+ ),
+ gleam_erlang_ffi:merge_selector(
+ _pipe@1,
+ gleam_erlang_ffi:map_selector(
+ Selector,
+ fun(Field@0) -> {message, Field@0} end
+ )
+ ).
+
+-spec loop(self(any(), any())) -> gleam@erlang@process:exit_reason().
+loop(Self) ->
+ case receive_message(Self) of
+ {system, System} ->
+ case System of
+ {get_state, Callback} ->
+ Callback(gleam@dynamic:from(erlang:element(4, Self))),
+ loop(Self);
+
+ {resume, Callback@1} ->
+ Callback@1(),
+ loop(erlang:setelement(2, Self, running));
+
+ {suspend, Callback@2} ->
+ Callback@2(),
+ loop(erlang:setelement(2, Self, suspended));
+
+ {get_status, Callback@3} ->
+ Callback@3(process_status_info(Self)),
+ loop(Self)
+ end;
+
+ {unexpected, Message} ->
+ logger:warning(
+ unicode:characters_to_list(
+ <<"Actor discarding unexpected message: ~s"/utf8>>
+ ),
+ [unicode:characters_to_list(gleam@string:inspect(Message))]
+ ),
+ loop(Self);
+
+ {message, Msg} ->
+ case (erlang:element(8, Self))(Msg, erlang:element(4, Self)) of
+ {stop, Reason} ->
+ exit_process(Reason);
+
+ {continue, State, New_selector} ->
+ Selector = begin
+ _pipe = New_selector,
+ _pipe@1 = gleam@option:map(
+ _pipe,
+ fun(_capture) ->
+ init_selector(erlang:element(5, Self), _capture)
+ end
+ ),
+ gleam@option:unwrap(_pipe@1, erlang:element(6, Self))
+ end,
+ loop(
+ erlang:setelement(
+ 6,
+ erlang:setelement(4, Self, State),
+ Selector
+ )
+ )
+ end
+ end.
+
+-spec initialise_actor(
+ spec(any(), GCP),
+ gleam@erlang@process:subject({ok, gleam@erlang@process:subject(GCP)} |
+ {error, gleam@erlang@process:exit_reason()})
+) -> gleam@erlang@process:exit_reason().
+initialise_actor(Spec, Ack) ->
+ Subject = gleam@erlang@process:new_subject(),
+ case (erlang:element(2, Spec))() of
+ {ready, State, Selector} ->
+ Selector@1 = init_selector(Subject, Selector),
+ gleam@erlang@process:send(Ack, {ok, Subject}),
+ Self = {self,
+ running,
+ gleam@erlang@process:subject_owner(Ack),
+ State,
+ Subject,
+ Selector@1,
+ sys:debug_options([]),
+ erlang:element(4, Spec)},
+ loop(Self);
+
+ {failed, Reason} ->
+ gleam@erlang@process:send(Ack, {error, {abnormal, Reason}}),
+ exit_process({abnormal, Reason})
+ end.
+
+-spec to_erlang_start_result(
+ {ok, gleam@erlang@process:subject(any())} | {error, start_error()}
+) -> {ok, gleam@erlang@process:pid_()} | {error, gleam@dynamic:dynamic_()}.
+to_erlang_start_result(Res) ->
+ case Res of
+ {ok, X} ->
+ {ok, gleam@erlang@process:subject_owner(X)};
+
+ {error, X@1} ->
+ {error, gleam@dynamic:from(X@1)}
+ end.
+
+-spec start_spec(spec(any(), GDD)) -> {ok, gleam@erlang@process:subject(GDD)} |
+ {error, start_error()}.
+start_spec(Spec) ->
+ Ack_subject = gleam@erlang@process:new_subject(),
+ Child = gleam@erlang@process:start(
+ fun() -> initialise_actor(Spec, Ack_subject) end,
+ true
+ ),
+ Monitor = gleam@erlang@process:monitor_process(Child),
+ Selector = begin
+ _pipe = gleam_erlang_ffi:new_selector(),
+ _pipe@1 = gleam@erlang@process:selecting(
+ _pipe,
+ Ack_subject,
+ fun(Field@0) -> {ack, Field@0} end
+ ),
+ gleam@erlang@process:selecting_process_down(
+ _pipe@1,
+ Monitor,
+ fun(Field@0) -> {mon, Field@0} end
+ )
+ end,
+ Result = case gleam_erlang_ffi:select(Selector, erlang:element(3, Spec)) of
+ {ok, {ack, {ok, Channel}}} ->
+ {ok, Channel};
+
+ {ok, {ack, {error, Reason}}} ->
+ {error, {init_failed, Reason}};
+
+ {ok, {mon, Down}} ->
+ {error, {init_crashed, erlang:element(3, Down)}};
+
+ {error, nil} ->
+ gleam@erlang@process:kill(Child),
+ {error, init_timeout}
+ end,
+ gleam_erlang_ffi:demonitor(Monitor),
+ Result.
+
+-spec start(GDJ, fun((GDK, GDJ) -> next(GDK, GDJ))) -> {ok,
+ gleam@erlang@process:subject(GDK)} |
+ {error, start_error()}.
+start(State, Loop) ->
+ start_spec(
+ {spec,
+ fun() -> {ready, State, gleam_erlang_ffi:new_selector()} end,
+ 5000,
+ Loop}
+ ).
+
+-spec send(gleam@erlang@process:subject(GDQ), GDQ) -> nil.
+send(Subject, Msg) ->
+ gleam@erlang@process:send(Subject, Msg).
+
+-spec call(
+ gleam@erlang@process:subject(GDS),
+ fun((gleam@erlang@process:subject(GDU)) -> GDS),
+ integer()
+) -> GDU.
+call(Selector, Make_message, Timeout) ->
+ gleam@erlang@process:call(Selector, Make_message, Timeout).