{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}

-- |
--
-- This module contains facilities for replacing variable names in
-- syntactic constructs.
module Futhark.Transform.Substitute
  ( Substitutions,
    Substitute (..),
    Substitutable,
  )
where

import Control.Monad.Identity
import qualified Data.Map.Strict as M
import Futhark.Analysis.PrimExp
import Futhark.IR.Prop.Names
import Futhark.IR.Prop.Scope
import Futhark.IR.Syntax
import Futhark.IR.Traversals

-- | The substitutions to be made are given by a mapping from names to
-- names.
type Substitutions = M.Map VName VName

-- | A type that is an instance of this class supports substitution of
-- any names contained within.
class Substitute a where
  -- | @substituteNames m e@ replaces the variable names in @e@ with
  -- new names, based on the mapping in @m@.  It is assumed that all
  -- names in @e@ are unique, i.e. there is no shadowing.
  substituteNames :: M.Map VName VName -> a -> a

instance Substitute a => Substitute [a] where
  substituteNames :: Map VName VName -> [a] -> [a]
substituteNames Map VName VName
substs = (a -> a) -> [a] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map ((a -> a) -> [a] -> [a]) -> (a -> a) -> [a] -> [a]
forall a b. (a -> b) -> a -> b
$ Map VName VName -> a -> a
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs

instance Substitute (Stm lore) => Substitute (Stms lore) where
  substituteNames :: Map VName VName -> Stms lore -> Stms lore
substituteNames Map VName VName
substs = (Stm lore -> Stm lore) -> Stms lore -> Stms lore
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Stm lore -> Stm lore) -> Stms lore -> Stms lore)
-> (Stm lore -> Stm lore) -> Stms lore -> Stms lore
forall a b. (a -> b) -> a -> b
$ Map VName VName -> Stm lore -> Stm lore
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs

instance (Substitute a, Substitute b) => Substitute (a, b) where
  substituteNames :: Map VName VName -> (a, b) -> (a, b)
substituteNames Map VName VName
substs (a
x, b
y) =
    (Map VName VName -> a -> a
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs a
x, Map VName VName -> b -> b
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs b
y)

instance (Substitute a, Substitute b, Substitute c) => Substitute (a, b, c) where
  substituteNames :: Map VName VName -> (a, b, c) -> (a, b, c)
substituteNames Map VName VName
substs (a
x, b
y, c
z) =
    ( Map VName VName -> a -> a
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs a
x,
      Map VName VName -> b -> b
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs b
y,
      Map VName VName -> c -> c
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs c
z
    )

instance (Substitute a, Substitute b, Substitute c, Substitute d) => Substitute (a, b, c, d) where
  substituteNames :: Map VName VName -> (a, b, c, d) -> (a, b, c, d)
substituteNames Map VName VName
substs (a
x, b
y, c
z, d
u) =
    ( Map VName VName -> a -> a
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs a
x,
      Map VName VName -> b -> b
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs b
y,
      Map VName VName -> c -> c
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs c
z,
      Map VName VName -> d -> d
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs d
u
    )

instance Substitute a => Substitute (Maybe a) where
  substituteNames :: Map VName VName -> Maybe a -> Maybe a
substituteNames Map VName VName
substs = (a -> a) -> Maybe a -> Maybe a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((a -> a) -> Maybe a -> Maybe a) -> (a -> a) -> Maybe a -> Maybe a
forall a b. (a -> b) -> a -> b
$ Map VName VName -> a -> a
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs

instance Substitute Bool where
  substituteNames :: Map VName VName -> Bool -> Bool
substituteNames = (Bool -> Bool) -> Map VName VName -> Bool -> Bool
forall a b. a -> b -> a
const Bool -> Bool
forall a. a -> a
id

instance Substitute VName where
  substituteNames :: Map VName VName -> VName -> VName
substituteNames Map VName VName
substs VName
k = VName -> VName -> Map VName VName -> VName
forall k a. Ord k => a -> k -> Map k a -> a
M.findWithDefault VName
k VName
k Map VName VName
substs

instance Substitute SubExp where
  substituteNames :: Map VName VName -> SubExp -> SubExp
substituteNames Map VName VName
substs (Var VName
v) = VName -> SubExp
Var (VName -> SubExp) -> VName -> SubExp
forall a b. (a -> b) -> a -> b
$ Map VName VName -> VName -> VName
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs VName
v
  substituteNames Map VName VName
