    {-
    %
    % (c) The University of Glasgow 2006
    % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
    %
    -}

    -- | FastStringEnv: FastString environments
    module GHC.Data.FastString.Env (
            -- * FastString environments (maps)
            FastStringEnv,

            -- ** Manipulating these environments
            mkFsEnv,
            emptyFsEnv, unitFsEnv,
            extendFsEnv_C, extendFsEnv_Acc, extendFsEnv,
            extendFsEnvList, extendFsEnvList_C,
            filterFsEnv,
            plusFsEnv, plusFsEnv_C, alterFsEnv,
            lookupFsEnv, lookupFsEnv_NF, delFromFsEnv, delListFromFsEnv,
            elemFsEnv, mapFsEnv, strictMapFsEnv, mapMaybeFsEnv,
            nonDetFoldFsEnv,

            -- * Deterministic FastString environments (maps)
            DFastStringEnv,

            -- ** Manipulating these environments
            mkDFsEnv, emptyDFsEnv, dFsEnvElts, lookupDFsEnv
        ) where

    import GHC.Prelude

    import GHC.Types.Unique.FM
    import GHC.Types.Unique.DFM
    import GHC.Data.Maybe
    import GHC.Data.FastString

    -- | A non-deterministic set of FastStrings.
    -- See Note [Deterministic UniqFM] in "GHC.Types.Unique.DFM" for explanation why it's not
    -- deterministic and why it matters. Use DFastStringEnv if the set eventually
    -- gets converted into a list or folded over in a way where the order
    -- changes the generated code.
    type FastStringEnv a = UniqFM FastString a  -- Domain is FastString

    emptyFsEnv         :: FastStringEnv a
    mkFsEnv            :: [(FastString,a)] -> FastStringEnv a
    alterFsEnv         :: (Maybe a-> Maybe a) -> FastStringEnv a -> FastString -> FastStringEnv a
    extendFsEnv_C      :: (a->a->a) -> FastStringEnv a -> FastString -> a -> FastStringEnv a
    extendFsEnv_Acc    :: (a->b->b) -> (a->b) -> FastStringEnv b -> FastString -> a -> FastStringEnv b
    extendFsEnv        :: FastStringEnv a -> FastString -> a -> FastStringEnv a
    plusFsEnv          :: FastStringEnv a -> FastStringEnv a -> FastStringEnv a
    plusFsEnv_C        :: (a->a->a) -> FastStringEnv a -> FastStringEnv a -> FastStringEnv a
    extendFsEnvList    :: FastStringEnv a -> [(FastString,a)] -> FastStringEnv a
    extendFsEnvList_C  :: (a->a->a) -> FastStringEnv a -> [(FastString,a)] -> FastStringEnv a
    delFromFsEnv       :: FastStringEnv a -> FastString -> FastStringEnv a
    delListFromFsEnv   :: FastStringEnv a -> [FastString] -> FastStringEnv a
    elemFsEnv          :: FastString -> FastStringEnv a -> Bool
    unitFsEnv          :: FastString -> a -> FastStringEnv a
    lookupFsEnv        :: FastStringEnv a -> FastString -> Maybe a
    lookupFsEnv_NF     :: FastStringEnv a -> FastString -> a
    filterFsEnv        :: (elt -> Bool) -> FastStringEnv elt -> FastStringEnv elt
    mapFsEnv           :: (elt1 -> elt2) -> FastStringEnv elt1 -> FastStringEnv elt2
    mapMaybeFsEnv      :: (elt1 -> Maybe elt2) -> FastStringEnv elt1 -> FastStringEnv elt2

    emptyFsEnv :: forall a. FastStringEnv a
    emptyFsEnv                = UniqFM FastString a
    forall {k} (key :: k) elt. UniqFM key elt
    emptyUFM
    unitFsEnv :: forall a. FastString -> a -> FastStringEnv a
    unitFsEnv FastString
    x a
    y             = FastString -> a -> UniqFM FastString a
    forall key elt. Uniquable key => key -> elt -> UniqFM key elt
    unitUFM FastString
    x a
    y
    extendFsEnv :: forall a. FastStringEnv a -> FastString -> a -> FastStringEnv a
    extendFsEnv FastStringEnv a
    x FastString
    y a
    z         = FastStringEnv a -> FastString -> a -> FastStringEnv a
    forall key elt.
    Uniquable key =>
    UniqFM key elt -> key -> elt -> UniqFM key elt
    addToUFM FastStringEnv a
    x FastString
    y a
    z
    extendFsEnvList :: forall a. FastStringEnv a -> [(FastString, a)] -> FastStringEnv a
    extendFsEnvList FastStringEnv a
    x [(FastString, a)]
    l       = FastStringEnv a -> [(FastString, a)] -> FastStringEnv a
    forall key elt.
    Uniquable key =>
    UniqFM key elt -> [(key, elt)] -> UniqFM key elt
    addListToUFM FastStringEnv a
    x [(FastString, a)]
    l
    lookupFsEnv :: forall a. FastStringEnv a -> FastString -> Maybe a
    lookupFsEnv FastStringEnv a
    x FastString
    y           = FastStringEnv a -> FastString -> Maybe a
    forall key elt. Uniquable key => UniqFM key elt -> key -> Maybe elt
    lookupUFM FastStringEnv a
    x FastString
    y
    alterFsEnv :: forall a.
    (Maybe a -> Maybe a)
    -> FastStringEnv a -> FastString -> FastStringEnv a
    alterFsEnv                = (Maybe a -> Maybe a)
    -> UniqFM FastString a -> FastString -> UniqFM FastString a
    forall key elt.
    Uniquable key =>
    (Maybe elt -> Maybe elt) -> UniqFM key elt -> key -> UniqFM key elt
    alterUFM
    mkFsEnv :: forall a. [(FastString, a)] -> FastStringEnv a
    mkFsEnv     [(FastString, a)]
    l             = [(FastString, a)] -> UniqFM FastString a
    forall key elt. Uniquable key => [(key, elt)] -> UniqFM key elt
    listToUFM [(FastString, a)]
    l
    elemFsEnv :: forall a. FastString -> FastStringEnv a -> Bool
    elemFsEnv FastString
    x FastStringEnv a
    y             = FastString -> FastStringEnv a -> Bool
    forall key elt. Uniquable key => key -> UniqFM key elt -> Bool
    elemUFM FastString
    x FastStringEnv a
    y
    plusFsEnv :: forall a. FastStringEnv a -> FastStringEnv a -> FastStringEnv a
    plusFsEnv FastStringEnv a
    x FastStringEnv a
    y             = FastStringEnv a -> FastStringEnv a -> FastStringEnv a
    forall {k} (key :: k) elt.
    UniqFM key elt -> UniqFM key elt -> UniqFM key elt
    plusUFM FastStringEnv a
    x FastStringEnv a
    y
    plusFsEnv_C :: forall a.
    (a -> a -> a)
    -> FastStringEnv a -> FastStringEnv a -> FastStringEnv a
    plusFsEnv_C a -> a -> a
    f FastStringEnv a
    x FastStringEnv a
    y         = (a -> a -> a)
    -> FastStringEnv a -> FastStringEnv a -> FastStringEnv a
    forall {k} elt (key :: k).
    (elt -> elt -> elt)
    -> UniqFM key elt -> UniqFM key elt -> UniqFM key elt
    plusUFM_C a -> a -> a
    f FastStringEnv a
    x FastStringEnv a
    y
    extendFsEnv_C :: forall a.
    (a -> a -> a)
    -> FastStringEnv a -> FastString -> a -> FastStringEnv a
    extendFsEnv_C a -> a -> a
    f FastStringEnv a
    x FastString
    y a
    z     = (a -> a -> a)
    -> FastStringEnv a -> FastString -> a -> FastStringEnv a
    forall key elt.
    Uniquable key =>
    (elt -> elt -> elt)
    -> UniqFM key elt -> key -> elt -> UniqFM key elt
    addToUFM_C a -> a -> a
    f FastStringEnv a
    x FastString
    y a
    z
    mapFsEnv :: forall elt1 elt2.
    (elt1 -> elt2) -> FastStringEnv elt1 -> FastStringEnv elt2
    mapFsEnv elt1 -> elt2
    f FastStringEnv elt1
    x              = (elt1 -> elt2) -> FastStringEnv elt1 -> UniqFM FastString elt2
    forall {k} elt1 elt2 (key :: k).
    (elt1 -> elt2) -> UniqFM key elt1 -> UniqFM key elt2
    mapUFM elt1 -> elt2
    f FastStringEnv elt1
    x
    extendFsEnv_Acc :: forall a b.
    (a -> b -> b)
    -> (a -> b)
    -> FastStringEnv b
    -> FastString
    -> a
    -> FastStringEnv b
    extendFsEnv_Acc a -> b -> b
    x a -> b
    y FastStringEnv b
    z FastString
    a a
    b = (a -> b -> b)
    -> (a -> b)
    -> FastStringEnv b
    -> FastString
    -> a
    -> FastStringEnv b
    forall key elt elts.
    Uniquable key =>
    (elt -> elts -> elts)
    -> (elt -> elts)
    -> UniqFM key elts
    -> key
    -> elt
    -> UniqFM key elts
    addToUFM_Acc a -> b -> b
    x a -> b
    y FastStringEnv b
    z FastString
    a a
    b
    extendFsEnvList_C :: forall a.
    (a -> a -> a)
    -> FastStringEnv a -> [(FastString, a)] -> FastStringEnv a
    extendFsEnvList_C a -> a -> a
    x FastStringEnv a
    y [(FastString, a)]
    z   = (a -> a -> a)
    -> FastStringEnv a -> [(FastString, a)] -> FastStringEnv a
    forall key elt.
    Uniquable key =>
    (elt -> elt -> elt)
    -> UniqFM key elt -> [(key, elt)] -> UniqFM key elt
    addListToUFM_C a -> a -> a
    x FastStringEnv a
    y [(FastString, a)]
    z
    delFromFsEnv :: forall a. FastStringEnv a -> FastString -> FastStringEnv a
    delFromFsEnv FastStringEnv a
    x FastString
    y          = FastStringEnv a -> FastString -> FastStringEnv a
    forall key elt.
    Uniquable key =>
    UniqFM key elt -> key -> UniqFM key elt
    delFromUFM FastStringEnv a
    x FastString
    y
    delListFromFsEnv :: forall a. FastStringEnv a -> [FastString] -> FastStringEnv a
    delListFromFsEnv FastStringEnv a
    x [FastString]
    y      = FastStringEnv a -> [FastString] -> FastStringEnv a
    forall key elt.
    Uniquable key =>
    UniqFM key elt -> [key] -> UniqFM key elt
    delListFromUFM FastStringEnv a
    x [FastString]
    y
    filterFsEnv :: forall elt. (elt -> Bool) -> FastStringEnv elt -> FastStringEnv elt
    filterFsEnv elt -> Bool
    x FastStringEnv elt
    y           = (elt -> Bool) -> FastStringEnv elt -> FastStringEnv elt
    forall {k} elt (key :: k).
    (elt -> Bool) -> UniqFM key elt -> UniqFM key elt
    filterUFM elt -> Bool
    x FastStringEnv elt
    y
    mapMaybeFsEnv :: forall elt1 elt2.
    (elt1 -> Maybe elt2) -> FastStringEnv elt1 -> FastStringEnv elt2
    mapMaybeFsEnv elt1 -> Maybe elt2
    f FastStringEnv elt1
    x         = (elt1 -> Maybe elt2)
    -> FastStringEnv elt1 -> UniqFM FastString elt2
    forall {k} elt1 elt2 (key :: k).
    (elt1 -> Maybe elt2) -> UniqFM key elt1 -> UniqFM key elt2
    mapMaybeUFM elt1 -> Maybe elt2
    f FastStringEnv elt1
    x

    lookupFsEnv_NF :: forall a. FastStringEnv a -> FastString -> a
    lookupFsEnv_NF FastStringEnv a
    env FastString
    n = String -> Maybe a -> a
    forall a. HasDebugCallStack => String -> Maybe a -> a
    expectJust String
    "lookupFsEnv_NF" (FastStringEnv a -> FastString -> Maybe a
    forall a. FastStringEnv a -> FastString -> Maybe a
    lookupFsEnv FastStringEnv a
    env FastString
    n)

    strictMapFsEnv :: (a -> b) -> FastStringEnv a -> FastStringEnv b
    strictMapFsEnv :: forall elt1 elt2.
    (elt1 -> elt2) -> FastStringEnv elt1 -> FastStringEnv elt2
    strictMapFsEnv = (a -> b) -> UniqFM FastString a -> UniqFM FastString b
    forall {k} elt1 elt2 (key :: k).
    (elt1 -> elt2) -> UniqFM key elt1 -> UniqFM key elt2
    strictMapUFM

    -- | Fold over a 'FastStringEnv'.
    --
    -- Non-deterministic, unless the folding function is commutative
    -- (i.e. @a1 `f` ( a2 `f` b ) == a2 `f` ( a1 `f` b )@ for all @a1@, @a2@, @b@).
    nonDetFoldFsEnv :: (a -> b -> b) -> b -> FastStringEnv a -> b
    nonDetFoldFsEnv :: forall a b. (a -> b -> b) -> b -> FastStringEnv a -> b
    nonDetFoldFsEnv = (a -> b -> b) -> b -> UniqFM FastString a -> b
    forall {k} elt a (key :: k).
    (elt -> a -> a) -> a -> UniqFM key elt -> a
    nonDetFoldUFM

    -- Deterministic FastStringEnv
    -- See Note [Deterministic UniqFM] in GHC.Types.Unique.DFM for explanation why we need
    -- DFastStringEnv.

    type DFastStringEnv a = UniqDFM FastString a  -- Domain is FastString

    emptyDFsEnv :: DFastStringEnv a
    emptyDFsEnv :: forall a. DFastStringEnv a
    emptyDFsEnv = UniqDFM FastString a
    forall {k} (key :: k) elt. UniqDFM key elt
    emptyUDFM

    dFsEnvElts :: DFastStringEnv a -> [a]
    dFsEnvElts :: forall a. DFastStringEnv a -> [a]
    dFsEnvElts = UniqDFM FastString a -> [a]
    forall {k} (key :: k) elt. UniqDFM key elt -> [elt]
    eltsUDFM

    mkDFsEnv :: [(FastString,a)] -> DFastStringEnv a
    mkDFsEnv :: forall a. [(FastString, a)] -> DFastStringEnv a
    mkDFsEnv [(FastString, a)]
    l = [(FastString, a)] -> UniqDFM FastString a
    forall key elt. Uniquable key => [(key, elt)] -> UniqDFM key elt
    listToUDFM [(FastString, a)]
    l

    lookupDFsEnv :: DFastStringEnv a -> FastString -> Maybe a
    lookupDFsEnv :: forall a. DFastStringEnv a -> FastString -> Maybe a
    lookupDFsEnv = UniqDFM FastString a -> FastString -> Maybe a
    forall key elt.
    Uniquable key =>
    UniqDFM key elt -> key -> Maybe elt
    lookupUDFM