11{-# LANGUAGE  CPP #-}
2- {-# LANGUAGE  GADTs, ScopedTypeVariables #-}
2+ {-# LANGUAGE  GADTs, ScopedTypeVariables, TupleSections  #-}
33
44module  Development.Shake.Internal.Core.Monad (
55    RAW , Capture , runRAW ,
@@ -11,6 +11,8 @@ module Development.Shake.Internal.Core.Monad(
1111import  Control.Exception.Extra 
1212import  Control.Monad.IO.Class 
1313import  Data.IORef 
14+ import  Control.Monad 
15+ import  System.IO 
1416import  Data.Semigroup 
1517import  Prelude 
1618
@@ -65,9 +67,26 @@ instance (Semigroup a, Monoid a) => Monoid (RAW ro rw a) where
6567type  Capture  a  =  (a  ->  IO () ) ->  IO () 
6668
6769
70+ --  Useful for checking that all continuations are run only once
71+ --  Cannot be enabled for performance reasons and because some of
72+ --  "monad test" deliberately breaks the invariant to check it doesn't go wrong
73+ assertOnceCheck =  False 
74+ 
75+ assertOnce  ::  MonadIO  m  =>  String ->  (a  ->  m  b ) ->  IO a  ->  m  b )
76+ assertOnce msg k
77+     |  not  assertOnceCheck =  return  k
78+     |  otherwise  =  do 
79+         ref <-  liftIO $  newIORef False 
80+         return  $  \ v ->  do 
81+             liftIO $  join $  atomicModifyIORef ref $  \ old ->  (True $  when old $  do 
82+                 hPutStrLn stderr " FATAL ERROR: assertOnce failed" 
83+                 Prelude. fail  $  " assertOnce failed: " ++  msg
84+             k v
85+ 
6886--  |  Run and then call a continuation. 
6987runRAW  ::  ro  ->  rw  ->  RAW  ro  rw  a  ->  Capture  (Either SomeException  a )
7088runRAW ro rw m k =  do 
89+     k <-  assertOnce " runRAW" 
7190    rw <-  newIORef rw
7291    handler <-  newIORef throwIO
7392    writeIORef handler $  \ e ->  do 
@@ -79,6 +98,7 @@ runRAW ro rw m k = do
7998    goRAW handler ro rw m (\ v ->  do  writeIORef handler throwIO; k $  Right 
8099        `catch_`  \ e ->  ($  e) =<<  readIORef handler
81100
101+ 
82102goRAW  ::  forall  ro  rw  a  .  IORef  (SomeException  ->  IO () ) ->  ro  ->  IORef  rw  ->  RAW  ro  rw  a  ->  Capture  a 
83103goRAW handler ro rw =  go
84104    where 
@@ -97,6 +117,7 @@ goRAW handler ro rw = go
97117            ModifyRW  f ->  modifyIORef' rw f >>  k () 
98118
99119            CatchRAW  m hdl ->  do 
120+                 hdl <-  assertOnce " CatchRAW" 
100121                old <-  readIORef handler
101122                writeIORef handler $  \ e ->  do 
102123                    writeIORef handler old
@@ -105,6 +126,7 @@ goRAW handler ro rw = go
105126                go m $  \ x ->  writeIORef handler old >>  k x
106127
107128            CaptureRAW  f ->  do 
129+                 f <-  assertOnce " CaptureRAW" 
108130                old <-  readIORef handler
109131                writeIORef handler throwIO
110132                f $  \ x ->  case  x of 
0 commit comments