Current section
Files
Jump to
Current section
Files
priv/Control/Behaviour/GenStatem.phi
-----------------------------------------------------------------------------
-- |
-- Module : Control.Behaviour.GenStatem
-- Copyright : (c) 2020-2021 EMQ Technologies Co., Ltd.
-- License : BSD-style (see the LICENSE file)
--
-- Maintainer : Feng Lee, feng@emqx.io
-- Yang M, yangm@emqx.io
-- Stability : experimental
-- Portability : portable
--
-- The GenStatem Behaviour.
--
-----------------------------------------------------------------------------
module Control.Behaviour.GenStatem
( class GenStatem
, Init
, OnEvent
, HandleEvent
, handleEvent
, handleWith
-- * start/stop
, start
, startWith
, startLink
, startLinkWith
, startMonitor
, startMonitorWith
, stop
, stopPid
, stopRef
, stopWith
-- * client apis
, call
, callTo
, callRef
, callTimeout
, cast
, castTo
, castRef
, sendRequest
-- * init result
, initOk
, initOkWith
, initIgnore
, initStop
-- * transition
, keep
, keepWith
, next
, nextWith
, repeat
, repeatWith
, shutdown
-- * helper funcs
, replyTo
, unhandled
, module Control.Behaviour.GenStatem.Types
) where
import Control.Monad (pure)
import Control.Process (Process, ExitReason(..))
import Data.Function (($), (<<<))
import Data.Map as M
import Data.Pid (Pid)
import Data.Ref (Reference)
import Data.Timeout (Timeout)
import Data.Unit (Unit)
import Foreign (ffiIO1, ffiIO2)
import Control.Behaviour.GenStatem.Types
-- | Init Action
type Init e s d = Process (InitResult e s d)
-- | Handle Event
type HandleEvent e s d
= EventType -> e -> s -> d -> Process (Transition e s d)
-- | On Event
type OnEvent e s d
= EventType -> e -> d -> Process (Transition e s d)
class GenStatem e s d | e -> s, s -> d, d -> e where
handleEvent :: HandleEvent e s d
foreign import start
:: forall e s d. GenStatem e s d => (Init e s d) -> Process Pid
foreign import startWith
:: forall e s d. GenStatem e s d => Name -> (Init e s d) -> Process Pid
foreign import startLink
:: forall e s d. GenStatem e s d => (Init e s d) -> Process Pid
foreign import startLinkWith
:: forall e s d. GenStatem e s d => Name -> (Init e s d) -> Process Pid
foreign import startMonitor
:: forall e s d. GenStatem e s d => (Init e s d) -> Process (Pid, Reference)
foreign import startMonitorWith
:: forall e s d. GenStatem e s d => Name -> (Init e s d) -> Process (Pid, Reference)
-- Stop the Statem Process.
stop :: Name -> Process ()
stop = ffiIO1 :gen_statem :stop
stopPid :: Pid -> Process ()
stopPid = ffiIO1 :gen_statem :stop
-- Stop the Statem Process.
foreign import stopRef :: StatemRef -> Process ()
-- Stop the Statem Process with ExitReason.
foreign import stopWith
:: StatemRef -> ExitReason -> Timeout -> Process ()
call :: forall req rep. Name -> req -> Process rep
call = ffiIO2 :gen_statem :call
-- | Synchronous call to the Server process directly.
callTo :: forall req rep. Pid -> req -> Process rep
callTo = ffiIO2 :gen_statem :call
foreign import callRef
:: forall req rep. StatemRef -> req -> Process rep
foreign import callTimeout
:: forall req rep. StatemRef -> req -> Timeout -> Process rep
cast :: forall msg. Name -> msg -> Process ()
cast = ffiIO2 :gen_statem :cast
-- | Sends an asynchronous request to the Server process directly.
castTo :: forall req. Pid -> req -> Process ()
castTo = ffiIO2 :gen_statem :cast
foreign import castRef
:: forall msg. StatemRef -> msg -> Process ()
replyTo :: forall rep. From -> rep -> Process ()
replyTo = ffiIO2 :gen_statem :reply
foreign import sendRequest
:: forall req. StatemRef -> req -> Process RequestId
-- TODO:
-- wait_response(RequestId :: request_id()) ->
-- {reply, Reply :: term()} | {error, {term(), server_ref()}}
-- | Handle with state functions.
handleWith :: forall e s d. [(s, OnEvent e s d)] -> HandleEvent e s d
handleWith stateFuns =
let funsMap = M.fromList stateFuns
in \t e s d -> let f = M.get s funsMap in f t e d
foreign import unhandled :: forall e s d. HandleEvent e s d
-----------------------------------------------------------------------------
-- | Init result
-----------------------------------------------------------------------------
initOk :: forall e s d. s -> d -> Process (InitResult e s d)
initOk s d = pure $ InitOk s d []
initOkWith :: forall e s d. s -> d -> [Action e] -> Process (InitResult e s d)
initOkWith s d = pure <<< InitOk s d
initIgnore :: forall e s d. Process (InitResult e s d)
initIgnore = pure InitIgnore
initStop :: forall e s d. ExitReason -> Process (InitResult e s d)
initStop = pure <<< InitStop
-----------------------------------------------------------------------------
-- | State Transition
-----------------------------------------------------------------------------
keep :: forall e s d. d -> Process (Transition e s d)
keep d = pure $ Keep d []
keepWith :: forall e s d. d -> [Action e] -> Process (Transition e s d)
keepWith d = pure <<< Keep d
next :: forall e s d. s -> d -> Process (Transition e s d)
next s d = pure $ Next s d []
nextWith :: forall e s d. s -> d -> [Action e] -> Process (Transition e s d)
nextWith s d = pure <<< Next s d
repeat :: forall e s d. d -> Process (Transition e s d)
repeat d = pure $ Repeat d []
repeatWith :: forall e s d. d -> [Action e] -> Process (Transition e s d)
repeatWith d = pure <<< Repeat d
shutdown :: forall e s d. Atom -> d -> Process (Transition e s d)
shutdown r = pure <<< Shutdown (ExitReason r)