_ (Constant PrimValue
v) = PrimValue -> SubExp
Constant PrimValue
v

instance Substitutable lore => Substitute (Exp lore) where
  substituteNames :: Map VName VName -> Exp lore -> Exp lore
substituteNames Map VName VName
substs = Mapper lore lore Identity -> Exp lore -> Exp lore
forall flore tlore.
Mapper flore tlore Identity -> Exp flore -> Exp tlore
mapExp (Mapper lore lore Identity -> Exp lore -> Exp lore)
-> Mapper lore lore Identity -> Exp lore -> Exp lore
forall a b. (a -> b) -> a -> b
$ Map VName VName -> Mapper lore lore Identity
forall lore.
Substitutable lore =>
Map VName VName -> Mapper lore lore Identity
replace Map VName VName
substs

instance Substitute dec => Substitute (PatElemT dec) where
  substituteNames :: Map VName VName -> PatElemT dec -> PatElemT dec
substituteNames Map VName VName
substs (PatElem VName
ident dec
dec) =
    VName -> dec -> PatElemT dec
forall dec. VName -> dec -> PatElemT dec
PatElem (Map VName VName -> VName -> VName
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs VName
ident) (Map VName VName -> dec -> dec
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs dec
dec)

instance Substitute Attrs where
  substituteNames :: Map VName VName -> Attrs -> Attrs
substituteNames Map VName VName
_ Attrs
attrs = Attrs
attrs

instance Substitute dec => Substitute (StmAux dec) where
  substituteNames :: Map VName VName -> StmAux dec -> StmAux dec
substituteNames Map VName VName
substs (StmAux Certificates
cs Attrs
attrs dec
dec) =
    Certificates -> Attrs -> dec -> StmAux dec
forall dec. Certificates -> Attrs -> dec -> StmAux dec
StmAux
      (Map VName VName -> Certificates -> Certificates
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs Certificates
cs)
      (Map VName VName -> Attrs -> Attrs
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs Attrs
attrs)
      (Map VName VName -> dec -> dec
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs dec
dec)

instance Substitute dec => Substitute (Param dec) where
  substituteNames :: Map VName VName -> Param dec -> Param dec
substituteNames Map VName VName
substs (Param VName
name dec
dec) =
    VName -> dec -> Param dec
forall dec. VName -> dec -> Param dec
Param
      (Map VName VName -> VName -> VName
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs VName
name)
      (Map VName VName -> dec -> dec
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs dec
dec)

instance Substitute dec => Substitute (PatternT dec) where
  substituteNames :: Map VName VName -> PatternT dec -> PatternT dec
substituteNames Map VName VName
substs (Pattern [PatElemT dec]
context [PatElemT dec]
values) =
    [PatElemT dec] -> [PatElemT dec] -> PatternT dec
forall dec. [PatElemT dec] -> [PatElemT dec] -> PatternT dec
Pattern (Map VName VName -> [PatElemT dec] -> [PatElemT dec]
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs [PatElemT dec]
context) (Map VName VName -> [PatElemT dec] -> [PatElemT dec]
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs [PatElemT dec]
values)

instance Substitute Certificates where
  substituteNames :: Map VName VName -> Certificates -> Certificates
substituteNames Map VName VName
substs (Certificates [VName]
cs) =
    [VName] -> Certificates
Certificates ([VName] -> Certificates) -> [VName] -> Certificates
forall a b. (a -> b) -> a -> b
$ Map VName VName -> [VName] -> [VName]
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs [VName]
cs

instance Substitutable lore => Substitute (Stm lore) where
  substituteNames :: Map VName VName -> Stm lore -> Stm lore
substituteNames Map VName VName
substs (Let Pattern lore
pat StmAux (ExpDec lore)
annot Exp lore
e) =
    Pattern lore -> StmAux (ExpDec lore) -> Exp lore -> Stm lore
forall lore.
Pattern lore -> StmAux (ExpDec lore) -> Exp lore -> Stm lore
Let
      (Map VName VName -> Pattern lore -> Pattern lore
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs Pattern lore
pat)
      (Map VName VName -> StmAux (ExpDec lore) -> StmAux (ExpDec lore)
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs StmAux (ExpDec lore)
annot)
      (Map VName VName -> Exp lore -> Exp lore
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs Exp lore
e)

instance Substitutable lore => Substitute (Body lore) where
  substituteNames :: Map VName VName -> Body lore -> Body lore
