{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleInstances #-}
-- | A representation where all bindings are annotated with aliasing
-- information.
module Futhark.Representation.Aliases
       ( -- * The Lore definition
         Aliases
       , Names' (..)
       , VarAliases
       , ConsumedInExp
       , BodyAliasing
       , module Futhark.Representation.AST.Attributes.Aliases
         -- * Module re-exports
       , module Futhark.Representation.AST.Attributes
       , module Futhark.Representation.AST.Traversals
       , module Futhark.Representation.AST.Pretty
       , module Futhark.Representation.AST.Syntax
         -- * Adding aliases
       , addAliasesToPattern
       , mkAliasedLetStm
       , mkAliasedBody
       , mkPatternAliases
       , mkBodyAliases
         -- * Removing aliases
       , removeProgAliases
       , removeFunDefAliases
       , removeExpAliases
       , removeStmAliases
       , removeLambdaAliases
       , removePatternAliases
       , removeScopeAliases
       -- * Tracking aliases
       , AliasesAndConsumed
       , trackAliases
       , consumedInStms
       )
where

import Control.Monad.Identity
import Control.Monad.Reader
import Data.Maybe
import qualified Data.Map.Strict as M

import Futhark.Representation.AST.Syntax
import Futhark.Representation.AST.Attributes
import Futhark.Representation.AST.Attributes.Aliases
import Futhark.Representation.AST.Traversals
import Futhark.Representation.AST.Pretty
import Futhark.Transform.Rename
import Futhark.Binder
import Futhark.Transform.Substitute
import Futhark.Analysis.Rephrase
import qualified Futhark.Util.Pretty as PP

-- | The lore for the basic representation.
data Aliases lore

-- | A wrapper around 'Names' to get around the fact that we need an
-- 'Ord' instance, which 'Names' does not have.
newtype Names' = Names' { Names' -> Names
unNames :: Names }
               deriving (Int -> Names' -> ShowS
[Names'] -> ShowS
Names' -> String
(Int -> Names' -> ShowS)
-> (Names' -> String) -> ([Names'] -> ShowS) -> Show Names'
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Names'] -> ShowS
$cshowList :: [Names'] -> ShowS
show :: Names' -> String
$cshow :: Names' -> String
showsPrec :: Int -> Names' -> ShowS
$cshowsPrec :: Int -> Names' -> ShowS
Show)

instance Semigroup Names' where
  Names'
x <> :: Names' -> Names' -> Names'
<> Names'
y = Names -> Names'
Names' (Names -> Names') -> Names -> Names'
forall a b. (a -> b) -> a -> b
$ Names' -> Names
unNames Names'
x Names -> Names -> Names
forall a. Semigroup a => a -> a -> a
<> Names' -> Names
unNames Names'
y

instance Monoid Names' where
  mempty :: Names'
mempty = Names -> Names'
Names' Names
forall a. Monoid a => a
mempty

instance Eq Names' where
  Names'
_ == :: Names' -> Names' -> Bool
== Names'
_ = Bool
True

instance Ord Names' where
  Names'
_ compare :: Names' -> Names' -> Ordering
`compare` Names'
_ = Ordering
EQ

instance Rename Names' where
  rename :: Names' -> RenameM Names'
rename (Names' Names
names) = Names -> Names'
Names' (Names -> Names') -> RenameM Names -> RenameM Names'
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Names -> RenameM Names
forall a. Rename a => a -> RenameM a
rename Names
names

instance Substitute Names' where
  substituteNames :: Map VName VName -> Names' -> Names'
substituteNames Map VName VName
substs (Names' Names
names) = Names -> Names'
Names' (Names -> Names') -> Names -> Names'
forall a b. (a -> b) -> a -> b
$ Map VName VName -> Names -> Names
forall a. Substitute a => Map VName VName -> a -> a
substituteNames Map VName VName
substs Names
names

instance FreeIn Names' where
  freeIn' :: Names' -> FV
freeIn' = FV -> Names' -> FV
forall a b. a -> b -> a
const FV
forall a. Monoid a => a
mempty

instance PP.Pretty Names' where
  ppr :: Names' -> Doc
