Skip to content

Commit

Permalink
Clean up module structure
Browse files Browse the repository at this point in the history
  • Loading branch information
Manuel Bärenz authored and turion committed Nov 29, 2024
1 parent ee69116 commit 27d03a3
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 213 deletions.
1 change: 1 addition & 0 deletions rhine/rhine.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ library
FRP.Rhine.ResamplingBuffer.Util
FRP.Rhine.SN
FRP.Rhine.SN.Combinators
FRP.Rhine.SN.Type
FRP.Rhine.Schedule
FRP.Rhine.Type

Expand Down
134 changes: 10 additions & 124 deletions rhine/src/FRP/Rhine/Reactimation/ClockErasure.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}

{- | Translate clocked signal processing components to stream functions without explicit clock types.
Expand All @@ -12,9 +11,6 @@ and is thus not exported from 'FRP.Rhine'.
-}
module FRP.Rhine.Reactimation.ClockErasure where

-- base
import Control.Monad (join)

-- automaton
import Data.Automaton.Trans.Reader
import Data.Stream.Result (Result (..))
Expand All @@ -25,7 +21,7 @@ import FRP.Rhine.Clock
import FRP.Rhine.Clock.Proxy
import FRP.Rhine.Clock.Util
import FRP.Rhine.ResamplingBuffer
import FRP.Rhine.Schedule (In, Out, SequentialClock)
import FRP.Rhine.SN.Type (SN (..))

