-module(gleam@otp@actor). -compile(no_auto_import). -export([to_erlang_start_result/1, from_erlang_start_result/1, wrap_erlang_starter/1, start_spec/1, start/2, send/2, call/3, pid/1]). -export_type([message/1, next/1, init_result/2, self/2, spec/2, start_error/0, start_init_message/1]). -type message(ETR) :: {message, ETR} | {system, gleam@otp@process:system_message()}. -type next(ETS) :: {continue, ETS} | {stop, gleam@otp@process:exit_reason()}. -type init_result(ETT, ETU) :: {ready, ETT, gleam@option:option(gleam@otp@process:receiver(ETU))} | {failed, gleam@otp@process:exit_reason()}. -type self(ETV, ETW) :: {self, gleam@otp@process:pid_(), gleam@otp@process:mode(), gleam@otp@process:pid_(), ETV, gleam@otp@process:receiver(message(ETW)), gleam@otp@process:debug_state(), fun((ETW, ETV) -> next(ETV))}. -type spec(ETX, ETY) :: {spec, fun(() -> init_result(ETX, ETY)), integer(), fun((ETY, ETX) -> next(ETX))}. -type start_error() :: init_timeout | {init_failed, gleam@otp@process:exit_reason()} | {init_crashed, gleam@dynamic:dynamic()}. -type start_init_message(EUF) :: {ack, {ok, gleam@otp@process:sender(EUF)} | {error, gleam@otp@process:exit_reason()}} | {mon, gleam@otp@process:process_down()}. -spec exit_process(gleam@otp@process:exit_reason()) -> gleam@otp@process:exit_reason(). exit_process(Reason) -> Reason. -spec receive_message(self(any(), EUV)) -> message(EUV). receive_message(Self) -> System_receiver = begin _pipe = gleam@otp@process:system_receiver(), gleam@otp@process:map_receiver(_pipe, fun(A) -> {system, A} end) end, Receiver = case erlang:element(3, Self) of suspended -> System_receiver; running -> _pipe@1 = erlang:element(6, Self), gleam@otp@process:merge_receiver(_pipe@1, System_receiver) end, gleam@otp@process:receive_forever(Receiver). -spec process_status_info(self(any(), any())) -> gleam@otp@process:status_info(). process_status_info(Self) -> {status_info, gleam@erlang@atom:create_from_string(<<"gleam@otp@actor"/utf8>>), erlang:element(4, Self), erlang:element(3, Self), erlang:element(7, Self), gleam@dynamic:from(erlang:element(5, Self))}. -spec loop(self(any(), any())) -> gleam@otp@process:exit_reason(). loop(Self) -> case receive_message(Self) of {system, {get_state, Caller}} -> gleam@otp@process:send( Caller, gleam@dynamic:from(erlang:element(5, Self)) ), loop(Self); {system, {resume, Caller@1}} -> gleam@otp@process:send(Caller@1, nil), loop(erlang:setelement(3, Self, running)); {system, {suspend, Caller@2}} -> gleam@otp@process:send(Caller@2, nil), loop(erlang:setelement(3, Self, suspended)); {system, {get_status, Caller@3}} -> gleam@otp@process:send(Caller@3, process_status_info(Self)), loop(Self); {message, Msg} -> case (erlang:element(8, Self))(Msg, erlang:element(5, Self)) of {stop, Reason} -> exit_process(Reason); {continue, State} -> loop(erlang:setelement(5, Self, State)) end; _@1 -> gleam@io:println( <<"Gleam Action: unsupported system message dropped"/utf8>> ), loop(Self) end. -spec merge_extra_receiver( gleam@otp@process:receiver(message(EZT)), gleam@option:option(gleam@otp@process:receiver(EZT)) ) -> gleam@otp@process:receiver(message(EZT)). merge_extra_receiver(R1, R2) -> case R2 of none -> R1; {some, R2@1} -> gleam@otp@process:merge_receiver( R1, gleam@otp@process:map_receiver(R2@1, fun(A) -> {message, A} end) ) end. -spec initialise_actor( spec(any(), EVL), gleam@otp@process:sender({ok, gleam@otp@process:sender(EVL)} | {error, gleam@otp@process:exit_reason()}) ) -> gleam@otp@process:exit_reason(). initialise_actor(Spec, Ack_channel) -> {Sender, Receiver} = gleam@otp@process:new_channel(), Receiver@1 = gleam@otp@process:map_receiver( Receiver, fun(A) -> {message, A} end ), case (erlang:element(2, Spec))() of {ready, State, Extra_receiver} -> gleam@otp@process:send(Ack_channel, {ok, Sender}), Self = {self, gleam@otp@process:self(), running, gleam@otp@process:pid(Ack_channel), State, merge_extra_receiver(Receiver@1, Extra_receiver), gleam@otp@process:debug_state([]), erlang:element(4, Spec)}, loop(Self); {failed, Reason} -> gleam@otp@process:send(Ack_channel, {error, Reason}), exit_process(Reason) end. -spec to_erlang_start_result( {ok, gleam@otp@process:sender(any())} | {error, start_error()} ) -> {ok, gleam@otp@process:pid_()} | {error, gleam@dynamic:dynamic()}. to_erlang_start_result(Res) -> case Res of {ok, X} -> {ok, gleam@otp@process:pid(X)}; {error, X@1} -> {error, gleam@dynamic:from(X@1)} end. -spec from_erlang_start_result({ok, gleam@otp@process:pid_()} | {error, any()}) -> {ok, gleam@otp@process:sender(any())} | {error, start_error()}. from_erlang_start_result(Start) -> case Start of {ok, Pid} -> {ok, gleam@otp@process:null_sender(Pid)}; {error, Error} -> {error, {init_crashed, gleam@dynamic:from(Error)}} end. -spec wrap_erlang_starter( fun(() -> {ok, gleam@otp@process:pid_()} | {error, any()}) ) -> fun(() -> {ok, gleam@otp@process:sender(any())} | {error, start_error()}). wrap_erlang_starter(Start) -> fun() -> from_erlang_start_result(Start()) end. -spec start_spec(spec(any(), EWJ)) -> {ok, gleam@otp@process:sender(EWJ)} | {error, start_error()}. start_spec(Spec) -> {Ack_sender, Ack_receiver} = gleam@otp@process:new_channel(), Child = gleam@otp@process:start( fun() -> initialise_actor(Spec, Ack_sender) end ), Receiver = begin _pipe = Ack_receiver, _pipe@1 = gleam@otp@process:map_receiver(_pipe, fun(A) -> {ack, A} end), gleam@otp@process:merge_receiver( _pipe@1, begin _pipe@2 = Child, _pipe@3 = gleam@otp@process:monitor_process(_pipe@2), gleam@otp@process:map_receiver(_pipe@3, fun(A) -> {mon, A} end) end ) end, case gleam@otp@process:'receive'(Receiver, erlang:element(3, Spec)) of {ok, {ack, {ok, Channel}}} -> gleam@otp@process:close_channels(Receiver), {ok, Channel}; {ok, {ack, {error, Reason}}} -> gleam@otp@process:close_channels(Receiver), {error, {init_failed, Reason}}; {ok, {mon, Down}} -> gleam@otp@process:close_channels(Receiver), {error, {init_crashed, erlang:element(3, Down)}}; {error, nil} -> gleam@otp@process:kill(Child), gleam@otp@process:close_channels(Receiver), {error, init_timeout} end. -spec start(EWP, fun((EWQ, EWP) -> next(EWP))) -> {ok, gleam@otp@process:sender(EWQ)} | {error, start_error()}. start(State, Loop) -> start_spec({spec, fun() -> {ready, State, none} end, 5000, Loop}). -spec send(gleam@otp@process:sender(EWV), EWV) -> gleam@otp@process:sender(EWV). send(Channel, Msg) -> gleam@otp@process:send(Channel, Msg). -spec call( gleam@otp@process:sender(EWY), fun((gleam@otp@process:sender(EXA)) -> EWY), integer() ) -> EXA. call(Receiver, Make_message, Timeout) -> gleam@otp@process:call(Receiver, Make_message, Timeout). -spec pid(gleam@otp@process:sender(any())) -> gleam@otp@process:pid_(). pid(Sender) -> gleam@otp@process:pid(Sender).