<commit_before>-- | A Compiler manages targets and dependencies between targets.
--
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Hakyll.Core.Compiler
    ( Dependencies
    , CompilerM
    , Compiler
    , runCompiler
    , require
    , target
    , targetFromString
    ) 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
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

-- | Construct a target from a string, this string being the content of the
-- resource.
--
targetFromString :: (String -> TargetM a a)  -- ^ Function to create the target
                 -> Compiler a               -- ^ Resulting compiler
targetFromString = target . (getResourceString >>=)<commit_msg>Consistent naming: target vs compiler<commit_after>-- | A Compiler manages targets and dependencies between targets.
--
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Hakyll.Core.Compiler
    ( Dependencies
    , CompilerM
    , Compiler
    , runCompiler
    , require
    , compileFromString
    ) 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
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 from a string, this string being the content of the
-- resource.
--
compileFromString :: (String -> TargetM a a)  -- ^ Function to create the target
                  -> Compiler a               -- ^ Resulting compiler
compileFromString = return . (getResourceString >>=)
{'fraction_non_alphanumeric': 0.08693949481104367, 'fraction_numerical': 0.0, 'mean_word_length': 3.4186851211072664, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 24, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2105318', 'n_tokens_mistral': 1378, 'n_tokens_neox': 1338, 'n_words': 493}