{-# LANGUAGE GADTs #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RecordWildCards #-}
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.SN
data Tickable m cla clb cl clc cld a b c d = Tickable
{
buffer1 :: ResamplingBuffer m cla clb a b
, ticksn :: SN m cl b c
, buffer2 :: ResamplingBuffer m clc cld c d
, parClockIn :: ParClockInclusion (In cl) clb
, parClockOut :: ParClockInclusion (Out cl) clc
, lastTime :: LastTime cl
, initTime :: Time cl
}
initLastTime :: SN m cl a b -> Time cl -> LastTime cl
initLastTime (Synchronous _) initTime = LeafLastTime initTime
initLastTime (Sequential sn1 _ sn2) initTime =
SequentialLastTime
(initLastTime sn1 initTime)
(initLastTime sn2 initTime)
initLastTime (Parallel sn1 sn2) initTime =
ParallelLastTime
(initLastTime sn1 initTime)
(initLastTime sn2 initTime)
createTickable
:: ResamplingBuffer m cla (In cl) a b
-> SN m cl b c
-> ResamplingBuffer m (Out cl) cld c d
-> Time cl
-> Tickable m cla (In cl) cl (Out cl) cld a b c d
createTickable buffer1 ticksn buffer2 initTime = Tickable
{ parClockIn = ParClockRefl
, parClockOut = ParClockRefl
, lastTime = initLastTime ticksn initTime
, ..
}
tick :: ( Monad m, Clock m cl
, Time cla ~ Time cl
, Time clb ~ Time cl
, Time clc ~ Time cl
, Time cld ~ Time cl
, Time (In cl) ~ Time cl
, Time (Out cl) ~ Time cl
)
=> Tickable m cla clb cl clc cld a b c d
-> Time cl
-> Tag cl
-> m (Tickable m cla clb cl clc cld a b c d)
tick Tickable
{ ticksn = Synchronous clsf
, lastTime = LeafLastTime lastTime
, .. } now tag = do
let
ti = TimeInfo
{ sinceLast = diffTime now lastTime
, sinceInit = diffTime now initTime
, absolute = now
, tag = tag
}
(b, buffer1') <- get buffer1 $ retag (parClockTagInclusion parClockIn ) ti
(c, clsf') <- unMSF clsf b `runReaderT` ti
buffer2' <- put buffer2 (retag (parClockTagInclusion parClockOut) ti) c
return Tickable
{ buffer1 = buffer1'
, ticksn = Synchronous clsf'
, buffer2 = buffer2'
, lastTime = LeafLastTime now
, .. }
tick tickable@Tickable
{ ticksn = Sequential sn1 bufferMiddle sn2
, lastTime = SequentialLastTime lastTimeL lastTimeR
, initTime
, parClockIn
} now (Left tag) = do
leftTickable <- tick Tickable
{ buffer1 = buffer1 tickable
, ticksn = sn1
, buffer2 = bufferMiddle
, parClockIn = parClockIn
, parClockOut = ParClockRefl
, lastTime = lastTimeL
, initTime = initTime
} now tag
return $ tickable
{ buffer1 = buffer1 leftTickable
, ticksn = Sequential (ticksn leftTickable) (buffer2 leftTickable) sn2
, lastTime = SequentialLastTime (lastTime leftTickable) lastTimeR
}
tick tickable@Tickable
{ ticksn = Sequential sn1 bufferMiddle sn2
, lastTime = SequentialLastTime lastTimeL lastTimeR
, initTime
, parClockOut
} now (Right tag) = do
rightTickable <- tick Tickable
{ buffer1 = bufferMiddle
, ticksn = sn2
, buffer2 = buffer2 tickable
, parClockIn = ParClockRefl
, parClockOut = parClockOut
, lastTime = lastTimeR
, initTime = initTime
} now tag
return $ tickable
{ buffer2 = buffer2 rightTickable
, ticksn = Sequential sn1 (buffer1 rightTickable) (ticksn rightTickable)
, lastTime = SequentialLastTime lastTimeL (lastTime rightTickable)
}
tick tickable@Tickable
{ ticksn = Parallel snA snB
, lastTime = ParallelLastTime lastTimeA lastTimeB
, initTime
, parClockIn
, parClockOut
} now tag = case tag of
Left tagL -> do
leftTickable <- tick Tickable
{ buffer1 = buffer1 tickable
, ticksn = snA
, buffer2 = buffer2 tickable
, parClockIn = ParClockInL parClockIn
, parClockOut = ParClockInL parClockOut
, lastTime = lastTimeA
, initTime = initTime
} now tagL
return $ tickable
{ buffer1 = buffer1 leftTickable
, ticksn = Parallel (ticksn leftTickable) snB
, buffer2 = buffer2 leftTickable
, lastTime = ParallelLastTime (lastTime leftTickable) lastTimeB
}
Right tagR -> do
rightTickable <- tick Tickable
{ buffer1 = buffer1 tickable
, ticksn = snB
, buffer2 = buffer2 tickable
, parClockIn = ParClockInR parClockIn
, parClockOut = ParClockInR parClockOut
, lastTime = lastTimeB
, initTime = initTime
} now tagR
return $ tickable
{ buffer1 = buffer1 rightTickable
, ticksn = Parallel snA (ticksn rightTickable)
, buffer2 = buffer2 rightTickable
, lastTime = ParallelLastTime lastTimeA (lastTime rightTickable)
}
tick Tickable {} _ _ = error "Impossible pattern in tick"
trivialResamplingBuffer
:: Monad m => cl
-> ResamplingBuffer m (Out cl) (In cl) () ()
trivialResamplingBuffer _ = go
where
go = ResamplingBuffer {..}
put _ _ = return go
get _ = return ((), go)