substituteNames Map VName VName
substs (Body BodyDec lore
dec Stms lore
stms Result
res) =
    BodyDec lore -> Stms lore -> Result -> Body lore
forall lore. BodyDec lore -> Stms lore -> Result -> BodyT lore
Body
      (Map VName VName -> BodyDec lore -> BodyDec lore
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs BodyDec lore
dec)
      (Map VName VName -> Stms lore -> Stms lore
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs Stms lore
stms)
      (Map VName VName -> Result -> Result
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs Result
res)

replace :: Substitutable lore => M.Map VName VName -> Mapper lore lore Identity
replace :: Map VName VName -> Mapper lore lore Identity
replace Map VName VName
substs =
  Mapper :: forall flore tlore (m :: * -> *).
(SubExp -> m SubExp)
-> (Scope tlore -> Body flore -> m (Body tlore))
-> (VName -> m VName)
-> (RetType flore -> m (RetType tlore))
-> (BranchType flore -> m (BranchType tlore))
-> (FParam flore -> m (FParam tlore))
-> (LParam flore -> m (LParam tlore))
-> (Op flore -> m (Op tlore))
-> Mapper flore tlore m
Mapper
    { mapOnVName :: VName -> Identity VName
mapOnVName = VName -> Identity VName
forall (m :: * -> *) a. Monad m => a -> m a
return (VName -> Identity VName)
-> (VName -> VName) -> VName -> Identity VName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map VName VName -> VName -> VName
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs,
      mapOnSubExp :: SubExp -> Identity SubExp
mapOnSubExp = SubExp -> Identity SubExp
forall (m :: * -> *) a. Monad m => a -> m a
return (SubExp -> Identity SubExp)
-> (SubExp -> SubExp) -> SubExp -> Identity SubExp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map VName VName -> SubExp -> SubExp
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs,
      mapOnBody :: Scope lore -> Body lore -> Identity (Body lore)
mapOnBody = (Body lore -> Identity (Body lore))
-> Scope lore -> Body lore -> Identity (Body lore)
forall a b. a -> b -> a
const ((Body lore -> Identity (Body lore))
 -> Scope lore -> Body lore -> Identity (Body lore))
-> (Body lore -> Identity (Body lore))
-> Scope lore
-> Body lore
-> Identity (Body lore)
forall a b. (a -> b) -> a -> b
$ Body lore -> Identity (Body lore)
forall (m :: * -> *) a. Monad m => a -> m a
return (Body lore -> Identity (Body lore))
-> (Body lore -> Body lore) -> Body lore -> Identity (Body lore)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map VName VName -> Body lore -> Body lore
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs,
      mapOnRetType :: RetType lore -> Identity (RetType lore)
mapOnRetType = RetType lore -> Identity (RetType lore)
forall (m :: * -> *) a. Monad m => a -> m a
return (RetType lore -> Identity (RetType lore))
-> (RetType lore -> RetType lore)
-> RetType lore
-> Identity (RetType lore)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map VName VName -> RetType lore -> RetType lore
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs,
      mapOnBranchType :: BranchType lore -> Identity (BranchType lore)
mapOnBranchType = BranchType lore -> Identity (BranchType lore)
forall (m :: * -> *) a. Monad m => a -> m a
return (BranchType lore -> Identity (BranchType lore))
-> (BranchType lore -> BranchType lore)
-> BranchType lore
-> Identity (BranchType lore)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map VName VName -> BranchType lore -> BranchType lore
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs,
      mapOnFParam :: FParam lore -> Identity (FParam lore)
mapOnFParam = FParam lore -> Identity (FParam lore)
forall (m :: * -> *) a. Monad m => a -> m a
return (FParam lore -> Identity (FParam lore))
-> (FParam lore -> FParam lore)
-> FParam lore
-> Identity (FParam lore)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map VName VName -> FParam lore -> FParam lore
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs,
      mapOnLParam :: LParam lore -> Identity (LParam lore)
mapOnLParam = LParam lore -> Identity (LParam lore)
forall (m :: * -> *) a. Monad m => a -> m a
return (LParam lore -> Identity (LParam lore))
-> (LParam lore -> LParam lore)
-> LParam lore
-> Identity (LParam lore)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map VName VName -> LParam lore -> LParam lore
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs,
      mapOnOp :: Op lore -> Identity (Op lore)
mapOnOp = Op lore -> Identity (Op lore)
forall (m :: * -> *) a. Monad m => a -> m a
return (Op lore -> Identity (Op lore))
-> (Op lore -> Op lore) -> Op lore -> Identity (Op lore)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map VName VName -> Op lore -> Op lore
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs
    }

