    module GHC.Unit.Module.Stage ( ModuleStage(..)
                                 , allStages
                                 , nowAndFutureStages
                                 , onlyFutureStages
                                 , minStage
                                 , maxStage
                                 , zeroStage
                                 , decModuleStage
                                 , incModuleStage
                                 ) where

    import GHC.Prelude
    import GHC.Utils.Outputable

    {- Note [Stage vs Level]
    ~~~~~~~~~~~~~~~~~~~~~~~~

    Modules are compiled at a specific stage. Levels within a module are interpreted
    as offsets to the specific stage at which the module is being compiled.

    * A **level** is a typechecking concept. The type checker performs level checking
      to ensure that the evaluation can proceed in a well-staged manner.
    * A **stage** is an operational construct. The execution of the program happens
      in stages.

    GHC at the moment knows about two stages, a module is either compiled for
    compile time (*C*) or runtime (*R*), with *C* before *R*. Then:

    * The main module is compiled for `R`.

    * A normal import does not shift the stage at which the dependent module is required.

    * If a module `M` splice imports module `A`, then compiling `M` at stage
      *R* requires compiling module `A` at stage *C*.

    * If a module `N` quote imports module `B`, then compiling `N` at stage
      *C* requires compiling module `B` at stage *R*.

    The compiler can then choose appropiately how modules needed at `C` are compiled
    and how modules needed at `R` are compiled.

    For example:

    * In `-fno-code` mode, `C` modules may be compiled in dynamic way, but `R` modules
      are not compiled at all.
    * When using a profiled GHC. `C` modules must be compiled in profiled way but `R` modules
      will be compiled in static way.

    Further structure as needed by cross-compilation settings may require more stages.

    -}

    -- The order of these constructors is important for definitions such as
    -- 'futureStages'.
    data ModuleStage = CompileStage | RunStage deriving (ModuleStage -> ModuleStage -> Bool
    (ModuleStage -> ModuleStage -> Bool)
    -> (ModuleStage -> ModuleStage -> Bool) -> Eq ModuleStage
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: ModuleStage -> ModuleStage -> Bool
    == :: ModuleStage -> ModuleStage -> Bool
    $c/= :: ModuleStage -> ModuleStage -> Bool
    /= :: ModuleStage -> ModuleStage -> Bool
    Eq, Eq ModuleStage
    Eq ModuleStage =>
    (ModuleStage -> ModuleStage -> Ordering)
    -> (ModuleStage -> ModuleStage -> Bool)
    -> (ModuleStage -> ModuleStage -> Bool)
    -> (ModuleStage -> ModuleStage -> Bool)
    -> (ModuleStage -> ModuleStage -> Bool)
    -> (ModuleStage -> ModuleStage -> ModuleStage)
    -> (ModuleStage -> ModuleStage -> ModuleStage)
    -> Ord ModuleStage
    ModuleStage -> ModuleStage -> Bool
    ModuleStage -> ModuleStage -> Ordering
    ModuleStage -> ModuleStage -> ModuleStage
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: ModuleStage -> ModuleStage -> Ordering
    compare :: ModuleStage -> ModuleStage -> Ordering
    $c< :: ModuleStage -> ModuleStage -> Bool
    < :: ModuleStage -> ModuleStage -> Bool
    $c<= :: ModuleStage -> ModuleStage -> Bool
    <= :: ModuleStage -> ModuleStage -> Bool
    $c> :: ModuleStage -> ModuleStage -> Bool
    > :: ModuleStage -> ModuleStage -> Bool
    $c>= :: ModuleStage -> ModuleStage -> Bool
    >= :: ModuleStage -> ModuleStage -> Bool
    $cmax :: ModuleStage -> ModuleStage -> ModuleStage
    max :: ModuleStage -> ModuleStage -> ModuleStage
    $cmin :: ModuleStage -> ModuleStage -> ModuleStage
    min :: ModuleStage -> ModuleStage -> ModuleStage
    Ord, Int -> ModuleStage
    ModuleStage -> Int
    ModuleStage -> [ModuleStage]
    ModuleStage -> ModuleStage
    ModuleStage -> ModuleStage -> [ModuleStage]
    ModuleStage -> ModuleStage -> ModuleStage -> [ModuleStage]
    (ModuleStage -> ModuleStage)
    -> (ModuleStage -> ModuleStage)
    -> (Int -> ModuleStage)
    -> (ModuleStage -> Int)
    -> (ModuleStage -> [ModuleStage])
    -> (ModuleStage -> ModuleStage -> [ModuleStage])
    -> (ModuleStage -> ModuleStage -> [ModuleStage])
    -> (ModuleStage -> ModuleStage -> ModuleStage -> [ModuleStage])
    -> Enum ModuleStage
    forall a.
    (a -> a)
    -> (a -> a)
    -> (Int -> a)
    -> (a -> Int)
    -> (a -> [a])
    -> (a -> a -> [a])
    -> (a -> a -> [a])
    -> (a -> a -> a -> [a])
    -> Enum a
    $csucc :: ModuleStage -> ModuleStage
    succ :: ModuleStage -> ModuleStage
    $cpred :: ModuleStage -> ModuleStage
    pred :: ModuleStage -> ModuleStage
    $ctoEnum :: Int -> ModuleStage
    toEnum :: Int -> ModuleStage
    $cfromEnum :: ModuleStage -> Int
    fromEnum :: ModuleStage -> Int
    $cenumFrom :: ModuleStage -> [ModuleStage]
    enumFrom :: ModuleStage -> [ModuleStage]
    $cenumFromThen :: ModuleStage -> ModuleStage -> [ModuleStage]
    enumFromThen :: ModuleStage -> ModuleStage -> [ModuleStage]
    $cenumFromTo :: ModuleStage -> ModuleStage -> [ModuleStage]
    enumFromTo :: ModuleStage -> ModuleStage -> [ModuleStage]
    $cenumFromThenTo :: ModuleStage -> ModuleStage -> ModuleStage -> [ModuleStage]
    enumFromThenTo :: ModuleStage -> ModuleStage -> ModuleStage -> [ModuleStage]
    Enum, ModuleStage
    ModuleStage -> ModuleStage -> Bounded ModuleStage
    forall a. a -> a -> Bounded a
    $cminBound :: ModuleStage
    minBound :: ModuleStage
    $cmaxBound :: ModuleStage
    maxBound :: ModuleStage
    Bounded)

    allStages :: [ModuleStage]
    allStages :: [ModuleStage]
    allStages = [ModuleStage
    forall a. Bounded a => a
    minBound .. ModuleStage
    forall a. Bounded a => a
    maxBound]

    nowAndFutureStages :: ModuleStage -> [ModuleStage]
    nowAndFutureStages :: ModuleStage -> [ModuleStage]
    nowAndFutureStages ModuleStage
    cur_st = [ModuleStage
    cur_st .. ]

    onlyFutureStages :: ModuleStage -> [ModuleStage]
    onlyFutureStages :: ModuleStage -> [ModuleStage]
    onlyFutureStages ModuleStage
    cur_st | ModuleStage
    cur_st ModuleStage -> ModuleStage -> Bool
    forall a. Eq a => a -> a -> Bool
    == ModuleStage
    forall a. Bounded a => a
    maxBound = []
    onlyFutureStages ModuleStage
    cur_st = [ModuleStage -> ModuleStage
    forall a. Enum a => a -> a
    succ ModuleStage
    cur_st .. ]

    minStage :: ModuleStage
    minStage :: ModuleStage
    minStage = ModuleStage
    forall a. Bounded a => a
    minBound

    maxStage :: ModuleStage
    maxStage :: ModuleStage
    maxStage = ModuleStage
    forall a. Bounded a => a
    maxBound

    instance Outputable ModuleStage where
      ppr :: ModuleStage -> SDoc
    ppr ModuleStage
    CompileStage = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "compile"
      ppr ModuleStage
    RunStage = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "run"

    zeroStage :: ModuleStage
    zeroStage :: ModuleStage
    zeroStage = ModuleStage
    RunStage

    decModuleStage, incModuleStage :: ModuleStage -> ModuleStage
    incModuleStage :: ModuleStage -> ModuleStage
    incModuleStage ModuleStage
    RunStage = ModuleStage
    RunStage
    incModuleStage ModuleStage
    CompileStage = ModuleStage
    RunStage

    decModuleStage :: ModuleStage -> ModuleStage
    decModuleStage ModuleStage
    RunStage = ModuleStage
    CompileStage
    decModuleStage ModuleStage
    CompileStage = ModuleStage
    RunStage