summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJasper Van der Jeugt <jaspervdj@gmail.com>2010-12-25 18:15:44 +0100
committerJasper Van der Jeugt <jaspervdj@gmail.com>2010-12-25 18:15:44 +0100
commitc372fc47da1d29d6613b782d7c8974a2de5b13ff (patch)
tree042e3b62e1d1265e42dd566d39222b27eedf96b0 /src
parent12c446785c76130a65c46cc603e767893b4818b5 (diff)
downloadhakyll-c372fc47da1d29d6613b782d7c8974a2de5b13ff.tar.gz
Add Compiler module
Diffstat (limited to 'src')
-rw-r--r--src/Hakyll/Core/Compiler.hs80
-rw-r--r--src/Hakyll/Core/Target/Internal.hs1
2 files changed, 81 insertions, 0 deletions
diff --git a/src/Hakyll/Core/Compiler.hs b/src/Hakyll/Core/Compiler.hs
new file mode 100644
index 0000000..42598f6
--- /dev/null
+++ b/src/Hakyll/Core/Compiler.hs
@@ -0,0 +1,80 @@
+-- | A Compiler manages targets and dependencies between targets.
+--
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+module Hakyll.Core.Compiler
+ ( Dependencies
+ , CompilerM
+ , Compiler
+ , runCompiler
+ , require
+ , target
+ ) where
+
+import Control.Arrow (second)
+import Control.Applicative (Applicative, (<$>))
+import Control.Monad.State (State, modify, runState)
+import Control.Monad.Reader (ReaderT, ask, runReaderT)
+import Data.Set (Set)
+import qualified Data.Set as S
+
+import Hakyll.Core.Identifier
+import Hakyll.Core.Target.Internal
+
+-- | A set of dependencies
+--
+type Dependencies = Set Identifier
+
+-- | Add one dependency
+--
+addDependency :: Identifier -> CompilerM a ()
+addDependency dependency = CompilerM $ modify $ addDependency'
+ where
+ addDependency' x = x
+ { compilerDependencies = S.insert dependency $ compilerDependencies x
+ }
+
+-- | Environment in which a compiler runs
+--
+data CompilerEnvironment a = CompilerEnvironment
+ { compilerIdentifier :: Identifier -- ^ Target identifier
+ }
+
+-- | State carried along by a compiler
+--
+data CompilerState = CompilerState
+ { compilerDependencies :: Dependencies
+ }
+
+-- | The compiler monad
+--
+newtype CompilerM a b = CompilerM
+ { unCompilerM :: ReaderT (CompilerEnvironment a) (State CompilerState) b
+ } deriving (Monad, Functor, Applicative)
+
+-- | Simplified type for a compiler generating a target (which covers most
+-- cases)
+--
+type Compiler a = CompilerM a (TargetM a a)
+
+-- | Run a compiler, yielding the resulting target and it's dependencies
+--
+runCompiler :: Compiler a -> Identifier -> (TargetM a a, Dependencies)
+runCompiler compiler identifier = second compilerDependencies $
+ runState (runReaderT (unCompilerM compiler) env) state
+ where
+ env = CompilerEnvironment {compilerIdentifier = identifier}
+ state = CompilerState S.empty
+
+-- | Require another target. Using this function ensures automatic handling of
+-- dependencies
+--
+require :: Identifier
+ -> Compiler a
+require identifier = do
+ addDependency identifier
+ return $ TargetM $ flip targetDependencyLookup identifier <$> ask
+
+-- | Construct a target inside a compiler
+--
+target :: TargetM a a -> Compiler a
+target = return
diff --git a/src/Hakyll/Core/Target/Internal.hs b/src/Hakyll/Core/Target/Internal.hs
index a58f736..96e3087 100644
--- a/src/Hakyll/Core/Target/Internal.hs
+++ b/src/Hakyll/Core/Target/Internal.hs
@@ -3,6 +3,7 @@
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Hakyll.Core.Target.Internal
( DependencyLookup
+ , TargetEnvironment (..)
, TargetM (..)
, Target
, runTarget