-- | Facilities for computing free variables in an expression, which
-- we need for both lambda-lifting and defunctionalisation.
module Futhark.Internalise.FreeVars
  ( freeVars,
    without,
    ident,
    size,
    sizes,
    NameSet (..),
    patVars,
  )
where

import qualified Data.Map.Strict as M
import qualified Data.Set as S
import Futhark.IR.Pretty ()
import Language.Futhark

-- | A set of names where we also track uniqueness.
newtype NameSet = NameSet {NameSet -> Map VName StructType
unNameSet :: M.Map VName StructType}
  deriving (Int -> NameSet -> ShowS
[NameSet] -> ShowS
NameSet -> String
(Int -> NameSet -> ShowS)
-> (NameSet -> String) -> ([NameSet] -> ShowS) -> Show NameSet
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [NameSet] -> ShowS
$cshowList :: [NameSet] -> ShowS
show :: NameSet -> String
$cshow :: NameSet -> String
showsPrec :: Int -> NameSet -> ShowS
$cshowsPrec :: Int -> NameSet -> ShowS
Show)

instance Semigroup NameSet where
  NameSet Map VName StructType
x <> :: NameSet -> NameSet -> NameSet
<> NameSet Map VName StructType
y = Map VName StructType -> NameSet
NameSet (Map VName StructType -> NameSet)
-> Map VName StructType -> NameSet
forall a b. (a -> b) -> a -> b
$ (StructType -> StructType -> StructType)
-> Map VName StructType
-> Map VName StructType
-> Map VName StructType
forall k a. Ord k => (a -> a -> a) -> Map k a -> Map k a -> Map k a
M.unionWith StructType -> StructType -> StructType
forall a. Ord a => a -> a -> a
max Map VName StructType
x Map VName StructType
y

instance Monoid NameSet where
  mempty :: NameSet
mempty = Map VName StructType -> NameSet
NameSet Map VName StructType
forall a. Monoid a => a
mempty

-- | Set subtraction.
without :: NameSet -> S.Set VName -> NameSet
without :: NameSet -> Set VName -> NameSet
without (NameSet Map VName StructType
x) Set VName
y = Map VName StructType -> NameSet
NameSet (Map VName StructType -> NameSet)
-> Map VName StructType -> NameSet
forall a b. (a -> b) -> a -> b
$ (VName -> StructType -> Bool)
-> Map VName StructType -> Map VName StructType
forall k a. (k -> a -> Bool) -> Map k a -> Map k a
M.filterWithKey VName -> StructType -> Bool
forall p. VName -> p -> Bool
keep Map VName StructType
x
  where
    keep :: VName -> p -> Bool
keep VName
k p
_ = VName
k VName -> Set VName -> Bool
forall a. Ord a => a -> Set a -> Bool
`S.notMember` Set VName
y

withoutM :: NameSet -> NameSet -> NameSet
withoutM :: NameSet -> NameSet -> NameSet
withoutM (NameSet Map VName StructType
x) (NameSet Map VName StructType
y) = Map VName StructType -> NameSet
NameSet (Map VName StructType -> NameSet)
-> Map VName StructType -> NameSet
forall a b. (a -> b) -> a -> b
$ Map VName StructType
x Map VName StructType
-> Map VName StructType -> Map VName StructType
forall k a b. Ord k => Map k a -> Map k b -> Map k a
`M.difference` Map VName StructType
y

-- | A 'NameSet' with a single 'Nonunique' name.
ident :: Ident -> NameSet
ident :: Ident -> NameSet
ident Ident
v = Map VName StructType -> NameSet
NameSet (Map VName StructType -> NameSet)
-> Map VName StructType -> NameSet
forall a b. (a -> b) -> a -> b
$ VName -> StructType -> Map VName StructType
forall k a. k -> a -> Map k a
M.singleton (Ident -> VName
forall (f :: * -> *) vn. IdentBase f vn -> vn
identName Ident
v) (TypeBase (DimDecl VName) Aliasing -> StructType
forall dim as. TypeBase dim as -> TypeBase dim ()
toStruct (TypeBase (DimDecl VName) Aliasing -> StructType)
-> TypeBase (DimDecl VName) Aliasing -> StructType
forall a b. (a -> b) -> a -> b
$ Info (TypeBase (DimDecl VName) Aliasing)
-> TypeBase (DimDecl VName) Aliasing
forall a. Info a -> a
unInfo (Info (TypeBase (DimDecl VName) Aliasing)
 -> TypeBase (DimDecl VName) Aliasing)
-> Info (TypeBase (DimDecl VName) Aliasing)
-> TypeBase (DimDecl VName) Aliasing
forall a b. (a -> b) -> a -> b
$ Ident -> Info (TypeBase (DimDecl VName) Aliasing)
forall (f :: * -> *) vn.
IdentBase f vn -> f (TypeBase (DimDecl VName) Aliasing)
identType Ident
v)

