on f104f91 help sign in
108 lines 3.5 kB history raw
1-- | Internally used compiler module
2--
3{-# LANGUAGE GeneralizedNewtypeDeriving #-}
4module Hakyll.Core.Compiler.Internal
5 ( Dependencies
6 , CompilerEnvironment (..)
7 , CompilerM (..)
8 , Compiler (..)
9 , runCompilerJob
10 , runCompilerDependencies
11 , fromJob
12 , fromDependencies
13 , fromDependency
14 ) where
16import Prelude hiding ((.), id)
17import Control.Applicative (Applicative, (<$>))
18import Control.Monad.Reader (ReaderT, Reader, ask, runReaderT, runReader)
19import Control.Monad ((<=<), liftM2)
20import Data.Set (Set)
21import qualified Data.Set as S
22import Control.Category (Category, (.), id)
23import Control.Arrow (Arrow, arr, first)
25import Hakyll.Core.Identifier
26import Hakyll.Core.ResourceProvider
27import Hakyll.Core.Store
29-- | A set of dependencies
30--
31type Dependencies = Set Identifier
33-- | Environment in which a compiler runs
34--
35data CompilerEnvironment = CompilerEnvironment
36 { -- | Target identifier
37 compilerIdentifier :: Identifier
38 , -- | Resource provider
39 compilerResourceProvider :: ResourceProvider
40 , -- | Site route
41 compilerRoute :: Maybe FilePath
42 , -- | Compiler store
43 compilerStore :: Store
44 , -- | Flag indicating if the underlying resource was modified
45 compilerResourceModified :: Bool
46 }
48-- | The compiler monad
49--
50newtype CompilerM a = CompilerM
51 { unCompilerM :: ReaderT CompilerEnvironment IO a
52 } deriving (Monad, Functor, Applicative)
54-- | The compiler arrow
55--
56data Compiler a b = Compiler
57 { compilerDependencies :: Reader ResourceProvider Dependencies
58 , compilerJob :: a -> CompilerM b
59 }
61instance Category Compiler where
62 id = Compiler (return S.empty) return
63 (Compiler d1 j1) . (Compiler d2 j2) =
64 Compiler (liftM2 S.union d1 d2) (j1 <=< j2)
66instance Arrow Compiler where
67 arr f = Compiler (return S.empty) (return . f)
68 first (Compiler d j) = Compiler d $ \(x, y) -> do
69 x' <- j x
70 return (x', y)
72-- | Run a compiler, yielding the resulting target and it's dependencies
73--
74runCompilerJob :: Compiler () a -- ^ Compiler to run
75 -> Identifier -- ^ Target identifier
76 -> ResourceProvider -- ^ Resource provider
77 -> Maybe FilePath -- ^ Route
78 -> Store -- ^ Store
79 -> Bool -- ^ Was the resource modified?
80 -> IO a
81runCompilerJob compiler identifier provider route store modified =
82 runReaderT (unCompilerM $ compilerJob compiler ()) env
83 where
84 env = CompilerEnvironment
85 { compilerIdentifier = identifier
86 , compilerResourceProvider = provider
87 , compilerRoute = route
88 , compilerStore = store
89 , compilerResourceModified = modified
90 }
92runCompilerDependencies :: Compiler () a
93 -> ResourceProvider
94 -> Dependencies
95runCompilerDependencies compiler = runReader (compilerDependencies compiler)
97fromJob :: (a -> CompilerM b)
98 -> Compiler a b
99fromJob = Compiler (return S.empty)
101fromDependencies :: (ResourceProvider -> [Identifier])
102 -> Compiler b b
103fromDependencies deps = Compiler (S.fromList . deps <$> ask) return
105-- | Wait until another compiler has finished before running this compiler
106--
107fromDependency :: Identifier -> Compiler a a
108fromDependency = fromDependencies . const . return