instance Substitute Rank where
  substituteNames :: Map VName VName -> Rank -> Rank
substituteNames Map VName VName
_ = Rank -> Rank
forall a. a -> a
id

instance Substitute () where
  substituteNames :: Map VName VName -> () -> ()
substituteNames Map VName VName
_ = () -> ()
forall a. a -> a
id

instance Substitute d => Substitute (ShapeBase d) where
  substituteNames :: Map VName VName -> ShapeBase d -> ShapeBase d
substituteNames Map VName VName
substs (Shape [d]
es) =
    [d] -> ShapeBase d
forall d. [d] -> ShapeBase d
Shape ([d] -> ShapeBase d) -> [d] -> ShapeBase d
forall a b. (a -> b) -> a -> b
$ (d -> d) -> [d] -> [d]
forall a b. (a -> b) -> [a] -> [b]
map (Map VName VName -> d -> d
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs) [d]
es

instance Substitute d => Substitute (Ext d) where
  substituteNames :: Map VName VName -> Ext d -> Ext d
substituteNames Map VName VName
substs (Free d
x) = d -> Ext d
forall a. a -> Ext a
Free (d -> Ext d) -> d -> Ext d
forall a b. (a -> b) -> a -> b
$ Map VName VName -> d -> d
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs d
x
  substituteNames Map VName VName
_ (Ext Int
x) = Int -> Ext d
forall a. Int -> Ext a
Ext Int
x

instance Substitute Names where
  substituteNames :: Map VName VName -> Names -> Names
substituteNames = (VName -> VName) -> Names -> Names
mapNames ((VName -> VName) -> Names -> Names)
-> (Map VName VName -> VName -> VName)
-> Map VName VName
-> Names
-> Names
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map VName VName -> VName -> VName
forall a. Substitute a => Map VName VName -> a -> a
substituteNames

instance Substitute shape => Substitute (TypeBase shape u) where
  substituteNames :: Map VName VName -> TypeBase shape u -> TypeBase shape u
substituteNames Map VName VName
_ (Prim PrimType
et) = PrimType -> TypeBase shape u
forall shape u. PrimType -> TypeBase shape u
Prim PrimType
et
  substituteNames Map VName VName
substs (Array PrimType
et shape
sz u
u) =
    PrimType -> shape -> u -> TypeBase shape u
forall shape u. PrimType -> shape -> u -> TypeBase shape u
Array PrimType
et (Map VName VName -> shape -> shape
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs shape
sz) u
u
  substituteNames Map VName VName
_ (Mem Space
space) =
    Space -> TypeBase shape u
forall shape u. Space -> TypeBase shape u
Mem Space
space

instance Substitutable lore => Substitute (Lambda lore) where
  substituteNames :: Map VName VName -> Lambda lore -> Lambda lore
substituteNames Map VName VName
substs (Lambda [LParam lore]
params BodyT lore
body [Type]
rettype) =
    [LParam lore] -> BodyT lore -> [Type] -> Lambda lore
forall lore. [LParam lore] -> BodyT lore -> [Type] -> LambdaT lore
Lambda
      (Map VName VName -> [LParam lore] -> [LParam lore]
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs [LParam lore]
params)
      (Map VName VName -> BodyT lore -> BodyT lore
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs BodyT lore
body)
      ((Type -> Type) -> [Type] -> [Type]
forall a b. (a -> b) -> [a] -> [b]
map (Map VName VName -> Type -> Type
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs) [Type]
rettype)

instance Substitute Ident where
  substituteNames :: Map VName VName -> Ident -> Ident
substituteNames Map VName VName
substs Ident
v =
    Ident
v
      { identName :: VName
identName = Map VName VName -> VName -> VName
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs (VName -> VName) -> VName -> VName
forall a b. (a -> b) -> a -> b
$ Ident -> VName
identName Ident
v,
        identType :: Type
identType = Map VName VName -> Type -> Type
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs (Type -> Type) -> Type -> Type
forall a b. (a -> b) -> a -> b
$ Ident -> Type
identType Ident
v
      }

instance Substitute d => Substitute (DimChange d) where
  substituteNames :: Map VName VName -> DimChange d -> DimChange d