size :: VName -> NameSet
size :: VName -> NameSet
size VName
v = Map VName StructType -> NameSet
NameSet (Map VName StructType -> NameSet)
-> Map VName StructType -> NameSet
forall a b. (a -> b) -> a -> b
$ VName -> StructType -> Map VName StructType
forall k a. k -> a -> Map k a
M.singleton VName
v (StructType -> Map VName StructType)
-> StructType -> Map VName StructType
forall a b. (a -> b) -> a -> b
$ ScalarTypeBase (DimDecl VName) () -> StructType
forall dim as. ScalarTypeBase dim as -> TypeBase dim as
Scalar (ScalarTypeBase (DimDecl VName) () -> StructType)
-> ScalarTypeBase (DimDecl VName) () -> StructType
forall a b. (a -> b) -> a -> b
$ PrimType -> ScalarTypeBase (DimDecl VName) ()
forall dim as. PrimType -> ScalarTypeBase dim as
Prim (PrimType -> ScalarTypeBase (DimDecl VName) ())
-> PrimType -> ScalarTypeBase (DimDecl VName) ()
forall a b. (a -> b) -> a -> b
$ IntType -> PrimType
Signed IntType
Int64

sizes :: S.Set VName -> NameSet
sizes :: Set VName -> NameSet
sizes = (VName -> NameSet) -> Set VName -> NameSet
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap VName -> NameSet
size

-- | Compute the set of free variables of an expression.
freeVars :: Exp -> NameSet
freeVars :: Exp -> NameSet
freeVars Exp
expr = case Exp
expr of
  Literal {} -> NameSet
forall a. Monoid a => a
mempty
  IntLit {} -> NameSet
forall a. Monoid a => a
mempty
  FloatLit {} -> NameSet
forall a. Monoid a => a
mempty
  StringLit {} -> NameSet
forall a. Monoid a => a
mempty
  Parens Exp
e SrcLoc
_ -> Exp -> NameSet
freeVars Exp
e
  QualParens (QualName VName, SrcLoc)
_ Exp
e SrcLoc
_ -> Exp -> NameSet
freeVars Exp
e
  TupLit [Exp]
es SrcLoc
_ -> (Exp -> NameSet) -> [Exp] -> NameSet
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Exp -> NameSet
freeVars [Exp]
es
  RecordLit [FieldBase Info VName]
fs SrcLoc
_ -> (FieldBase Info VName -> NameSet)
-> [FieldBase Info VName] -> NameSet
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap FieldBase Info VName -> NameSet
freeVarsField [FieldBase Info VName]
fs
    where
      freeVarsField :: FieldBase Info VName -> NameSet
freeVarsField (RecordFieldExplicit Name
_ Exp
e SrcLoc
_) = Exp -> NameSet
freeVars Exp
e
      freeVarsField (RecordFieldImplicit VName
vn Info (TypeBase (DimDecl VName) Aliasing)
t SrcLoc
_) = Ident -> NameSet
ident (Ident -> NameSet) -> Ident -> NameSet
forall a b. (a -> b) -> a -> b
$ VName
-> Info (TypeBase (DimDecl VName) Aliasing) -> SrcLoc -> Ident
forall (f :: * -> *) vn.
vn
-> f (TypeBase (DimDecl VName) Aliasing)
-> SrcLoc
-> IdentBase f vn
Ident VName
vn Info (TypeBase (DimDecl VName) Aliasing)
t SrcLoc
forall a. Monoid a => a
mempty
  ArrayLit [Exp]
