-- | Module environment
module GHC.Unit.Module.Env
   ( -- * Module mappings
     ModuleEnv
   , elemModuleEnv, extendModuleEnv, extendModuleEnvList
   , extendModuleEnvList_C, plusModuleEnv_C
   , delModuleEnvList, delModuleEnv, plusModuleEnv, lookupModuleEnv
   , lookupWithDefaultModuleEnv, mapModuleEnv, mkModuleEnv, emptyModuleEnv
   , partitionModuleEnv
   , moduleEnvKeys, moduleEnvElts, moduleEnvToList
   , unitModuleEnv, isEmptyModuleEnv
   , extendModuleEnvWith, filterModuleEnv

     -- * ModuleName mappings
   , ModuleNameEnv, DModuleNameEnv

     -- * Sets of Modules
   , ModuleSet
   , emptyModuleSet, mkModuleSet, moduleSetElts
   , extendModuleSet, extendModuleSetList, delModuleSet
   , elemModuleSet, intersectModuleSet, minusModuleSet, unionModuleSet
   , unitModuleSet, isEmptyModuleSet
   , unionManyModuleSets

     -- * InstalledModuleEnv
   , InstalledModuleEnv
   , emptyInstalledModuleEnv
   , lookupInstalledModuleEnv
   , extendInstalledModuleEnv
   , filterInstalledModuleEnv
   , delInstalledModuleEnv
   , mergeInstalledModuleEnv
   , plusInstalledModuleEnv
   , installedModuleEnvElts
   )
where

import GHC.Prelude

import GHC.Unit.Module.Name (ModuleName)
import GHC.Types.Unique
import GHC.Types.Unique.FM
import GHC.Types.Unique.DFM
import GHC.Unit.Types
import GHC.Utils.Misc
import Data.List (sortBy, sort)
import Data.Ord

import Data.Coerce
import Data.Map (Map)
import Data.Set (Set)
import qualified Data.Map as Map
import qualified Data.Set as Set
import qualified GHC.Data.FiniteMap as Map
import GHC.Utils.Outputable

-- | A map keyed off of 'Module's
newtype ModuleEnv elt = ModuleEnv (Map NDModule elt)

instance Outputable a => Outputable (ModuleEnv a) where
  ppr :: ModuleEnv a -> SDoc
ppr (ModuleEnv Map NDModule a
m) = Map NDModule a -> SDoc
forall a. Outputable a => a -> SDoc
ppr Map NDModule a
m

{-
Note [ModuleEnv performance and determinism]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To prevent accidental reintroduction of nondeterminism the Ord instance
for Module was changed to not depend on Unique ordering and to use the
lexicographic order. This is potentially expensive, but when measured
there was no difference in performance.

To be on the safe side and not pessimize ModuleEnv uses nondeterministic
ordering on Module and normalizes by doing the lexicographic sort when
turning the env to a list.
See Note [Unique Determinism] for more information about the source of
nondeterminismand and Note [Deterministic UniqFM] for explanation of why
it matters for maps.
-}

newtype NDModule = NDModule { NDModule -> Module
unNDModule :: Module }
  deriving NDModule -> NDModule -> Bool
(NDModule -> NDModule -> Bool)
-> (NDModule -> NDModule -> Bool) -> Eq NDModule
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NDModule -> NDModule -> Bool
$c/= :: NDModule -> NDModule -> Bool
== :: NDModule -> NDModule -> Bool
$c== :: NDModule -> NDModule -> Bool
Eq
  -- A wrapper for Module with faster nondeterministic Ord.
  -- Don't export, See [ModuleEnv performance and determinism]
  --
instance Outputable NDModule where
  ppr :: NDModule -> SDoc
ppr (NDModule Module
a) = Module -> SDoc
forall a. Outputable a => a -> SDoc
ppr Module
a

instance Ord NDModule where
  compare :: NDModule -> NDModule -> Ordering
