    -- |
    -- Module      :  Cryptol.ModuleSystem.Env
    -- Copyright   :  (c) 2013-2016 Galois, Inc.
    -- License     :  BSD3
    -- Maintainer  :  cryptol@galois.com
    -- Stability   :  provisional
    -- Portability :  portable

    {-# LANGUAGE CPP #-}
    {-# LANGUAGE DeriveAnyClass #-}
    {-# LANGUAGE DeriveGeneric #-}
    {-# LANGUAGE PatternGuards #-}
    {-# LANGUAGE RecordWildCards #-}
    module Cryptol.ModuleSystem.Env where

    #ifndef RELOCATABLE
    import Paths_cryptol (getDataDir)
    #endif

    import Cryptol.Eval (EvalEnv)
    import Cryptol.ModuleSystem.Fingerprint
    import Cryptol.ModuleSystem.Interface
    import Cryptol.ModuleSystem.Name (Supply,emptySupply)
    import qualified Cryptol.ModuleSystem.NamingEnv as R
    import Cryptol.Parser.AST
    import qualified Cryptol.TypeCheck as T
    import qualified Cryptol.TypeCheck.AST as T
    import Cryptol.Utils.PP (PP(..),text,parens,NameDisp)

    import Data.ByteString(ByteString)
    import Control.Monad (guard,mplus)
    import qualified Control.Exception as X
    import Data.Function (on)
    import qualified Data.Map as Map
    import Data.Maybe(fromMaybe)
    import Data.Semigroup
    import System.Directory (getAppUserDataDirectory, getCurrentDirectory)
    import System.Environment(getExecutablePath)
    import System.FilePath ((</>), normalise, joinPath, splitPath, takeDirectory)
    import qualified Data.List as List

    import GHC.Generics (Generic)
    import Control.DeepSeq

    import Prelude ()
    import Prelude.Compat

    -- Module Environment ----------------------------------------------------------

    -- | This is the current state of the interpreter.
    data ModuleEnv = ModuleEnv
      { ModuleEnv -> LoadedModules
    meLoadedModules :: LoadedModules
        -- ^ Information about all loaded modules.  See 'LoadedModule'.
        -- Contains information such as the file where the module was loaded
        -- from, as well as the module's interface, used for type checking.

      , ModuleEnv -> NameSeeds
    meNameSeeds     :: T.NameSeeds
        -- ^ A source of new names for the type checker.

      , ModuleEnv -> SolverConfig
    meSolverConfig  :: T.SolverConfig
        -- ^ Configuration settings for the SMT solver used for type-checking.

      , ModuleEnv -> EvalEnv
    meEvalEnv       :: EvalEnv
        -- ^ The evaluation environment.  Contains the values for all loaded
        -- modules, both public and private.

      , ModuleEnv -> CoreLint
    meCoreLint      :: CoreLint
        -- ^ Should we run the linter to ensure sanity.

      , ModuleEnv -> Bool
    meMonoBinds     :: !Bool
        -- ^ Are we assuming that local bindings are monomorphic.
        -- XXX: We should probably remove this flag, and set it to 'True'.

      , ModuleEnv -> Maybe ModName
    meFocusedModule :: Maybe ModName
        -- ^ The "current" module.  Used to decide how to print names, for example.

      , ModuleEnv -> [FilePath]
    meSearchPath    :: [FilePath]
        -- ^ Where we look for things.

      , ModuleEnv -> DynamicEnv
    meDynEnv        :: DynamicEnv
        -- ^ This contains additional definitions that were made at the command
        -- line, and so they don't reside in any module.

      , ModuleEnv -> Supply
    meSupply        :: !Supply
        -- ^ Name source for the renamer

      } deriving (forall x. ModuleEnv -> Rep ModuleEnv x)
    -> (forall x. Rep ModuleEnv x -> ModuleEnv) -> Generic ModuleEnv
    forall x. Rep ModuleEnv x -> ModuleEnv
    forall x. ModuleEnv -> Rep ModuleEnv x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cto :: forall x. Rep ModuleEnv x -> ModuleEnv
    $cfrom :: forall x. ModuleEnv -> Rep ModuleEnv x
    Generic

    instance NFData ModuleEnv

    -- | Should we run the linter?
    data CoreLint = NoCoreLint        -- ^ Don't run core lint
                  | CoreLint          -- ^ Run core lint
      deriving ((forall x. CoreLint -> Rep CoreLint x)
    -> (forall x. Rep CoreLint x -> CoreLint) -> Generic CoreLint
    forall x. Rep CoreLint x -> CoreLint
    forall x. CoreLint -> Rep CoreLint x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cto :: forall x. Rep CoreLint x -> CoreLint
    $cfrom :: forall x. CoreLint -> Rep CoreLint x
    Generic, CoreLint -> ()
    (CoreLint -> ()) -> NFData CoreLint
    forall a. (a -> ()) -> NFData a
    rnf :: CoreLint -> ()
    $crnf :: CoreLint -> ()
    NFData)

    resetModuleEnv :: ModuleEnv -> ModuleEnv
    resetModuleEnv :: ModuleEnv -> ModuleEnv
    resetModuleEnv env :: ModuleEnv
    env = ModuleEnv
    env
      { meLoadedModules :: LoadedModules
    meLoadedModules = LoadedModules
    forall a. Monoid a => a
    mempty
      , meNameSeeds :: NameSeeds
    meNameSeeds     = NameSeeds
    T.nameSeeds
      , meEvalEnv :: EvalEnv
    meEvalEnv       = EvalEnv
    forall a. Monoid a => a
    mempty
      , meFocusedModule :: Maybe ModName
    meFocusedModule = Maybe ModName
    forall a. Maybe a
    Nothing
      , meDynEnv :: DynamicEnv
    meDynEnv        = DynamicEnv
    forall a. Monoid a => a
    mempty
      }

    initialModuleEnv :: IO ModuleEnv
    initialModuleEnv :: IO ModuleEnv
    initialModuleEnv = do
      FilePath
    curDir <- IO FilePath
    getCurrentDirectory
    #ifndef RELOCATABLE
      dataDir <- getDataDir
    #endif
      FilePath
    binDir <- FilePath -> FilePath
    takeDirectory (FilePath -> FilePath) -> IO FilePath -> IO FilePath
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    `fmap` IO FilePath
    getExecutablePath
      let instDir :: FilePath
    instDir = FilePath -> FilePath
    normalise (FilePath -> FilePath)
    -> (FilePath -> FilePath) -> FilePath -> FilePath
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [FilePath] -> FilePath
    joinPath ([FilePath] -> FilePath)
    -> (FilePath -> [FilePath]) -> FilePath -> FilePath
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [FilePath] -> [FilePath]
    forall a. [a] -> [a]
    init ([FilePath] -> [FilePath])
    -> (FilePath -> [FilePath]) -> FilePath -> [FilePath]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FilePath -> [FilePath]
    splitPath (FilePath -> FilePath) -> FilePath -> FilePath
    forall a b. (a -> b) -> a -> b
    $ FilePath
    binDir
      -- looking up this directory can fail if no HOME is set, as in some
      -- CI settings
      let handle :: X.IOException -> IO String
          handle :: IOException -> IO FilePath
    handle _e :: IOException
    _e = FilePath -> IO FilePath
    forall (m :: * -> *) a. Monad m => a -> m a
    return ""
      FilePath
    userDir <- IO FilePath -> (IOException -> IO FilePath) -> IO FilePath
    forall e a. Exception e => IO a -> (e -> IO a) -> IO a
    X.catch (FilePath -> IO FilePath
    getAppUserDataDirectory "cryptol") IOException -> IO FilePath
    handle
      let searchPath :: [FilePath]
    searchPath = [ FilePath
    curDir
                       -- something like $HOME/.cryptol
                       , FilePath
    userDir
    #if defined(mingw32_HOST_OS) || defined(__MINGW32__)
                       -- ../cryptol on win32
                       , instDir </> "cryptol"
    #else
                       -- ../share/cryptol on others
                       , FilePath
    instDir FilePath -> FilePath -> FilePath
    </> "share" FilePath -> FilePath -> FilePath
    </> "cryptol"
    #endif

    #ifndef RELOCATABLE
                       -- Cabal-defined data directory. Since this
                       -- is usually a global location like
                       -- /usr/local, search this one last in case
                       -- someone has multiple Cryptols
                       , dataDir
    #endif
                       ]

      ModuleEnv -> IO ModuleEnv
    forall (m :: * -> *) a. Monad m => a -> m a
    return $WModuleEnv :: LoadedModules
    -> NameSeeds
    -> SolverConfig
    -> EvalEnv
    -> CoreLint
    -> Bool
    -> Maybe ModName
    -> [FilePath]
    -> DynamicEnv
    -> Supply
    -> ModuleEnv
    ModuleEnv
        { meLoadedModules :: LoadedModules
    meLoadedModules = LoadedModules
    forall a. Monoid a => a
    mempty
        , meNameSeeds :: NameSeeds
    meNameSeeds     = NameSeeds
    T.nameSeeds
        , meEvalEnv :: EvalEnv
    meEvalEnv       = EvalEnv
    forall a. Monoid a => a
    mempty
        , meFocusedModule :: Maybe ModName
    meFocusedModule = Maybe ModName
    forall a. Maybe a
    Nothing
          -- we search these in order, taking the first match
        , meSearchPath :: [FilePath]
    meSearchPath    = [FilePath]
    searchPath
        , meDynEnv :: DynamicEnv
    meDynEnv        = DynamicEnv
    forall a. Monoid a => a
    mempty
        , meMonoBinds :: Bool
    meMonoBinds     = Bool
    True
        , meSolverConfig :: SolverConfig
    meSolverConfig  = SolverConfig :: FilePath -> [FilePath] -> Int -> [FilePath] -> SolverConfig
    T.SolverConfig
                              { solverPath :: FilePath
    T.solverPath = "z3"
                              , solverArgs :: [FilePath]
    T.solverArgs = [ "-smt2", "-in" ]
                              , solverVerbose :: Int
    T.solverVerbose = 0
                              , solverPreludePath :: [FilePath]
    T.solverPreludePath = [FilePath]
    searchPath
                              }
        , meCoreLint :: CoreLint
    meCoreLint      = CoreLint
    NoCoreLint
        , meSupply :: Supply
    meSupply        = Supply
    emptySupply
        }

    -- | Try to focus a loaded module in the module environment.
    focusModule :: ModName -> ModuleEnv -> Maybe ModuleEnv
    focusModule :: ModName -> ModuleEnv -> Maybe ModuleEnv
    focusModule n :: ModName
    n me :: ModuleEnv
    me = do
      Bool -> Maybe ()
    forall (f :: * -> *). Alternative f => Bool -> f ()
    guard (ModName -> LoadedModules -> Bool
    isLoaded ModName
    n (ModuleEnv -> LoadedModules
    meLoadedModules ModuleEnv
    me))
      ModuleEnv -> Maybe ModuleEnv
    forall (m :: * -> *) a. Monad m => a -> m a
    return ModuleEnv
    me { meFocusedModule :: Maybe ModName
    meFocusedModule = ModName -> Maybe ModName
    forall a. a -> Maybe a
    Just ModName
    n }

    -- | Get a list of all the loaded modules. Each module in the
    -- resulting list depends only on other modules that precede it.
    -- Note that this includes parameterized modules.
    loadedModules :: ModuleEnv -> [T.Module]
    loadedModules :: ModuleEnv -> [Module]
    loadedModules = (LoadedModule -> Module) -> [LoadedModule] -> [Module]
    forall a b. (a -> b) -> [a] -> [b]
    map LoadedModule -> Module
    lmModule ([LoadedModule] -> [Module])
    -> (ModuleEnv -> [LoadedModule]) -> ModuleEnv -> [Module]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . LoadedModules -> [LoadedModule]
    getLoadedModules (LoadedModules -> [LoadedModule])
    -> (ModuleEnv -> LoadedModules) -> ModuleEnv -> [LoadedModule]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ModuleEnv -> LoadedModules
    meLoadedModules

    -- | Get a list of all the loaded non-parameterized modules.
    -- These are the modules that can be used for evaluation, proving etc.
    loadedNonParamModules :: ModuleEnv -> [T.Module]
    loadedNonParamModules :: ModuleEnv -> [Module]
    loadedNonParamModules = (LoadedModule -> Module) -> [LoadedModule] -> [Module]
    forall a b. (a -> b) -> [a] -> [b]
    map LoadedModule -> Module
    lmModule ([LoadedModule] -> [Module])
    -> (ModuleEnv -> [LoadedModule]) -> ModuleEnv -> [Module]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . LoadedModules -> [LoadedModule]
    lmLoadedModules (LoadedModules -> [LoadedModule])
    -> (ModuleEnv -> LoadedModules) -> ModuleEnv -> [LoadedModule]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ModuleEnv -> LoadedModules
    meLoadedModules

    -- | Are any parameterized modules loaded?
    hasParamModules :: ModuleEnv -> Bool
    hasParamModules :: ModuleEnv -> Bool
    hasParamModules = Bool -> Bool
    not (Bool -> Bool) -> (ModuleEnv -> Bool) -> ModuleEnv -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [LoadedModule] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null ([LoadedModule] -> Bool)
    -> (ModuleEnv -> [LoadedModule]) -> ModuleEnv -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . LoadedModules -> [LoadedModule]
    lmLoadedParamModules (LoadedModules -> [LoadedModule])
    -> (ModuleEnv -> LoadedModules) -> ModuleEnv -> [LoadedModule]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ModuleEnv -> LoadedModules
    meLoadedModules

    -- | Produce an ifaceDecls that represents the focused environment of the module
    -- system, as well as a 'NameDisp' for pretty-printing names according to the
    -- imports.
    --
    -- XXX This could really do with some better error handling, just returning
    -- mempty when one of the imports fails isn't really desirable.
    --
    -- XXX: This is not quite right.   For example, it does not take into
    -- account *how* things were imported in a module (e.g., qualified).
    -- It would be simpler to simply store the naming environment that was
    -- actually used when we renamed the module.
    focusedEnv :: ModuleEnv -> (IfaceParams,IfaceDecls,R.NamingEnv,NameDisp)
    focusedEnv :: ModuleEnv -> (IfaceParams, IfaceDecls, NamingEnv, NameDisp)
    focusedEnv me :: ModuleEnv
    me =
      (IfaceParams, IfaceDecls, NamingEnv, NameDisp)
    -> Maybe (IfaceParams, IfaceDecls, NamingEnv, NameDisp)
    -> (IfaceParams, IfaceDecls, NamingEnv, NameDisp)
    forall a. a -> Maybe a -> a
    fromMaybe (IfaceParams
    noIfaceParams, IfaceDecls
    forall a. Monoid a => a
    mempty, NamingEnv
    forall a. Monoid a => a
    mempty, NameDisp
    forall a. Monoid a => a
    mempty) (Maybe (IfaceParams, IfaceDecls, NamingEnv, NameDisp)
     -> (IfaceParams, IfaceDecls, NamingEnv, NameDisp))
    -> Maybe (IfaceParams, IfaceDecls, NamingEnv, NameDisp)
    -> (IfaceParams, IfaceDecls, NamingEnv, NameDisp)
    forall a b. (a -> b) -> a -> b
    $
      do ModName
    fm   <- ModuleEnv -> Maybe ModName
    meFocusedModule ModuleEnv
    me
         LoadedModule
    lm   <- ModName -> ModuleEnv -> Maybe LoadedModule
    lookupModule ModName
    fm ModuleEnv
    me
         [(IfaceDecls, NamingEnv)]
    deps <- (Import -> Maybe (IfaceDecls, NamingEnv))
    -> [Import] -> Maybe [(IfaceDecls, NamingEnv)]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    mapM Import -> Maybe (IfaceDecls, NamingEnv)
    loadImport (Module -> [Import]
    T.mImports (LoadedModule -> Module
    lmModule LoadedModule
    lm))
         let (ifaces :: [IfaceDecls]
    ifaces,names :: [NamingEnv]
    names) = [(IfaceDecls, NamingEnv)] -> ([IfaceDecls], [NamingEnv])
    forall a b. [(a, b)] -> ([a], [b])
    unzip [(IfaceDecls, NamingEnv)]
    deps
             Iface { .. }   = LoadedModule -> Iface
    lmInterface LoadedModule
    lm
             localDecls :: IfaceDecls
    localDecls     = IfaceDecls
    ifPublic IfaceDecls -> IfaceDecls -> IfaceDecls
    forall a. Monoid a => a -> a -> a
    `mappend` IfaceDecls
    ifPrivate
             localNames :: NamingEnv
    localNames     = IfaceDecls -> NamingEnv
    R.unqualifiedEnv IfaceDecls
    localDecls NamingEnv -> NamingEnv -> NamingEnv
    forall a. Monoid a => a -> a -> a
    `mappend`
                                                  IfaceParams -> NamingEnv
    R.modParamsNamingEnv IfaceParams
    ifParams
             namingEnv :: NamingEnv
    namingEnv      = NamingEnv
    localNames NamingEnv -> NamingEnv -> NamingEnv
    `R.shadowing` [NamingEnv] -> NamingEnv
    forall a. Monoid a => [a] -> a
    mconcat [NamingEnv]
    names

         (IfaceParams, IfaceDecls, NamingEnv, NameDisp)
    -> Maybe (IfaceParams, IfaceDecls, NamingEnv, NameDisp)
    forall (m :: * -> *) a. Monad m => a -> m a
    return ( IfaceParams
    ifParams
                , [IfaceDecls] -> IfaceDecls
    forall a. Monoid a => [a] -> a
    mconcat (IfaceDecls
    localDeclsIfaceDecls -> [IfaceDecls] -> [IfaceDecls]
    forall a. a -> [a] -> [a]
    :[IfaceDecls]
    ifaces)
                , NamingEnv
    namingEnv
                , NamingEnv -> NameDisp
    R.toNameDisp NamingEnv
    namingEnv)
      where
      loadImport :: Import -> Maybe (IfaceDecls, NamingEnv)
    loadImport imp :: Import
    imp =
        do LoadedModule
    lm <- ModName -> ModuleEnv -> Maybe LoadedModule
    lookupModule (Import -> ModName
    iModule Import
    imp) ModuleEnv
    me
           let decls :: IfaceDecls
    decls = Iface -> IfaceDecls
    ifPublic (LoadedModule -> Iface
    lmInterface LoadedModule
    lm)
           (IfaceDecls, NamingEnv) -> Maybe (IfaceDecls, NamingEnv)
    forall (m :: * -> *) a. Monad m => a -> m a
    return (IfaceDecls
    decls,Import -> IfaceDecls -> NamingEnv
    R.interpImport Import
    imp IfaceDecls
    decls)

    -- | The unqualified declarations and name environment for the dynamic
    -- environment.
    dynamicEnv :: ModuleEnv -> (IfaceDecls,R.NamingEnv,NameDisp)
    dynamicEnv :: ModuleEnv -> (IfaceDecls, NamingEnv, NameDisp)
    dynamicEnv me :: ModuleEnv
    me = (IfaceDecls
    decls,NamingEnv
    names,NamingEnv -> NameDisp
    R.toNameDisp NamingEnv
    names)
      where
      decls :: IfaceDecls
    decls = DynamicEnv -> IfaceDecls
    deIfaceDecls (ModuleEnv -> DynamicEnv
    meDynEnv ModuleEnv
    me)
      names :: NamingEnv
    names = IfaceDecls -> NamingEnv
    R.unqualifiedEnv IfaceDecls
    decls

    -- Loaded Modules --------------------------------------------------------------

    -- | The location of a module
    data ModulePath = InFile FilePath
                    | InMem String ByteString -- ^ Label, content
        deriving (Int -> ModulePath -> FilePath -> FilePath
    [ModulePath] -> FilePath -> FilePath
    ModulePath -> FilePath
    (Int -> ModulePath -> FilePath -> FilePath)
    -> (ModulePath -> FilePath)
    -> ([ModulePath] -> FilePath -> FilePath)
    -> Show ModulePath
    forall a.
    (Int -> a -> FilePath -> FilePath)
    -> (a -> FilePath) -> ([a] -> FilePath -> FilePath) -> Show a
    showList :: [ModulePath] -> FilePath -> FilePath
    $cshowList :: [ModulePath] -> FilePath -> FilePath
    show :: ModulePath -> FilePath
    $cshow :: ModulePath -> FilePath
    showsPrec :: Int -> ModulePath -> FilePath -> FilePath
    $cshowsPrec :: Int -> ModulePath -> FilePath -> FilePath
    Show, (forall x. ModulePath -> Rep ModulePath x)
    -> (forall x. Rep ModulePath x -> ModulePath) -> Generic ModulePath
    forall x. Rep ModulePath x -> ModulePath
    forall x. ModulePath -> Rep ModulePath x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cto :: forall x. Rep ModulePath x -> ModulePath
    $cfrom :: forall x. ModulePath -> Rep ModulePath x
    Generic, ModulePath -> ()
    (ModulePath -> ()) -> NFData ModulePath
    forall a. (a -> ()) -> NFData a
    rnf :: ModulePath -> ()
    $crnf :: ModulePath -> ()
    NFData)

    -- | In-memory things are compared by label.
    instance Eq ModulePath where
      p1 :: ModulePath
    p1 == :: ModulePath -> ModulePath -> Bool
    == p2 :: ModulePath
    p2 =
        case (ModulePath
    p1,ModulePath
    p2) of
          (InFile x :: FilePath
    x, InFile y :: FilePath
    y) -> FilePath
    x FilePath -> FilePath -> Bool
    forall a. Eq a => a -> a -> Bool
    == FilePath
    y
          (InMem a :: FilePath
    a _, InMem b :: FilePath
    b _) -> FilePath
    a FilePath -> FilePath -> Bool
    forall a. Eq a => a -> a -> Bool
    == FilePath
    b
          _ -> Bool
    False

    instance PP ModulePath where
      ppPrec :: Int -> ModulePath -> Doc
    ppPrec _ e :: ModulePath
    e =
        case ModulePath
    e of
          InFile p :: FilePath
    p  -> FilePath -> Doc
    text FilePath
    p
          InMem l :: FilePath
    l _ -> Doc -> Doc
    parens (FilePath -> Doc
    text FilePath
    l)

    -- | The name of the content---either the file path, or the provided label.
    modulePathLabel :: ModulePath -> String
    modulePathLabel :: ModulePath -> FilePath
    modulePathLabel p :: ModulePath
    p =
      case ModulePath
    p of
        InFile path :: FilePath
    path -> FilePath
    path
        InMem lab :: FilePath
    lab _ -> FilePath
    lab

    data LoadedModules = LoadedModules
      { LoadedModules -> [LoadedModule]
    lmLoadedModules      :: [LoadedModule]
        -- ^ Invariants:
        -- 1) All the dependencies of any module `m` must precede `m` in the list.
        -- 2) Does not contain any parameterized modules.

      , LoadedModules -> [LoadedModule]
    lmLoadedParamModules :: [LoadedModule]
        -- ^ Loaded parameterized modules.

      } deriving (Int -> LoadedModules -> FilePath -> FilePath
    [LoadedModules] -> FilePath -> FilePath
    LoadedModules -> FilePath
    (Int -> LoadedModules -> FilePath -> FilePath)
    -> (LoadedModules -> FilePath)
    -> ([LoadedModules] -> FilePath -> FilePath)
    -> Show LoadedModules
    forall a.
    (Int -> a -> FilePath -> FilePath)
    -> (a -> FilePath) -> ([a] -> FilePath -> FilePath) -> Show a
    showList :: [LoadedModules] -> FilePath -> FilePath
    $cshowList :: [LoadedModules] -> FilePath -> FilePath
    show :: LoadedModules -> FilePath
    $cshow :: LoadedModules -> FilePath
    showsPrec :: Int -> LoadedModules -> FilePath -> FilePath
    $cshowsPrec :: Int -> LoadedModules -> FilePath -> FilePath
    Show, (forall x. LoadedModules -> Rep LoadedModules x)
    -> (forall x. Rep LoadedModules x -> LoadedModules)
    -> Generic LoadedModules
    forall x. Rep LoadedModules x -> LoadedModules
    forall x. LoadedModules -> Rep LoadedModules x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cto :: forall x. Rep LoadedModules x -> LoadedModules
    $cfrom :: forall x. LoadedModules -> Rep LoadedModules x
    Generic, LoadedModules -> ()
    (LoadedModules -> ()) -> NFData LoadedModules
    forall a. (a -> ()) -> NFData a
    rnf :: LoadedModules -> ()
    $crnf :: LoadedModules -> ()
    NFData)

    getLoadedModules :: LoadedModules -> [LoadedModule]
    getLoadedModules :: LoadedModules -> [LoadedModule]
    getLoadedModules x :: LoadedModules
    x = LoadedModules -> [LoadedModule]
    lmLoadedParamModules LoadedModules
    x [LoadedModule] -> [LoadedModule] -> [LoadedModule]
    forall a. [a] -> [a] -> [a]
    ++ LoadedModules -> [LoadedModule]
    lmLoadedModules LoadedModules
    x

    instance Semigroup LoadedModules where
      l :: LoadedModules
    l <> :: LoadedModules -> LoadedModules -> LoadedModules
    <> r :: LoadedModules
    r = LoadedModules :: [LoadedModule] -> [LoadedModule] -> LoadedModules
    LoadedModules
        { lmLoadedModules :: [LoadedModule]
    lmLoadedModules = (LoadedModule -> LoadedModule -> Bool)
    -> [LoadedModule] -> [LoadedModule] -> [LoadedModule]
    forall a. (a -> a -> Bool) -> [a] -> [a] -> [a]
    List.unionBy (ModName -> ModName -> Bool
    forall a. Eq a => a -> a -> Bool
    (==) (ModName -> ModName -> Bool)
    -> (LoadedModule -> ModName)
    -> LoadedModule
    -> LoadedModule
    -> Bool
    forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
    `on` LoadedModule -> ModName
    lmName)
                                          (LoadedModules -> [LoadedModule]
    lmLoadedModules LoadedModules
    l) (LoadedModules -> [LoadedModule]
    lmLoadedModules LoadedModules
    r)
        , lmLoadedParamModules :: [LoadedModule]
    lmLoadedParamModules = LoadedModules -> [LoadedModule]
    lmLoadedParamModules LoadedModules
    l [LoadedModule] -> [LoadedModule] -> [LoadedModule]
    forall a. [a] -> [a] -> [a]
    ++ LoadedModules -> [LoadedModule]
    lmLoadedParamModules LoadedModules
    r }

    instance Monoid LoadedModules where
      mempty :: LoadedModules
    mempty = LoadedModules :: [LoadedModule] -> [LoadedModule] -> LoadedModules
    LoadedModules { lmLoadedModules :: [LoadedModule]
    lmLoadedModules = []
                             , lmLoadedParamModules :: [LoadedModule]
    lmLoadedParamModules = []
                             }
      mappend :: LoadedModules -> LoadedModules -> LoadedModules
    mappend l :: LoadedModules
    l r :: LoadedModules
    r = LoadedModules
    l LoadedModules -> LoadedModules -> LoadedModules
    forall a. Semigroup a => a -> a -> a
    <> LoadedModules
    r

    data LoadedModule = LoadedModule
      { LoadedModule -> ModName
    lmName              :: ModName
      , LoadedModule -> ModulePath
    lmFilePath          :: ModulePath
        -- ^ The file path used to load this module (may not be canonical)
      , LoadedModule -> FilePath
    lmModuleId          :: String
        -- ^ An identifier used to identify the source of the bytes for the module.
        -- For files we just use the cononical path, for in memory things we
        -- use their label.
      , LoadedModule -> Iface
    lmInterface         :: Iface
      , LoadedModule -> Module
    lmModule            :: T.Module
      , LoadedModule -> Fingerprint
    lmFingerprint       :: Fingerprint
      } deriving (Int -> LoadedModule -> FilePath -> FilePath
    [LoadedModule] -> FilePath -> FilePath
    LoadedModule -> FilePath
    (Int -> LoadedModule -> FilePath -> FilePath)
    -> (LoadedModule -> FilePath)
    -> ([LoadedModule] -> FilePath -> FilePath)
    -> Show LoadedModule
    forall a.
    (Int -> a -> FilePath -> FilePath)
    -> (a -> FilePath) -> ([a] -> FilePath -> FilePath) -> Show a
    showList :: [LoadedModule] -> FilePath -> FilePath
    $cshowList :: [LoadedModule] -> FilePath -> FilePath
    show :: LoadedModule -> FilePath
    $cshow :: LoadedModule -> FilePath
    showsPrec :: Int -> LoadedModule -> FilePath -> FilePath
    $cshowsPrec :: Int -> LoadedModule -> FilePath -> FilePath
    Show, (forall x. LoadedModule -> Rep LoadedModule x)
    -> (forall x. Rep LoadedModule x -> LoadedModule)
    -> Generic LoadedModule
    forall x. Rep LoadedModule x -> LoadedModule
    forall x. LoadedModule -> Rep LoadedModule x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cto :: forall x. Rep LoadedModule x -> LoadedModule
    $cfrom :: forall x. LoadedModule -> Rep LoadedModule x
    Generic, LoadedModule -> ()
    (LoadedModule -> ()) -> NFData LoadedModule
    forall a. (a -> ()) -> NFData a
    rnf :: LoadedModule -> ()
    $crnf :: LoadedModule -> ()
    NFData)

    -- | Has this module been loaded already.
    isLoaded :: ModName -> LoadedModules -> Bool
    isLoaded :: ModName -> LoadedModules -> Bool
    isLoaded mn :: ModName
    mn lm :: LoadedModules
    lm = (LoadedModule -> Bool) -> [LoadedModule] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any ((ModName
    mn ModName -> ModName -> Bool
    forall a. Eq a => a -> a -> Bool
    ==) (ModName -> Bool)
    -> (LoadedModule -> ModName) -> LoadedModule -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . LoadedModule -> ModName
    lmName) (LoadedModules -> [LoadedModule]
    getLoadedModules LoadedModules
    lm)

    -- | Is this a loaded parameterized module.
    isLoadedParamMod :: ModName -> LoadedModules -> Bool
    isLoadedParamMod :: ModName -> LoadedModules -> Bool
    isLoadedParamMod mn :: ModName
    mn ln :: LoadedModules
    ln = (LoadedModule -> Bool) -> [LoadedModule] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any ((ModName
    mn ModName -> ModName -> Bool
    forall a. Eq a => a -> a -> Bool
    ==) (ModName -> Bool)
    -> (LoadedModule -> ModName) -> LoadedModule -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . LoadedModule -> ModName
    lmName) (LoadedModules -> [LoadedModule]
    lmLoadedParamModules LoadedModules
    ln)

    -- | Try to find a previously loaded module
    lookupModule :: ModName -> ModuleEnv -> Maybe LoadedModule
    lookupModule :: ModName -> ModuleEnv -> Maybe LoadedModule
    lookupModule mn :: ModName
    mn me :: ModuleEnv
    me = (LoadedModules -> [LoadedModule]) -> Maybe LoadedModule
    forall (t :: * -> *).
    Foldable t =>
    (LoadedModules -> t LoadedModule) -> Maybe LoadedModule
    search LoadedModules -> [LoadedModule]
    lmLoadedModules Maybe LoadedModule -> Maybe LoadedModule -> Maybe LoadedModule
    forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
    `mplus` (LoadedModules -> [LoadedModule]) -> Maybe LoadedModule
    forall (t :: * -> *).
    Foldable t =>
    (LoadedModules -> t LoadedModule) -> Maybe LoadedModule
    search LoadedModules -> [LoadedModule]
    lmLoadedParamModules
      where
      search :: (LoadedModules -> t LoadedModule) -> Maybe LoadedModule
    search how :: LoadedModules -> t LoadedModule
    how = (LoadedModule -> Bool) -> t LoadedModule -> Maybe LoadedModule
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
    List.find ((ModName
    mn ModName -> ModName -> Bool
    forall a. Eq a => a -> a -> Bool
    ==) (ModName -> Bool)
    -> (LoadedModule -> ModName) -> LoadedModule -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . LoadedModule -> ModName
    lmName) (LoadedModules -> t LoadedModule
    how (ModuleEnv -> LoadedModules
    meLoadedModules ModuleEnv
    me))

    -- | Add a freshly loaded module.  If it was previously loaded, then
    -- the new version is ignored.
    addLoadedModule ::
      ModulePath -> String -> Fingerprint -> T.Module -> LoadedModules -> LoadedModules
    addLoadedModule :: ModulePath
    -> FilePath
    -> Fingerprint
    -> Module
    -> LoadedModules
    -> LoadedModules
    addLoadedModule path :: ModulePath
    path ident :: FilePath
    ident fp :: Fingerprint
    fp tm :: Module
    tm lm :: LoadedModules
    lm
      | ModName -> LoadedModules -> Bool
    isLoaded (Module -> ModName
    T.mName Module
    tm) LoadedModules
    lm  = LoadedModules
    lm
      | Module -> Bool
    T.isParametrizedModule Module
    tm = LoadedModules
    lm { lmLoadedParamModules :: [LoadedModule]
    lmLoadedParamModules = LoadedModule
    loaded LoadedModule -> [LoadedModule] -> [LoadedModule]
    forall a. a -> [a] -> [a]
    :
                                                    LoadedModules -> [LoadedModule]
    lmLoadedParamModules LoadedModules
    lm }
      | Bool
    otherwise                = LoadedModules
    lm { lmLoadedModules :: [LoadedModule]
    lmLoadedModules =
                                              LoadedModules -> [LoadedModule]
    lmLoadedModules LoadedModules
    lm [LoadedModule] -> [LoadedModule] -> [LoadedModule]
    forall a. [a] -> [a] -> [a]
    ++ [LoadedModule
    loaded] }
      where
      loaded :: LoadedModule
    loaded = LoadedModule :: ModName
    -> ModulePath
    -> FilePath
    -> Iface
    -> Module
    -> Fingerprint
    -> LoadedModule
    LoadedModule
        { lmName :: ModName
    lmName            = Module -> ModName
    T.mName Module
    tm
        , lmFilePath :: ModulePath
    lmFilePath        = ModulePath
    path
        , lmModuleId :: FilePath
    lmModuleId        = FilePath
    ident
        , lmInterface :: Iface
    lmInterface       = Module -> Iface
    genIface Module
    tm
        , lmModule :: Module
    lmModule          = Module
    tm
        , lmFingerprint :: Fingerprint
    lmFingerprint     = Fingerprint
    fp
        }

    -- | Remove a previously loaded module.
    removeLoadedModule :: (LoadedModule -> Bool) -> LoadedModules -> LoadedModules
    removeLoadedModule :: (LoadedModule -> Bool) -> LoadedModules -> LoadedModules
    removeLoadedModule rm :: LoadedModule -> Bool
    rm lm :: LoadedModules
    lm =
      LoadedModules :: [LoadedModule] -> [LoadedModule] -> LoadedModules
    LoadedModules
        { lmLoadedModules :: [LoadedModule]
    lmLoadedModules = (LoadedModule -> Bool) -> [LoadedModule] -> [LoadedModule]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (Bool -> Bool
    not (Bool -> Bool) -> (LoadedModule -> Bool) -> LoadedModule -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . LoadedModule -> Bool
    rm) (LoadedModules -> [LoadedModule]
    lmLoadedModules LoadedModules
    lm)
        , lmLoadedParamModules :: [LoadedModule]
    lmLoadedParamModules = (LoadedModule -> Bool) -> [LoadedModule] -> [LoadedModule]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (Bool -> Bool
    not (Bool -> Bool) -> (LoadedModule -> Bool) -> LoadedModule -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . LoadedModule -> Bool
    rm) (LoadedModules -> [LoadedModule]
    lmLoadedParamModules LoadedModules
    lm)
        }

    -- Dynamic Environments --------------------------------------------------------

    -- | Extra information we need to carry around to dynamically extend
    -- an environment outside the context of a single module. Particularly
    -- useful when dealing with interactive declarations as in @:let@ or
    -- @it@.

    data DynamicEnv = DEnv
      { DynamicEnv -> NamingEnv
    deNames :: R.NamingEnv
      , DynamicEnv -> [DeclGroup]
    deDecls :: [T.DeclGroup]
      , DynamicEnv -> EvalEnv
    deEnv   :: EvalEnv
      } deriving ((forall x. DynamicEnv -> Rep DynamicEnv x)
    -> (forall x. Rep DynamicEnv x -> DynamicEnv) -> Generic DynamicEnv
    forall x. Rep DynamicEnv x -> DynamicEnv
    forall x. DynamicEnv -> Rep DynamicEnv x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cto :: forall x. Rep DynamicEnv x -> DynamicEnv
    $cfrom :: forall x. DynamicEnv -> Rep DynamicEnv x
    Generic, DynamicEnv -> ()
    (DynamicEnv -> ()) -> NFData DynamicEnv
    forall a. (a -> ()) -> NFData a
    rnf :: DynamicEnv -> ()
    $crnf :: DynamicEnv -> ()
    NFData)

    instance Semigroup DynamicEnv where
      de1 :: DynamicEnv
    de1 <> :: DynamicEnv -> DynamicEnv -> DynamicEnv
    <> de2 :: DynamicEnv
    de2 = DEnv :: NamingEnv -> [DeclGroup] -> EvalEnv -> DynamicEnv
    DEnv
        { deNames :: NamingEnv
    deNames = DynamicEnv -> NamingEnv
    deNames DynamicEnv
    de1 NamingEnv -> NamingEnv -> NamingEnv
    forall a. Semigroup a => a -> a -> a
    <> DynamicEnv -> NamingEnv
    deNames DynamicEnv
    de2
        , deDecls :: [DeclGroup]
    deDecls = DynamicEnv -> [DeclGroup]
    deDecls DynamicEnv
    de1 [DeclGroup] -> [DeclGroup] -> [DeclGroup]
    forall a. Semigroup a => a -> a -> a
    <> DynamicEnv -> [DeclGroup]
    deDecls DynamicEnv
    de2
        , deEnv :: EvalEnv
    deEnv   = DynamicEnv -> EvalEnv
    deEnv   DynamicEnv
    de1 EvalEnv -> EvalEnv -> EvalEnv
    forall a. Semigroup a => a -> a -> a
    <> DynamicEnv -> EvalEnv
    deEnv   DynamicEnv
    de2
        }

    instance Monoid DynamicEnv where
      mempty :: DynamicEnv
    mempty = DEnv :: NamingEnv -> [DeclGroup] -> EvalEnv -> DynamicEnv
    DEnv
        { deNames :: NamingEnv
    deNames = NamingEnv
    forall a. Monoid a => a
    mempty
        , deDecls :: [DeclGroup]
    deDecls = [DeclGroup]
    forall a. Monoid a => a
    mempty
        , deEnv :: EvalEnv
    deEnv   = EvalEnv
    forall a. Monoid a => a
    mempty
        }
      mappend :: DynamicEnv -> DynamicEnv -> DynamicEnv
    mappend de1 :: DynamicEnv
    de1 de2 :: DynamicEnv
    de2 = DynamicEnv
    de1 DynamicEnv -> DynamicEnv -> DynamicEnv
    forall a. Semigroup a => a -> a -> a
    <> DynamicEnv
    de2

    -- | Build 'IfaceDecls' that correspond to all of the bindings in the
    -- dynamic environment.
    --
    -- XXX: if we ever add type synonyms or newtypes at the REPL, revisit
    -- this.
    deIfaceDecls :: DynamicEnv -> IfaceDecls
    deIfaceDecls :: DynamicEnv -> IfaceDecls
    deIfaceDecls DEnv { deDecls :: DynamicEnv -> [DeclGroup]
    deDecls = [DeclGroup]
    dgs } =
      [IfaceDecls] -> IfaceDecls
    forall a. Monoid a => [a] -> a
    mconcat [ IfaceDecls :: Map Name IfaceTySyn
    -> Map Name IfaceNewtype
    -> Map Name IfaceAbstractType
    -> Map Name IfaceDecl
    -> IfaceDecls
    IfaceDecls
                { ifTySyns :: Map Name IfaceTySyn
    ifTySyns   = Map Name IfaceTySyn
    forall k a. Map k a
    Map.empty
                , ifNewtypes :: Map Name IfaceNewtype
    ifNewtypes = Map Name IfaceNewtype
    forall k a. Map k a
    Map.empty
                , ifAbstractTypes :: Map Name IfaceAbstractType
    ifAbstractTypes = Map Name IfaceAbstractType
    forall k a. Map k a
    Map.empty
                , ifDecls :: Map Name IfaceDecl
    ifDecls    = Name -> IfaceDecl -> Map Name IfaceDecl
    forall k a. k -> a -> Map k a
    Map.singleton (IfaceDecl -> Name
    ifDeclName IfaceDecl
    ifd) IfaceDecl
    ifd
                }
              | Decl
    decl <- (DeclGroup -> [Decl]) -> [DeclGroup] -> [Decl]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap DeclGroup -> [Decl]
    T.groupDecls [DeclGroup]
    dgs
              , let ifd :: IfaceDecl
    ifd = Decl -> IfaceDecl
    mkIfaceDecl Decl
    decl
              ]