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

module VarEnv (
        -- * Var, Id and TyVar environments (maps)
        VarEnv, IdEnv, TyVarEnv, CoVarEnv, TyCoVarEnv,

        -- ** Manipulating these environments
        emptyVarEnv, unitVarEnv, mkVarEnv, mkVarEnv_Directly,
        elemVarEnv, disjointVarEnv,
        extendVarEnv, extendVarEnv_C, extendVarEnv_Acc, extendVarEnv_Directly,
        extendVarEnvList,
        plusVarEnv, plusVarEnv_C, plusVarEnv_CD, plusMaybeVarEnv_C,
        plusVarEnvList, alterVarEnv,
        delVarEnvList, delVarEnv, delVarEnv_Directly,
        minusVarEnv, intersectsVarEnv,
        lookupVarEnv, lookupVarEnv_NF, lookupWithDefaultVarEnv,
        mapVarEnv, zipVarEnv,
        modifyVarEnv, modifyVarEnv_Directly,
        isEmptyVarEnv,
        elemVarEnvByKey, lookupVarEnv_Directly,
        filterVarEnv, filterVarEnv_Directly, restrictVarEnv,
        partitionVarEnv,

        -- * Deterministic Var environments (maps)
        DVarEnv, DIdEnv, DTyVarEnv,

        -- ** Manipulating these environments
        emptyDVarEnv, mkDVarEnv,
        dVarEnvElts,
        extendDVarEnv, extendDVarEnv_C,
        extendDVarEnvList,
        lookupDVarEnv, elemDVarEnv,
        isEmptyDVarEnv, foldDVarEnv,
        mapDVarEnv, filterDVarEnv,
        modifyDVarEnv,
        alterDVarEnv,
        plusDVarEnv, plusDVarEnv_C,
        unitDVarEnv,
        delDVarEnv,
        delDVarEnvList,
        minusDVarEnv,
        partitionDVarEnv,
        anyDVarEnv,

        -- * The InScopeSet type
        InScopeSet,

        -- ** Operations on InScopeSets
        emptyInScopeSet, mkInScopeSet, delInScopeSet,
        extendInScopeSet, extendInScopeSetList, extendInScopeSetSet,
        getInScopeVars, lookupInScope, lookupInScope_Directly,
        unionInScope, elemInScopeSet, uniqAway,
        varSetInScope,

        -- * The RnEnv2 type
        RnEnv2,

        -- ** Operations on RnEnv2s
        mkRnEnv2, rnBndr2, rnBndrs2, rnBndr2_var,
        rnOccL, rnOccR, inRnEnvL, inRnEnvR, rnOccL_maybe, rnOccR_maybe,
        rnBndrL, rnBndrR, nukeRnEnvL, nukeRnEnvR, rnSwap,
        delBndrL, delBndrR, delBndrsL, delBndrsR,
        addRnInScopeSet,
        rnEtaL, rnEtaR,
        rnInScope, rnInScopeSet, lookupRnInScope,
        rnEnvL, rnEnvR,

        -- * TidyEnv and its operation
        TidyEnv,
        emptyTidyEnv, mkEmptyTidyEnv
    ) where

import GhcPrelude

import OccName
import Var
import VarSet
import UniqSet
import UniqFM
import UniqDFM
import Unique
import Util
import Maybes
import Outputable

{-
************************************************************************
*                                                                      *
                In-scope sets
*                                                                      *
************************************************************************
-}

-- | A set of variables that are in scope at some point
-- "Secrets of the Glasgow Haskell Compiler inliner" Section 3.2 provides
-- the motivation for this abstraction.
data InScopeSet = InScope VarSet {-# UNPACK #-} !Int
        -- Note [Lookups in in-scope set]
        -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        -- We store a VarSet here, but we use this for lookups rather than just
        -- membership tests. Typically the InScopeSet contains the canonical
        -- version of the variable (e.g. with an informative unfolding), so this
        -- lookup is useful (see, for instance, Note [In-scope set as a
        -- substitution]).
        --
        -- The Int is a kind of hash-value used by uniqAway
        -- For example, it might be the size of the set
        -- INVARIANT: it's not zero; we use it as a multiplier in uniqAway

instance Outputable InScopeSet where
  ppr :: InScopeSet -> SDoc
ppr (InScope VarSet
s Int
_) =
    String -> SDoc
text String
"InScope" SDoc -> SDoc -> SDoc
<+>
    SDoc -> SDoc
braces ([SDoc] -> SDoc
fsep ((Var -> SDoc) -> [Var] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map (Name -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Name -> SDoc) -> (Var -> Name) -> Var -> SDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Var -> Name
Var.varName) (VarSet -> [Var]
forall elt. UniqSet elt -> [elt]
nonDetEltsUniqSet VarSet
s)))
                      -- It's OK to use nonDetEltsUniqSet here because it's
                      -- only for pretty printing
                      -- In-scope sets get big, and with -dppr-debug
                      -- the output is overwhelming

emptyInScopeSet :: InScopeSet
emptyInScopeSet :: InScopeSet
emptyInScopeSet = VarSet -> Int -> InScopeSet
InScope VarSet
emptyVarSet Int
1

getInScopeVars ::  InScopeSet -> VarSet
getInScopeVars :: InScopeSet -> VarSet
getInScopeVars (InScope VarSet
vs Int
_) = VarSet
vs

mkInScopeSet :: VarSet -> InScopeSet
mkInScopeSet :: VarSet -> InScopeSet
mkInScopeSet VarSet
in_scope = VarSet -> Int -> InScopeSet
InScope VarSet
in_scope Int
1

extendInScopeSet :: InScopeSet -> Var -> InScopeSet
extendInScopeSet :: InScopeSet -> Var -> InScopeSet
extendInScopeSet (InScope VarSet
in_scope Int
n) Var
v
   = VarSet -> Int -> InScopeSet
InScope (VarSet -> Var -> VarSet
extendVarSet VarSet
in_scope Var
v) (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)

extendInScopeSetList :: InScopeSet -> [Var] -> InScopeSet
extendInScopeSetList :: InScopeSet -> [Var] -> InScopeSet
extendInScopeSetList (InScope VarSet
in_scope Int
n) [Var]
vs
   = VarSet -> Int -> InScopeSet
InScope ((VarSet -> Var -> VarSet) -> VarSet -> [Var] -> VarSet
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\VarSet
s Var
v -> VarSet -> Var -> VarSet
extendVarSet VarSet
s Var
v) VarSet
in_scope [Var]
vs)
                    (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [Var] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Var]
vs)

extendInScopeSetSet :: InScopeSet -> VarSet -> InScopeSet
extendInScopeSetSet :: InScopeSet -> VarSet -> InScopeSet
extendInScopeSetSet (InScope VarSet
in_scope Int
n) VarSet
vs
   = VarSet -> Int -> InScopeSet
InScope (VarSet
in_scope VarSet -> VarSet -> VarSet
`unionVarSet` VarSet
vs) (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ VarSet -> Int
forall a. UniqSet a -> Int
sizeUniqSet VarSet
vs)

delInScopeSet :: InScopeSet -> Var -> InScopeSet
delInScopeSet :: InScopeSet -> Var -> InScopeSet
delInScopeSet (InScope VarSet
in_scope Int
n) Var
v = VarSet -> Int -> InScopeSet
InScope (VarSet
in_scope VarSet -> Var -> VarSet
`delVarSet` Var
v) Int
n

