module FRP.Rhine.Reactimation.Tick where
import Control.Monad.Trans.Reader
import Data.MonadicStreamFunction
import FRP.Rhine.Clock
import FRP.Rhine.ResamplingBuffer
import FRP.Rhine.Schedule
import FRP.Rhine.SF
import FRP.Rhine.TimeDomain
data Tickable m cla clb cl clc cld a b c d = Tickable
{
buffer1 :: ResamplingBuffer m cla clb a b
, ticksf :: SF m cl b c
, buffer2 :: ResamplingBuffer m clc cld c d
, parClockInL :: ParClockInclusion (Leftmost cl) clb
, parClockInR :: ParClockInclusion (Rightmost cl) clc
, lastTime :: LastTime cl
, initTime :: TimeDomainOf cl
}
initLastTime :: SF m cl a b -> TimeDomainOf cl -> LastTime cl
initLastTime (Synchronous _) initTime = LeafLastTime initTime
initLastTime (Sequential sf1 _ sf2) initTime =
SequentialLastTime
(initLastTime sf1 initTime)
(initLastTime sf2 initTime)
initLastTime (Parallel sf1 sf2) initTime =
ParallelLastTime
(initLastTime sf1 initTime)
(initLastTime sf2 initTime)
createTickable
:: ResamplingBuffer m cla (Leftmost cl) a b
-> SF m cl b c
-> ResamplingBuffer m (Rightmost cl) cld c d
-> TimeDomainOf cl
-> Tickable m cla (Leftmost cl) cl (Rightmost cl) cld a b c d
createTickable buffer1 ticksf buffer2 initTime = Tickable
{ parClockInL = ParClockRefl
, parClockInR = ParClockRefl
, lastTime = initLastTime ticksf initTime
, ..
}
tick :: ( Monad m, Clock m cl
, TimeDomainOf cla ~ TimeDomainOf cl
, TimeDomainOf clb ~ TimeDomainOf cl
, TimeDomainOf clc ~ TimeDomainOf cl
, TimeDomainOf cld ~ TimeDomainOf cl
, TimeDomainOf (Leftmost cl) ~ TimeDomainOf cl
, TimeDomainOf (Rightmost cl) ~ TimeDomainOf cl
)
=> Tickable m cla clb cl clc cld a b c d
-> TimeDomainOf cl
-> Tag cl
-> m (Tickable m cla clb cl clc cld a b c d)
tick Tickable
{ ticksf = Synchronous syncsf
, lastTime = LeafLastTime lastTime
, .. } now tag = do
let
ti = TimeInfo
{ sinceTick = diffTime now lastTime
, sinceStart = diffTime now initTime
, absolute = now
, tag = tag
}
(b, buffer1') <- get buffer1 $ retag (parClockTagInclusion parClockInL) ti
(c, syncsf') <- unMSF syncsf b `runReaderT` ti
buffer2' <- put buffer2 (retag (parClockTagInclusion parClockInR) ti) c
return Tickable
{ buffer1 = buffer1'
, ticksf = Synchronous syncsf'
, buffer2 = buffer2'
, lastTime = LeafLastTime now
, .. }
tick tickable@Tickable
{ ticksf = Sequential sf1 bufferMiddle sf2
, lastTime = SequentialLastTime lastTimeL lastTimeR
, initTime
, parClockInL
} now (Left tag) = do
leftTickable <- tick Tickable
{ buffer1 = buffer1 tickable
, ticksf = sf1
, buffer2 = bufferMiddle
, parClockInL = parClockInL
, parClockInR = ParClockRefl
, lastTime = lastTimeL
, initTime = initTime
} now tag
return $ tickable
{ buffer1 = buffer1 leftTickable
, ticksf = Sequential (ticksf leftTickable) (buffer2 leftTickable) sf2
, lastTime = SequentialLastTime (lastTime leftTickable) lastTimeR
}
tick tickable@Tickable
{ ticksf = Sequential sf1 bufferMiddle sf2
, lastTime = SequentialLastTime lastTimeL lastTimeR
, initTime
, parClockInR
} now (Right tag) = do
rightTickable <- tick Tickable
{ buffer1 = bufferMiddle
, ticksf = sf2
, buffer2 = buffer2 tickable
, parClockInL = ParClockRefl
, parClockInR = parClockInR
, lastTime = lastTimeR
, initTime = initTime
} now tag
return $ tickable
{ buffer2 = buffer2 rightTickable
, ticksf = Sequential sf1 (buffer1 rightTickable) (ticksf rightTickable)
, lastTime = SequentialLastTime lastTimeL (lastTime rightTickable)
}
tick tickable@Tickable
{ ticksf = Parallel sfA sfB
, lastTime = ParallelLastTime lastTimeA lastTimeB
, initTime
, parClockInL
, parClockInR
} now tag = case tag of
Left tagL -> do
leftTickable <- tick Tickable
{ buffer1 = buffer1 tickable
, ticksf = sfA
, buffer2 = buffer2 tickable
, parClockInL = ParClockInL parClockInL
, parClockInR = ParClockInL parClockInR
, lastTime = lastTimeA
, initTime = initTime
} now tagL
return $ tickable
{ buffer1 = buffer1 leftTickable
, ticksf = Parallel (ticksf leftTickable) sfB
, buffer2 = buffer2 leftTickable
, lastTime = ParallelLastTime (lastTime leftTickable) lastTimeB
}
Right tagR -> do
rightTickable <- tick Tickable
{ buffer1 = buffer1 tickable
, ticksf = sfB
, buffer2 = buffer2 tickable
, parClockInL = ParClockInR parClockInL
, parClockInR = ParClockInR parClockInR
, lastTime = lastTimeB
, initTime = initTime
} now tagR
return $ tickable
{ buffer1 = buffer1 rightTickable
, ticksf = Parallel sfA (ticksf rightTickable)
, buffer2 = buffer2 rightTickable
, lastTime = ParallelLastTime lastTimeA (lastTime rightTickable)
}
tick Tickable
{ ticksf = Synchronous _
, lastTime = SequentialLastTime {}
} _ _ = error "Impossible pattern in tick"
tick Tickable
{ ticksf = Synchronous _
, lastTime = ParallelLastTime {}
} _ _ = error "Impossible pattern in tick"
tick Tickable
{ ticksf = Sequential {}
, lastTime = LeafLastTime _
} _ _ = error "Impossible pattern in tick"
tick Tickable
{ ticksf = Parallel {}
, lastTime = LeafLastTime _
} _ _ = error "Impossible pattern in tick"
trivialResamplingBuffer
:: Monad m => cl
-> ResamplingBuffer m (Rightmost cl) (Leftmost cl) () ()
trivialResamplingBuffer _ = go
where
go = ResamplingBuffer {..}
put _ _ = return go
get _ = return ((), go)