compare (NDModule (Module Unit
p1 ModuleName
n1)) (NDModule (Module Unit
p2 ModuleName
n2)) =
    (Unit -> Unique
forall a. Uniquable a => a -> Unique
getUnique Unit
p1 Unique -> Unique -> Ordering
`nonDetCmpUnique` Unit -> Unique
forall a. Uniquable a => a -> Unique
getUnique Unit
p2) Ordering -> Ordering -> Ordering
`thenCmp`
    (ModuleName -> Unique
forall a. Uniquable a => a -> Unique
getUnique ModuleName
n1 Unique -> Unique -> Ordering
`nonDetCmpUnique` ModuleName -> Unique
forall a. Uniquable a => a -> Unique
getUnique ModuleName
n2)

filterModuleEnv :: (Module -> a -> Bool) -> ModuleEnv a -> ModuleEnv a
filterModuleEnv :: (Module -> a -> Bool) -> ModuleEnv a -> ModuleEnv a
filterModuleEnv Module -> a -> Bool
f (ModuleEnv Map NDModule a
e) =
  Map NDModule a -> ModuleEnv a
forall elt. Map NDModule elt -> ModuleEnv elt
ModuleEnv ((NDModule -> a -> Bool) -> Map NDModule a -> Map NDModule a
forall k a. (k -> a -> Bool) -> Map k a -> Map k a
Map.filterWithKey (Module -> a -> Bool
f (Module -> a -> Bool)
-> (NDModule -> Module) -> NDModule -> a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NDModule -> Module
unNDModule) Map NDModule a
e)

elemModuleEnv :: Module -> ModuleEnv a -> Bool
elemModuleEnv :: Module -> ModuleEnv a -> Bool
elemModuleEnv Module
m (ModuleEnv Map NDModule a
e) = NDModule -> Map NDModule a -> Bool
forall k a. Ord k => k -> Map k a -> Bool
Map.member (Module -> NDModule
NDModule Module
m) Map NDModule a
e

extendModuleEnv :: ModuleEnv a -> Module -> a -> ModuleEnv a
extendModuleEnv :: ModuleEnv a -> Module -> a -> ModuleEnv a
extendModuleEnv (ModuleEnv Map NDModule a
e) Module
m a
x = Map NDModule a -> ModuleEnv a
forall elt. Map NDModule elt -> ModuleEnv elt
ModuleEnv (NDModule -> a -> Map NDModule a -> Map NDModule a
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert (Module -> NDModule
NDModule Module
m) a
x Map NDModule a
e)

extendModuleEnvWith :: (a -> a -> a) -> ModuleEnv a -> Module -> a
                    -> ModuleEnv a
extendModuleEnvWith :: (a -> a -> a) -> ModuleEnv a -> Module -> a -> ModuleEnv a
extendModuleEnvWith a -> a -> a
f (ModuleEnv Map NDModule a
e) Module
m a
x =
  Map NDModule a -> ModuleEnv a
forall elt. Map NDModule elt -> ModuleEnv elt
ModuleEnv ((a -> a -> a) -> NDModule -> a -> Map NDModule a -> Map NDModule a
forall k a. Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a
Map.insertWith a -> a -> a
f (Module -> NDModule
NDModule Module
m) a
x Map NDModule a
e)

extendModuleEnvList :: ModuleEnv a -> [(Module, a)] -> ModuleEnv a
extendModuleEnvList :: ModuleEnv a -> [(Module, a)] -> ModuleEnv a
extendModuleEnvList (ModuleEnv Map NDModule a
e) [(Module, a)]
xs =
  Map NDModule a -> ModuleEnv a
forall elt. Map NDModule elt -> ModuleEnv elt
ModuleEnv ([(NDModule, a)] -> Map NDModule a -> Map NDModule a
forall key elt.
Ord key =>
[(key, elt)] -> Map key elt -> Map key elt
Map.insertList [(Module -> NDModule
NDModule Module
k, a
v) | (Module
k,a
v) <- [(Module, a)]
xs] Map NDModule a
e)

extendModuleEnvList_C :: (a -> a -> a) -> ModuleEnv a -> [(Module, a)]
                      -> ModuleEnv a
