@@ -1,38 +1,21 @@
1−{-# LANGUAGE OverloadedStrings #-}
1+{-# LANGUAGE OverloadedStrings, Rank2Types #-}
2module Reporting.Task
2module Reporting.Task
3− ( Task, Task_
3+ ( Task
7− , mapError
6+ -- progress
9− , getPackageCacheDir
8+ , ask
10− , getPackageCacheDirFor
9+ -- io
12− , getReporter
11+ , eio
13− , getApproval
12+ , withKey
21−import Control.Concurrent (forkIO)
16+
22−import Control.Concurrent.Chan (Chan, newChan, readChan, writeChan)
23−import Control.Monad (forever, join, replicateM_)
24−import Control.Monad.Except (ExceptT, runExceptT, throwError, withExceptT)
25−import qualified Control.Monad.Reader as R
26−import Control.Monad.Trans (liftIO)
27−import qualified Network.HTTP.Client as Http
28−import qualified Network.HTTP.Client.TLS as Http
29−import qualified System.Directory as Dir
30import qualified System.Exit as Exit
17import qualified System.Exit as Exit
31−import System.FilePath ((</>))
33−import qualified Elm.Package as Pkg
34−import qualified Elm.PerUserCache as PerUserCache
35−import qualified Elm.Version as V
36import qualified Reporting.Doc as D
19import qualified Reporting.Doc as D
37import qualified Reporting.Exit as Exit
20import qualified Reporting.Exit as Exit
38import qualified Reporting.Progress as Progress
21import qualified Reporting.Progress as Progress
@@ -42,148 +25,126 @@ import qualified Reporting.Progress as Progress
45−type Task =
28+newtype Task a =
46− Task_ Exit.Exit
29+ Task
50− ExceptT e (R.ReaderT Env IO)
33+ -> (a -> IO result)
34+ -> (Exit.Exit -> IO result)
55− { _cacheDir :: FilePath
56− , _worker :: IO () -> IO ()
57− , _httpManager :: Http.Manager
58− , _tell :: Progress.Progress -> IO ()
41+ { _tell :: Progress.Progress -> IO ()
59− , _ask :: D.Doc -> IO Bool
42+ , _ask :: D.Doc -> IO Bool
63−try :: Progress.Reporter -> Task a -> IO (Maybe a)
64−try (Progress.Reporter tell ask end) task =
65− do root <- PerUserCache.getPackageRoot
67− httpManager <- Http.newManager Http.tlsManagerSettings
68− let env = Env root pool httpManager tell ask
69− result <- R.runReaderT (runExceptT task) env
80run :: Progress.Reporter -> Task a -> IO ()
46run :: Progress.Reporter -> Task a -> IO ()
81−run reporter task =
47+run (Progress.Reporter pTell pAsk pEnd) (Task task) =
82− do maybeAnswer <- try reporter task
48+ task (Env pTell pAsk)
83− case maybeAnswer of
49+ (\_ ->
84− Nothing -> Exit.exitFailure
55+ Exit.exitFailure
85− Just _ -> return ()
56+ )
88−throw :: e -> Task_ e a
93−mapError :: (x -> y) -> Task_ x a -> Task_ y a
102−getPackageCacheDir :: Task_ e FilePath
107−getPackageCacheDirFor :: Pkg.Name -> V.Version -> Task_ e FilePath
108−getPackageCacheDirFor name version =
109− do cacheDir <- getPackageCacheDir
110− let dir = cacheDir </> Pkg.toFilePath name </> V.toChars version
111− liftIO (Dir.createDirectoryIfMissing True dir)
119−report :: Progress.Progress -> Task_ e ()
121− do tell <- R.asks _tell
122− liftIO (tell progress)
125−getReporter :: Task (Progress.Progress -> IO ())
59+throw :: Exit.Exit -> Task a
126−getReporter =
60+throw exit =
127− R.asks _tell
61+ Task $ \_ _ err -> err exit
131−-- APPROVAL
65+-- PROGRESS
134−getApproval :: D.Doc -> Task_ e Bool
68+notify :: Progress.Progress -> Task ()
135−getApproval doc =
69+notify progress =
136− do ask <- R.asks _ask
70+ Task $ \(Env pTell _) ok _ -> pTell progress >>= ok
73+ask :: D.Doc -> Task Bool
75+ Task $ \(Env _ pAsk) ok _ -> pAsk question >>= ok
144−silently :: Task_ e a -> Task_ e a
79+-- IO
146− do runner <- getSilentRunner
147− result <- liftIO (runner task)
148− either throw return result
151−getSilentRunner :: Task_ x (Task_ e a -> IO (Either e a))
82+{-# INLINE io #-}
152−getSilentRunner =
83+io :: IO a -> Task a
153− do env <- R.ask
84+io work =
154− let silentEnv = env { _tell = \_ -> return () }
85+ Task $ \_ ok _ -> work >>= ok
155− return $ \task -> R.runReaderT (runExceptT task) silentEnv
88+eio :: (x -> Exit.Exit) -> IO (Either x a) -> Task a
94+ Left e -> err (func e)
97+withKey :: (Progress.Key -> IO (Either Exit.Exit a)) -> Task a
99+ Task $ \(Env pTell _) ok err ->
100+ do result <- callback (Progress.Key pTell)
162−workerChan :: Chan (Either e a) -> Task_ e a -> Task_ x ()
163−workerChan chan task =
166− liftIO $ _worker env $
167− do result <- R.runReaderT (runExceptT task) env
168− writeChan chan result
171−initPool :: Int -> IO (IO () -> IO ())
175− replicateM_ size $ forkIO $ forever $
110+instance Functor Task where
176− join (readChan chan)
111+ {-# INLINE fmap #-}
112+ fmap func (Task taskA) =
113+ Task $ \env ok err ->
115+ okA arg = ok (func arg)
178− return $ writeChan chan
120+instance Applicative Task where
123+ Task $ \_ ok _ -> ok a
125+ {-# INLINE (<*>) #-}
126+ (<*>) (Task taskFunc) (Task taskArg) =
127+ Task $ \env ok err ->
131+ okArg arg = ok (func arg)
133+ taskArg env okArg err
135+ taskFunc env okFunc err
138+instance Monad Task where
139+ {-# INLINE return #-}
185−runHttp :: (Http.Manager -> (Progress.Progress -> IO ()) -> IO (Either Exit.Exit a)) -> Task a
142+ {-# INLINE (>>=) #-}
186−runHttp fetcher =
143+ (>>=) (Task taskA) callback =
187− do (Env _ _ manager tell _) <- R.ask
144+ Task $ \env ok err ->
188− result <- liftIO $ fetcher manager tell
145+ let
189− either throwError return result
146+ okA a =
148+ Task taskB -> taskB env ok err