es Info (TypeBase (DimDecl VName) Aliasing)
t SrcLoc
_ ->
    (Exp -> NameSet) -> [Exp] -> NameSet
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Exp -> NameSet
freeVars [Exp]
es NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> Set VName -> NameSet
sizes (TypeBase (DimDecl VName) Aliasing -> Set VName
forall als. TypeBase (DimDecl VName) als -> Set VName
typeDimNames (TypeBase (DimDecl VName) Aliasing -> Set VName)
-> TypeBase (DimDecl VName) Aliasing -> Set VName
forall a b. (a -> b) -> a -> b
$ Info (TypeBase (DimDecl VName) Aliasing)
-> TypeBase (DimDecl VName) Aliasing
forall a. Info a -> a
unInfo Info (TypeBase (DimDecl VName) Aliasing)
t)
  AppExp (Range Exp
e Maybe Exp
me Inclusiveness Exp
incl SrcLoc
_) Info AppRes
_ ->
    Exp -> NameSet
freeVars Exp
e NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> (Exp -> NameSet) -> Maybe Exp -> NameSet
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Exp -> NameSet
freeVars Maybe Exp
me NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> (Exp -> NameSet) -> Inclusiveness Exp -> NameSet
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Exp -> NameSet
freeVars Inclusiveness Exp
incl
  Var QualName VName
qn (Info TypeBase (DimDecl VName) Aliasing
t) SrcLoc
_ -> Map VName StructType -> NameSet
NameSet (Map VName StructType -> NameSet)
-> Map VName StructType -> NameSet
forall a b. (a -> b) -> a -> b
$ VName -> StructType -> Map VName StructType
forall k a. k -> a -> Map k a
M.singleton (QualName VName -> VName
forall vn. QualName vn -> vn
qualLeaf QualName VName
qn) (StructType -> Map VName StructType)
-> StructType -> Map VName StructType
forall a b. (a -> b) -> a -> b
$ TypeBase (DimDecl VName) Aliasing -> StructType
forall dim as. TypeBase dim as -> TypeBase dim ()
toStruct TypeBase (DimDecl VName) Aliasing
t
  Ascript Exp
e TypeDeclBase Info VName
t SrcLoc
_ -> Exp -> NameSet
freeVars Exp
e NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> Set VName -> NameSet
sizes (StructType -> Set VName
forall als. TypeBase (DimDecl VName) als -> Set VName
typeDimNames (StructType -> Set VName) -> StructType -> Set VName
forall a b. (a -> b) -> a -> b
$ Info StructType -> StructType
forall a. Info a -> a
unInfo (Info StructType -> StructType) -> Info StructType -> StructType
forall a b. (a -> b) -> a -> b
$ TypeDeclBase Info VName -> Info StructType
forall (f :: * -> *) vn. TypeDeclBase f vn -> f StructType
expandedType TypeDeclBase Info VName
t)
  AppExp (Coerce Exp
e TypeDeclBase Info VName
t SrcLoc
_) Info AppRes
_ -> Exp -> NameSet
freeVars Exp
e NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> Set VName -> NameSet
sizes (StructType -> Set VName
forall als. TypeBase (DimDecl VName) als -> Set VName
typeDimNames (StructType -> Set VName) -> StructType -> Set VName
forall a b. (a -> b) -> a -> b
$ Info StructType -> StructType
forall a. Info a -> a
unInfo (Info StructType -> StructType) -> Info StructType -> StructType
forall a b. (a -> b) -> a -> b
$ TypeDeclBase Info VName -> Info StructType
forall (f :: * -> *) vn. TypeDeclBase f vn -> f StructType
expandedType TypeDeclBase Info VName
t)
  AppExp (LetPat [SizeBinder VName]
let_sizes PatBase Info VName
pat Exp
e1 Exp
e2 SrcLoc
_) Info AppRes
_ ->
    Exp -> NameSet
