{-# 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 rep) => Substitute (Stms rep) where
  substituteNames :: Map VName VName -> Stms rep -> Stms rep
substituteNames Map VName VName
substs = (Stm rep -> Stm rep) -> Stms rep -> Stms rep
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Stm rep -> Stm rep) -> Stms rep -> Stms rep)
-> (Stm rep -> Stm rep) -> Stms rep -> Stms rep
forall a b. (a -> b) -> a -> b
$ Map VName VName -> Stm rep -> Stm rep
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 rep => Substitute (Exp rep) where
  substituteNames :: Map VName VName -> Exp rep -> Exp rep
substituteNames Map VName VName
substs = Mapper rep rep Identity -> Exp rep -> Exp rep
forall frep trep. Mapper frep trep Identity -> Exp frep -> Exp trep
mapExp (Mapper rep rep Identity -> Exp rep -> Exp rep)
-> Mapper rep rep Identity -> Exp rep -> Exp rep
forall a b. (a -> b) -> a -> b
$ Map VName VName -> Mapper rep rep Identity
forall rep.
Substitutable rep =>
Map VName VName -> Mapper rep rep 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 Certs
cs Attrs
attrs dec
dec) =
    Certs -> Attrs -> dec -> StmAux dec
forall dec. Certs -> Attrs -> dec -> StmAux dec
StmAux
      (Map VName VName -> Certs -> Certs
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs Certs
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 SubExpRes where
  substituteNames :: Map VName VName -> SubExpRes -> SubExpRes
substituteNames Map VName VName
substs (SubExpRes Certs
cs SubExp
se) =
    Certs -> SubExp -> SubExpRes
SubExpRes (Map VName VName -> Certs -> Certs
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs Certs
cs) (Map VName VName -> SubExp -> SubExp
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs SubExp
se)

instance Substitute dec => Substitute (PatT dec) where
  substituteNames :: Map VName VName -> PatT dec -> PatT dec
substituteNames Map VName VName
substs (Pat [PatElemT dec]
xs) =
    [PatElemT dec] -> PatT dec
forall dec. [PatElemT dec] -> PatT dec
Pat (Map VName VName -> [PatElemT dec] -> [PatElemT dec]
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs [PatElemT dec]
xs)

instance Substitute Certs where
  substituteNames :: Map VName VName -> Certs -> Certs
substituteNames Map VName VName
substs (Certs [VName]
cs) =
    [VName] -> Certs
Certs ([VName] -> Certs) -> [VName] -> Certs
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 rep => Substitute (Stm rep) where
  substituteNames :: Map VName VName -> Stm rep -> Stm rep
substituteNames Map VName VName
substs (Let Pat rep
pat StmAux (ExpDec rep)
annot Exp rep
e) =
    Pat rep -> StmAux (ExpDec rep) -> Exp rep -> Stm rep
forall rep. Pat rep -> StmAux (ExpDec rep) -> Exp rep -> Stm rep
Let
      (Map VName VName -> Pat rep -> Pat rep
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs Pat rep
pat)
      (Map VName VName -> StmAux (ExpDec rep) -> StmAux (ExpDec rep)
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs StmAux (ExpDec rep)
annot)
      (Map VName VName -> Exp rep -> Exp rep
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs Exp rep
e)

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

replace :: Substitutable rep => M.Map VName VName -> Mapper rep rep Identity
replace :: Map VName VName -> Mapper rep rep Identity
replace Map VName VName
substs =
  Mapper :: forall frep trep (m :: * -> *).
(SubExp -> m SubExp)
-> (Scope trep -> Body frep -> m (Body trep))
-> (VName -> m VName)
-> (RetType frep -> m (RetType trep))
-> (BranchType frep -> m (BranchType trep))
-> (FParam frep -> m (FParam trep))
-> (LParam frep -> m (LParam trep))
-> (Op frep -> m (Op trep))
-> Mapper frep trep 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 rep -> Body rep -> Identity (Body rep)
mapOnBody = (Body rep -> Identity (Body rep))
-> Scope rep -> Body rep -> Identity (Body rep)
forall a b. a -> b -> a
const ((Body rep -> Identity (Body rep))
 -> Scope rep -> Body rep -> Identity (Body rep))
-> (Body rep -> Identity (Body rep))
-> Scope rep
-> Body rep
-> Identity (Body rep)
forall a b. (a -> b) -> a -> b
$ Body rep -> Identity (Body rep)
forall (m :: * -> *) a. Monad m => a -> m a
return (Body rep -> Identity (Body rep))
-> (Body rep -> Body rep) -> Body rep -> Identity (Body rep)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map VName VName -> Body rep -> Body rep
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs,
      mapOnRetType :: RetType rep -> Identity (RetType rep)
mapOnRetType = RetType rep -> Identity (RetType rep)
forall (m :: * -> *) a. Monad m => a -> m a
return (RetType rep -> Identity (RetType rep))
-> (RetType rep -> RetType rep)
-> RetType rep
-> Identity (RetType rep)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map VName VName -> RetType rep -> RetType rep
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs,
      mapOnBranchType :: BranchType rep -> Identity (BranchType rep)
mapOnBranchType = BranchType rep -> Identity (BranchType rep)
forall (m :: * -> *) a. Monad m => a -> m a
return (BranchType rep -> Identity (BranchType rep))
-> (BranchType rep -> BranchType rep)
-> BranchType rep
-> Identity (BranchType rep)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map VName VName -> BranchType rep -> BranchType rep
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs,
      mapOnFParam :: FParam rep -> Identity (FParam rep)
mapOnFParam = FParam rep -> Identity (FParam rep)
forall (m :: * -> *) a. Monad m => a -> m a
return (FParam rep -> Identity (FParam rep))
-> (FParam rep -> FParam rep)
-> FParam rep
-> Identity (FParam rep)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map VName VName -> FParam rep -> FParam rep
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs,
      mapOnLParam :: LParam rep -> Identity (LParam rep)
mapOnLParam = LParam rep -> Identity (LParam rep)
forall (m :: * -> *) a. Monad m => a -> m a
return (LParam rep -> Identity (LParam rep))
-> (LParam rep -> LParam rep)
-> LParam rep
-> Identity (LParam rep)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map VName VName -> LParam rep -> LParam rep
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs,
      mapOnOp :: Op rep -> Identity (Op rep)
mapOnOp = Op rep -> Identity (Op rep)
forall (m :: * -> *) a. Monad m => a -> m a
return (Op rep -> Identity (Op rep))
-> (Op rep -> Op rep) -> Op rep -> Identity (Op rep)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map VName VName -> Op rep -> Op rep
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 PrimType where
  substituteNames :: Map VName VName -> PrimType -> PrimType
substituteNames Map VName VName
_ PrimType
t = PrimType
t

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 (Acc VName
acc Shape
ispace [Type]
ts u
u) =
    VName -> Shape -> [Type] -> u -> TypeBase shape u
forall shape u. VName -> Shape -> [Type] -> u -> TypeBase shape u
Acc
      (Map VName VName -> VName -> VName
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs VName
acc)
      (Map VName VName -> Shape -> Shape
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs Shape
ispace)
      (Map VName VName -> [Type] -> [Type]
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs [Type]
ts)
      u
u
  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 (Map VName VName -> PrimType -> PrimType
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs 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 rep => Substitute (Lambda rep) where
  substituteNames :: Map VName VName -> Lambda rep -> Lambda rep
substituteNames Map VName VName
substs (Lambda [LParam rep]
params BodyT rep
body [Type]
rettype) =
    [LParam rep] -> BodyT rep -> [Type] -> Lambda rep
forall rep. [LParam rep] -> BodyT rep -> [Type] -> LambdaT rep
Lambda
      (Map VName VName -> [LParam rep] -> [LParam rep]
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs [LParam rep]
params)
      (Map VName VName -> BodyT rep -> BodyT rep
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs BodyT rep
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 d => Substitute (Slice d) where
  substituteNames :: Map VName VName -> Slice d -> Slice d
substituteNames Map VName VName
substs = (d -> d) -> Slice d -> Slice d
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((d -> d) -> Slice d -> Slice d) -> (d -> d) -> Slice d -> Slice 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 (FlatDimIndex d) where
  substituteNames :: Map VName VName -> FlatDimIndex d -> FlatDimIndex d
substituteNames Map VName VName
substs = (d -> d) -> FlatDimIndex d -> FlatDimIndex d
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((d -> d) -> FlatDimIndex d -> FlatDimIndex d)
-> (d -> d) -> FlatDimIndex d -> FlatDimIndex 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 (FlatSlice d) where
  substituteNames :: Map VName VName -> FlatSlice d -> FlatSlice d
substituteNames Map VName VName
substs = (d -> d) -> FlatSlice d -> FlatSlice d
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((d -> d) -> FlatSlice d -> FlatSlice d)
-> (d -> d) -> FlatSlice d -> FlatSlice 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 rep => Substitute (NameInfo rep) where
  substituteNames :: Map VName VName -> NameInfo rep -> NameInfo rep
substituteNames Map VName VName
subst (LetName LetDec rep
dec) =
    LetDec rep -> NameInfo rep
forall rep. LetDec rep -> NameInfo rep
LetName (LetDec rep -> NameInfo rep) -> LetDec rep -> NameInfo rep
forall a b. (a -> b) -> a -> b
$ Map VName VName -> LetDec rep -> LetDec rep
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
subst LetDec rep
dec
  substituteNames Map VName VName
subst (FParamName FParamInfo rep
dec) =
    FParamInfo rep -> NameInfo rep
forall rep. FParamInfo rep -> NameInfo rep
FParamName (FParamInfo rep -> NameInfo rep) -> FParamInfo rep -> NameInfo rep
forall a b. (a -> b) -> a -> b
$ Map VName VName -> FParamInfo rep -> FParamInfo rep
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
subst FParamInfo rep
dec
  substituteNames Map VName VName
subst (LParamName LParamInfo rep
dec) =
    LParamInfo rep -> NameInfo rep
forall rep. LParamInfo rep -> NameInfo rep
LParamName (LParamInfo rep -> NameInfo rep) -> LParamInfo rep -> NameInfo rep
forall a b. (a -> b) -> a -> b
$ Map VName VName -> LParamInfo rep -> LParamInfo rep
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
subst LParamInfo rep
dec
  substituteNames Map VName VName
_ (IndexName IntType
it) =
    IntType -> NameInfo rep
forall rep. IntType -> NameInfo rep
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

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