elemInScopeSet :: Var -> InScopeSet -> Bool
elemInScopeSet :: Var -> InScopeSet -> Bool
elemInScopeSet Var
v (InScope VarSet
in_scope Int
_) = Var
v Var -> VarSet -> Bool
`elemVarSet` VarSet
in_scope

-- | Look up a variable the 'InScopeSet'.  This lets you map from
-- the variable's identity (unique) to its full value.
lookupInScope :: InScopeSet -> Var -> Maybe Var
lookupInScope :: InScopeSet -> Var -> Maybe Var
lookupInScope (InScope VarSet
in_scope Int
_) Var
v  = VarSet -> Var -> Maybe Var
lookupVarSet VarSet
in_scope Var
v

lookupInScope_Directly :: InScopeSet -> Unique -> Maybe Var
lookupInScope_Directly :: InScopeSet -> Unique -> Maybe Var
lookupInScope_Directly (InScope VarSet
in_scope Int
_) Unique
uniq
  = VarSet -> Unique -> Maybe Var
lookupVarSet_Directly VarSet
in_scope Unique
uniq

unionInScope :: InScopeSet -> InScopeSet -> InScopeSet
unionInScope :: InScopeSet -> InScopeSet -> InScopeSet
unionInScope (InScope VarSet
s1 Int
_) (InScope VarSet
s2 Int
n2)
  = VarSet -> Int -> InScopeSet
InScope (VarSet
s1 VarSet -> VarSet -> VarSet
`unionVarSet` VarSet
s2) Int
n2

varSetInScope :: VarSet -> InScopeSet -> Bool
varSetInScope :: VarSet -> InScopeSet -> Bool
varSetInScope VarSet
vars (InScope VarSet
s1 Int
_) = VarSet
vars VarSet -> VarSet -> Bool
`subVarSet` VarSet
s1

-- | @uniqAway in_scope v@ finds a unique that is not used in the
-- in-scope set, and gives that to v.
uniqAway :: InScopeSet -> Var -> Var
-- It starts with v's current unique, of course, in the hope that it won't
-- have to change, and thereafter uses a combination of that and the hash-code
-- found in the in-scope set
uniqAway :: InScopeSet -> Var -> Var
uniqAway InScopeSet
in_scope Var
var
  | Var
var Var -> InScopeSet -> Bool
`elemInScopeSet` InScopeSet
in_scope = InScopeSet -> Var -> Var
uniqAway' InScopeSet
in_scope Var
var      -- Make a new one
  | Bool
otherwise                     = Var
var                         -- Nothing to do

uniqAway' :: InScopeSet -> Var -> Var
-- This one *always* makes up a new variable
uniqAway' :: InScopeSet -> Var -> Var
uniqAway' (InScope VarSet
set Int
n) Var
var
  = Int -> Var
try Int
1
  where
    orig_unique :: Unique
orig_unique = Var -> Unique
forall a. Uniquable a => a -> Unique
getUnique Var
var
    try :: Int -> Var
try Int
k
          | Bool
debugIsOn Bool -> Bool -> Bool
&& (Int
k Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
1000)
          = String -> SDoc -> Var
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"uniqAway loop:" SDoc
msg
          | Unique