freeVars Exp
e1
      NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> ( (Set VName -> NameSet
sizes (PatBase Info VName -> Set VName
patternDimNames PatBase Info VName
pat) NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> Exp -> NameSet
freeVars Exp
e2)
             NameSet -> NameSet -> NameSet
`withoutM` (PatBase Info VName -> NameSet
patVars PatBase Info VName
pat NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> (SizeBinder VName -> NameSet) -> [SizeBinder VName] -> NameSet
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (VName -> NameSet
size (VName -> NameSet)
-> (SizeBinder VName -> VName) -> SizeBinder VName -> NameSet
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SizeBinder VName -> VName
forall vn. SizeBinder vn -> vn
sizeName) [SizeBinder VName]
let_sizes)
         )
  AppExp (LetFun VName
vn ([TypeParamBase VName]
tparams, [PatBase Info VName]
pats, Maybe (TypeExp VName)
_, Info StructType
_, Exp
e1) Exp
e2 SrcLoc
_) Info AppRes
_ ->
    ( (Exp -> NameSet
freeVars Exp
e1 NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> Set VName -> NameSet
sizes ((PatBase Info VName -> Set VName)
-> [PatBase Info VName] -> Set VName
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap PatBase Info VName -> Set VName
patternDimNames [PatBase Info VName]
pats))
        NameSet -> Set VName -> NameSet
`without` ( (Ident -> VName) -> Set Ident -> Set VName
forall b a. Ord b => (a -> b) -> Set a -> Set b
S.map Ident -> VName
forall (f :: * -> *) vn. IdentBase f vn -> vn
identName ((PatBase Info VName -> Set Ident)
-> [PatBase Info VName] -> Set Ident
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap PatBase Info VName -> Set Ident
forall (f :: * -> *) vn.
(Functor f, Ord vn) =>
PatBase f vn -> Set (IdentBase f vn)
patIdents [PatBase Info VName]
pats)
                      Set VName -> Set VName -> Set VName
forall a. Semigroup a => a -> a -> a
<> [VName] -> Set VName
forall a. Ord a => [a] -> Set a
S.fromList ((TypeParamBase VName -> VName) -> [TypeParamBase VName] -> [VName]
forall a b. (a -> b) -> [a] -> [b]
map TypeParamBase VName -> VName
forall vn. TypeParamBase vn -> vn
typeParamName [TypeParamBase VName]
tparams)
                  )
    )
      NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> (Exp -> NameSet
freeVars Exp
e2 NameSet -> Set VName -> NameSet
`without` VName -> Set VName
forall a. a -> Set a
S.singleton VName
vn)
  AppExp (If Exp
e1 Exp
e2 Exp
e3 SrcLoc
_) Info AppRes
_ -> Exp -> NameSet
freeVars Exp
e1 NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> Exp -> NameSet
freeVars Exp
e2 NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> Exp -> NameSet
freeVars Exp
e3
  AppExp (Apply Exp
e1 Exp
e2 Info (Diet, Maybe VName)
_ SrcLoc
_) Info AppRes
_ -> Exp -> NameSet
freeVars Exp
e1 NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> Exp -> NameSet
freeVars Exp
e2
  Negate Exp
e SrcLoc
_ -> Exp -> NameSet
freeVars Exp
e
  Not Exp
e SrcLoc
_ -> Exp -> NameSet
freeVars Exp
e
  Lambda [PatBase Info VName]
pats Exp
e0 Maybe (TypeExp VName)
_ (Info (Aliasing
_, StructType
t)) SrcLoc
_ ->
    (Set VName -> NameSet
sizes ((PatBase Info VName -> Set VName)
-> [PatBase Info VName] -> Set VName
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap PatBase Info VName -> Set VName
patternDimNames [PatBase Info VName]
pats) NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> Exp -> NameSet
freeVars Exp
e0 NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> Set VName -> NameSet
sizes (StructType -> Set VName
forall als. TypeBase (DimDecl VName) als -> Set VName
typeDimNames StructType
t))
      NameSet -> NameSet -> NameSet
`withoutM` (PatBase Info VName -> NameSet) -> [PatBase Info VName] -> NameSet
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap PatBase Info VName -> NameSet
patVars [PatBase Info VName]
pats
  OpSection {} -> NameSet
forall a. Monoid a => a
mempty
  OpSectionLeft QualName VName
_ Info (TypeBase (DimDecl VName) Aliasing)
_ Exp
e (Info (PName, StructType, Maybe VName), Info (PName, StructType))
_ (Info (TypeBase (DimDecl VName) Aliasing), Info [VName])
_ SrcLoc
_ -> Exp -> NameSet
freeVars Exp
e
  OpSectionRight QualName VName