substituteNames Map VName VName
substs = (d -> d) -> DimChange d -> DimChange d
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((d -> d) -> DimChange d -> DimChange d)
-> (d -> d) -> DimChange d -> DimChange d
forall a b. (a -> b) -> a -> b
$ Map VName VName -> d -> d
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs

instance Substitute d => Substitute (DimIndex d) where
  substituteNames :: Map VName VName -> DimIndex d -> DimIndex d
substituteNames Map VName VName
substs = (d -> d) -> DimIndex d -> DimIndex d
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((d -> d) -> DimIndex d -> DimIndex d)
-> (d -> d) -> DimIndex d -> DimIndex d
forall a b. (a -> b) -> a -> b
$ Map VName VName -> d -> d
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs

instance Substitute v => Substitute (PrimExp v) where
  substituteNames :: Map VName VName -> PrimExp v -> PrimExp v
substituteNames Map VName VName
substs = (v -> v) -> PrimExp v -> PrimExp v
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((v -> v) -> PrimExp v -> PrimExp v)
-> (v -> v) -> PrimExp v -> PrimExp v
forall a b. (a -> b) -> a -> b
$ Map VName VName -> v -> v
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs

instance Substitute v => Substitute (TPrimExp t v) where
  substituteNames :: Map VName VName -> TPrimExp t v -> TPrimExp t v
substituteNames Map VName VName
substs =
    PrimExp v -> TPrimExp t v
forall t v. PrimExp v -> TPrimExp t v
TPrimExp (PrimExp v -> TPrimExp t v)
-> (TPrimExp t v -> PrimExp v) -> TPrimExp t v -> TPrimExp t v
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (v -> v) -> PrimExp v -> PrimExp v
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Map VName VName -> v -> v
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs) (PrimExp v -> PrimExp v)
-> (TPrimExp t v -> PrimExp v) -> TPrimExp t v -> PrimExp v
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TPrimExp t v -> PrimExp v
forall t v. TPrimExp t v -> PrimExp v
untyped

instance Substitutable lore => Substitute (NameInfo lore) where
  substituteNames :: Map VName VName -> NameInfo lore -> NameInfo lore
substituteNames Map VName VName
subst (LetName LetDec lore
dec) =
    LetDec lore -> NameInfo lore
forall lore. LetDec lore -> NameInfo lore
LetName (LetDec lore -> NameInfo lore) -> LetDec lore -> NameInfo lore
forall a b. (a -> b) -> a -> b
$ Map VName VName -> LetDec lore -> LetDec lore
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
subst LetDec lore
dec
  substituteNames Map VName VName
subst (FParamName FParamInfo lore
dec) =
    FParamInfo lore -> NameInfo lore
forall lore. FParamInfo lore -> NameInfo lore
FParamName (FParamInfo lore -> NameInfo lore)
-> FParamInfo lore -> NameInfo lore
forall a b. (a -> b) -> a -> b
$ Map VName VName -> FParamInfo lore -> FParamInfo lore
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
subst FParamInfo lore
dec
  substituteNames Map VName VName
subst (LParamName LParamInfo lore
dec) =
    LParamInfo lore -> NameInfo lore
forall lore. LParamInfo lore -> NameInfo lore
LParamName (LParamInfo lore -> NameInfo lore)
-> LParamInfo lore -> NameInfo lore
forall a b. (a -> b) -> a -> b
$ Map VName VName -> LParamInfo lore -> LParamInfo lore
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
subst LParamInfo lore
dec
  substituteNames Map VName VName
_ (IndexName IntType
it) =
    IntType -> NameInfo lore
forall lore. IntType -> NameInfo lore
IndexName IntType
it

instance Substitute FV where
  substituteNames :: Map VName VName -> FV -> FV
substituteNames Map VName VName
subst = Names -> FV
fvNames (Names -> FV) -> (FV -> Names) -> FV -> FV
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map VName VName -> Names -> Names
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
subst (Names -> Names) -> (FV -> Names) -> FV -> Names
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FV -> Names
forall a. FreeIn a => a -> Names
freeIn

-- | Lores in which all annotations support name
-- substitution.
type Substitutable lore =
  ( Decorations lore,
    Substitute (ExpDec lore),
    Substitute (BodyDec lore),
    Substitute (LetDec lore),
    Substitute (FParamInfo lore),
    Substitute (LParamInfo lore),
    Substitute (RetType lore),
    Substitute (BranchType lore),
    Substitute (Op lore)
  )