{- | Run a clocked signal function as an automaton,
accepting the timestamps and tags as explicit inputs.
Expand All @@ -41,130 +37,20 @@ eraseClockClSF proxy initialTime clsf = proc (time, tag, a) -> do
runReaderS clsf -< (timeInfo, a)
{-# INLINE eraseClockClSF #-}

-- Andras' trick: Encode in the domain
newtype SN m cl a b = SN {getSN :: Reader (Time cl) (Automaton m (Time cl, Tag cl, Maybe a) (Maybe b))}

instance (GetClockProxy cl) => ToClockProxy (SN m cl a b) where
type Cl (SN m cl a b) = cl
{- | Remove the signal network type abstraction and reveal the underlying automaton.
eraseClockSN :: Time cl -> SN m cl a b -> (Automaton m (Time cl, Tag cl, Maybe a) (Maybe b))
* To drive the network, the timestamps and tags of the clock are needed
Since the input and output clocks are not always guaranteed to tick, the i
-}
eraseClockSN ::
-- | Initial time
Time cl ->
-- The original signal network
SN m cl a b -> Automaton m (Time cl, Tag cl, Maybe a) (Maybe b)
eraseClockSN time = flip runReader time . getSN
{-# INLINE eraseClockSN #-}

-- A synchronous signal network is run by erasing the clock from the clocked signal function.
synchronous ::
forall cl m a b.
(cl ~ In cl, cl ~ Out cl, Monad m, Clock m cl, GetClockProxy cl) =>
ClSF m cl a b ->
SN m cl a b
synchronous clsf = SN $ reader $ \initialTime -> proc (time, tag, Just a) -> do
b <- eraseClockClSF (getClockProxy @cl) initialTime clsf -< (time, tag, a)
returnA -< Just b
{-# INLINE synchronous #-}

-- A sequentially composed signal network may either be triggered in its first component,
-- or its second component. In either case,
-- the resampling buffer (which connects the two components) may be triggered,
-- but only if the outgoing clock of the first component ticks,
-- or the incoming clock of the second component ticks.
sequential ::
( Clock m clab
, Clock m clcd
, Clock m (Out clab)
, Clock m (Out clcd)
, Clock m (In clab)
, Clock m (In clcd)
, GetClockProxy clab
, GetClockProxy clcd
, Time clab ~ Time clcd
, Time clab ~ Time (Out clab)
, Time clcd ~ Time (In clcd)
, Monad m
) =>
SN m clab a b ->
ResamplingBuffer m (Out clab) (In clcd) b c ->
SN m clcd c d ->
SN m (SequentialClock clab clcd) a d
sequential sn1 resBuf sn2 = SN $ reader $ \initialTime ->
let
proxy1 = toClockProxy sn1
proxy2 = toClockProxy sn2
in
proc (time, tag, maybeA) -> do
resBufIn <- case tag of
Left tagL -> do
maybeB <- eraseClockSN initialTime sn1 -< (time, tagL, maybeA)
returnA -< Left <$> ((time,,) <$> outTag proxy1 tagL <*> maybeB)
Right tagR -> do
returnA -< Right . (time,) <$> inTag proxy2 tagR
maybeC <- mapMaybeS $ eraseClockResBuf (outProxy proxy1) (inProxy proxy2) initialTime resBuf -< resBufIn
case tag of
Left _ -> do
returnA -< Nothing
Right tagR -> do
eraseClockSN initialTime sn2 -< (time, tagR, join maybeC)
{-# INLINE sequential #-}

parallel snL snR = SN $ reader $ \initialTime -> proc (time, tag, maybeA) -> do
case tag of
Left tagL -> eraseClockSN initialTime snL -< (time, tagL, maybeA)
Right tagR -> eraseClockSN initialTime snR -< (time, tagR, maybeA)
{-# INLINE parallel #-}

postcompose sn clsf = SN $ reader $ \initialTime ->
let
proxy = toClockProxy sn
in
proc input@(time, tag, _) -> do
bMaybe <- eraseClockSN initialTime sn -< input
mapMaybeS $ eraseClockClSF (outProxy proxy) initialTime clsf -< (time,,) <$> outTag proxy tag <*> bMaybe
{-# INLINE postcompose #-}

precompose clsf sn = SN $ reader $ \initialTime ->
let
proxy = toClockProxy sn
in
proc (time, tag, aMaybe) -> do
bMaybe <- mapMaybeS $ eraseClockClSF (inProxy proxy) initialTime clsf -< (time,,) <$> inTag proxy tag <*> aMaybe
eraseClockSN initialTime sn -< (time, tag, bMaybe)
{-# INLINE precompose #-}

feedbackSN ResamplingBuffer {buffer, put, get} sn = SN $ reader $ \initialTime ->
let
proxy = toClockProxy sn
in
feedback buffer $ proc ((time, tag, aMaybe), buf) -> do
(cMaybe, buf') <- case inTag proxy tag of
Nothing -> do
returnA -< (Nothing, buf)
Just tagIn -> do
timeInfo <- genTimeInfo (inProxy proxy) initialTime -< (time, tagIn)
Result buf' c <- arrM $ uncurry get -< (timeInfo, buf)
returnA -< (Just c, buf')
bdMaybe <- eraseClockSN initialTime sn -< (time, tag, (,) <$> aMaybe <*> cMaybe)
case (,) <$> outTag proxy tag <*> bdMaybe of
Nothing -> do
returnA -< (Nothing, buf')
Just (tagOut, (b, d)) -> do
timeInfo <- genTimeInfo (outProxy proxy) initialTime -< (time, tagOut)
buf'' <- arrM $ uncurry $ uncurry put -< ((timeInfo, d), buf')
returnA -< (Just b, buf'')
{-# INLINE feedbackSN #-}

firstResampling sn buf = SN $ reader $ \initialTime ->
let
proxy = toClockProxy sn
in
proc (time, tag, acMaybe) -> do
bMaybe <- eraseClockSN initialTime sn -< (time, tag, fst <$> acMaybe)
let
resBufInput = case (inTag proxy tag, outTag proxy tag, snd <$> acMaybe) of
(Just tagIn, _, Just c) -> Just $ Left (time, tagIn, c)
(_, Just tagOut, _) -> Just $ Right (time, tagOut)
_ -> Nothing
dMaybe <- mapMaybeS $ eraseClockResBuf (inProxy proxy) (outProxy proxy) initialTime buf -< resBufInput
returnA -< (,) <$> bMaybe <*> join dMaybe
{-# INLINE firstResampling #-}

{- | Translate a resampling buffer into an automaton.
Expand Down
2 changes: 1 addition & 1 deletion rhine/src/FRP/Rhine/Reactimation/Combinators.hs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ module FRP.Rhine.Reactimation.Combinators where
import FRP.Rhine.ClSF.Core
import FRP.Rhine.Clock
import FRP.Rhine.Clock.Proxy
import FRP.Rhine.Reactimation.ClockErasure
import FRP.Rhine.ResamplingBuffer
import FRP.Rhine.SN.Combinators
import FRP.Rhine.Schedule
import FRP.Rhine.Type
import FRP.Rhine.SN

-- * Combinators and syntactic sugar for high-level composition of signal networks.

Expand Down
Loading

0 comments on commit 27d03a3

Please sign in to comment.