extendModuleEnvList_C :: (a -> a -> a) -> ModuleEnv a -> [(Module, a)] -> ModuleEnv a
extendModuleEnvList_C a -> a -> a
f (ModuleEnv Map NDModule a
e) [(Module, a)]
xs =
  Map NDModule a -> ModuleEnv a
forall elt. Map NDModule elt -> ModuleEnv elt
ModuleEnv ((a -> a -> a)
-> [(NDModule, a)] -> Map NDModule a -> Map NDModule a
forall key elt.
Ord key =>
(elt -> elt -> elt) -> [(key, elt)] -> Map key elt -> Map key elt
Map.insertListWith a -> a -> a
f [(Module -> NDModule
NDModule Module
k, a
v) | (Module
k,a
v) <- [(Module, a)]
xs] Map NDModule a
e)

plusModuleEnv_C :: (a -> a -> a) -> ModuleEnv a -> ModuleEnv a -> ModuleEnv a
plusModuleEnv_C :: (a -> a -> a) -> ModuleEnv a -> ModuleEnv a -> ModuleEnv a
plusModuleEnv_C a -> a -> a
f (ModuleEnv Map NDModule a
e1) (ModuleEnv Map NDModule a
e2) =
  Map NDModule a -> ModuleEnv a
forall elt. Map NDModule elt -> ModuleEnv elt
ModuleEnv ((a -> a -> a) -> Map NDModule a -> Map NDModule a -> Map NDModule a
forall k a. Ord k => (a -> a -> a) -> Map k a -> Map k a -> Map k a
Map.unionWith a -> a -> a
f Map NDModule a
e1 Map NDModule a
e2)

delModuleEnvList :: ModuleEnv a -> [Module] -> ModuleEnv a
delModuleEnvList :: ModuleEnv a -> [Module] -> ModuleEnv a
delModuleEnvList (ModuleEnv Map NDModule a
e) [Module]
ms =
  Map NDModule a -> ModuleEnv a
forall elt. Map NDModule elt -> ModuleEnv elt
ModuleEnv ([NDModule] -> Map NDModule a -> Map NDModule a
forall key elt. Ord key => [key] -> Map key elt -> Map key elt
Map.deleteList ((Module -> NDModule) -> [Module] -> [NDModule]
forall a b. (a -> b) -> [a] -> [b]
map Module -> NDModule
NDModule [Module]
ms) Map NDModule a
e)

delModuleEnv :: ModuleEnv a -> Module -> ModuleEnv a
delModuleEnv :: ModuleEnv a -> Module -> ModuleEnv a
delModuleEnv (ModuleEnv Map NDModule a
e) Module
m = Map NDModule a -> ModuleEnv a
forall elt. Map NDModule elt -> ModuleEnv elt
ModuleEnv (NDModule -> Map NDModule a -> Map NDModule a
forall k a. Ord k => k -> Map k a -> Map k a
Map.delete (Module -> NDModule
NDModule Module
m) Map NDModule a
e)

plusModuleEnv :: ModuleEnv a -> ModuleEnv a -> ModuleEnv a
plusModuleEnv :: ModuleEnv a -> ModuleEnv a -> ModuleEnv a
plusModuleEnv (ModuleEnv Map NDModule a
e1) (ModuleEnv Map NDModule a
e2) = Map NDModule a -> ModuleEnv a
forall elt. Map NDModule elt -> ModuleEnv elt
ModuleEnv (Map NDModule a -> Map NDModule a -> Map NDModule a
forall k a. Ord k => Map k a -> Map k a -> Map k a
Map.union Map NDModule a
e1 Map NDModule a
e2)

lookupModuleEnv :: ModuleEnv a -> Module -> Maybe a
lookupModuleEnv :: ModuleEnv a -> Module -> Maybe a
lookupModuleEnv (ModuleEnv Map NDModule a
e) Module
m = NDModule -> Map NDModule a -> Maybe a
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup (Module -> NDModule
NDModule Module
m) Map NDModule a
e

