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