module Reactive.Threepenny.Types where

import Control.Monad.Trans.RWS.Lazy
import Data.Functor.Identity ()

import           Data.Hashable
import qualified Data.Vault.Strict   as Vault.Strict
import           Data.Unique.Really

{-----------------------------------------------------------------------------
    Pulse and Latch
------------------------------------------------------------------------------}
type Values = Vault.Strict.Vault

type Handler  = EvalP (IO ())
data Priority = DoLatch | DoIO deriving (Priority -> Priority -> Bool
(Priority -> Priority -> Bool)
-> (Priority -> Priority -> Bool) -> Eq Priority
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Priority -> Priority -> Bool
== :: Priority -> Priority -> Bool
$c/= :: Priority -> Priority -> Bool
/= :: Priority -> Priority -> Bool
Eq,Int -> Priority -> ShowS
[Priority] -> ShowS
Priority -> String
(Int -> Priority -> ShowS)
-> (Priority -> String) -> ([Priority] -> ShowS) -> Show Priority
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Priority -> ShowS
showsPrec :: Int -> Priority -> ShowS
$cshow :: Priority -> String
show :: Priority -> String
$cshowList :: [Priority] -> ShowS
showList :: [Priority] -> ShowS
Show,Eq Priority
Eq Priority =>
(Priority -> Priority -> Ordering)
-> (Priority -> Priority -> Bool)
-> (Priority -> Priority -> Bool)
-> (Priority -> Priority -> Bool)
-> (Priority -> Priority -> Bool)
-> (Priority -> Priority -> Priority)
-> (Priority -> Priority -> Priority)
-> Ord Priority
Priority -> Priority -> Bool
Priority -> Priority -> Ordering
Priority -> Priority -> Priority
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Priority -> Priority -> Ordering
compare :: Priority -> Priority -> Ordering
$c< :: Priority -> Priority -> Bool
< :: Priority -> Priority -> Bool
$c<= :: Priority -> Priority -> Bool
<= :: Priority -> Priority -> Bool
$c> :: Priority -> Priority -> Bool
> :: Priority -> Priority -> Bool
$c>= :: Priority -> Priority -> Bool
>= :: Priority -> Priority -> Bool
$cmax :: Priority -> Priority -> Priority
max :: Priority -> Priority -> Priority
$cmin :: Priority -> Priority -> Priority
min :: Priority -> Priority -> Priority
Ord,Int -> Priority
Priority -> Int
Priority -> [Priority]
Priority -> Priority
Priority -> Priority -> [Priority]
Priority -> Priority -> Priority -> [Priority]
(Priority -> Priority)
-> (Priority -> Priority)
-> (Int -> Priority)
-> (Priority -> Int)
-> (Priority -> [Priority])
-> (Priority -> Priority -> [Priority])
-> (Priority -> Priority -> [Priority])
-> (Priority -> Priority -> Priority -> [Priority])
-> Enum Priority
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: Priority -> Priority
succ :: Priority -> Priority
$cpred :: Priority -> Priority
pred :: Priority -> Priority
$ctoEnum :: Int -> Priority
toEnum :: Int -> Priority
$cfromEnum :: Priority -> Int
fromEnum :: Priority -> Int
$cenumFrom :: Priority -> [Priority]
enumFrom :: Priority -> [Priority]
$cenumFromThen :: Priority -> Priority -> [Priority]
enumFromThen :: Priority -> Priority -> [Priority]
$cenumFromTo :: Priority -> Priority -> [Priority]
enumFromTo :: Priority -> Priority -> [Priority]
$cenumFromThenTo :: Priority -> Priority -> Priority -> [Priority]
enumFromThenTo :: Priority -> Priority -> Priority -> [Priority]
Enum)

data Pulse a = Pulse
    { forall a. Pulse a -> ((Unique, Priority), Handler) -> Build (IO ())
addHandlerP :: ((Unique, Priority), Handler) -> Build (IO ())
    , forall a. Pulse a -> EvalP (Maybe a)
evalP       :: EvalP (Maybe a)
    }

instance Hashable Priority where
    hashWithSalt :: Int -> Priority -> Int
hashWithSalt = (Priority -> Int) -> Int -> Priority -> Int
forall b a. Hashable b => (a -> b) -> Int -> a -> Int
hashUsing Priority -> Int
forall a. Enum a => a -> Int
fromEnum
    hash :: Priority -> Int
hash         = Priority -> Int
forall a. Enum a => a -> Int
fromEnum

data Latch a = Latch { forall a. Latch a -> EvalL a
readL :: EvalL a }

{-----------------------------------------------------------------------------
    Monads
------------------------------------------------------------------------------}
-- | The 'EvalP' monad is used to evaluate pulses.
type EvalP = RWST () () Values BuildIO
    -- state: current pulse values

-- | The 'EvalL' monad is used to evaluate latches.
type EvalL = IO

-- | The 'Build' monad is used to add pulses and latches to the graph.
type Build   = IO
type BuildIO = Build