lookupWithDefaultModuleEnv :: ModuleEnv a -> a -> Module -> a
lookupWithDefaultModuleEnv :: ModuleEnv a -> a -> Module -> a
lookupWithDefaultModuleEnv (ModuleEnv Map NDModule a
e) a
x Module
m =
  a -> NDModule -> Map NDModule a -> a
forall k a. Ord k => a -> k -> Map k a -> a
Map.findWithDefault a
x (Module -> NDModule
NDModule Module
m) Map NDModule a
e

mapModuleEnv :: (a -> b) -> ModuleEnv a -> ModuleEnv b
mapModuleEnv :: (a -> b) -> ModuleEnv a -> ModuleEnv b
mapModuleEnv a -> b
f (ModuleEnv Map NDModule a
e) = Map NDModule b -> ModuleEnv b
forall elt. Map NDModule elt -> ModuleEnv elt
ModuleEnv ((NDModule -> a -> b) -> Map NDModule a -> Map NDModule b
forall k a b. (k -> a -> b) -> Map k a -> Map k b
Map.mapWithKey (\NDModule
_ a
v -> a -> b
f a
v) Map NDModule a
e)

partitionModuleEnv :: (a -> Bool) -> ModuleEnv a -> (ModuleEnv a, ModuleEnv a)
partitionModuleEnv :: (a -> Bool) -> ModuleEnv a -> (ModuleEnv a, ModuleEnv a)
partitionModuleEnv a -> Bool
f (ModuleEnv Map NDModule a
e) = (Map NDModule a -> ModuleEnv a
forall elt. Map NDModule elt -> ModuleEnv elt
ModuleEnv Map NDModule a
a, Map NDModule a -> ModuleEnv a
forall elt. Map NDModule elt -> ModuleEnv elt
ModuleEnv Map NDModule a
b)
  where
    (Map NDModule a
a,Map NDModule a
b) = (a -> Bool) -> Map NDModule a -> (Map NDModule a, Map NDModule a)
forall a k. (a -> Bool) -> Map k a -> (Map k a, Map k a)
Map.partition a -> Bool
f Map NDModule a
e

mkModuleEnv :: [(Module, a)] -> ModuleEnv a
mkModuleEnv :: [(Module, a)] -> ModuleEnv a
mkModuleEnv [(Module, a)]
xs = Map NDModule a -> ModuleEnv a
forall elt. Map NDModule elt -> ModuleEnv elt
ModuleEnv ([(NDModule, a)] -> Map NDModule a
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [(Module -> NDModule
NDModule Module
k, a
v) | (Module
k,a
v) <- [(Module, a)]
xs])

emptyModuleEnv :: ModuleEnv a
emptyModuleEnv :: ModuleEnv a
emptyModuleEnv = Map NDModule a -> ModuleEnv a
forall elt. Map NDModule elt -> ModuleEnv elt
ModuleEnv Map NDModule a
forall k a. Map k a
Map.empty

moduleEnvKeys :: ModuleEnv a -> [Module]
moduleEnvKeys :: ModuleEnv a -> [Module]
moduleEnvKeys (ModuleEnv Map NDModule a
e) = [Module] -> [Module]
forall a. Ord a => [a] -> [a]
sort ([Module] -> [Module]) -> [Module] -> [Module]
forall a b. (a -> b) -> a -> b
$ (NDModule -> Module) -> [NDModule] -> [Module]
forall a b. (a -> b) -> [a] -> [b]
map NDModule -> Module
unNDModule ([NDModule] -> [Module]) -> [NDModule] -> [Module]
forall a b. (a -> b) -> a -> b
$ Map NDModule a -> [NDModule]
forall k a. Map k a -> [k]
Map.keys Map NDModule a
e
  -- See Note [ModuleEnv performance and determinism]