ppr = [Doc] -> Doc
PP.commasep ([Doc] -> Doc) -> (Names' -> [Doc]) -> Names' -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (VName -> Doc) -> [VName] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map VName -> Doc
forall a. Pretty a => a -> Doc
PP.ppr ([VName] -> [Doc]) -> (Names' -> [VName]) -> Names' -> [Doc]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Names -> [VName]
namesToList (Names -> [VName]) -> (Names' -> Names) -> Names' -> [VName]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Names' -> Names
unNames

-- | The aliases of the let-bound variable.
type VarAliases = Names'

-- | Everything consumed in the expression.
type ConsumedInExp = Names'

-- | The aliases of what is returned by the 'Body', and what is
-- consumed inside of it.
type BodyAliasing = ([VarAliases], ConsumedInExp)

instance (Annotations lore, CanBeAliased (Op lore)) =>
         Annotations (Aliases lore) where
  type LetAttr (Aliases lore) = (VarAliases, LetAttr lore)
  type ExpAttr (Aliases lore) = (ConsumedInExp, ExpAttr lore)
  type BodyAttr (Aliases lore) = (BodyAliasing, BodyAttr lore)
  type FParamAttr (Aliases lore) = FParamAttr lore
  type LParamAttr (Aliases lore) = LParamAttr lore
  type RetType (Aliases lore) = RetType lore
  type BranchType (Aliases lore) = BranchType lore
  type Op (Aliases lore) = OpWithAliases (Op lore)

instance AliasesOf (VarAliases, attr) where
  aliasesOf :: (Names', attr) -> Names
aliasesOf = Names' -> Names
unNames (Names' -> Names)
-> ((Names', attr) -> Names') -> (Names', attr) -> Names
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Names', attr) -> Names'
forall a b. (a, b) -> a
fst

instance FreeAttr Names' where

withoutAliases :: (HasScope (Aliases lore) m, Monad m) =>
                 ReaderT (Scope lore) m a -> m a
withoutAliases :: ReaderT (Scope lore) m a -> m a
withoutAliases ReaderT (Scope lore) m a
m = do
  Scope lore
scope <- (Scope (Aliases lore) -> Scope lore) -> m (Scope lore)
forall lore (m :: * -> *) a.
HasScope lore m =>
(Scope lore -> a) -> m a
asksScope Scope (Aliases lore) -> Scope lore
forall lore. Scope (Aliases lore) -> Scope lore
removeScopeAliases
  ReaderT (Scope lore) m a -> Scope lore -> m a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT ReaderT (Scope lore) m a
m Scope lore
scope

instance (Attributes lore, CanBeAliased (Op lore)) => Attributes (Aliases lore) where
  expTypesFromPattern :: Pattern (Aliases lore) -> m [BranchType (Aliases lore)]
expTypesFromPattern =
    ReaderT (Scope lore) m [BranchType lore] -> m [BranchType lore]
forall lore (m :: * -> *) a.
(HasScope (Aliases lore) m, Monad m) =>
ReaderT (Scope lore) m a -> m a
withoutAliases (ReaderT (Scope lore) m [BranchType lore] -> m [BranchType lore])
-> (PatternT (Names', LetAttr lore)
    -> ReaderT (Scope lore) m [BranchType lore])
-> PatternT (Names', LetAttr lore)
-> m [BranchType lore]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PatternT (LetAttr lore) -> ReaderT (Scope lore) m [BranchType lore]
forall lore (m :: * -> *).
(Attributes lore, HasScope lore m, Monad m) =>
Pattern lore -> m [BranchType lore]
expTypesFromPattern (PatternT (LetAttr lore)
 -> ReaderT (Scope lore) m [BranchType lore])
-> (PatternT (Names', LetAttr lore) -> PatternT (LetAttr lore))
-> PatternT (Names', LetAttr lore)
-> ReaderT (Scope lore) m [BranchType lore]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PatternT (Names', LetAttr lore) -> PatternT (LetAttr lore)
forall a. PatternT (Names', a) -> PatternT a
removePatternAliases

instance (Attributes lore, CanBeAliased (Op lore)) => Aliased (Aliases lore) where
  bodyAliases :: Body (Aliases lore) -> [Names]
bodyAliases = (Names' -> Names) -> [Names'] -> [Names]
forall a b. (a -> b) -> [a] -> [b]
map Names' -> Names
unNames ([Names'] -> [Names])
-> (Body (Aliases lore) -> [Names'])
-> Body (Aliases lore)
-> [Names]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Names'], Names') -> [Names']
forall a b. (a, b) -> a
fst (([Names'], Names') -> [Names'])
-> (Body (Aliases lore) -> ([Names'], Names'))
-> Body (Aliases lore)
-> [Names']
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (([Names'], Names'), BodyAttr lore) -> ([Names'], Names')
forall a b. (a, b) -> a
fst ((([Names'], Names'), BodyAttr lore) -> ([Names'], Names'))
-> (Body (Aliases lore) -> (([Names'], Names'), BodyAttr lore))
-> Body (Aliases lore)
-> ([Names'], Names')
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Body (Aliases lore) -> (([Names'], Names'), BodyAttr lore)
forall lore. BodyT lore -> BodyAttr lore
bodyAttr
  consumedInBody :: Body (Aliases lore) -> Names
consumedInBody = Names' -> Names
unNames (Names' -> Names)
-> (Body (Aliases lore) -> Names') -> Body (Aliases lore) -> Names
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Names'], Names') -> Names'
forall a b. (a, b) -> b
snd (([Names'], Names') -> Names')
-> (Body (Aliases lore) -> ([Names'], Names'))
-> Body (Aliases lore)
-> Names'
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (([Names'], Names'), BodyAttr lore) -> ([Names'], Names')
forall a b. (a, b) -> a
fst ((([Names'], Names'), BodyAttr lore) -> ([Names'], Names'))
-> (Body (Aliases lore) -> (([Names'], Names'), BodyAttr lore))
-> Body (Aliases lore)
-> ([Names'], Names')
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Body (Aliases lore) -> (([Names'], Names'), BodyAttr lore)
forall lore. BodyT lore -> BodyAttr lore
bodyAttr

instance PrettyAnnot (PatElemT attr) =>
  PrettyAnnot (PatElemT (VarAliases, attr)) where

  ppAnnot :: PatElemT (Names', attr) -> Maybe Doc
ppAnnot (PatElem VName
name (Names' Names
als, attr
attr)) =
    let alias_comment :: Maybe Doc
alias_comment = Doc -> Doc
PP.oneLine (Doc -> Doc) -> Maybe Doc -> Maybe Doc
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> VName -> Names -> Maybe Doc
forall a. Pretty a => a -> Names -> Maybe Doc
aliasComment VName
name Names
als
    in case (Maybe Doc
alias_comment, PatElemT attr -> Maybe Doc
forall a. PrettyAnnot a => a -> Maybe Doc
ppAnnot (VName -> attr -> PatElemT attr
forall attr. VName -> attr -> PatElemT attr
PatElem VName
name attr
attr)) of
         (Maybe Doc
_, Maybe Doc
Nothing) ->
           Maybe Doc
alias_comment
         (Just Doc
alias_comment', Just Doc
inner_comment) ->
           Doc -> Maybe Doc
forall a. a -> Maybe a
Just (Doc -> Maybe Doc) -> Doc -> Maybe Doc
forall a b. (a -> b) -> a -> b
$ Doc
alias_comment' Doc -> Doc -> Doc
PP.</> Doc
inner_comment
         (Maybe Doc
Nothing, Just Doc
inner_comment) ->
           Doc -> Maybe Doc
forall a. a -> Maybe a
Just Doc
inner_comment


instance (Attributes lore, CanBeAliased (Op lore)) => PrettyLore (Aliases lore) where
  ppExpLore :: ExpAttr (Aliases lore) -> Exp (Aliases lore) -> Maybe Doc
ppExpLore (consumed, inner) Exp (Aliases lore)
e =
    [Doc] -> Maybe Doc
maybeComment ([Doc] -> Maybe Doc) -> [Doc] -> Maybe Doc
forall a b. (a -> b) -> a -> b
$ [Maybe Doc] -> [Doc]
forall a. [Maybe a] -> [a]
catMaybes [Maybe Doc
expAttr,
                              Maybe Doc
mergeAttr,
                              ExpAttr lore -> Exp lore -> Maybe Doc
forall lore.
PrettyLore lore =>
ExpAttr lore -> Exp lore -> Maybe Doc
ppExpLore ExpAttr lore
inner (Exp lore -> Maybe Doc) -> Exp lore -> Maybe Doc
forall a b. (a -> b) -> a -> b
$ Exp (Aliases lore) -> Exp lore
forall lore.
CanBeAliased (Op lore) =>
Exp (Aliases lore) -> Exp lore
removeExpAliases Exp (Aliases lore)
e]
    where mergeAttr :: Maybe Doc
mergeAttr =
            case Exp (Aliases lore)
e of
              DoLoop [(Param (FParamAttr (Aliases lore)), SubExp)]
_ [(Param (FParamAttr (Aliases lore)), SubExp)]
merge LoopForm (Aliases lore)
_ BodyT (Aliases lore)
body ->
                let mergeParamAliases :: Param attr -> Names -> Maybe Doc
mergeParamAliases Param attr
fparam Names
als
                      | TypeBase Shape NoUniqueness -> Bool
forall shape u. TypeBase shape u -> Bool
primType (Param attr -> TypeBase Shape NoUniqueness
forall attr.
Typed attr =>
Param attr -> TypeBase Shape NoUniqueness
paramType Param attr
fparam) =
                          Maybe Doc
forall a. Maybe a
Nothing
                      | Bool
otherwise =
                          VName -> Names -> Maybe Doc
forall a. Pretty a => a -> Names -> Maybe Doc
resultAliasComment (Param attr -> VName
forall attr. Param attr -> VName
paramName Param attr
fparam) Names
als
                in [Doc] -> Maybe Doc
maybeComment ([Doc] -> Maybe Doc) -> [Doc] -> Maybe Doc
forall a b. (a -> b) -> a -> b
$ [Maybe Doc] -> [Doc]
forall a. [Maybe a] -> [a]
catMaybes ([Maybe Doc] -> [Doc]) -> [Maybe Doc] -> [Doc]
forall a b. (a -> b) -> a -> b
$
                   (Param (FParamAttr lore) -> Names -> Maybe Doc)
-> [Param (FParamAttr lore)] -> [Names] -> [Maybe Doc]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Param (FParamAttr lore) -> Names -> Maybe Doc
forall attr. Typed attr => Param attr -> Names -> Maybe Doc
mergeParamAliases (((Param (FParamAttr lore), SubExp) -> Param (FParamAttr lore))
-> [(Param (FParamAttr lore), SubExp)] -> [Param (FParamAttr lore)]
forall a b. (a -> b) -> [a] -> [b]
map (Param (FParamAttr lore), SubExp) -> Param (FParamAttr lore)
forall a b. (a, b) -> a
fst [(Param (FParamAttr lore), SubExp)]
[(Param (FParamAttr (Aliases lore)), SubExp)]
merge) ([Names] -> [Maybe Doc]) -> [Names] -> [Maybe Doc]
forall a b. (a -> b) -> a -> b
$
                   BodyT (Aliases lore) -> [Names]
forall lore. Aliased lore => Body lore -> [Names]
bodyAliases BodyT (Aliases lore)
body
              Exp (Aliases lore)
_ -> Maybe Doc
forall a. Maybe a
Nothing

          expAttr :: Maybe Doc
expAttr = case Names -> [VName]
namesToList (Names -> [VName]) -> Names -> [VName]
forall a b. (a -> b) -> a -> b
$ Names' -> Names
unNames Names'
consumed of
            []  -> Maybe Doc
forall a. Maybe a
Nothing
            [VName]
als -> Doc -> Maybe Doc
forall a. a -> Maybe a
Just (Doc -> Maybe Doc) -> Doc -> Maybe Doc
forall a b. (a -> b) -> a -> b
$ Doc -> Doc
PP.oneLine (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$
                   String -> Doc
PP.text String
"-- Consumes " Doc -> Doc -> Doc
forall a. Semigroup a => a -> a -> a
<> [Doc] -> Doc
PP.commasep ((VName -> Doc) -> [VName] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map VName -> Doc
forall a. Pretty a => a -> Doc
PP.ppr [VName]
als)

maybeComment :: [PP.Doc] -> Maybe PP.Doc
maybeComment :: [Doc] -> Maybe Doc
maybeComment [] = Maybe Doc
forall a. Maybe a
Nothing
maybeComment [Doc]
cs = Doc -> Maybe Doc
forall a. a -> Maybe a
Just (Doc -> Maybe Doc) -> Doc -> Maybe Doc
forall a b. (a -> b) -> a -> b
$ (Doc -> Doc -> Doc) -> [Doc] -> Doc
PP.folddoc Doc -> Doc -> Doc
(PP.</>) [Doc]
cs

aliasComment :: PP.Pretty a => a -> Names -> Maybe PP.Doc
aliasComment :: a -> Names -> Maybe Doc
aliasComment a
name Names
als =
  case Names -> [VName]
namesToList Names
als of
    [] -> Maybe Doc
forall a. Maybe a
Nothing
    [VName]
als' -> Doc -> Maybe Doc
forall a. a -> Maybe a
Just (Doc -> Maybe Doc) -> Doc -> Maybe Doc
forall a b. (a -> b) -> a -> b
$ Doc -> Doc
PP.oneLine (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$
            String -> Doc
PP.text String
"-- " Doc -> Doc -> Doc
forall a. Semigroup a => a -> a -> a
<> a -> Doc
forall a. Pretty a => a -> Doc
PP.ppr a
name Doc -> Doc -> Doc
forall a. Semigroup a => a -> a -> a
<> String -> Doc
PP.text String
" aliases " Doc -> Doc -> Doc
forall a. Semigroup a => a -> a -> a
<>
            [Doc] -> Doc
PP.commasep ((VName -> Doc) -> [VName] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map VName -> Doc
forall a. Pretty a => a -> Doc
PP.ppr [VName]
als')

resultAliasComment :: PP.Pretty a => a -> Names -> Maybe PP.Doc
resultAliasComment :: a -> Names -> Maybe Doc
resultAliasComment a
name Names
als =
  case Names -> [VName]
namesToList Names
als of
    [] -> Maybe Doc
forall a. Maybe a
Nothing
    [VName]
als' -> Doc -> Maybe Doc
forall a. a -> Maybe a
Just (Doc -> Maybe Doc) -> Doc -> Maybe Doc
forall a b. (a -> b) -> a -> b
$ Doc -> Doc
PP.oneLine (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$
            String -> Doc
PP.text String
"-- Result of " Doc -> Doc -> Doc
forall a. Semigroup a => a -> a -> a
<> a -> Doc
forall a. Pretty a => a -> Doc
PP.ppr a
name Doc -> Doc -> Doc
forall a. Semigroup a => a -> a -> a
<> String -> Doc
PP.text String
" aliases " Doc -> Doc -> Doc
forall a. Semigroup a => a -> a -> a
<>
            [Doc] -> Doc
PP.commasep ((VName -> Doc) -> [VName] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map VName -> Doc
forall a. Pretty a => a -> Doc
PP.ppr [VName]
als')

removeAliases :: CanBeAliased (Op lore) => Rephraser Identity (Aliases lore) lore
removeAliases :: Rephraser Identity (Aliases lore) lore
removeAliases = Rephraser :: forall (m :: * -> *) from to.
(ExpAttr from -> m (ExpAttr to))
-> (LetAttr from -> m (LetAttr to))
-> (FParamAttr from -> m (FParamAttr to))
-> (LParamAttr from -> m (LParamAttr to))
-> (BodyAttr from -> m (BodyAttr to))
-> (RetType from -> m (RetType to))
-> (BranchType from -> m (BranchType to))
-> (Op from -> m (Op to))
-> Rephraser m from to
Rephraser { rephraseExpLore :: ExpAttr (Aliases lore) -> Identity (ExpAttr lore)
rephraseExpLore = ExpAttr lore -> Identity (ExpAttr lore)
forall (m :: * -> *) a. Monad m => a -> m a
return (ExpAttr lore -> Identity (ExpAttr lore))
-> ((Names', ExpAttr lore) -> ExpAttr lore)
-> (Names', ExpAttr lore)
-> Identity (ExpAttr lore)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Names', ExpAttr lore) -> ExpAttr lore
forall a b. (a, b) -> b
snd
                          , rephraseLetBoundLore :: LetAttr (Aliases lore) -> Identity (LetAttr lore)
rephraseLetBoundLore = LetAttr lore -> Identity (LetAttr lore)
forall (m :: * -> *) a. Monad m => a -> m a
return (LetAttr lore -> Identity (LetAttr lore))
-> ((Names', LetAttr lore) -> LetAttr lore)
-> (Names', LetAttr lore)
-> Identity (LetAttr lore)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Names', LetAttr lore) -> LetAttr lore
forall a b. (a, b) -> b
snd
                          , rephraseBodyLore :: BodyAttr (Aliases lore) -> Identity (BodyAttr lore)
rephraseBodyLore = BodyAttr lore -> Identity (BodyAttr lore)
forall (m :: * -> *) a. Monad m => a -> m a
return (BodyAttr lore -> Identity (BodyAttr lore))
-> ((([Names'], Names'), BodyAttr lore) -> BodyAttr lore)
-> (([Names'], Names'), BodyAttr lore)
-> Identity (BodyAttr lore)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (([Names'], Names'), BodyAttr lore) -> BodyAttr lore
forall a b. (a, b) -> b
snd
                          , rephraseFParamLore :: FParamAttr (Aliases lore) -> Identity (FParamAttr lore)
rephraseFParamLore = FParamAttr (Aliases lore) -> Identity (FParamAttr lore)
forall (m :: * -> *) a. Monad m => a -> m a
return
                          , rephraseLParamLore :: LParamAttr (Aliases lore) -> Identity (LParamAttr lore)
rephraseLParamLore = LParamAttr (Aliases lore) -> Identity (LParamAttr lore)
forall (m :: * -> *) a. Monad m => a -> m a
return
                          , rephraseRetType :: RetType (Aliases lore) -> Identity (RetType lore)
rephraseRetType = RetType (Aliases lore) -> Identity (RetType lore)
forall (m :: * -> *) a. Monad m => a -> m a
return
                          , rephraseBranchType :: BranchType (Aliases lore) -> Identity (BranchType lore)
rephraseBranchType = BranchType (Aliases lore) -> Identity (BranchType lore)
forall (m :: * -> *) a. Monad m => a -> m a
return
                          , rephraseOp :: Op (Aliases lore) -> Identity (Op lore)
rephraseOp = Op lore -> Identity (Op lore)
forall (m :: * -> *) a. Monad m => a -> m a
return (Op lore -> Identity (Op lore))
-> (OpWithAliases (Op lore) -> Op lore)
-> OpWithAliases (Op lore)
-> Identity (Op lore)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OpWithAliases (Op lore) -> Op lore
forall op. CanBeAliased op => OpWithAliases op -> op
removeOpAliases
                          }

removeScopeAliases :: Scope (Aliases lore) -> Scope lore
removeScopeAliases :: Scope (Aliases lore) -> Scope lore
removeScopeAliases = (NameInfo (Aliases lore) -> NameInfo lore)
-> Scope (Aliases lore) -> Scope lore
forall a b k. (a -> b) -> Map k a -> Map k b
M.map NameInfo (Aliases lore) -> NameInfo lore
forall lore a lore.
(LetAttr lore ~ (a, LetAttr lore),
 FParamAttr lore ~ FParamAttr lore,
 LParamAttr lore ~ LParamAttr lore) =>
NameInfo lore -> NameInfo lore
unAlias
  where unAlias :: NameInfo lore -> NameInfo lore
unAlias (LetInfo (_, attr)) = LetAttr lore -> NameInfo lore
forall lore. LetAttr lore -> NameInfo lore
LetInfo LetAttr lore
attr
        unAlias (FParamInfo FParamAttr lore
attr) = FParamAttr lore -> NameInfo lore
forall lore. FParamAttr lore -> NameInfo lore
FParamInfo FParamAttr lore
FParamAttr lore
attr
        unAlias (LParamInfo LParamAttr lore
attr) = LParamAttr lore -> NameInfo lore
forall lore. LParamAttr lore -> NameInfo lore
LParamInfo LParamAttr lore
LParamAttr lore
attr
        unAlias (IndexInfo IntType
it) = IntType -> NameInfo lore
forall lore. IntType -> NameInfo lore
IndexInfo IntType
it

removeProgAliases :: CanBeAliased (Op lore) =>
                     Prog (Aliases lore) -> Prog lore
removeProgAliases :: Prog (Aliases lore) -> Prog lore
removeProgAliases = Identity (Prog lore) -> Prog lore
forall a. Identity a -> a
runIdentity (Identity (Prog lore) -> Prog lore)
-> (Prog (Aliases lore) -> Identity (Prog lore))
-> Prog (Aliases lore)
-> Prog lore
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rephraser Identity (Aliases lore) lore
-> Prog (Aliases lore) -> Identity (Prog lore)
forall (m :: * -> *) from to.
Monad m =>
Rephraser m from to -> Prog from -> m (Prog to)
rephraseProg Rephraser Identity (Aliases lore) lore
forall lore.
CanBeAliased (Op lore) =>
Rephraser Identity (Aliases lore) lore
removeAliases

removeFunDefAliases :: CanBeAliased (Op lore) =>
                       FunDef (Aliases lore) -> FunDef lore
removeFunDefAliases :: FunDef (Aliases lore) -> FunDef lore
removeFunDefAliases = Identity (FunDef lore) -> FunDef lore
forall a. Identity a -> a
runIdentity (Identity (FunDef lore) -> FunDef lore)
-> (FunDef (Aliases lore) -> Identity (FunDef lore))
-> FunDef (Aliases lore)
-> FunDef lore
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rephraser Identity (Aliases lore) lore
-> FunDef (Aliases lore) -> Identity (FunDef lore)
forall (m :: * -> *) from to.
Monad m =>
Rephraser m from to -> FunDef from -> m (FunDef to)
rephraseFunDef Rephraser Identity (Aliases lore) lore
forall lore.
CanBeAliased (Op lore) =>
Rephraser Identity (Aliases lore) lore
removeAliases

removeExpAliases :: CanBeAliased (Op lore) =>
                    Exp (Aliases lore) -> Exp lore
removeExpAliases :: Exp (Aliases lore) -> Exp lore
removeExpAliases = Identity (Exp lore) -> Exp lore
forall a. Identity a -> a
runIdentity (Identity (Exp lore) -> Exp lore)
-> (Exp (Aliases lore) -> Identity (Exp lore))
-> Exp (Aliases lore)
-> Exp lore
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rephraser Identity (Aliases lore) lore
-> Exp (Aliases lore) -> Identity (Exp lore)
forall (m :: * -> *) from to.
Monad m =>
Rephraser m from to -> Exp from -> m (Exp to)
rephraseExp Rephraser Identity (Aliases lore) lore
forall lore.
CanBeAliased (Op lore) =>
Rephraser Identity (Aliases lore) lore
removeAliases

removeStmAliases :: CanBeAliased (Op lore) =>
                        Stm (Aliases lore) -> Stm lore
removeStmAliases :: Stm (Aliases lore) -> Stm lore
removeStmAliases = Identity (Stm lore) -> Stm lore
forall a. Identity a -> a
runIdentity (Identity (Stm lore) -> Stm lore)
-> (Stm (Aliases lore) -> Identity (Stm lore))
-> Stm (Aliases lore)
-> Stm lore
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rephraser Identity (Aliases lore) lore
-> Stm (Aliases lore) -> Identity (Stm lore)
forall (m :: * -> *) from to.
Monad m =>
Rephraser m from to -> Stm from -> m (Stm to)
rephraseStm Rephraser Identity (Aliases lore) lore
forall lore.
CanBeAliased (Op lore) =>
Rephraser Identity (Aliases lore) lore
removeAliases

removeLambdaAliases :: CanBeAliased (Op lore) =>
                       Lambda (Aliases lore) -> Lambda lore
removeLambdaAliases :: Lambda (Aliases lore) -> Lambda lore
removeLambdaAliases = Identity (Lambda lore) -> Lambda lore
forall a. Identity a -> a
runIdentity (Identity (Lambda lore) -> Lambda lore)
-> (Lambda (Aliases lore) -> Identity (Lambda lore))
-> Lambda (Aliases lore)
-> Lambda lore
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rephraser Identity (Aliases lore) lore
-> Lambda (Aliases lore) -> Identity (Lambda lore)
forall (m :: * -> *) from to.
Monad m =>
Rephraser m from to -> Lambda from -> m (Lambda to)
rephraseLambda Rephraser Identity (Aliases lore) lore
forall lore.
CanBeAliased (Op lore) =>
Rephraser Identity (Aliases lore) lore
removeAliases

removePatternAliases :: PatternT (Names', a)
                     -> PatternT a
removePatternAliases :: PatternT (Names', a) -> PatternT a
removePatternAliases = Identity (PatternT a) -> PatternT a
forall a. Identity a -> a
runIdentity (Identity (PatternT a) -> PatternT a)
-> (PatternT (Names', a) -> Identity (PatternT a))
-> PatternT (Names', a)
-> PatternT a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Names', a) -> Identity a)
-> PatternT (Names', a) -> Identity (PatternT a)
forall (m :: * -> *) from to.
Monad m =>
(from -> m to) -> PatternT from -> m (PatternT to)
rephrasePattern (a -> Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> Identity a)
-> ((Names', a) -> a) -> (Names', a) -> Identity a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Names', a) -> a
forall a b. (a, b) -> b
snd)

addAliasesToPattern :: (Attributes lore, CanBeAliased (Op lore), Typed attr) =>
                       PatternT attr -> Exp (Aliases lore)
                    -> PatternT (VarAliases, attr)
addAliasesToPattern :: PatternT attr -> Exp (Aliases lore) -> PatternT (Names', attr)
addAliasesToPattern PatternT attr
pat Exp (Aliases lore)
e =
  ([PatElemT (Names', attr)]
 -> [PatElemT (Names', attr)] -> PatternT (Names', attr))
-> ([PatElemT (Names', attr)], [PatElemT (Names', attr)])
-> PatternT (Names', attr)
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry [PatElemT (Names', attr)]
-> [PatElemT (Names', attr)] -> PatternT (Names', attr)
forall attr. [PatElemT attr] -> [PatElemT attr] -> PatternT attr
Pattern (([PatElemT (Names', attr)], [PatElemT (Names', attr)])
 -> PatternT (Names', attr))
-> ([PatElemT (Names', attr)], [PatElemT (Names', attr)])
-> PatternT (Names', attr)
forall a b. (a -> b) -> a -> b
$ PatternT attr
-> Exp (Aliases lore)
-> ([PatElemT (Names', attr)], [PatElemT (Names', attr)])
forall lore attr.
(Aliased lore, Typed attr) =>
PatternT attr
-> Exp lore
-> ([PatElemT (Names', attr)], [PatElemT (Names', attr)])
mkPatternAliases PatternT attr
pat Exp (Aliases lore)
e

mkAliasedBody :: (Attributes lore, CanBeAliased (Op lore)) =>
                 BodyAttr lore -> Stms (Aliases lore) -> Result -> Body (Aliases lore)
mkAliasedBody :: BodyAttr lore
-> Stms (Aliases lore) -> Result -> Body (Aliases lore)
mkAliasedBody BodyAttr lore
innerlore Stms (Aliases lore)
bnds Result
res =
  BodyAttr (Aliases lore)
-> Stms (Aliases lore) -> Result -> Body (Aliases lore)
forall lore. BodyAttr lore -> Stms lore -> Result -> BodyT lore
Body (Stms (Aliases lore) -> Result -> ([Names'], Names')
forall lore.
Aliased lore =>
Stms lore -> Result -> ([Names'], Names')
mkBodyAliases Stms (Aliases lore)
bnds Result
res, BodyAttr lore
innerlore) Stms (Aliases lore)
bnds Result
res

mkPatternAliases :: (Aliased lore, Typed attr) =>
                    PatternT attr -> Exp lore
                 -> ([PatElemT (VarAliases, attr)],
                     [PatElemT (VarAliases, attr)])
mkPatternAliases :: PatternT attr
-> Exp lore
-> ([PatElemT (Names', attr)], [PatElemT (Names', attr)])
mkPatternAliases PatternT attr
pat Exp lore
e =
  -- Some part of the pattern may be the context.  This does not have
  -- aliases from expAliases, so we use a hack to compute aliases of
  -- the context.
  let als :: [Names]
als = Exp lore -> [Names]
forall lore. Aliased lore => Exp lore -> [Names]
expAliases Exp lore
e [Names] -> [Names] -> [Names]
forall a. [a] -> [a] -> [a]
++ Names -> [Names]
forall a. a -> [a]
repeat Names
forall a. Monoid a => a
mempty -- In case the pattern has
                                          -- more elements (this
                                          -- implies a type error).
      context_als :: [Names]
context_als = PatternT attr -> Exp lore -> [Names]
forall lore attr.
Aliased lore =>
PatternT attr -> Exp lore -> [Names]
mkContextAliases PatternT attr
pat Exp lore
e
  in ((PatElemT attr -> Names -> PatElemT (Names', attr))
-> [PatElemT attr] -> [Names] -> [PatElemT (Names', attr)]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith PatElemT attr -> Names -> PatElemT (Names', attr)
forall b. Typed b => PatElemT b -> Names -> PatElemT (Names', b)
annotateBindee (PatternT attr -> [PatElemT attr]
forall attr. PatternT attr -> [PatElemT attr]
patternContextElements PatternT attr
pat) [Names]
context_als,
      (PatElemT attr -> Names -> PatElemT (Names', attr))
-> [PatElemT attr] -> [Names] -> [PatElemT (Names', attr)]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith PatElemT attr -> Names -> PatElemT (Names', attr)
forall b. Typed b => PatElemT b -> Names -> PatElemT (Names', b)
annotateBindee (PatternT attr -> [PatElemT attr]
forall attr. PatternT attr -> [PatElemT attr]
patternValueElements PatternT attr
pat) [Names]
als)
  where annotateBindee :: PatElemT b -> Names -> PatElemT (Names', b)
annotateBindee PatElemT b
bindee Names
names =
            PatElemT b
bindee PatElemT b -> (Names', b) -> PatElemT (Names', b)
forall oldattr newattr.
PatElemT oldattr -> newattr -> PatElemT newattr
`setPatElemLore` (Names -> Names'
Names' Names
names', PatElemT b -> b
forall attr. PatElemT attr -> attr
patElemAttr PatElemT b
bindee)
          where names' :: Names
names' =
                  case PatElemT b -> TypeBase Shape NoUniqueness
forall attr.
Typed attr =>
PatElemT attr -> TypeBase Shape NoUniqueness
patElemType PatElemT b
bindee of
                    Array {} -> Names
names
                    Mem Space
_    -> Names
names
                    TypeBase Shape NoUniqueness
_        -> Names
forall a. Monoid a => a
mempty

mkContextAliases :: Aliased lore =>
                    PatternT attr -> Exp lore -> [Names]
mkContextAliases :: PatternT attr -> Exp lore -> [Names]
mkContextAliases PatternT attr
pat (DoLoop [(FParam lore, SubExp)]
ctxmerge [(FParam lore, SubExp)]
valmerge LoopForm lore
_ BodyT lore
body) =
  let ctx :: [FParam lore]
ctx = ((FParam lore, SubExp) -> FParam lore)
-> [(FParam lore, SubExp)] -> [FParam lore]
forall a b. (a -> b) -> [a] -> [b]
map (FParam lore, SubExp) -> FParam lore
forall a b. (a, b) -> a
fst [(FParam lore, SubExp)]
ctxmerge
      init_als :: [(VName, Names)]
init_als = [VName] -> [Names] -> [(VName, Names)]
forall a b. [a] -> [b] -> [(a, b)]
zip [VName]
mergenames ([Names] -> [(VName, Names)]) -> [Names] -> [(VName, Names)]
forall a b. (a -> b) -> a -> b
$ ((FParam lore, SubExp) -> Names)
-> [(FParam lore, SubExp)] -> [Names]
forall a b. (a -> b) -> [a] -> [b]
map (SubExp -> Names
subExpAliases (SubExp -> Names)
-> ((FParam lore, SubExp) -> SubExp)
-> (FParam lore, SubExp)
-> Names
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FParam lore, SubExp) -> SubExp
forall a b. (a, b) -> b
snd) ([(FParam lore, SubExp)] -> [Names])
-> [(FParam lore, SubExp)] -> [Names]
forall a b. (a -> b) -> a -> b
$ [(FParam lore, SubExp)]
ctxmerge [(FParam lore, SubExp)]
-> [(FParam lore, SubExp)] -> [(FParam lore, SubExp)]
forall a. [a] -> [a] -> [a]
++ [(FParam lore, SubExp)]
valmerge
      expand :: Names -> Names
expand Names
als = Names
als Names -> Names -> Names
forall a. Semigroup a => a -> a -> a
<> [Names] -> Names
forall a. Monoid a => [a] -> a
mconcat ((VName -> Maybe Names) -> [VName] -> [Names]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (VName -> [(VName, Names)] -> Maybe Names
forall a b. Eq a => a -> [(a, b)] -> Maybe b
`lookup` [(VName, Names)]
init_als) (Names -> [VName]
namesToList Names
als))
      merge_als :: [(VName, Names)]
merge_als = [VName] -> [Names] -> [(VName, Names)]
forall a b. [a] -> [b] -> [(a, b)]
zip [VName]
mergenames ([Names] -> [(VName, Names)]) -> [Names] -> [(VName, Names)]
forall a b. (a -> b) -> a -> b
$
                  (Names -> Names) -> [Names] -> [Names]
forall a b. (a -> b) -> [a] -> [b]
map ((Names -> Names -> Names
`namesSubtract` Names
mergenames_set) (Names -> Names) -> (Names -> Names) -> Names -> Names
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Names -> Names
expand) ([Names] -> [Names]) -> [Names] -> [Names]
forall a b. (a -> b) -> a -> b
$
                  BodyT lore -> [Names]
forall lore. Aliased lore => Body lore -> [Names]
bodyAliases BodyT lore
body
  in if [FParam lore] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [FParam lore]
ctx Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== [PatElemT attr] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (PatternT attr -> [PatElemT attr]
forall attr. PatternT attr -> [PatElemT attr]
patternContextElements PatternT attr
pat)
     then (FParam lore -> Names) -> [FParam lore] -> [Names]
forall a b. (a -> b) -> [a] -> [b]
map (Names -> Maybe Names -> Names
forall a. a -> Maybe a -> a
fromMaybe Names
forall a. Monoid a => a
mempty (Maybe Names -> Names)
-> (FParam lore -> Maybe Names) -> FParam lore -> Names
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (VName -> [(VName, Names)] -> Maybe Names)
-> [(VName, Names)] -> VName -> Maybe Names
forall a b c. (a -> b -> c) -> b -> a -> c
flip VName -> [(VName, Names)] -> Maybe Names
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup [(VName, Names)]
merge_als (VName -> Maybe Names)
-> (FParam lore -> VName) -> FParam lore -> Maybe Names
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FParam lore -> VName
forall attr. Param attr -> VName
paramName) [FParam lore]
ctx
     else (PatElemT attr -> Names) -> [PatElemT attr] -> [Names]
forall a b. (a -> b) -> [a] -> [b]
map (Names -> PatElemT attr -> Names
forall a b. a -> b -> a
const Names
forall a. Monoid a => a
mempty) ([PatElemT attr] -> [Names]) -> [PatElemT attr] -> [Names]
forall a b. (a -> b) -> a -> b
$ PatternT attr -> [PatElemT attr]
forall attr. PatternT attr -> [PatElemT attr]
patternContextElements PatternT attr
pat
  where mergenames :: [VName]
mergenames = ((FParam lore, SubExp) -> VName)
-> [(FParam lore, SubExp)] -> [VName]
forall a b. (a -> b) -> [a] -> [b]
map (FParam lore -> VName
forall attr. Param attr -> VName
paramName (FParam lore -> VName)
-> ((FParam lore, SubExp) -> FParam lore)
-> (FParam lore, SubExp)
-> VName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FParam lore, SubExp) -> FParam lore
forall a b. (a, b) -> a
fst) ([(FParam lore, SubExp)] -> [VName])
-> [(FParam lore, SubExp)] -> [VName]
forall a b. (a -> b) -> a -> b
$ [(FParam lore, SubExp)]
ctxmerge [(FParam lore, SubExp)]
-> [(FParam lore, SubExp)] -> [(FParam lore, SubExp)]
forall a. [a] -> [a] -> [a]
++ [(FParam lore, SubExp)]
valmerge
        mergenames_set :: Names
mergenames_set = [VName] -> Names
namesFromList [VName]
mergenames
mkContextAliases PatternT attr
pat (If SubExp
_ BodyT lore
tbranch BodyT lore
fbranch IfAttr (BranchType lore)
_) =
  Int -> [Names] -> [Names]
forall a. Int -> [a] -> [a]
take ([VName] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([VName] -> Int) -> [VName] -> Int
forall a b. (a -> b) -> a -> b
$ PatternT attr -> [VName]
forall attr. PatternT attr -> [VName]
patternContextNames PatternT attr
pat) ([Names] -> [Names]) -> [Names] -> [Names]
forall a b. (a -> b) -> a -> b
$
  (Names -> Names -> Names) -> [Names] -> [Names] -> [Names]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Names -> Names -> Names
forall a. Semigroup a => a -> a -> a
(<>) (BodyT lore -> [Names]
forall lore. Aliased lore => Body lore -> [Names]
bodyAliases BodyT lore
tbranch) (BodyT lore -> [Names]
forall lore. Aliased lore => Body lore -> [Names]
bodyAliases BodyT lore
fbranch)
mkContextAliases PatternT attr
pat Exp lore
_ =
  Int -> Names -> [Names]
forall a. Int -> a -> [a]
replicate ([PatElemT attr] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([PatElemT attr] -> Int) -> [PatElemT attr] -> Int
forall a b. (a -> b) -> a -> b
$ PatternT attr -> [PatElemT attr]
forall attr. PatternT attr -> [PatElemT attr]
patternContextElements PatternT attr
pat) Names
forall a. Monoid a => a
mempty

mkBodyAliases :: Aliased lore =>
                 Stms lore
              -> Result
              -> BodyAliasing
mkBodyAliases :: Stms lore -> Result -> ([Names'], Names')
mkBodyAliases Stms lore
bnds Result
res =
  -- We need to remove the names that are bound in bnds from the alias
  -- and consumption sets.  We do this by computing the transitive
  -- closure of the alias map (within bnds), then removing anything
  -- bound in bnds.
  let ([Names]
aliases, Names
consumed) = Stms lore -> Result -> ([Names], Names)
forall lore.
Aliased lore =>
Stms lore -> Result -> ([Names], Names)
mkStmsAliases Stms lore
bnds Result
res
      boundNames :: Names
boundNames =
        (Stm lore -> Names) -> Stms lore -> Names
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap ([VName] -> Names
namesFromList ([VName] -> Names) -> (Stm lore -> [VName]) -> Stm lore -> Names
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PatternT (LetAttr lore) -> [VName]
forall attr. PatternT attr -> [VName]
patternNames (PatternT (LetAttr lore) -> [VName])
-> (Stm lore -> PatternT (LetAttr lore)) -> Stm lore -> [VName]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Stm lore -> PatternT (LetAttr lore)
forall lore. Stm lore -> Pattern lore
stmPattern) Stms lore
bnds
      aliases' :: [Names]
aliases' = (Names -> Names) -> [Names] -> [Names]
forall a b. (a -> b) -> [a] -> [b]
map (Names -> Names -> Names
`namesSubtract` Names
boundNames) [Names]
aliases
      consumed' :: Names
consumed' = Names
consumed Names -> Names -> Names
`namesSubtract` Names
boundNames
  in ((Names -> Names') -> [Names] -> [Names']
forall a b. (a -> b) -> [a] -> [b]
map Names -> Names'
Names' [Names]
aliases', Names -> Names'
Names' Names
consumed')

mkStmsAliases :: Aliased lore =>
                 Stms lore -> [SubExp]
              -> ([Names], Names)
mkStmsAliases :: Stms lore -> Result -> ([Names], Names)
mkStmsAliases Stms lore
bnds Result
res = AliasesAndConsumed -> [Stm lore] -> ([Names], Names)
delve AliasesAndConsumed
forall a. Monoid a => a
mempty ([Stm lore] -> ([Names], Names)) -> [Stm lore] -> ([Names], Names)
forall a b. (a -> b) -> a -> b
$ Stms lore -> [Stm lore]
forall lore. Stms lore -> [Stm lore]
stmsToList Stms lore
bnds
  where delve :: AliasesAndConsumed -> [Stm lore] -> ([Names], Names)
delve (Map VName Names
aliasmap, Names
consumed) [] =
          ((SubExp -> Names) -> Result -> [Names]
forall a b. (a -> b) -> [a] -> [b]
map (Map VName Names -> Names -> Names
aliasClosure Map VName Names
aliasmap (Names -> Names) -> (SubExp -> Names) -> SubExp -> Names
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SubExp -> Names
subExpAliases) Result
res,
           Names
consumed)
        delve (Map VName Names
aliasmap, Names
consumed) (Stm lore
bnd:[Stm lore]
bnds') =
          AliasesAndConsumed -> [Stm lore] -> ([Names], Names)
delve (AliasesAndConsumed -> Stm lore -> AliasesAndConsumed
forall lore.
Aliased lore =>
AliasesAndConsumed -> Stm lore -> AliasesAndConsumed
trackAliases (Map VName Names
aliasmap, Names
consumed) Stm lore
bnd) [Stm lore]
bnds'
        aliasClosure :: Map VName Names -> Names -> Names
aliasClosure Map VName Names
aliasmap Names
names =
          Names
names Names -> Names -> Names
forall a. Semigroup a => a -> a -> a
<> [Names] -> Names
forall a. Monoid a => [a] -> a
mconcat ((VName -> Names) -> [VName] -> [Names]
forall a b. (a -> b) -> [a] -> [b]
map VName -> Names
look ([VName] -> [Names]) -> [VName] -> [Names]
forall a b. (a -> b) -> a -> b
$ Names -> [VName]
namesToList Names
names)
          where look :: VName -> Names
look VName
k = Names -> VName -> Map VName Names -> Names
forall k a. Ord k => a -> k -> Map k a -> a
M.findWithDefault Names
forall a. Monoid a => a
mempty VName
k Map VName Names
aliasmap

-- | Everything consumed in the given statements and result (even
-- transitively).
consumedInStms :: Aliased lore => Stms lore -> Names
consumedInStms :: Stms lore -> Names
consumedInStms = ([Names], Names) -> Names
forall a b. (a, b) -> b
snd (([Names], Names) -> Names)
-> (Stms lore -> ([Names], Names)) -> Stms lore -> Names
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Stms lore -> Result -> ([Names], Names))
-> Result -> Stms lore -> ([Names], Names)
forall a b c. (a -> b -> c) -> b -> a -> c
flip Stms lore -> Result -> ([Names], Names)
forall lore.
Aliased lore =>
Stms lore -> Result -> ([Names], Names)
mkStmsAliases []

type AliasesAndConsumed = (M.Map VName Names,
                           Names)

trackAliases :: Aliased lore =>
                AliasesAndConsumed -> Stm lore
             -> AliasesAndConsumed
trackAliases :: AliasesAndConsumed -> Stm lore -> AliasesAndConsumed
trackAliases (Map VName Names
aliasmap, Names
consumed) Stm lore
bnd =
  let pat :: Pattern lore
pat = Stm lore -> Pattern lore
forall lore. Stm lore -> Pattern lore
stmPattern Stm lore
bnd
      als :: Map VName Names
als = [(VName, Names)] -> Map VName Names
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([(VName, Names)] -> Map VName Names)
-> [(VName, Names)] -> Map VName Names
forall a b. (a -> b) -> a -> b
$
            [VName] -> [Names] -> [(VName, Names)]
forall a b. [a] -> [b] -> [(a, b)]
zip (Pattern lore -> [VName]
forall attr. PatternT attr -> [VName]
patternNames Pattern lore
pat) ((Names -> Names) -> [Names] -> [Names]
forall a b. (a -> b) -> [a] -> [b]
map Names -> Names
addAliasesOfAliases ([Names] -> [Names]) -> [Names] -> [Names]
forall a b. (a -> b) -> a -> b
$ Pattern lore -> [Names]
forall attr. AliasesOf attr => PatternT attr -> [Names]
patternAliases Pattern lore
pat)
      aliasmap' :: Map VName Names
aliasmap' = Map VName Names
als Map VName Names -> Map VName Names -> Map VName Names
forall a. Semigroup a => a -> a -> a
<> Map VName Names
aliasmap
      consumed' :: Names
consumed' = Names
consumed Names -> Names -> Names
forall a. Semigroup a => a -> a -> a
<> Names -> Names
addAliasesOfAliases (Stm lore -> Names
forall lore. Aliased lore => Stm lore -> Names
consumedInStm Stm lore
bnd)
  in (Map VName Names
aliasmap', Names
consumed')
  where addAliasesOfAliases :: Names -> Names
addAliasesOfAliases Names
names = Names
names Names -> Names -> Names
forall a. Semigroup a => a -> a -> a
<> Names -> Names
aliasesOfAliases Names
names
        aliasesOfAliases :: Names -> Names
aliasesOfAliases =  [Names] -> Names
forall a. Monoid a => [a] -> a
mconcat ([Names] -> Names) -> (Names -> [Names]) -> Names -> Names
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (VName -> Names) -> [VName] -> [Names]
forall a b. (a -> b) -> [a] -> [b]
map VName -> Names
look ([VName] -> [Names]) -> (Names -> [VName]) -> Names -> [Names]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Names -> [VName]
namesToList
        look :: VName -> Names
look VName
k = Names -> VName -> Map VName Names -> Names
forall k a. Ord k => a -> k -> Map k a -> a
M.findWithDefault Names
forall a. Monoid a => a
mempty VName
k Map VName Names
aliasmap

mkAliasedLetStm :: (Attributes lore, CanBeAliased (Op lore)) =>
                   Pattern lore
                -> StmAux (ExpAttr lore) -> Exp (Aliases lore)
                -> Stm (Aliases lore)
mkAliasedLetStm :: Pattern lore
-> StmAux (ExpAttr lore)
-> Exp (Aliases lore)
-> Stm (Aliases lore)
mkAliasedLetStm Pattern lore
pat (StmAux Certificates
cs ExpAttr lore
attr) Exp (Aliases lore)
e =
  Pattern (Aliases lore)
-> StmAux (ExpAttr (Aliases lore))
-> Exp (Aliases lore)
-> Stm (Aliases lore)
forall lore.
Pattern lore -> StmAux (ExpAttr lore) -> Exp lore -> Stm lore
Let (Pattern lore
-> Exp (Aliases lore) -> PatternT (Names', LetAttr lore)
forall lore attr.
(Attributes lore, CanBeAliased (Op lore), Typed attr) =>
PatternT attr -> Exp (Aliases lore) -> PatternT (Names', attr)
addAliasesToPattern Pattern lore
pat Exp (Aliases lore)
e)
  (Certificates
-> (Names', ExpAttr lore) -> StmAux (Names', ExpAttr lore)
forall attr. Certificates -> attr -> StmAux attr
StmAux Certificates
cs (Names -> Names'
Names' (Names -> Names') -> Names -> Names'
forall a b. (a -> b) -> a -> b
$ Exp (Aliases lore) -> Names
forall lore. Aliased lore => Exp lore -> Names
consumedInExp Exp (Aliases lore)
e, ExpAttr lore
attr))
  Exp (Aliases lore)
e

instance (Bindable lore, CanBeAliased (Op lore)) => Bindable (Aliases lore) where
  mkExpAttr :: Pattern (Aliases lore)
-> Exp (Aliases lore) -> ExpAttr (Aliases lore)
mkExpAttr Pattern (Aliases lore)
pat Exp (Aliases lore)
e =
    let attr :: ExpAttr lore
attr = Pattern lore -> Exp lore -> ExpAttr lore
forall lore.
Bindable lore =>
Pattern lore -> Exp lore -> ExpAttr lore
mkExpAttr (PatternT (Names', LetAttr lore) -> Pattern lore
forall a. PatternT (Names', a) -> PatternT a
removePatternAliases PatternT (Names', LetAttr lore)
Pattern (Aliases lore)
pat) (Exp lore -> ExpAttr lore) -> Exp lore -> ExpAttr lore
forall a b. (a -> b) -> a -> b
$ Exp (Aliases lore) -> Exp lore
forall lore.
CanBeAliased (Op lore) =>
Exp (Aliases lore) -> Exp lore
removeExpAliases Exp (Aliases lore)
e
    in (Names -> Names'
Names' (Names -> Names') -> Names -> Names'
forall a b. (a -> b) -> a -> b
$ Exp (Aliases lore) -> Names
forall lore. Aliased lore => Exp lore -> Names
consumedInExp Exp (Aliases lore)
e, ExpAttr lore
attr)

  mkExpPat :: [Ident] -> [Ident] -> Exp (Aliases lore) -> Pattern (Aliases lore)
mkExpPat [Ident]
ctx [Ident]
val Exp (Aliases lore)
e =
    Pattern lore
-> Exp (Aliases lore) -> PatternT (Names', LetAttr lore)
forall lore attr.
(Attributes lore, CanBeAliased (Op lore), Typed attr) =>
PatternT attr -> Exp (Aliases lore) -> PatternT (Names', attr)
addAliasesToPattern ([Ident] -> [Ident] -> Exp lore -> Pattern lore
forall lore.
Bindable lore =>
[Ident] -> [Ident] -> Exp lore -> Pattern lore
mkExpPat [Ident]
ctx [Ident]
val (Exp lore -> Pattern lore) -> Exp lore -> Pattern lore
forall a b. (a -> b) -> a -> b
$ Exp (Aliases lore) -> Exp lore
forall lore.
CanBeAliased (Op lore) =>
Exp (Aliases lore) -> Exp lore
removeExpAliases Exp (Aliases lore)
e) Exp (Aliases lore)
e

  mkLetNames :: [VName] -> Exp (Aliases lore) -> m (Stm (Aliases lore))
mkLetNames [VName]
names Exp (Aliases lore)
e = do
    Scope lore
env <- (Scope (Aliases lore) -> Scope lore) -> m (Scope lore)
forall lore (m :: * -> *) a.
HasScope lore m =>
(Scope lore -> a) -> m a
asksScope Scope (Aliases lore) -> Scope lore
forall lore. Scope (Aliases lore) -> Scope lore
removeScopeAliases
    (ReaderT (Scope lore) m (Stm (Aliases lore))
 -> Scope lore -> m (Stm (Aliases lore)))
-> Scope lore
-> ReaderT (Scope lore) m (Stm (Aliases lore))
-> m (Stm (Aliases lore))
forall a b c. (a -> b -> c) -> b -> a -> c
flip ReaderT (Scope lore) m (Stm (Aliases lore))
-> Scope lore -> m (Stm (Aliases lore))
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT Scope lore
env (ReaderT (Scope lore) m (Stm (Aliases lore))
 -> m (Stm (Aliases lore)))
-> ReaderT (Scope lore) m (Stm (Aliases lore))
-> m (Stm (Aliases lore))
forall a b. (a -> b) -> a -> b
$ do
      Let Pattern lore
pat StmAux (ExpAttr lore)
attr Exp lore
_ <- [VName] -> Exp lore -> ReaderT (Scope lore) m (Stm lore)
forall lore (m :: * -> *).
(Bindable lore, MonadFreshNames m, HasScope lore m) =>
[VName] -> Exp lore -> m (Stm lore)
mkLetNames [VName]
names (Exp lore -> ReaderT (Scope lore) m (Stm lore))
-> Exp lore -> ReaderT (Scope lore) m (Stm lore)
forall a b. (a -> b) -> a -> b
$ Exp (Aliases lore) -> Exp lore
forall lore.
CanBeAliased (Op lore) =>
Exp (Aliases lore) -> Exp lore
removeExpAliases Exp (Aliases lore)
e
      Stm (Aliases lore) -> ReaderT (Scope lore) m (Stm (Aliases lore))
forall (m :: * -> *) a. Monad m => a -> m a
return (Stm (Aliases lore) -> ReaderT (Scope lore) m (Stm (Aliases lore)))
-> Stm (Aliases lore)
-> ReaderT (Scope lore) m (Stm (Aliases lore))
forall a b. (a -> b) -> a -> b
$ Pattern lore
-> StmAux (ExpAttr lore)
-> Exp (Aliases lore)
-> Stm (Aliases lore)
forall lore.
(Attributes lore, CanBeAliased (Op lore)) =>
Pattern lore
-> StmAux (ExpAttr lore)
-> Exp (Aliases lore)
-> Stm (Aliases lore)
mkAliasedLetStm Pattern lore
pat StmAux (ExpAttr lore)
attr Exp (Aliases lore)
e

  mkBody :: Stms (Aliases lore) -> Result -> Body (Aliases lore)
mkBody Stms (Aliases lore)
bnds Result
res =
    let Body BodyAttr lore
bodylore Stms lore
_ Result
_ = Stms lore -> Result -> BodyT lore
forall lore. Bindable lore => Stms lore -> Result -> Body lore
mkBody ((Stm (Aliases lore) -> Stm lore)
-> Stms (Aliases lore) -> Stms lore
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Stm (Aliases lore) -> Stm lore
forall lore.
CanBeAliased (Op lore) =>
Stm (Aliases lore) -> Stm lore
removeStmAliases Stms (Aliases lore)
bnds) Result
res
    in BodyAttr lore
-> Stms (Aliases lore) -> Result -> Body (Aliases lore)
forall lore.
(Attributes lore, CanBeAliased (Op lore)) =>
BodyAttr lore
-> Stms (Aliases lore) -> Result -> Body (Aliases lore)
mkAliasedBody BodyAttr lore
bodylore Stms (Aliases lore)
bnds Result
res

instance (Attributes (Aliases lore), Bindable (Aliases lore)) => BinderOps (Aliases lore) where
  mkBodyB :: Stms (Aliases lore) -> Result -> m (Body (Aliases lore))
mkBodyB = Stms (Aliases lore) -> Result -> m (Body (Aliases lore))
forall (m :: * -> *).
(MonadBinder m, Bindable (Lore m)) =>
Stms (Lore m) -> Result -> m (Body (Lore m))
bindableMkBodyB
  mkExpAttrB :: Pattern (Aliases lore)
-> Exp (Aliases lore) -> m (ExpAttr (Aliases lore))
mkExpAttrB = Pattern (Aliases lore)
-> Exp (Aliases lore) -> m (ExpAttr (Aliases lore))
forall (m :: * -> *).
(MonadBinder m, Bindable (Lore m)) =>
Pattern (Lore m) -> Exp (Lore m) -> m (ExpAttr (Lore m))
bindableMkExpAttrB
  mkLetNamesB :: [VName] -> Exp (Aliases lore) -> m (Stm (Aliases lore))
mkLetNamesB = [VName] -> Exp (Aliases lore) -> m (Stm (Aliases lore))
forall (m :: * -> *).
(MonadBinder m, Bindable (Lore m)) =>
[VName] -> Exp (Lore m) -> m (Stm (Lore m))
bindableMkLetNamesB