PageRenderTime 43ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/reactive-banana/src/Reactive/Banana/Prim/Compile.hs

https://github.com/pkamenarsky/reactive-banana
Haskell | 83 lines | 49 code | 11 blank | 23 comment | 0 complexity | 6ecaa2a484da0febb9a4b3f488ffb2e9 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. {-----------------------------------------------------------------------------
  2. reactive-banana
  3. ------------------------------------------------------------------------------}
  4. module Reactive.Banana.Prim.Compile where
  5. import Data.Functor
  6. import Data.IORef
  7. import qualified Data.Vault.Lazy as Lazy
  8. import Reactive.Banana.Prim.Combinators
  9. import Reactive.Banana.Prim.IO
  10. import Reactive.Banana.Prim.Plumbing
  11. import Reactive.Banana.Prim.Types
  12. {-----------------------------------------------------------------------------
  13. Compilation
  14. ------------------------------------------------------------------------------}
  15. -- | Change a 'Network' of pulses and latches by
  16. -- executing a 'BuildIO' action.
  17. compile :: BuildIO a -> Network -> IO (a, Network)
  18. compile = flip runBuildIO
  19. {-----------------------------------------------------------------------------
  20. Testing
  21. ------------------------------------------------------------------------------}
  22. -- | Simple interpreter for pulse/latch networks.
  23. --
  24. -- Mainly useful for testing functionality
  25. --
  26. -- Note: The result is not computed lazily, for similar reasons
  27. -- that the 'sequence' function does not compute its result lazily.
  28. interpret :: (Pulse a -> BuildIO (Pulse b)) -> [Maybe a] -> IO [Maybe b]
  29. interpret f xs = do
  30. key <- Lazy.newKey
  31. o <- newIORef Nothing
  32. let network = do
  33. (pin, sin) <- liftBuild $ newInput key
  34. pmid <- f pin
  35. pout <- liftBuild $ mapP return pmid
  36. liftBuild $ addHandler pout (writeIORef o . Just)
  37. return sin
  38. -- compile initial network
  39. (sin, state) <- compile network emptyNetwork
  40. let go Nothing s1 = return (Nothing,s1)
  41. go (Just a) s1 = do
  42. (reactimate,s2) <- sin a s1
  43. reactimate -- write output
  44. ma <- readIORef o -- read output
  45. writeIORef o Nothing
  46. return (ma,s2)
  47. mapAccumM go state xs -- run several steps
  48. -- | Execute an FRP network with a sequence of inputs, but discard results.
  49. --
  50. -- Mainly useful for testing whether there are space leaks.
  51. runSpaceProfile :: (Pulse a -> BuildIO void) -> [a] -> IO ()
  52. runSpaceProfile f xs = do
  53. key <- Lazy.newKey
  54. let g = do
  55. (p1, fire) <- liftBuild $ newInput key
  56. f p1
  57. return fire
  58. (fire,network) <- compile g emptyNetwork
  59. mapAccumM_ fire network xs
  60. -- | 'mapAccum' for a monad.
  61. mapAccumM :: Monad m => (a -> s -> m (b,s)) -> s -> [a] -> m [b]
  62. mapAccumM _ _ [] = return []
  63. mapAccumM f s0 (x:xs) = do
  64. (b,s1) <- f x s0
  65. bs <- mapAccumM f s1 xs
  66. return (b:bs)
  67. -- | Strict 'mapAccum' for a monad. Discards results.
  68. mapAccumM_ :: Monad m => (a -> s -> m (b,s)) -> s -> [a] -> m ()
  69. mapAccumM_ _ _ [] = return ()
  70. mapAccumM_ f s0 (x:xs) = do
  71. (_,s1) <- f x s0
  72. mapAccumM_ f s1 xs