moduleEnvElts :: ModuleEnv a -> [a]
moduleEnvElts :: ModuleEnv a -> [a]
moduleEnvElts ModuleEnv a
e = ((Module, a) -> a) -> [(Module, a)] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map (Module, a) -> a
forall a b. (a, b) -> b
snd ([(Module, a)] -> [a]) -> [(Module, a)] -> [a]
forall a b. (a -> b) -> a -> b
$ ModuleEnv a -> [(Module, a)]
forall a. ModuleEnv a -> [(Module, a)]
moduleEnvToList ModuleEnv a
e
  -- See Note [ModuleEnv performance and determinism]

moduleEnvToList :: ModuleEnv a -> [(Module, a)]
moduleEnvToList :: ModuleEnv a -> [(Module, a)]
moduleEnvToList (ModuleEnv Map NDModule a
e) =
  ((Module, a) -> (Module, a) -> Ordering)
-> [(Module, a)] -> [(Module, a)]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy (((Module, a) -> Module) -> (Module, a) -> (Module, a) -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing (Module, a) -> Module
forall a b. (a, b) -> a
fst) [(Module
m, a
v) | (NDModule Module
m, a
v) <- Map NDModule a -> [(NDModule, a)]
forall k a. Map k a -> [(k, a)]
Map.toList Map NDModule a
e]
  -- See Note [ModuleEnv performance and determinism]

unitModuleEnv :: Module -> a -> ModuleEnv a
unitModuleEnv :: Module -> a -> ModuleEnv a
unitModuleEnv Module
m a
x = Map NDModule a -> ModuleEnv a
forall elt. Map NDModule elt -> ModuleEnv elt
ModuleEnv (NDModule -> a -> Map NDModule a
forall k a. k -> a -> Map k a
Map.singleton (Module -> NDModule
NDModule Module
m) a
x)

isEmptyModuleEnv :: ModuleEnv a -> Bool
isEmptyModuleEnv :: ModuleEnv a -> Bool
isEmptyModuleEnv (ModuleEnv Map NDModule a
e) = Map NDModule a -> Bool
forall k a. Map k a -> Bool
Map.null Map NDModule a
e

-- | A set of 'Module's
type ModuleSet = Set NDModule

mkModuleSet :: [Module] -> ModuleSet
mkModuleSet :: [Module] -> ModuleSet
mkModuleSet = [NDModule] -> ModuleSet
forall a. Ord a => [a] -> Set a
Set.fromList ([NDModule] -> ModuleSet)
-> ([Module] -> [NDModule]) -> [Module] -> ModuleSet
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Module] -> [NDModule]
coerce

extendModuleSet :: ModuleSet -> Module -> ModuleSet
extendModuleSet :: ModuleSet -> Module -> ModuleSet
extendModuleSet ModuleSet
s Module
m = NDModule -> ModuleSet -> ModuleSet
forall a. Ord a => a -> Set a -> Set a
Set.insert (Module -> NDModule
NDModule Module
m) ModuleSet
s

extendModuleSetList :: ModuleSet -> [Module] -> ModuleSet
extendModuleSetList :: ModuleSet -> [Module] -> ModuleSet
extendModuleSetList ModuleSet
s [Module]
ms = (ModuleSet -> Module -> ModuleSet)
-> ModuleSet -> [Module] -> ModuleSet
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' ((NDModule -> ModuleSet) -> Module -> ModuleSet
coerce ((NDModule -> ModuleSet) -> Module -> ModuleSet)
-> (ModuleSet -> NDModule -> ModuleSet)
-> ModuleSet
-> Module
-> ModuleSet
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (NDModule -> ModuleSet -> ModuleSet)
-> ModuleSet -> NDModule -> ModuleSet
forall a b c. (a -> b -> c) -> b -> a -> c
flip NDModule -> ModuleSet -> ModuleSet
forall a. Ord a => a -> Set a -> Set a
Set.insert) ModuleSet
s [Module]
ms

emptyModuleSet :: ModuleSet
emptyModuleSet :: ModuleSet
emptyModuleSet = ModuleSet
forall a. Set a
Set.empty

isEmptyModuleSet :: ModuleSet -> Bool
isEmptyModuleSet :: ModuleSet -> Bool
isEmptyModuleSet = ModuleSet -> Bool
forall a. Set a -> Bool
Set.null

