@@ -1,63 +1,35 @@
1--------------------------------------------------------------------------------
1--------------------------------------------------------------------------------
2-- | Internally used compiler module
2-- | Internally used compiler module
3{-# LANGUAGE GeneralizedNewtypeDeriving #-}
4{-# LANGUAGE GeneralizedNewtypeDeriving #-}
4module Hakyll.Core.Compiler.Internal
5module Hakyll.Core.Compiler.Internal
5− ( Dependencies
6+ ( CompilerRead (..)
6− , DependencyEnvironment (..)
7− , CompilerEnvironment (..)
10 , Compiler (..)
7 , Compiler (..)
11− , runCompilerJob
8+ , compilerTell
12− , runCompilerDependencies
9+ , compilerAsk
13− , fromJob
10+ , compilerThrow
14− , fromDependencies
11+ , compilerCatch
19--------------------------------------------------------------------------------
15--------------------------------------------------------------------------------
20−import Control.Applicative (Alternative (..), Applicative,
16+import Control.Applicative (Alternative (..),
21− pure, (<$>), (<*>))
17+ Applicative (..))
23−import Control.Category (Category, id, (.))
24−import Control.Monad (liftM2, (<=<))
25−import Control.Monad.Error (ErrorT, catchError, runErrorT,
27−import Control.Monad.Reader (Reader, ReaderT, ask, runReader,
29−import Data.Set (Set)
18+import Data.Monoid (mappend, mempty)
30−import qualified Data.Set as S
31−import Prelude hiding (id, (.))
34--------------------------------------------------------------------------------
21--------------------------------------------------------------------------------
22+import Hakyll.Core.Dependencies
35import Hakyll.Core.Identifier
23import Hakyll.Core.Identifier
36import Hakyll.Core.Logger
24import Hakyll.Core.Logger
37import Hakyll.Core.ResourceProvider
25import Hakyll.Core.ResourceProvider
38import Hakyll.Core.Routes
26import Hakyll.Core.Routes
39import Hakyll.Core.Store
27import Hakyll.Core.Store
40−import Hakyll.Core.Util.Arrow
43−--------------------------------------------------------------------------------
44−-- | A set of dependencies
45−type Dependencies = Set (Identifier ())
48−--------------------------------------------------------------------------------
49−-- | Environment in which the dependency analyzer runs
50−data DependencyEnvironment = DependencyEnvironment
51− { -- | Target identifier
52− dependencyIdentifier :: Identifier ()
53− , -- | List of available identifiers we can depend upon
54− dependencyUniverse :: [Identifier ()]
58--------------------------------------------------------------------------------
30--------------------------------------------------------------------------------
59-- | Environment in which a compiler runs
31-- | Environment in which a compiler runs
60−data CompilerEnvironment = CompilerEnvironment
32+data CompilerRead = CompilerRead
61 { -- | Target identifier
33 { -- | Target identifier
62 compilerIdentifier :: Identifier ()
34 compilerIdentifier :: Identifier ()
63 , -- | Resource provider
35 , -- | Resource provider
@@ -76,164 +48,127 @@ data CompilerEnvironment = CompilerEnvironment
78--------------------------------------------------------------------------------
50--------------------------------------------------------------------------------
79−-- | A calculation possibly throwing an error
51+type CompilerWrite = [Dependency]
80−type Throwing a = Either String a
83--------------------------------------------------------------------------------
54--------------------------------------------------------------------------------
84−-- | The compiler monad
55+data CompilerResult a where
85−newtype CompilerM a = CompilerM
56+ CompilerDone :: a -> CompilerWrite -> CompilerResult a
86− { unCompilerM :: ErrorT String (ReaderT CompilerEnvironment IO) a
57+ CompilerError :: String -> CompilerResult a
87− } deriving (Monad, Functor, Applicative)
58+ CompilerRequire :: Identifier b -> (b -> Compiler a) -> CompilerResult a
90--------------------------------------------------------------------------------
61--------------------------------------------------------------------------------
91−-- | The compiler arrow
92−data Compiler a b = Compiler
62+newtype Compiler a = Compiler
93− { compilerDependencies :: Reader DependencyEnvironment Dependencies
63+ { unCompiler :: CompilerRead -> IO (CompilerResult a)
94− , compilerJob :: a -> CompilerM b
98--------------------------------------------------------------------------------
67--------------------------------------------------------------------------------
99−instance Functor (Compiler a) where
68+instance Functor Compiler where
100− fmap f (Compiler d j) = Compiler d $ fmap f . j
69+ fmap f (Compiler c) = Compiler $ \r -> do
72+ CompilerDone x w -> CompilerDone (f x) w
73+ CompilerError e -> CompilerError e
74+ CompilerRequire i g -> CompilerRequire i (\x -> fmap f (g x))
101 {-# INLINE fmap #-}
75 {-# INLINE fmap #-}
104--------------------------------------------------------------------------------
78--------------------------------------------------------------------------------
105−instance Applicative (Compiler a) where
79+instance Monad Compiler where
106− pure = fromJob . const . return
80+ return x = Compiler $ \_ -> return $ CompilerDone x mempty
107− {-# INLINE pure #-}
81+ {-# INLINE return #-}
109− Compiler d1 j1 <*> Compiler d2 j2 =
83+ Compiler c >>= f = Compiler $ \r -> do
110− Compiler (liftM2 S.union d1 d2) $ \x -> j1 x <*> j2 x
84+ res <- c r
111− {-# INLINE (<*>) #-}
85+ case res of
112−
86+ CompilerDone x w -> do
113−
87+ res' <- unCompiler (f x) r
114−--------------------------------------------------------------------------------
88+ return $ case res' of
115−instance Alternative (Compiler a) where
89+ CompilerDone y w' -> CompilerDone y (w `mappend` w')
116− empty = fromJob $ const $ CompilerM $
90+ CompilerError e -> CompilerError e
117− throwError "Hakyll.Core.Compiler.Internal: empty alternative"
91+ CompilerRequire i g -> CompilerRequire i $ \z -> do
92+ compilerTell w -- Save dependencies!
119− Compiler d1 j1 <|> Compiler d2 j2 =
95+ CompilerError e -> return $ CompilerError e
120− Compiler (liftM2 S.union d1 d2) $ \x -> CompilerM $
96+ CompilerRequire i g -> return $ CompilerRequire i $ \z -> g z >>= f
121− catchError (unCompilerM $ j1 x) (\_ -> unCompilerM $ j2 x)
122− {-# INLINE (<|>) #-}
97+ {-# INLINE (>>=) #-}
125--------------------------------------------------------------------------------
100--------------------------------------------------------------------------------
126−instance Category Compiler where
101+instance Applicative Compiler where
127− id = Compiler (return S.empty) return
102+ pure x = return x
128− {-# INLINE id #-}
103+ {-# INLINE pure #-}
130− Compiler d1 j1 . Compiler d2 j2 =
105+ f <*> x = f >>= \f' -> fmap f' x
131− Compiler (liftM2 S.union d1 d2) (j1 <=< j2)
132− {-# INLINE (.) #-}
106+ {-# INLINE (<*>) #-}
135--------------------------------------------------------------------------------
109--------------------------------------------------------------------------------
136−instance Arrow Compiler where
110+instance Alternative Compiler where
137− arr f = fromJob (return . f)
111+ empty = compilerThrow "Hakyll.Core.Compiler.Internal: empty alternative"
138− {-# INLINE arr #-}
112+ x <|> y = compilerCatch x (\_ -> y)
140− first (Compiler d j) = Compiler d $ \(x, y) -> do
143− {-# INLINE first #-}
145− second (Compiler d j) = Compiler d $ \(x, y) -> do
148− {-# INLINE second #-}
113+ {-# INLINE (<|>) #-}
150− Compiler d1 j1 *** Compiler d2 j2 =
151− Compiler (liftM2 S.union d1 d2) $ \(x, y) -> do
155− {-# INLINE (***) #-}
157− Compiler d1 j1 &&& Compiler d2 j2 =
116+--------------------------------------------------------------------------------
158− Compiler (liftM2 S.union d1 d2) $ \x -> do
117+compilerAsk :: Compiler CompilerRead
159− y1 <- j1 x
118+compilerAsk = Compiler $ \r -> return $ CompilerDone r mempty
162− {-# INLINE (&&&) #-}
119+{-# INLINE compilerAsk #-}
165--------------------------------------------------------------------------------
122--------------------------------------------------------------------------------
166−instance ArrowChoice Compiler where
123+compilerTell :: [Dependency] -> Compiler ()
167− left (Compiler d j) = Compiler d $ \e -> case e of
124+compilerTell deps = Compiler $ \_ -> return $ CompilerDone () deps
168− Left l -> Left <$> j l
169− Right r -> Right <$> return r
172− Compiler d1 j1 ||| Compiler d2 j2 = Compiler (liftM2 S.union d1 d2) $
173− \e -> case e of Left x -> j1 x; Right y -> j2 y
174− {-# INLINE (|||) #-}
125+{-# INLINE compilerTell #-}
177--------------------------------------------------------------------------------
128--------------------------------------------------------------------------------
178−instance ArrowMap Compiler where
129+compilerThrow :: String -> Compiler a
179− mapA (Compiler d j) = Compiler d $ mapM j
130+compilerThrow e = Compiler $ \_ -> return $ CompilerError e
180− {-# INLINE mapA #-}
131+{-# INLINE compilerThrow #-}
183--------------------------------------------------------------------------------
134--------------------------------------------------------------------------------
184−-- | Run a compiler, yielding the resulting target
135+compilerCatch :: Compiler a -> (String -> Compiler a) -> Compiler a
185−runCompilerJob :: Compiler () a -- ^ Compiler to run
136+compilerCatch (Compiler x) f = Compiler $ \r -> do
186− -> Identifier () -- ^ Target identifier
137+ res <- x r
187− -> ResourceProvider -- ^ Resource provider
138+ case res of
188− -> [Identifier ()] -- ^ Universe
139+ CompilerError e -> unCompiler (f e) r
189− -> Routes -- ^ Route
140+ _ -> return res
190− -> Store -- ^ Store
141+{-# INLINE compilerCatch #-}
191− -> Bool -- ^ Was the resource modified?
192− -> Logger -- ^ Logger
193− -> IO (Throwing a) -- ^ Result
194−runCompilerJob compiler id' provider universe route store modified logger =
195− runReaderT (runErrorT $ unCompilerM $ compilerJob compiler ()) env
197− env = CompilerEnvironment
198− { compilerIdentifier = id'
199− , compilerResourceProvider = provider
200− , compilerUniverse = universe
201− , compilerRoutes = route
202− , compilerStore = store
203− , compilerResourceModified = modified
204− , compilerLogger = logger
208--------------------------------------------------------------------------------
145--------------------------------------------------------------------------------
209−runCompilerDependencies :: Compiler () a
146+-- | The compiler monad
210− -> Identifier ()
147+newtype CompilerM a = CompilerM
211− -> [Identifier ()]
148+ { unCompilerM :: ErrorT String (ReaderT CompilerEnvironment IO) a
212− -> Dependencies
149+ } deriving (Monad, Functor, Applicative)
213−runCompilerDependencies compiler identifier universe =
214− runReader (compilerDependencies compiler) env
216− env = DependencyEnvironment
217− { dependencyIdentifier = identifier
218− , dependencyUniverse = universe
222--------------------------------------------------------------------------------
152--------------------------------------------------------------------------------
223−fromJob :: (a -> CompilerM b) -> Compiler a b
153+-- | The compiler arrow
224−fromJob = Compiler $ return S.empty
154+data Compiler a = Compiler
225−{-# INLINE fromJob #-}
155+ { compilerDependencies :: Reader DependencyEnvironment Dependencies
156+ , compilerJob :: CompilerM a
228--------------------------------------------------------------------------------
160--------------------------------------------------------------------------------
229−fromDependencies :: (Identifier () -> [Identifier ()] -> [Identifier ()])
161+instance Functor Compiler where
230− -> Compiler b b
162+ fmap f (Compiler d j) = Compiler d $ fmap f j
231−fromDependencies collectDeps = flip Compiler return $ do
163+ {-# INLINE fmap #-}
232− DependencyEnvironment identifier universe <- ask
233− return $ S.fromList $ collectDeps identifier universe
236--------------------------------------------------------------------------------
166--------------------------------------------------------------------------------
237−-- | Wait until another compiler has finished before running this compiler
167+instance Applicative Compiler where
238−fromDependency :: Identifier a -> Compiler b b
168+ pure = fromJob . return
239−fromDependency = fromDependencies . const . const . return . castIdentifier
169+ {-# INLINE pure #-}
171+ Compiler d1 j1 <*> Compiler d2 j2 =
172+ Compiler (liftM2 S.union d1 d2) $ j1 <*> j2
173+ {-# INLINE (<*>) #-}