    {-# LANGUAGE GADTs #-}
    {-# LANGUAGE RankNTypes #-}

    module GHC.Driver.Pipeline.Phases (TPhase(..), PhaseHook(..)) where

    import GHC.Prelude
    import GHC.Driver.Pipeline.Monad
    import GHC.Driver.Env.Types
    import GHC.Driver.DynFlags
    import GHC.Types.SourceFile
    import GHC.Unit.Module.ModSummary
    import GHC.Unit.Module.Status
    import GHC.Tc.Types ( FrontendResult )
    import GHC.Types.Error
    import GHC.Driver.Errors.Types
    import GHC.Fingerprint.Type
    import GHC.Unit.Module.Location ( ModLocation )
    import GHC.Unit.Module.ModIface
    import GHC.Driver.Phases

    import Language.Haskell.Syntax.Module.Name ( ModuleName )
    import GHC.Unit.Home.ModInfo

    -- Typed Pipeline Phases
    -- MP: TODO: We need to refine the arguments to each of these phases so recompilation
    -- can be smarter. For example, rather than passing a whole HscEnv, just pass the options
    -- which each phase depends on, then recompilation checking can decide to only rerun each
    -- phase if the inputs have been modified.
    data TPhase res where
      T_Unlit :: PipeEnv -> HscEnv -> FilePath -> TPhase FilePath
      T_FileArgs :: HscEnv -> FilePath -> TPhase (DynFlags, Messages PsMessage, Messages DriverMessage)
      T_Cpp   :: PipeEnv -> HscEnv -> FilePath -> TPhase FilePath
      T_HsPp  :: PipeEnv -> HscEnv -> FilePath -> FilePath -> TPhase FilePath
      T_HscRecomp :: PipeEnv -> HscEnv -> FilePath -> HscSource -> TPhase (HscEnv, ModSummary, HscRecompStatus)
      T_Hsc :: HscEnv -> ModSummary -> TPhase (FrontendResult, Messages GhcMessage)
      T_HscPostTc :: HscEnv -> ModSummary
                  -> FrontendResult
                  -> Messages GhcMessage
                  -> Maybe Fingerprint
                  -> TPhase HscBackendAction
      T_HscBackend :: PipeEnv -> HscEnv -> ModuleName -> HscSource -> ModLocation -> HscBackendAction -> TPhase ([FilePath], ModIface, HomeModLinkable, FilePath)
      T_CmmCpp :: PipeEnv -> HscEnv -> FilePath -> TPhase FilePath
      T_Cmm :: PipeEnv -> HscEnv -> FilePath -> TPhase ([FilePath], FilePath)
      T_Cc :: Phase -> PipeEnv -> HscEnv -> Maybe ModLocation -> FilePath -> TPhase FilePath
      T_As :: Bool -> PipeEnv -> HscEnv -> Maybe ModLocation -> FilePath -> TPhase FilePath
      T_Js :: PipeEnv -> HscEnv -> Maybe ModLocation -> FilePath -> TPhase FilePath
      T_ForeignJs :: PipeEnv -> HscEnv -> Maybe ModLocation -> FilePath -> TPhase FilePath
      T_LlvmOpt :: PipeEnv -> HscEnv -> FilePath -> TPhase FilePath
      T_LlvmLlc :: PipeEnv -> HscEnv -> FilePath -> TPhase FilePath
      T_LlvmAs :: Bool -> PipeEnv -> HscEnv -> Maybe ModLocation -> FilePath -> TPhase FilePath
      T_LlvmMangle :: PipeEnv -> HscEnv -> FilePath -> TPhase FilePath
      T_MergeForeign :: PipeEnv -> HscEnv -> FilePath -> [FilePath] -> TPhase FilePath

    -- | A wrapper around the interpretation function for phases.
    data PhaseHook = PhaseHook (forall a . TPhase a -> IO a)