moduleSetElts :: ModuleSet -> [Module]
moduleSetElts :: ModuleSet -> [Module]
moduleSetElts = [Module] -> [Module]
forall a. Ord a => [a] -> [a]
sort ([Module] -> [Module])
-> (ModuleSet -> [Module]) -> ModuleSet -> [Module]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [NDModule] -> [Module]
coerce ([NDModule] -> [Module])
-> (ModuleSet -> [NDModule]) -> ModuleSet -> [Module]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ModuleSet -> [NDModule]
forall a. Set a -> [a]
Set.toList

elemModuleSet :: Module -> ModuleSet -> Bool
elemModuleSet :: Module -> ModuleSet -> Bool
elemModuleSet = NDModule -> ModuleSet -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.member (NDModule -> ModuleSet -> Bool)
-> (Module -> NDModule) -> Module -> ModuleSet -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Module -> NDModule
coerce

intersectModuleSet :: ModuleSet -> ModuleSet -> ModuleSet
intersectModuleSet :: ModuleSet -> ModuleSet -> ModuleSet
intersectModuleSet = (ModuleSet -> ModuleSet -> ModuleSet)
-> ModuleSet -> ModuleSet -> ModuleSet
coerce ModuleSet -> ModuleSet -> ModuleSet
forall a. Ord a => Set a -> Set a -> Set a
Set.intersection

minusModuleSet :: ModuleSet -> ModuleSet -> ModuleSet
minusModuleSet :: ModuleSet -> ModuleSet -> ModuleSet
minusModuleSet = (ModuleSet -> ModuleSet -> ModuleSet)
-> ModuleSet -> ModuleSet -> ModuleSet
coerce ModuleSet -> ModuleSet -> ModuleSet
forall a. Ord a => Set a -> Set a -> Set a
Set.difference

delModuleSet :: ModuleSet -> Module -> ModuleSet
delModuleSet :: ModuleSet -> Module -> ModuleSet
delModuleSet = (ModuleSet -> NDModule -> ModuleSet)
-> ModuleSet -> Module -> ModuleSet
coerce ((NDModule -> ModuleSet -> ModuleSet)
-> ModuleSet -> NDModule -> ModuleSet
forall a b c. (a -> b -> c) -> b -> a -> c
flip NDModule -> ModuleSet -> ModuleSet
forall a. Ord a => a -> Set a -> Set a
Set.delete)

unionModuleSet :: ModuleSet -> ModuleSet -> ModuleSet
unionModuleSet :: ModuleSet -> ModuleSet -> ModuleSet
unionModuleSet = (ModuleSet -> ModuleSet -> ModuleSet)
-> ModuleSet -> ModuleSet -> ModuleSet
coerce ModuleSet -> ModuleSet -> ModuleSet
forall a. Ord a => Set a -> Set a -> Set a
Set.union

unionManyModuleSets :: [ModuleSet] -> ModuleSet
unionManyModuleSets :: [ModuleSet] -> ModuleSet
unionManyModuleSets = ([ModuleSet] -> ModuleSet) -> [ModuleSet] -> ModuleSet
coerce ([ModuleSet] -> ModuleSet
forall (f :: * -> *) a. (Foldable f, Ord a) => f (Set a) -> Set a
Set.unions :: [Set NDModule] -> Set NDModule)

unitModuleSet :: Module -> ModuleSet
unitModuleSet :: Module -> ModuleSet
unitModuleSet = (NDModule -> ModuleSet) -> Module -> ModuleSet
coerce NDModule -> ModuleSet
forall a. a -> Set a
Set.singleton

{-
A ModuleName has a Unique, so we can build mappings of these using
UniqFM.
-}

-- | A map keyed off of 'ModuleName's (actually, their 'Unique's)
type ModuleNameEnv elt = UniqFM ModuleName elt


-- | A map keyed off of 'ModuleName's (actually, their 'Unique's)
-- Has deterministic folds and can be deterministically converted to a list
type DModuleNameEnv elt = UniqDFM ModuleName elt