uniq Unique -> VarSet -> Bool
`elemVarSetByKey` VarSet
set = Int -> Var
try (Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
          | Int
k Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
3
          = String -> SDoc -> (Var -> Unique -> Var) -> Var -> Unique -> Var
forall a. String -> SDoc -> a -> a
pprTraceDebug String
"uniqAway:" SDoc
msg
            Var -> Unique -> Var
setVarUnique Var
var Unique
uniq
          | Bool
otherwise = Var -> Unique -> Var
setVarUnique Var
var Unique
uniq
          where
            msg :: SDoc
msg  = Int -> SDoc
forall a. Outputable a => a -> SDoc
ppr Int
k SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"tries" SDoc -> SDoc -> SDoc
<+> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
var SDoc -> SDoc -> SDoc
<+> Int -> SDoc
int Int
n
            uniq :: Unique
uniq = Unique -> Int -> Unique
deriveUnique Unique
orig_unique (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
k)

{-
************************************************************************
*                                                                      *
                Dual renaming
*                                                                      *
************************************************************************
-}

-- | Rename Environment 2
--
-- When we are comparing (or matching) types or terms, we are faced with
-- \"going under\" corresponding binders.  E.g. when comparing:
--
-- > \x. e1     ~   \y. e2
--
-- Basically we want to rename [@x@ -> @y@] or [@y@ -> @x@], but there are lots of
-- things we must be careful of.  In particular, @x@ might be free in @e2@, or
-- y in @e1@.  So the idea is that we come up with a fresh binder that is free
-- in neither, and rename @x@ and @y@ respectively.  That means we must maintain:
--
-- 1. A renaming for the left-hand expression
--
-- 2. A renaming for the right-hand expressions
--
-- 3. An in-scope set
--
-- Furthermore, when matching, we want to be able to have an 'occurs check',
-- to prevent:
--
-- > \x. f   ~   \y. y
--
-- matching with [@f@ -> @y@].  So for each expression we want to know that set of
-- locally-bound variables. That is precisely the domain of the mappings 1.
-- and 2., but we must ensure that we always extend the mappings as we go in.
--
-- All of this information is bundled up in the 'RnEnv2'
data RnEnv2
  = RV2 { RnEnv2 -> VarEnv Var
envL     :: VarEnv Var        -- Renaming for Left term
        , RnEnv2 -> VarEnv Var
envR     :: VarEnv Var        -- Renaming for Right term
        , RnEnv2 -> InScopeSet
in_scope :: InScopeSet }      -- In scope in left or right terms

-- The renamings envL and envR are *guaranteed* to contain a binding
-- for every variable bound as we go into the term, even if it is not
-- renamed.  That way we can ask what variables are locally bound
-- (inRnEnvL, inRnEnvR)

mkRnEnv2 :: InScopeSet -> RnEnv2
mkRnEnv2 :: InScopeSet -> RnEnv2
mkRnEnv2 InScopeSet
vars = RV2 :: VarEnv Var -> VarEnv Var -> InScopeSet -> RnEnv2
RV2     { envL :: VarEnv Var
envL     = VarEnv Var
forall a. VarEnv a
emptyVarEnv
                        , envR :: VarEnv Var
envR     = VarEnv Var
forall a. VarEnv a
emptyVarEnv
                        , in_scope :: InScopeSet
in_scope = InScopeSet
vars }

addRnInScopeSet :: RnEnv2 -> VarSet -> RnEnv2
addRnInScopeSet :: RnEnv2 -> VarSet -> RnEnv2
addRnInScopeSet RnEnv2
env VarSet
vs
  | VarSet -> Bool
isEmptyVarSet VarSet
vs = RnEnv2
env
  | Bool
otherwise        = RnEnv2
env { in_scope :: InScopeSet
in_scope = InScopeSet -> VarSet -> InScopeSet
extendInScopeSetSet (RnEnv2 -> InScopeSet
in_scope RnEnv2
env) VarSet
vs }

rnInScope :: Var -> RnEnv2 -> Bool
rnInScope :: Var -> RnEnv2 -> Bool
rnInScope Var
x RnEnv2
env = Var
x Var -> InScopeSet -> Bool
`elemInScopeSet` RnEnv2 -> InScopeSet
in_scope RnEnv2
env

rnInScopeSet :: RnEnv2 -> InScopeSet
rnInScopeSet :: RnEnv2 -> InScopeSet
rnInScopeSet = RnEnv2 -> InScopeSet
in_scope

-- | Retrieve the left mapping
rnEnvL :: RnEnv2 -> VarEnv Var
rnEnvL :: RnEnv2 -> VarEnv Var
rnEnvL = RnEnv2 -> VarEnv Var
envL

-- | Retrieve the right mapping
rnEnvR :: RnEnv2 -> VarEnv Var
rnEnvR :: RnEnv2 -> VarEnv Var
rnEnvR = RnEnv2 -> VarEnv Var
envR

rnBndrs2 :: RnEnv2 -> [Var] -> [Var] -> RnEnv2
-- ^ Applies 'rnBndr2' to several variables: the two variable lists must be of equal length
rnBndrs2 :: RnEnv2 -> [Var] -> [Var] -> RnEnv2
rnBndrs2 RnEnv2
env [Var]
bsL [Var]
bsR = (RnEnv2 -> Var -> Var -> RnEnv2)
-> RnEnv2 -> [Var] -> [Var] -> RnEnv2
forall acc a b. (acc -> a -> b -> acc) -> acc -> [a] -> [b] -> acc
foldl2 RnEnv2 -> Var -> Var -> RnEnv2
rnBndr2 RnEnv2
env [Var]
bsL [Var]
bsR

rnBndr2 :: RnEnv2 -> Var -> Var -> RnEnv2
-- ^ @rnBndr2 env bL bR@ goes under a binder @bL@ in the Left term,
--                       and binder @bR@ in the Right term.
-- It finds a new binder, @new_b@,
-- and returns an environment mapping @bL -> new_b@ and @bR -> new_b@
rnBndr2 :: RnEnv2 -> Var -> Var -> RnEnv2
rnBndr2 RnEnv2
env Var
bL Var
bR = (RnEnv2, Var) -> RnEnv2
forall a b. (a, b) -> a
fst ((RnEnv2, Var) -> RnEnv2) -> (RnEnv2, Var) -> RnEnv2
forall a b. (a -> b) -> a -> b
$ RnEnv2 -> Var -> Var -> (RnEnv2, Var)
rnBndr2_var RnEnv2
env Var
bL Var
bR

rnBndr2_var :: RnEnv2 -> Var -> Var -> (RnEnv2, Var)
-- ^ Similar to 'rnBndr2' but returns the new variable as well as the
-- new environment
rnBndr2_var :: RnEnv2 -> Var -> Var -> (RnEnv2, Var)
rnBndr2_var (RV2 { envL :: RnEnv2 -> VarEnv Var
envL = VarEnv Var
envL, envR :: RnEnv2 -> VarEnv Var
envR = VarEnv Var
envR, in_scope :: RnEnv2 -> InScopeSet
in_scope = InScopeSet
in_scope }) Var
bL Var
bR
  = (RV2 :: VarEnv Var -> VarEnv Var -> InScopeSet -> RnEnv2
RV2 { envL :: VarEnv Var
envL            = VarEnv Var -> Var -> Var -> VarEnv Var
forall a. VarEnv a -> Var -> a -> VarEnv a
extendVarEnv VarEnv Var
envL Var
bL Var
new_b   -- See Note
         , envR :: VarEnv Var
envR            = VarEnv Var -> Var -> Var -> VarEnv Var
forall a. VarEnv a -> Var -> a -> VarEnv a
extendVarEnv VarEnv Var
envR Var
bR Var
new_b   -- [Rebinding]
         , in_scope :: InScopeSet
in_scope = InScopeSet -> Var -> InScopeSet
extendInScopeSet InScopeSet
in_scope Var
new_b }, Var
new_b)
  where
        -- Find a new binder not in scope in either term
    new_b :: Var
new_b | Bool -> Bool
not (Var
bL Var -> InScopeSet -> Bool
`elemInScopeSet` InScopeSet
in_scope) = Var
bL
          | Bool -> Bool
not (Var
bR Var -> InScopeSet -> Bool
`elemInScopeSet` InScopeSet
in_scope) = Var
bR
          | Bool
otherwise                          = InScopeSet -> Var -> Var
uniqAway' InScopeSet
in_scope Var
bL

        -- Note [Rebinding]
        -- If the new var is the same as the old one, note that
        -- the extendVarEnv *deletes* any current renaming
        -- E.g.   (\x. \x. ...)  ~  (\y. \z. ...)
        --
        --   Inside \x  \y      { [x->y], [y->y],       {y} }
        --       \x  \z         { [x->x], [y->y, z->x], {y,x} }

rnBndrL :: RnEnv2 -> Var -> (RnEnv2, Var)
-- ^ Similar to 'rnBndr2' but used when there's a binder on the left
-- side only.
rnBndrL :: RnEnv2 -> Var -> (RnEnv2, Var)
rnBndrL (RV2 { envL :: RnEnv2 -> VarEnv Var
envL = VarEnv Var
envL, envR :: RnEnv2 -> VarEnv Var
envR = VarEnv Var
envR, in_scope :: RnEnv2 -> InScopeSet
in_scope = InScopeSet
in_scope }) Var
bL
  = (RV2 :: VarEnv Var -> VarEnv Var -> InScopeSet -> RnEnv2
RV2 { envL :: VarEnv Var
envL     = VarEnv Var -> Var -> Var -> VarEnv Var
forall a. VarEnv a -> Var -> a -> VarEnv a
extendVarEnv VarEnv Var
envL Var
bL Var
new_b
         , envR :: VarEnv Var
envR     = VarEnv Var
envR
         , in_scope :: InScopeSet
in_scope = InScopeSet -> Var -> InScopeSet
extendInScopeSet InScopeSet
in_scope Var
new_b }, Var
new_b)
  where
    new_b :: Var
new_b = InScopeSet -> Var -> Var
uniqAway InScopeSet
in_scope Var
bL

rnBndrR :: RnEnv2 -> Var -> (RnEnv2, Var)
-- ^ Similar to 'rnBndr2' but used when there's a binder on the right
-- side only.
rnBndrR :: RnEnv2 -> Var -> (RnEnv2, Var)
rnBndrR (RV2 { envL :: RnEnv2 -> VarEnv Var
envL = VarEnv Var
envL, envR :: RnEnv2 -> VarEnv Var
envR = VarEnv Var
envR, in_scope :: RnEnv2 -> InScopeSet
in_scope = InScopeSet
in_scope }) Var
bR
  = (RV2 :: VarEnv Var -> VarEnv Var -> InScopeSet -> RnEnv2
RV2 { envR :: VarEnv Var
envR     = VarEnv Var -> Var -> Var -> VarEnv Var
forall a. VarEnv a -> Var -> a -> VarEnv a
extendVarEnv VarEnv Var
envR Var
bR Var
new_b
         , envL :: VarEnv Var
envL     = VarEnv Var
envL
         , in_scope :: InScopeSet
in_scope = InScopeSet -> Var -> InScopeSet
extendInScopeSet InScopeSet
in_scope Var
new_b }, Var
new_b)
  where
    new_b :: Var
new_b = InScopeSet -> Var -> Var
uniqAway InScopeSet
in_scope Var
bR

rnEtaL :: RnEnv2 -> Var -> (RnEnv2, Var)
-- ^ Similar to 'rnBndrL' but used for eta expansion
-- See Note [Eta expansion]
rnEtaL :: RnEnv2 -> Var -> (RnEnv2, Var)
rnEtaL (RV2 { envL :: RnEnv2 -> VarEnv Var
envL = VarEnv Var
envL, envR :: RnEnv2 -> VarEnv Var
envR = VarEnv Var
envR, in_scope :: RnEnv2 -> InScopeSet
in_scope = InScopeSet
in_scope }) Var
bL
  = (RV2 :: VarEnv Var -> VarEnv Var -> InScopeSet -> RnEnv2
RV2 { envL :: VarEnv Var
envL     = VarEnv Var -> Var -> Var -> VarEnv Var
forall a. VarEnv a -> Var -> a -> VarEnv a
extendVarEnv VarEnv Var
envL Var
bL Var
new_b
         , envR :: VarEnv Var
envR     = VarEnv Var -> Var -> Var -> VarEnv Var
forall a. VarEnv a -> Var -> a -> VarEnv a
extendVarEnv VarEnv Var
envR Var
new_b Var
new_b     -- Note [Eta expansion]
         , in_scope :: InScopeSet
in_scope = InScopeSet -> Var -> InScopeSet
extendInScopeSet InScopeSet
in_scope Var
new_b }, Var
new_b)
  where
    new_b :: Var
new_b = InScopeSet -> Var -> Var
uniqAway InScopeSet
in_scope Var
bL

rnEtaR :: RnEnv2 -> Var -> (RnEnv2, Var)
-- ^ Similar to 'rnBndr2' but used for eta expansion
-- See Note [Eta expansion]
rnEtaR :: RnEnv2 -> Var -> (RnEnv2, Var)
rnEtaR (RV2 { envL :: RnEnv2 -> VarEnv Var
envL = VarEnv Var
envL, envR :: RnEnv2 -> VarEnv Var
envR = VarEnv Var
envR, in_scope :: RnEnv2 -> InScopeSet
in_scope = InScopeSet
in_scope }) Var
bR
  = (RV2 :: VarEnv Var -> VarEnv Var -> InScopeSet -> RnEnv2
RV2 { envL :: VarEnv Var
envL     = VarEnv Var -> Var -> Var -> VarEnv Var
forall a. VarEnv a -> Var -> a -> VarEnv a
extendVarEnv VarEnv Var
envL Var
new_b Var
new_b     -- Note [Eta expansion]
         , envR :: VarEnv Var
envR     = VarEnv Var -> Var -> Var -> VarEnv Var
forall a. VarEnv a -> Var -> a -> VarEnv a
extendVarEnv VarEnv Var
envR Var
bR Var
new_b
         , in_scope :: InScopeSet
in_scope = InScopeSet -> Var -> InScopeSet
extendInScopeSet InScopeSet
in_scope Var
new_b }, Var
new_b)
  where
    new_b :: Var
new_b = InScopeSet -> Var -> Var
uniqAway InScopeSet
in_scope Var
bR

delBndrL, delBndrR :: RnEnv2 -> Var -> RnEnv2
delBndrL :: RnEnv2 -> Var -> RnEnv2
delBndrL rn :: RnEnv2
rn@(RV2 { envL :: RnEnv2 -> VarEnv Var
envL = VarEnv Var
env, in_scope :: RnEnv2 -> InScopeSet
in_scope = InScopeSet
in_scope }) Var
v
  = RnEnv2
rn { envL :: VarEnv Var
envL = VarEnv Var
env VarEnv Var -> Var -> VarEnv Var
forall a. VarEnv a -> Var -> VarEnv a
`delVarEnv` Var
v, in_scope :: InScopeSet
in_scope = InScopeSet
in_scope InScopeSet -> Var -> InScopeSet
`extendInScopeSet` Var
v }
delBndrR :: RnEnv2 -> Var -> RnEnv2
delBndrR rn :: RnEnv2
rn@(RV2 { envR :: RnEnv2 -> VarEnv Var
envR = VarEnv Var
env, in_scope :: RnEnv2 -> InScopeSet
in_scope = InScopeSet
in_scope }) Var
v
  = RnEnv2
rn { envR :: VarEnv Var
envR = VarEnv Var
env VarEnv Var -> Var -> VarEnv Var
forall a. VarEnv a -> Var -> VarEnv a
`delVarEnv` Var
v, in_scope :: InScopeSet
in_scope = InScopeSet
in_scope InScopeSet -> Var -> InScopeSet
`extendInScopeSet` Var
v }

delBndrsL, delBndrsR :: RnEnv2 -> [Var] -> RnEnv2
delBndrsL :: RnEnv2 -> [Var] -> RnEnv2
delBndrsL rn :: RnEnv2
rn@(RV2 { envL :: RnEnv2 -> VarEnv Var
envL = VarEnv Var
env, in_scope :: RnEnv2 -> InScopeSet
in_scope = InScopeSet
in_scope }) [Var]
v
  = RnEnv2
rn { envL :: VarEnv Var
envL = VarEnv Var
env VarEnv Var -> [Var] -> VarEnv Var
forall a. VarEnv a -> [Var] -> VarEnv a
`delVarEnvList` [Var]
v, in_scope :: InScopeSet
in_scope = InScopeSet
in_scope InScopeSet -> [Var] -> InScopeSet
`extendInScopeSetList` [Var]
v }
delBndrsR :: RnEnv2 -> [Var] -> RnEnv2
delBndrsR rn :: RnEnv2
rn@(RV2 { envR :: RnEnv2 -> VarEnv Var
envR = VarEnv Var
env, in_scope :: RnEnv2 -> InScopeSet
in_scope = InScopeSet
in_scope }) [Var]
v
  = RnEnv2
rn { envR :: VarEnv Var
envR = VarEnv Var
env VarEnv Var -> [Var] -> VarEnv Var
forall a. VarEnv a -> [Var] -> VarEnv a
`delVarEnvList` [Var]
v, in_scope :: InScopeSet
in_scope = InScopeSet
in_scope InScopeSet -> [Var] -> InScopeSet
`extendInScopeSetList` [Var]
v }

rnOccL, rnOccR :: RnEnv2 -> Var -> Var
-- ^ Look up the renaming of an occurrence in the left or right term
rnOccL :: RnEnv2 -> Var -> Var
rnOccL (RV2 { envL :: RnEnv2 -> VarEnv Var
envL = VarEnv Var
env }) Var
v = VarEnv Var -> Var -> Maybe Var
forall a. VarEnv a -> Var -> Maybe a
lookupVarEnv VarEnv Var
env Var
v Maybe Var -> Var -> Var
forall a. Maybe a -> a -> a
`orElse` Var
v
rnOccR :: RnEnv2 -> Var -> Var
rnOccR (RV2 { envR :: RnEnv2 -> VarEnv Var
envR = VarEnv Var
env }) Var
v = VarEnv Var -> Var -> Maybe Var
forall a. VarEnv a -> Var -> Maybe a
lookupVarEnv VarEnv Var
env Var
v Maybe Var -> Var -> Var
forall a. Maybe a -> a -> a
`orElse` Var
v

rnOccL_maybe, rnOccR_maybe :: RnEnv2 -> Var -> Maybe Var
-- ^ Look up the renaming of an occurrence in the left or right term
rnOccL_maybe :: RnEnv2 -> Var -> Maybe Var
rnOccL_maybe (RV2 { envL :: RnEnv2 -> VarEnv Var
envL = VarEnv Var
env }) Var
v = VarEnv Var -> Var -> Maybe Var
forall a. VarEnv a -> Var -> Maybe a
lookupVarEnv VarEnv Var
env Var
v
rnOccR_maybe :: RnEnv2 -> Var -> Maybe Var
rnOccR_maybe (RV2 { envR :: RnEnv2 -> VarEnv Var
envR = VarEnv Var
env }) Var
v = VarEnv Var -> Var -> Maybe Var
forall a. VarEnv a -> Var -> Maybe a
lookupVarEnv VarEnv Var
env Var
v

inRnEnvL, inRnEnvR :: RnEnv2 -> Var -> Bool
-- ^ Tells whether a variable is locally bound
inRnEnvL :: RnEnv2 -> Var -> Bool
inRnEnvL (RV2 { envL :: RnEnv2 -> VarEnv Var
envL = VarEnv Var
env }) Var
v = Var
v Var -> VarEnv Var -> Bool
forall a. Var -> VarEnv a -> Bool
`elemVarEnv` VarEnv Var
env
inRnEnvR :: RnEnv2 -> Var -> Bool
inRnEnvR (RV2 { envR :: RnEnv2 -> VarEnv Var
envR = VarEnv Var
env }) Var
v = Var
v Var -> VarEnv Var -> Bool
forall a. Var -> VarEnv a -> Bool
`elemVarEnv` VarEnv Var
env

lookupRnInScope :: RnEnv2 -> Var -> Var
lookupRnInScope :: RnEnv2 -> Var -> Var
lookupRnInScope RnEnv2
env Var
v = InScopeSet -> Var -> Maybe Var
lookupInScope (RnEnv2 -> InScopeSet
in_scope RnEnv2
env) Var
v Maybe Var -> Var -> Var
forall a. Maybe a -> a -> a
`orElse` Var
v

nukeRnEnvL, nukeRnEnvR :: RnEnv2 -> RnEnv2
-- ^ Wipe the left or right side renaming
nukeRnEnvL :: RnEnv2 -> RnEnv2
nukeRnEnvL RnEnv2
env = RnEnv2
env { envL :: VarEnv Var
envL = VarEnv Var
forall a. VarEnv a
emptyVarEnv }
nukeRnEnvR :: RnEnv2 -> RnEnv2
nukeRnEnvR RnEnv2
env = RnEnv2
env { envR :: VarEnv Var
envR = VarEnv Var
forall a. VarEnv a
emptyVarEnv }

rnSwap :: RnEnv2 -> RnEnv2
-- ^ swap the meaning of left and right
rnSwap :: RnEnv2 -> RnEnv2
rnSwap (RV2 { envL :: RnEnv2 -> VarEnv Var
envL = VarEnv Var
envL, envR :: RnEnv2 -> VarEnv Var
envR = VarEnv Var
envR, in_scope :: RnEnv2 -> InScopeSet
in_scope = InScopeSet
in_scope })
  = RV2 :: VarEnv Var -> VarEnv Var -> InScopeSet -> RnEnv2
RV2 { envL :: VarEnv Var
envL = VarEnv Var
envR, envR :: VarEnv Var
envR = VarEnv Var
envL, in_scope :: InScopeSet
in_scope = InScopeSet
in_scope }

{-
Note [Eta expansion]
~~~~~~~~~~~~~~~~~~~~
When matching
     (\x.M) ~ N
we rename x to x' with, where x' is not in scope in
either term.  Then we want to behave as if we'd seen
     (\x'.M) ~ (\x'.N x')
Since x' isn't in scope in N, the form (\x'. N x') doesn't
capture any variables in N.  But we must nevertheless extend
the envR with a binding [x' -> x'], to support the occurs check.
For example, if we don't do this, we can get silly matches like
        forall a.  (\y.a)  ~   v
succeeding with [a -> v y], which is bogus of course.


************************************************************************
*                                                                      *
                Tidying
*                                                                      *
************************************************************************
-}

-- | Tidy Environment
--
-- When tidying up print names, we keep a mapping of in-scope occ-names
-- (the 'TidyOccEnv') and a Var-to-Var of the current renamings
type TidyEnv = (TidyOccEnv, VarEnv Var)

emptyTidyEnv :: TidyEnv
emptyTidyEnv :: TidyEnv
emptyTidyEnv = (TidyOccEnv
emptyTidyOccEnv, VarEnv Var
forall a. VarEnv a
emptyVarEnv)

mkEmptyTidyEnv :: TidyOccEnv -> TidyEnv
mkEmptyTidyEnv :: TidyOccEnv -> TidyEnv
mkEmptyTidyEnv TidyOccEnv
occ_env = (TidyOccEnv
occ_env, VarEnv Var
forall a. VarEnv a
emptyVarEnv)

{-
************************************************************************
*                                                                      *
\subsection{@VarEnv@s}
*                                                                      *
************************************************************************
-}

-- | Variable Environment
type VarEnv elt     = UniqFM elt

-- | Identifier Environment
type IdEnv elt      = VarEnv elt

-- | Type Variable Environment
type TyVarEnv elt   = VarEnv elt

-- | Type or Coercion Variable Environment
type TyCoVarEnv elt = VarEnv elt

-- | Coercion Variable Environment
type CoVarEnv elt   = VarEnv elt

emptyVarEnv       :: VarEnv a
mkVarEnv          :: [(Var, a)] -> VarEnv a
mkVarEnv_Directly :: [(Unique, a)] -> VarEnv a
zipVarEnv         :: [Var] -> [a] -> VarEnv a
unitVarEnv        :: Var -> a -> VarEnv a
alterVarEnv       :: (Maybe a -> Maybe a) -> VarEnv a -> Var -> VarEnv a
extendVarEnv      :: VarEnv a -> Var -> a -> VarEnv a
extendVarEnv_C    :: (a->a->a) -> VarEnv a -> Var -> a -> VarEnv a
extendVarEnv_Acc  :: (a->b->b) -> (a->b) -> VarEnv b -> Var -> a -> VarEnv b
extendVarEnv_Directly :: VarEnv a -> Unique -> a -> VarEnv a
plusVarEnv        :: VarEnv a -> VarEnv a -> VarEnv a
plusVarEnvList    :: [VarEnv a] -> VarEnv a
extendVarEnvList  :: VarEnv a -> [(Var, a)] -> VarEnv a

lookupVarEnv_Directly :: VarEnv a -> Unique -> Maybe a
filterVarEnv_Directly :: (Unique -> a -> Bool) -> VarEnv a -> VarEnv a
delVarEnv_Directly    :: VarEnv a -> Unique -> VarEnv a
partitionVarEnv   :: (a -> Bool) -> VarEnv a -> (VarEnv a, VarEnv a)
restrictVarEnv    :: VarEnv a -> VarSet -> VarEnv a
delVarEnvList     :: VarEnv a -> [Var] -> VarEnv a
delVarEnv         :: VarEnv a -> Var -> VarEnv a
minusVarEnv       :: VarEnv a -> VarEnv b -> VarEnv a
intersectsVarEnv  :: VarEnv a -> VarEnv a -> Bool
plusVarEnv_C      :: (a -> a -> a) -> VarEnv a -> VarEnv a -> VarEnv a
plusVarEnv_CD     :: (a -> a -> a) -> VarEnv a -> a -> VarEnv a -> a -> VarEnv a
plusMaybeVarEnv_C :: (a -> a -> Maybe a) -> VarEnv a -> VarEnv a -> VarEnv a
mapVarEnv         :: (a -> b) -> VarEnv a -> VarEnv b
modifyVarEnv      :: (a -> a) -> VarEnv a -> Var -> VarEnv a

isEmptyVarEnv     :: VarEnv a -> Bool
lookupVarEnv      :: VarEnv a -> Var -> Maybe a
filterVarEnv      :: (a -> Bool) -> VarEnv a -> VarEnv a
lookupVarEnv_NF   :: VarEnv a -> Var -> a
lookupWithDefaultVarEnv :: VarEnv a -> a -> Var -> a
elemVarEnv        :: Var -> VarEnv a -> Bool
elemVarEnvByKey   :: Unique -> VarEnv a -> Bool
disjointVarEnv    :: VarEnv a -> VarEnv a -> Bool

elemVarEnv :: Var -> VarEnv a -> Bool
elemVarEnv       = Var -> VarEnv a -> Bool
forall key elt. Uniquable key => key -> UniqFM elt -> Bool
elemUFM
elemVarEnvByKey :: Unique -> VarEnv a -> Bool
elemVarEnvByKey  = Unique -> VarEnv a -> Bool
forall elt. Unique -> UniqFM elt -> Bool
elemUFM_Directly
disjointVarEnv :: VarEnv a -> VarEnv a -> Bool
disjointVarEnv   = VarEnv a -> VarEnv a -> Bool
forall elt1 elt2. UniqFM elt1 -> UniqFM elt2 -> Bool
disjointUFM
alterVarEnv :: (Maybe a -> Maybe a) -> VarEnv a -> Var -> VarEnv a
alterVarEnv      = (Maybe a -> Maybe a) -> VarEnv a -> Var -> VarEnv a
forall key elt.
Uniquable key =>
(Maybe elt -> Maybe elt) -> UniqFM elt -> key -> UniqFM elt
alterUFM
extendVarEnv :: VarEnv a -> Var -> a -> VarEnv a
extendVarEnv     = VarEnv a -> Var -> a -> VarEnv a
forall key elt.
Uniquable key =>
UniqFM elt -> key -> elt -> UniqFM elt
addToUFM
extendVarEnv_C :: (a -> a -> a) -> VarEnv a -> Var -> a -> VarEnv a
extendVarEnv_C   = (a -> a -> a) -> VarEnv a -> Var -> a -> VarEnv a
forall key elt.
Uniquable key =>
(elt -> elt -> elt) -> UniqFM elt -> key -> elt -> UniqFM elt
addToUFM_C
extendVarEnv_Acc :: (a -> b -> b) -> (a -> b) -> VarEnv b -> Var -> a -> VarEnv b
extendVarEnv_Acc = (a -> b -> b) -> (a -> b) -> VarEnv b -> Var -> a -> VarEnv b
forall key elt elts.
Uniquable key =>
(elt -> elts -> elts)
-> (elt -> elts) -> UniqFM elts -> key -> elt -> UniqFM elts
addToUFM_Acc
extendVarEnv_Directly :: VarEnv a -> Unique -> a -> VarEnv a
extendVarEnv_Directly = VarEnv a -> Unique -> a -> VarEnv a
forall elt. UniqFM elt -> Unique -> elt -> UniqFM elt
addToUFM_Directly
extendVarEnvList :: VarEnv a -> [(Var, a)] -> VarEnv a
extendVarEnvList = VarEnv a -> [(Var, a)] -> VarEnv a
forall key elt.
Uniquable key =>
UniqFM elt -> [(key, elt)] -> UniqFM elt
addListToUFM
plusVarEnv_C :: (a -> a -> a) -> VarEnv a -> VarEnv a -> VarEnv a
plusVarEnv_C     = (a -> a -> a) -> VarEnv a -> VarEnv a -> VarEnv a
forall elt.
(elt -> elt -> elt) -> UniqFM elt -> UniqFM elt -> UniqFM elt
plusUFM_C
plusVarEnv_CD :: (a -> a -> a) -> VarEnv a -> a -> VarEnv a -> a -> VarEnv a
plusVarEnv_CD    = (a -> a -> a) -> VarEnv a -> a -> VarEnv a -> a -> VarEnv a
forall elt.
(elt -> elt -> elt)
-> UniqFM elt -> elt -> UniqFM elt -> elt -> UniqFM elt
plusUFM_CD
plusMaybeVarEnv_C :: (a -> a -> Maybe a) -> VarEnv a -> VarEnv a -> VarEnv a
plusMaybeVarEnv_C = (a -> a -> Maybe a) -> VarEnv a -> VarEnv a -> VarEnv a
forall elt.
(elt -> elt -> Maybe elt) -> UniqFM elt -> UniqFM elt -> UniqFM elt
plusMaybeUFM_C
delVarEnvList :: VarEnv a -> [Var] -> VarEnv a
delVarEnvList    = VarEnv a -> [Var] -> VarEnv a
forall key elt. Uniquable key => UniqFM elt -> [key] -> UniqFM elt
delListFromUFM
delVarEnv :: VarEnv a -> Var -> VarEnv a
delVarEnv        = VarEnv a -> Var -> VarEnv a
forall key elt. Uniquable key => UniqFM elt -> key -> UniqFM elt
delFromUFM
minusVarEnv :: VarEnv a -> VarEnv b -> VarEnv a
minusVarEnv      = VarEnv a -> VarEnv b -> VarEnv a
forall elt1 elt2. UniqFM elt1 -> UniqFM elt2 -> UniqFM elt1
minusUFM
intersectsVarEnv :: VarEnv a -> VarEnv a -> Bool
intersectsVarEnv VarEnv a
e1 VarEnv a
e2 = Bool -> Bool
not (VarEnv a -> Bool
forall a. VarEnv a -> Bool
isEmptyVarEnv (VarEnv a
e1 VarEnv a -> VarEnv a -> VarEnv a
forall elt1 elt2. UniqFM elt1 -> UniqFM elt2 -> UniqFM elt1
`intersectUFM` VarEnv a
e2))
plusVarEnv :: VarEnv a -> VarEnv a -> VarEnv a
plusVarEnv       = VarEnv a -> VarEnv a -> VarEnv a
forall elt. UniqFM elt -> UniqFM elt -> UniqFM elt
plusUFM
plusVarEnvList :: [VarEnv a] -> VarEnv a
plusVarEnvList   = [VarEnv a] -> VarEnv a
forall elt. [UniqFM elt] -> UniqFM elt
plusUFMList
lookupVarEnv :: VarEnv a -> Var -> Maybe a
lookupVarEnv     = VarEnv a -> Var -> Maybe a
forall key elt. Uniquable key => UniqFM elt -> key -> Maybe elt
lookupUFM
filterVarEnv :: (a -> Bool) -> VarEnv a -> VarEnv a
filterVarEnv     = (a -> Bool) -> VarEnv a -> VarEnv a
forall elt. (elt -> Bool) -> UniqFM elt -> UniqFM elt
filterUFM
lookupWithDefaultVarEnv :: VarEnv a -> a -> Var -> a
lookupWithDefaultVarEnv = VarEnv a -> a -> Var -> a
forall key elt. Uniquable key => UniqFM elt -> elt -> key -> elt
lookupWithDefaultUFM
mapVarEnv :: (a -> b) -> VarEnv a -> VarEnv b
mapVarEnv        = (a -> b) -> VarEnv a -> VarEnv b
forall elt1 elt2. (elt1 -> elt2) -> UniqFM elt1 -> UniqFM elt2
mapUFM
mkVarEnv :: [(Var, a)] -> VarEnv a
mkVarEnv         = [(Var, a)] -> VarEnv a
forall key elt. Uniquable key => [(key, elt)] -> UniqFM elt
listToUFM
mkVarEnv_Directly :: [(Unique, a)] -> VarEnv a
mkVarEnv_Directly= [(Unique, a)] -> VarEnv a
forall elt. [(Unique, elt)] -> UniqFM elt
listToUFM_Directly
emptyVarEnv :: VarEnv a
emptyVarEnv      = VarEnv a
forall a. VarEnv a
emptyUFM
unitVarEnv :: Var -> a -> VarEnv a
unitVarEnv       = Var -> a -> VarEnv a
forall key elt. Uniquable key => key -> elt -> UniqFM elt
unitUFM
isEmptyVarEnv :: VarEnv a -> Bool
isEmptyVarEnv    = VarEnv a -> Bool
forall a. VarEnv a -> Bool
isNullUFM
lookupVarEnv_Directly :: VarEnv a -> Unique -> Maybe a
lookupVarEnv_Directly = VarEnv a -> Unique -> Maybe a
forall elt. UniqFM elt -> Unique -> Maybe elt
lookupUFM_Directly
filterVarEnv_Directly :: (Unique -> a -> Bool) -> VarEnv a -> VarEnv a
filterVarEnv_Directly = (Unique -> a -> Bool) -> VarEnv a -> VarEnv a
forall elt. (Unique -> elt -> Bool) -> UniqFM elt -> UniqFM elt
filterUFM_Directly
delVarEnv_Directly :: VarEnv a -> Unique -> VarEnv a
delVarEnv_Directly    = VarEnv a -> Unique -> VarEnv a
forall elt. UniqFM elt -> Unique -> UniqFM elt
delFromUFM_Directly
partitionVarEnv :: (a -> Bool) -> VarEnv a -> (VarEnv a, VarEnv a)
partitionVarEnv       = (a -> Bool) -> VarEnv a -> (VarEnv a, VarEnv a)
forall elt. (elt -> Bool) -> UniqFM elt -> (UniqFM elt, UniqFM elt)
partitionUFM

restrictVarEnv :: VarEnv a -> VarSet -> VarEnv a
restrictVarEnv VarEnv a
env VarSet
vs = (Unique -> a -> Bool) -> VarEnv a -> VarEnv a
forall elt. (Unique -> elt -> Bool) -> UniqFM elt -> UniqFM elt
filterVarEnv_Directly Unique -> a -> Bool
forall p. Unique -> p -> Bool
keep VarEnv a
env
  where
    keep :: Unique -> p -> Bool
keep Unique
u p
_ = Unique
u Unique -> VarSet -> Bool
`elemVarSetByKey` VarSet
vs

zipVarEnv :: [Var] -> [a] -> VarEnv a
zipVarEnv [Var]
tyvars [a]
tys   = [(Var, a)] -> VarEnv a
forall a. [(Var, a)] -> VarEnv a
mkVarEnv (String -> [Var] -> [a] -> [(Var, a)]
forall a b. String -> [a] -> [b] -> [(a, b)]
zipEqual String
"zipVarEnv" [Var]
tyvars [a]
tys)
lookupVarEnv_NF :: VarEnv a -> Var -> a
lookupVarEnv_NF VarEnv a
env Var
id = case VarEnv a -> Var -> Maybe a
forall a. VarEnv a -> Var -> Maybe a
lookupVarEnv VarEnv a
env Var
id of
                         Just a
xx -> a
xx
                         Maybe a
Nothing -> String -> a
forall a. String -> a
panic String
"lookupVarEnv_NF: Nothing"

{-
@modifyVarEnv@: Look up a thing in the VarEnv,
then mash it with the modify function, and put it back.
-}

modifyVarEnv :: (a -> a) -> VarEnv a -> Var -> VarEnv a
modifyVarEnv a -> a
mangle_fn VarEnv a
env Var
key
  = case (VarEnv a -> Var -> Maybe a
forall a. VarEnv a -> Var -> Maybe a
lookupVarEnv VarEnv a
env Var
key) of
      Maybe a
Nothing -> VarEnv a
env
      Just a
xx -> VarEnv a -> Var -> a -> VarEnv a
forall a. VarEnv a -> Var -> a -> VarEnv a
extendVarEnv VarEnv a
env Var
key (a -> a
mangle_fn a
xx)

modifyVarEnv_Directly :: (a -> a) -> UniqFM a -> Unique -> UniqFM a
modifyVarEnv_Directly :: (a -> a) -> UniqFM a -> Unique -> UniqFM a
modifyVarEnv_Directly a -> a
mangle_fn UniqFM a
env Unique
key
  = case (UniqFM a -> Unique -> Maybe a
forall elt. UniqFM elt -> Unique -> Maybe elt
lookupUFM_Directly UniqFM a
env Unique
key) of
      Maybe a
Nothing -> UniqFM a
env
      Just a
xx -> UniqFM a -> Unique -> a -> UniqFM a
forall elt. UniqFM elt -> Unique -> elt -> UniqFM elt
addToUFM_Directly UniqFM a
env Unique
key (a -> a
mangle_fn a
xx)

-- Deterministic VarEnv
-- See Note [Deterministic UniqFM] in UniqDFM for explanation why we need
-- DVarEnv.

-- | Deterministic Variable Environment
type DVarEnv elt = UniqDFM elt

-- | Deterministic Identifier Environment
type DIdEnv elt = DVarEnv elt

-- | Deterministic Type Variable Environment
type DTyVarEnv elt = DVarEnv elt

emptyDVarEnv :: DVarEnv a
emptyDVarEnv :: DVarEnv a
emptyDVarEnv = DVarEnv a
forall elt. UniqDFM elt
emptyUDFM

dVarEnvElts :: DVarEnv a -> [a]
dVarEnvElts :: DVarEnv a -> [a]
dVarEnvElts = DVarEnv a -> [a]
forall elt. UniqDFM elt -> [elt]
eltsUDFM

mkDVarEnv :: [(Var, a)] -> DVarEnv a
mkDVarEnv :: [(Var, a)] -> DVarEnv a
mkDVarEnv = [(Var, a)] -> DVarEnv a
forall key elt. Uniquable key => [(key, elt)] -> UniqDFM elt
listToUDFM

extendDVarEnv :: DVarEnv a -> Var -> a -> DVarEnv a
extendDVarEnv :: DVarEnv a -> Var -> a -> DVarEnv a
extendDVarEnv = DVarEnv a -> Var -> a -> DVarEnv a
forall key elt.
Uniquable key =>
UniqDFM elt -> key -> elt -> UniqDFM elt
addToUDFM

minusDVarEnv :: DVarEnv a -> DVarEnv a' -> DVarEnv a
minusDVarEnv :: DVarEnv a -> DVarEnv a' -> DVarEnv a
minusDVarEnv = DVarEnv a -> DVarEnv a' -> DVarEnv a
forall elt1 elt2. UniqDFM elt1 -> UniqDFM elt2 -> UniqDFM elt1
minusUDFM

lookupDVarEnv :: DVarEnv a -> Var -> Maybe a
lookupDVarEnv :: DVarEnv a -> Var -> Maybe a
lookupDVarEnv = DVarEnv a -> Var -> Maybe a
forall key elt. Uniquable key => UniqDFM elt -> key -> Maybe elt
lookupUDFM

foldDVarEnv :: (a -> b -> b) -> b -> DVarEnv a -> b
foldDVarEnv :: (a -> b -> b) -> b -> DVarEnv a -> b
foldDVarEnv = (a -> b -> b) -> b -> DVarEnv a -> b
forall elt a. (elt -> a -> a) -> a -> UniqDFM elt -> a
foldUDFM

mapDVarEnv :: (a -> b) -> DVarEnv a -> DVarEnv b
mapDVarEnv :: (a -> b) -> DVarEnv a -> DVarEnv b
mapDVarEnv = (a -> b) -> DVarEnv a -> DVarEnv b
forall elt1 elt2. (elt1 -> elt2) -> UniqDFM elt1 -> UniqDFM elt2
mapUDFM

filterDVarEnv      :: (a -> Bool) -> DVarEnv a -> DVarEnv a
filterDVarEnv :: (a -> Bool) -> DVarEnv a -> DVarEnv a
filterDVarEnv = (a -> Bool) -> DVarEnv a -> DVarEnv a
forall elt. (elt -> Bool) -> UniqDFM elt -> UniqDFM elt
filterUDFM

alterDVarEnv :: (Maybe a -> Maybe a) -> DVarEnv a -> Var -> DVarEnv a
alterDVarEnv :: (Maybe a -> Maybe a) -> DVarEnv a -> Var -> DVarEnv a
alterDVarEnv = (Maybe a -> Maybe a) -> DVarEnv a -> Var -> DVarEnv a
forall key elt.
Uniquable key =>
(Maybe elt -> Maybe elt) -> UniqDFM elt -> key -> UniqDFM elt
alterUDFM

plusDVarEnv :: DVarEnv a -> DVarEnv a -> DVarEnv a
plusDVarEnv :: DVarEnv a -> DVarEnv a -> DVarEnv a
plusDVarEnv = DVarEnv a -> DVarEnv a -> DVarEnv a
forall elt. UniqDFM elt -> UniqDFM elt -> UniqDFM elt
plusUDFM

plusDVarEnv_C :: (a -> a -> a) -> DVarEnv a -> DVarEnv a -> DVarEnv a
plusDVarEnv_C :: (a -> a -> a) -> DVarEnv a -> DVarEnv a -> DVarEnv a
plusDVarEnv_C = (a -> a -> a) -> DVarEnv a -> DVarEnv a -> DVarEnv a
forall elt.
(elt -> elt -> elt) -> UniqDFM elt -> UniqDFM elt -> UniqDFM elt
plusUDFM_C

unitDVarEnv :: Var -> a -> DVarEnv a
unitDVarEnv :: Var -> a -> DVarEnv a
unitDVarEnv = Var -> a -> DVarEnv a
forall key elt. Uniquable key => key -> elt -> UniqDFM elt
unitUDFM

delDVarEnv :: DVarEnv a -> Var -> DVarEnv a
delDVarEnv :: DVarEnv a -> Var -> DVarEnv a
delDVarEnv = DVarEnv a -> Var -> DVarEnv a
forall key elt. Uniquable key => UniqDFM elt -> key -> UniqDFM elt
delFromUDFM

delDVarEnvList :: DVarEnv a -> [Var] -> DVarEnv a
delDVarEnvList :: DVarEnv a -> [Var] -> DVarEnv a
delDVarEnvList = DVarEnv a -> [Var] -> DVarEnv a
forall key elt.
Uniquable key =>
UniqDFM elt -> [key] -> UniqDFM elt
delListFromUDFM

isEmptyDVarEnv :: DVarEnv a -> Bool
isEmptyDVarEnv :: DVarEnv a -> Bool
isEmptyDVarEnv = DVarEnv a -> Bool
forall elt. UniqDFM elt -> Bool
isNullUDFM

elemDVarEnv :: Var -> DVarEnv a -> Bool
elemDVarEnv :: Var -> DVarEnv a -> Bool
elemDVarEnv = Var -> DVarEnv a -> Bool
forall key elt. Uniquable key => key -> UniqDFM elt -> Bool
elemUDFM

extendDVarEnv_C :: (a -> a -> a) -> DVarEnv a -> Var -> a -> DVarEnv a
extendDVarEnv_C :: (a -> a -> a) -> DVarEnv a -> Var -> a -> DVarEnv a
extendDVarEnv_C = (a -> a -> a) -> DVarEnv a -> Var -> a -> DVarEnv a
forall key elt.
Uniquable key =>
(elt -> elt -> elt) -> UniqDFM elt -> key -> elt -> UniqDFM elt
addToUDFM_C

modifyDVarEnv :: (a -> a) -> DVarEnv a -> Var -> DVarEnv a
modifyDVarEnv :: (a -> a) -> DVarEnv a -> Var -> DVarEnv a
modifyDVarEnv a -> a
mangle_fn DVarEnv a
env Var
key
  = case (DVarEnv a -> Var -> Maybe a
forall a. DVarEnv a -> Var -> Maybe a
lookupDVarEnv DVarEnv a
env Var
key) of
      Maybe a
Nothing -> DVarEnv a
env
      Just a
xx -> DVarEnv a -> Var -> a -> DVarEnv a
forall a. DVarEnv a -> Var -> a -> DVarEnv a
extendDVarEnv DVarEnv a
env Var
key (a -> a
mangle_fn a
xx)

partitionDVarEnv :: (a -> Bool) -> DVarEnv a -> (DVarEnv a, DVarEnv a)
partitionDVarEnv :: (a -> Bool) -> DVarEnv a -> (DVarEnv a, DVarEnv a)
partitionDVarEnv = (a -> Bool) -> DVarEnv a -> (DVarEnv a, DVarEnv a)
forall elt.
(elt -> Bool) -> UniqDFM elt -> (UniqDFM elt, UniqDFM elt)
partitionUDFM

extendDVarEnvList :: DVarEnv a -> [(Var, a)] -> DVarEnv a
extendDVarEnvList :: DVarEnv a -> [(Var, a)] -> DVarEnv a
extendDVarEnvList = DVarEnv a -> [(Var, a)] -> DVarEnv a
forall key elt.
Uniquable key =>
UniqDFM elt -> [(key, elt)] -> UniqDFM elt
addListToUDFM

anyDVarEnv :: (a -> Bool) -> DVarEnv a -> Bool
anyDVarEnv :: (a -> Bool) -> DVarEnv a -> Bool
anyDVarEnv = (a -> Bool) -> DVarEnv a -> Bool
forall elt. (elt -> Bool) -> UniqDFM elt -> Bool
anyUDFM