_ Info (TypeBase (DimDecl VName) Aliasing)
_ Exp
e (Info (PName, StructType), Info (PName, StructType, Maybe VName))
_ Info (TypeBase (DimDecl VName) Aliasing)
_ SrcLoc
_ -> Exp -> NameSet
freeVars Exp
e
  ProjectSection {} -> NameSet
forall a. Monoid a => a
mempty
  IndexSection SliceBase Info VName
idxs Info (TypeBase (DimDecl VName) Aliasing)
_ SrcLoc
_ -> (DimIndexBase Info VName -> NameSet)
-> SliceBase Info VName -> NameSet
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap DimIndexBase Info VName -> NameSet
freeDimIndex SliceBase Info VName
idxs
  AppExp (DoLoop [VName]
sparams PatBase Info VName
pat Exp
e1 LoopFormBase Info VName
form Exp
e3 SrcLoc
_) Info AppRes
_ ->
    let (NameSet
e2fv, NameSet
e2ident) = LoopFormBase Info VName -> (NameSet, NameSet)
formVars LoopFormBase Info VName
form
     in Exp -> NameSet
freeVars Exp
e1
          NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> ( (NameSet
e2fv NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> Exp -> NameSet
freeVars Exp
e3)
                 NameSet -> NameSet -> NameSet
`withoutM` (Set VName -> NameSet
sizes ([VName] -> Set VName
forall a. Ord a => [a] -> Set a
S.fromList [VName]
sparams) NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> PatBase Info VName -> NameSet
patVars PatBase Info VName
pat NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> NameSet
e2ident)
             )
    where
      formVars :: LoopFormBase Info VName -> (NameSet, NameSet)
formVars (For Ident
v Exp
e2) = (Exp -> NameSet
freeVars Exp
e2, Ident -> NameSet
ident Ident
v)
      formVars (ForIn PatBase Info VName
p Exp
e2) = (Exp -> NameSet
freeVars Exp
e2, PatBase Info VName -> NameSet
patVars PatBase Info VName
p)
      formVars (While Exp
e2) = (Exp -> NameSet
freeVars Exp
e2, NameSet
forall a. Monoid a => a
mempty)
  AppExp (BinOp (QualName VName
qn, SrcLoc
_) (Info TypeBase (DimDecl VName) Aliasing
qn_t) (Exp
e1, Info (StructType, Maybe VName)
_) (Exp
e2, Info (StructType, Maybe VName)
_) SrcLoc
_) Info AppRes
_ ->
    Map VName StructType -> NameSet
NameSet (VName -> StructType -> Map VName StructType
forall k a. k -> a -> Map k a
M.singleton (QualName VName -> VName
forall vn. QualName vn -> vn
qualLeaf QualName VName
qn) (StructType -> Map VName StructType)
-> StructType -> Map VName StructType
forall a b. (a -> b) -> a -> b
$ TypeBase (DimDecl VName) Aliasing -> StructType
forall dim as. TypeBase dim as -> TypeBase dim ()
toStruct TypeBase (DimDecl VName) Aliasing
qn_t)
      NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> Exp -> NameSet
freeVars Exp
e1
      NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> Exp -> NameSet
freeVars Exp
e2
  Project Name
_ Exp
e Info (TypeBase (DimDecl VName) Aliasing)
_ SrcLoc
_ -> Exp -> NameSet
freeVars Exp
e
  AppExp (LetWith Ident
id1 Ident
id2 SliceBase Info VName
idxs Exp
e1 Exp
e2 SrcLoc
_) Info AppRes
_ ->
    Ident -> NameSet
ident Ident
id2 NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> (DimIndexBase Info VName -> NameSet)
-> SliceBase Info VName -> NameSet
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap DimIndexBase Info VName -> NameSet
freeDimIndex SliceBase Info VName
idxs NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> Exp -> NameSet
freeVars Exp
e1
      NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> (Exp -> NameSet
freeVars Exp
e2 NameSet -> Set VName -> NameSet
`without` VName -> Set VName
forall a. a -> Set a
S.singleton (Ident -> VName
forall (f :: * -> *) vn. IdentBase f vn -> vn
identName Ident
id1))
  AppExp (Index Exp
e SliceBase Info VName
idxs SrcLoc
_) Info AppRes
_ -> Exp -> NameSet
freeVars Exp
e NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> (DimIndexBase Info VName -> NameSet)
-> SliceBase Info VName -> NameSet
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap DimIndexBase Info VName -> NameSet
freeDimIndex SliceBase Info VName
idxs
  Update Exp