--------------------------------------------------------------------
-- InstalledModuleEnv
--------------------------------------------------------------------

-- | A map keyed off of 'InstalledModule'
newtype InstalledModuleEnv elt = InstalledModuleEnv (Map InstalledModule elt)

instance Outputable elt => Outputable (InstalledModuleEnv elt) where
  ppr :: InstalledModuleEnv elt -> SDoc
ppr (InstalledModuleEnv Map InstalledModule elt
env) = Map InstalledModule elt -> SDoc
forall a. Outputable a => a -> SDoc
ppr Map InstalledModule elt
env


emptyInstalledModuleEnv :: InstalledModuleEnv a
emptyInstalledModuleEnv :: InstalledModuleEnv a
emptyInstalledModuleEnv = Map InstalledModule a -> InstalledModuleEnv a
forall elt. Map InstalledModule elt -> InstalledModuleEnv elt
InstalledModuleEnv Map InstalledModule a
forall k a. Map k a
Map.empty

lookupInstalledModuleEnv :: InstalledModuleEnv a -> InstalledModule -> Maybe a
lookupInstalledModuleEnv :: InstalledModuleEnv a -> InstalledModule -> Maybe a
lookupInstalledModuleEnv (InstalledModuleEnv Map InstalledModule a
e) InstalledModule
m = InstalledModule -> Map InstalledModule a -> Maybe a
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup InstalledModule
m Map InstalledModule a
e

extendInstalledModuleEnv :: InstalledModuleEnv a -> InstalledModule -> a -> InstalledModuleEnv a
extendInstalledModuleEnv :: InstalledModuleEnv a
-> InstalledModule -> a -> InstalledModuleEnv a
extendInstalledModuleEnv (InstalledModuleEnv Map InstalledModule a
e) InstalledModule
m a
x = Map InstalledModule a -> InstalledModuleEnv a
forall elt. Map InstalledModule elt -> InstalledModuleEnv elt
InstalledModuleEnv (InstalledModule
-> a -> Map InstalledModule a -> Map InstalledModule a
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert InstalledModule
m a
x Map InstalledModule a
e)

filterInstalledModuleEnv :: (InstalledModule -> a -> Bool) -> InstalledModuleEnv a -> InstalledModuleEnv a
filterInstalledModuleEnv :: (InstalledModule -> a -> Bool)
-> InstalledModuleEnv a -> InstalledModuleEnv a
filterInstalledModuleEnv InstalledModule -> a -> Bool
f (InstalledModuleEnv Map InstalledModule a
e) =
  Map InstalledModule a -> InstalledModuleEnv a
forall elt. Map InstalledModule elt -> InstalledModuleEnv elt
InstalledModuleEnv ((InstalledModule -> a -> Bool)
-> Map InstalledModule a -> Map InstalledModule a
forall k a. (k -> a -> Bool) -> Map k a -> Map k a
Map.filterWithKey InstalledModule -> a -> Bool
f Map InstalledModule a
e)

delInstalledModuleEnv :: InstalledModuleEnv a -> InstalledModule -> InstalledModuleEnv a
delInstalledModuleEnv :: InstalledModuleEnv a -> InstalledModule -> InstalledModuleEnv a
delInstalledModuleEnv (InstalledModuleEnv Map InstalledModule a
e) InstalledModule
m = Map InstalledModule a -> InstalledModuleEnv a
forall elt. Map InstalledModule elt -> InstalledModuleEnv elt
InstalledModuleEnv (InstalledModule -> Map InstalledModule a -> Map InstalledModule a
forall k a. Ord k => k -> Map k a -> Map k a
Map.delete InstalledModule
m Map InstalledModule a
e)

installedModuleEnvElts :: InstalledModuleEnv a -> [(InstalledModule, a)]
installedModuleEnvElts :: InstalledModuleEnv a -> [(InstalledModule, a)]
installedModuleEnvElts (InstalledModuleEnv Map InstalledModule a
e) = Map InstalledModule a -> [(InstalledModule, a)]
forall k a. Map k a -> [(k, a)]
Map.assocs Map InstalledModule a
e

