@@ -4,26 +4,32 @@
4module Hakyll.Core.Compiler
4module Hakyll.Core.Compiler
5 ( Dependencies
5 ( Dependencies
6 , CompilerM
6 , CompilerM
7− , Compiler
7+ , Compiler (..)
8 , runCompiler
8 , runCompiler
10− , requireAll
12+ -- , requireAll
11− , compileFromString
13+ -- , compileFromString
16+import Prelude hiding ((.), id)
14−import Control.Arrow (second)
17+import Control.Arrow (second, (>>>))
15import Control.Applicative (Applicative, (<$>))
18import Control.Applicative (Applicative, (<$>))
16import Control.Monad.State (State, modify, runState)
19import Control.Monad.State (State, modify, runState)
17import Control.Monad.Reader (ReaderT, ask, runReaderT)
20import Control.Monad.Reader (ReaderT, ask, runReaderT)
21+import Control.Monad.Trans (liftIO)
22+import Control.Monad ((<=<))
18import Data.Set (Set)
23import Data.Set (Set)
19import qualified Data.Set as S
24import qualified Data.Set as S
20−import Data.Typeable (Typeable)
25+import Control.Category (Category, (.), id)
26+import Control.Arrow (Arrow, arr, first)
21import Data.Binary (Binary)
28import Data.Binary (Binary)
29+import Data.Typeable (Typeable)
23import Hakyll.Core.Identifier
31import Hakyll.Core.Identifier
24import Hakyll.Core.Identifier.Pattern
32import Hakyll.Core.Identifier.Pattern
25−import Hakyll.Core.Target
26−import Hakyll.Core.Target.Internal
27import Hakyll.Core.CompiledItem
33import Hakyll.Core.CompiledItem
28import Hakyll.Core.Writable
34import Hakyll.Core.Writable
29import Hakyll.Core.ResourceProvider
35import Hakyll.Core.ResourceProvider
@@ -32,65 +38,92 @@ import Hakyll.Core.ResourceProvider
33type Dependencies = Set Identifier
39type Dependencies = Set Identifier
35−-- | Add one dependency
41+-- | A lookup with which we can get dependencies
37−addDependency :: Identifier -> CompilerM ()
43+type DependencyLookup = Identifier -> CompiledItem
38−addDependency dependency = CompilerM $ modify $ addDependency'
41− { compilerDependencies = S.insert dependency $ compilerDependencies x
44-- | Environment in which a compiler runs
45-- | Environment in which a compiler runs
46data CompilerEnvironment = CompilerEnvironment
47data CompilerEnvironment = CompilerEnvironment
47 { compilerIdentifier :: Identifier -- ^ Target identifier
48 { compilerIdentifier :: Identifier -- ^ Target identifier
48 , compilerResourceProvider :: ResourceProvider -- ^ Resource provider
49 , compilerResourceProvider :: ResourceProvider -- ^ Resource provider
49− }
50+ , compilerDependencyLookup :: DependencyLookup -- ^ Dependency lookup
51−-- | State carried along by a compiler
53−data CompilerState = CompilerState
54− { compilerDependencies :: Dependencies
57-- | The compiler monad
53-- | The compiler monad
59newtype CompilerM a = CompilerM
55newtype CompilerM a = CompilerM
60− { unCompilerM :: ReaderT CompilerEnvironment (State CompilerState) a
56+ { unCompilerM :: ReaderT CompilerEnvironment IO a
61 } deriving (Monad, Functor, Applicative)
57 } deriving (Monad, Functor, Applicative)
63−-- | Simplified type for a compiler generating a target (which covers most
59+-- | The compiler arrow
66−type Compiler a = CompilerM (TargetM a)
61+data Compiler a b = Compiler
62+ { -- TODO: Reader ResourceProvider Dependencies
63+ compilerDependencies :: Dependencies
64+ , compilerJob :: a -> CompilerM b
67+instance Category Compiler where
68+ id = Compiler S.empty return
69+ (Compiler d1 j1) . (Compiler d2 j2) =
70+ Compiler (d1 `S.union` d2) (j1 <=< j2)
72+instance Arrow Compiler where
73+ arr f = Compiler S.empty (return . f)
74+ first (Compiler d j) = Compiler d $ \(x, y) -> do
68-- | Run a compiler, yielding the resulting target and it's dependencies
78-- | Run a compiler, yielding the resulting target and it's dependencies
70−runCompiler :: Compiler a -> Identifier -> ResourceProvider
80+runCompiler :: Compiler () a
71− -> (TargetM a, Dependencies)
81+ -> Identifier
72−runCompiler compiler identifier provider = second compilerDependencies $
85+runCompiler compiler identifier provider lookup' =
73− runState (runReaderT (unCompilerM compiler) env) state
86+ runReaderT (unCompilerM $ compilerJob compiler ()) env
75− state = CompilerState S.empty
76 env = CompilerEnvironment
88 env = CompilerEnvironment
77 { compilerIdentifier = identifier
89 { compilerIdentifier = identifier
78 , compilerResourceProvider = provider
90 , compilerResourceProvider = provider
91+ , compilerDependencyLookup = lookup'
94+addDependency :: Identifier
96+addDependency id' = Compiler (S.singleton id') return
98+fromCompilerM :: (a -> CompilerM b)
100+fromCompilerM = Compiler S.empty
102+getIdentifier :: Compiler () Identifier
103+getIdentifier = fromCompilerM $ const $ CompilerM $
104+ compilerIdentifier <$> ask
106+getResourceString :: Compiler () String
107+getResourceString = getIdentifier >>> getResourceString'
109+ getResourceString' = fromCompilerM $ \id' -> CompilerM $ do
110+ provider <- compilerResourceProvider <$> ask
111+ liftIO $ resourceString provider id'
82-- | Require another target. Using this function ensures automatic handling of
113-- | Require another target. Using this function ensures automatic handling of
83-- dependencies
114-- dependencies
85require :: (Binary a, Typeable a, Writable a)
116require :: (Binary a, Typeable a, Writable a)
86 => Identifier
117 => Identifier
87− -> Compiler a
119+ -> Compiler b c
88−require identifier = do
89− addDependency identifier
120+require identifier f = addDependency identifier >>> fromCompilerM require'
90− return $ TargetM $ do
121+ where
91− lookup' <- targetDependencyLookup <$> ask
122+ require' x = CompilerM $ do
123+ lookup' <- compilerDependencyLookup <$> ask
92− return $ unCompiledItem $ lookup' identifier
124+ return $ f (unCompiledItem $ lookup' identifier) x
94-- | Require a number of targets. Using this function ensures automatic handling
127-- | Require a number of targets. Using this function ensures automatic handling
95-- of dependencies
128-- of dependencies
@@ -108,3 +141,4 @@ requireAll pattern = CompilerM $ do
108compileFromString :: (String -> TargetM a) -- ^ Function to create the target
141compileFromString :: (String -> TargetM a) -- ^ Function to create the target
109 -> Compiler a -- ^ Resulting compiler
142 -> Compiler a -- ^ Resulting compiler
110compileFromString = return . (getResourceString >>=)
143compileFromString = return . (getResourceString >>=)