content: module Expression (
      -- * Expressions
      Expr, Predicate, Args, Ways,
  
      -- ** Construction and modification
      expr, exprIO, arg, remove,
  
      -- ** Predicates
      (?), stage, stage0, stage1, stage2, notStage0, package, notPackage,
      libraryPackage, builder, way, input, inputs, output, outputs,
  
      -- ** Evaluation
      interpret, interpretInContext,
  
      -- * Convenient accessors
      getBuildRoot, getContext, getOutputs, getInputs,
      getInput, getOutput, getContextData,
  
      -- * Re-exports
      module Base,
      module Builder,
      module Context,
      ) where
  
  import Base
  import Builder
  import Context hiding (stage, package, way)
  import Expression.Type
  import Hadrian.Expression hiding (Expr, Predicate, Args)
  import Hadrian.Haskell.Cabal.Type
  import Hadrian.Oracles.Cabal
  
  -- | Get values from a configured cabal stage.
  getContextData :: (ContextData -> a) -> Expr a
  getContextData key = do
      contextData <- expr . readContextData =<< getContext
      return $ key contextData
  
  -- | Is the build currently in the provided stage?
  stage :: Stage -> Predicate
  stage s = (s ==) <$> getStage
  
  -- | Is a particular package being built?
  package :: Package -> Predicate
  package p = (p ==) <$> getPackage
  
  -- | This type class allows the user to construct both precise builder
  -- predicates, such as @builder (Ghc CompileHs Stage1)@, as well as predicates
  -- covering a set of similar builders. For example, @builder (Ghc CompileHs)@
  -- matches any stage, and @builder Ghc@ matches any stage and any GHC mode.
  class BuilderPredicate a where
      -- | Is a particular builder being used?
      builder :: a -> Predicate
  
  instance BuilderPredicate Builder where
      builder b = (b ==) <$> getBuilder
  
  instance BuilderPredicate a => BuilderPredicate (Stage -> a) where
      builder f = builder . f =<< getStage
  
  instance BuilderPredicate a => BuilderPredicate (CcMode -> a) where
      builder f = do
          b <- getBuilder
          case b of
              Cc  c _ -> builder (f c)
              _       -> return False
  
  instance BuilderPredicate a => BuilderPredicate (GhcMode -> a) where
      builder f = do
          b <- getBuilder
          case b of
              Ghc c _ -> builder (f c)
              _       -> return False
  
  instance BuilderPredicate a => BuilderPredicate (FilePath -> a) where
      builder f = do
          b <- getBuilder
          case b of
              Configure path -> builder (f path)
              _              -> return False
  
  -- | Is the current build 'Way' equal to a certain value?
  way :: Way -> Predicate
  way w = (w ==) <$> getWay
  
  -- | Is the build currently in stage 0?
  stage0 :: Predicate
  stage0 = stage Stage0
  
  -- | Is the build currently in stage 1?
  stage1 :: Predicate
  stage1 = stage Stage1
  
  -- | Is the build currently in stage 2?
  stage2 :: Predicate
  stage2 = stage Stage2
  
  -- | Is the build /not/ in stage 0 right now?
  notStage0 :: Predicate
  notStage0 = notM stage0
  
  -- | Is a certain package /not/ built right now?
  notPackage :: Package -> Predicate
  notPackage = notM . package
  
  -- | Is a library package currently being built?
  libraryPackage :: Predicate
  libraryPackage = isLibrary <$> getPackage
  