mergeInstalledModuleEnv
  :: (elta -> eltb -> Maybe eltc)
  -> (InstalledModuleEnv elta -> InstalledModuleEnv eltc)  -- map X
  -> (InstalledModuleEnv eltb -> InstalledModuleEnv eltc) -- map Y
  -> InstalledModuleEnv elta
  -> InstalledModuleEnv eltb
  -> InstalledModuleEnv eltc
mergeInstalledModuleEnv :: (elta -> eltb -> Maybe eltc)
-> (InstalledModuleEnv elta -> InstalledModuleEnv eltc)
-> (InstalledModuleEnv eltb -> InstalledModuleEnv eltc)
-> InstalledModuleEnv elta
-> InstalledModuleEnv eltb
-> InstalledModuleEnv eltc
mergeInstalledModuleEnv elta -> eltb -> Maybe eltc
f InstalledModuleEnv elta -> InstalledModuleEnv eltc
g InstalledModuleEnv eltb -> InstalledModuleEnv eltc
h (InstalledModuleEnv Map InstalledModule elta
xm) (InstalledModuleEnv Map InstalledModule eltb
ym)
  = Map InstalledModule eltc -> InstalledModuleEnv eltc
forall elt. Map InstalledModule elt -> InstalledModuleEnv elt
InstalledModuleEnv (Map InstalledModule eltc -> InstalledModuleEnv eltc)
-> Map InstalledModule eltc -> InstalledModuleEnv eltc
forall a b. (a -> b) -> a -> b
$ (InstalledModule -> elta -> eltb -> Maybe eltc)
-> (Map InstalledModule elta -> Map InstalledModule eltc)
-> (Map InstalledModule eltb -> Map InstalledModule eltc)
-> Map InstalledModule elta
-> Map InstalledModule eltb
-> Map InstalledModule eltc
forall k a b c.
Ord k =>
(k -> a -> b -> Maybe c)
-> (Map k a -> Map k c)
-> (Map k b -> Map k c)
-> Map k a
-> Map k b
-> Map k c
Map.mergeWithKey
      (\InstalledModule
_ elta
x eltb
y -> (elta
x elta -> eltb -> Maybe eltc
`f` eltb
y))
      ((InstalledModuleEnv elta -> InstalledModuleEnv eltc)
-> Map InstalledModule elta -> Map InstalledModule eltc
coerce InstalledModuleEnv elta -> InstalledModuleEnv eltc
g)
      ((InstalledModuleEnv eltb -> InstalledModuleEnv eltc)
-> Map InstalledModule eltb -> Map InstalledModule eltc
coerce InstalledModuleEnv eltb -> InstalledModuleEnv eltc
h)
      Map InstalledModule elta
xm Map InstalledModule eltb
ym

plusInstalledModuleEnv :: (elt -> elt -> elt)
  -> InstalledModuleEnv elt
  -> InstalledModuleEnv elt
  -> InstalledModuleEnv elt
plusInstalledModuleEnv :: (elt -> elt -> elt)
-> InstalledModuleEnv elt
-> InstalledModuleEnv elt
-> InstalledModuleEnv elt
plusInstalledModuleEnv elt -> elt -> elt
f (InstalledModuleEnv Map InstalledModule elt
xm) (InstalledModuleEnv Map InstalledModule elt
ym) =
  Map InstalledModule elt -> InstalledModuleEnv elt
forall elt. Map InstalledModule elt -> InstalledModuleEnv elt
InstalledModuleEnv (Map InstalledModule elt -> InstalledModuleEnv elt)
-> Map InstalledModule elt -> InstalledModuleEnv elt
forall a b. (a -> b) -> a -> b
$ (elt -> elt -> elt)
-> Map InstalledModule elt
-> Map InstalledModule elt
-> Map InstalledModule elt
forall k a. Ord k => (a -> a -> a) -> Map k a -> Map k a -> Map k a
Map.unionWith elt -> elt -> elt
f Map InstalledModule elt
xm Map InstalledModule elt
ym