e1 SliceBase Info VName
idxs Exp
e2 SrcLoc
_ -> Exp -> NameSet
freeVars Exp
e1 NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> (DimIndexBase Info VName -> NameSet)
-> SliceBase Info VName -> NameSet
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap DimIndexBase Info VName -> NameSet
freeDimIndex SliceBase Info VName
idxs NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> Exp -> NameSet
freeVars Exp
e2
  RecordUpdate Exp
e1 [Name]
_ Exp
e2 Info (TypeBase (DimDecl VName) Aliasing)
_ SrcLoc
_ -> Exp -> NameSet
freeVars Exp
e1 NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> Exp -> NameSet
freeVars Exp
e2
  Assert Exp
e1 Exp
e2 Info String
_ SrcLoc
_ -> Exp -> NameSet
freeVars Exp
e1 NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> Exp -> NameSet
freeVars Exp
e2
  Constr Name
_ [Exp]
es Info (TypeBase (DimDecl VName) Aliasing)
_ SrcLoc
_ -> (Exp -> NameSet) -> [Exp] -> NameSet
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Exp -> NameSet
freeVars [Exp]
es
  Attr AttrInfo
_ Exp
e SrcLoc
_ -> Exp -> NameSet
freeVars Exp
e
  AppExp (Match Exp
e NonEmpty (CaseBase Info VName)
cs SrcLoc
_) Info AppRes
_ -> Exp -> NameSet
freeVars Exp
e NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> (CaseBase Info VName -> NameSet)
-> NonEmpty (CaseBase Info VName) -> NameSet
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap CaseBase Info VName -> NameSet
caseFV NonEmpty (CaseBase Info VName)
cs
    where
      caseFV :: CaseBase Info VName -> NameSet
caseFV (CasePat PatBase Info VName
p Exp
eCase SrcLoc
_) =
        (Set VName -> NameSet
sizes (PatBase Info VName -> Set VName
patternDimNames PatBase Info VName
p) NameSet -> NameSet -> NameSet
forall a. Semigroup a => a -> a -> a
<> Exp -> NameSet
freeVars Exp
eCase)
          NameSet -> NameSet -> NameSet
`withoutM` PatBase Info VName -> NameSet
patVars PatBase Info VName
p

freeDimIndex :: DimIndexBase Info VName -> NameSet
freeDimIndex :: DimIndexBase Info VName -> NameSet
freeDimIndex (DimFix Exp
e) = Exp -> NameSet
freeVars Exp
e
freeDimIndex (DimSlice Maybe Exp
me1 Maybe Exp
me2 Maybe Exp
me3) =
  (Maybe Exp -> NameSet) -> [Maybe Exp] -> NameSet
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap ((Exp -> NameSet) -> Maybe Exp -> NameSet
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Exp -> NameSet
freeVars) [Maybe Exp
me1, Maybe Exp
me2, Maybe Exp
me3]

-- | Extract all the variable names bound in a pattern.
patVars :: Pat -> NameSet
patVars :: PatBase Info VName -> NameSet
patVars = [NameSet] -> NameSet
forall a. Monoid a => [a] -> a
mconcat ([NameSet] -> NameSet)
-> (PatBase Info VName -> [NameSet])
-> PatBase Info VName
-> NameSet
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Ident -> NameSet) -> [Ident] -> [NameSet]
forall a b. (a -> b) -> [a] -> [b]
map Ident -> NameSet
ident ([Ident] -> [NameSet])
-> (PatBase Info VName -> [Ident])
-> PatBase Info VName
-> [NameSet]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Set Ident -> [Ident]
forall a. Set a -> [a]
S.toList (Set Ident -> [Ident])
-> (PatBase Info VName -> Set Ident)
-> PatBase Info VName
-> [Ident]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PatBase Info VName -> Set Ident
forall (f :: * -> *) vn.
(Functor f, Ord vn) =>
PatBase f vn -> Set (IdentBase f vn)
patIdents