{-# LANGUAGE TypeFamilies #-}
module Futhark.Analysis.Alias
( aliasAnalysis,
AliasableRep,
analyseFun,
analyseStms,
analyseStm,
analyseExp,
analyseBody,
analyseLambda,
)
where
import Data.List qualified as L
import Data.Map qualified as M
import Futhark.IR.Aliases
aliasAnalysis ::
(AliasableRep rep) =>
Prog rep ->
Prog (Aliases rep)
aliasAnalysis :: forall rep. AliasableRep rep => Prog rep -> Prog (Aliases rep)
aliasAnalysis Prog rep
prog =
Prog rep
prog
{ progConsts = fst (analyseStms mempty (progConsts prog)),
progFuns = map analyseFun (progFuns prog)
}
analyseFun ::
(AliasableRep rep) =>
FunDef rep ->
FunDef (Aliases rep)
analyseFun :: forall rep. AliasableRep rep => FunDef rep -> FunDef (Aliases rep)
analyseFun (FunDef Maybe EntryPoint
entry Attrs
attrs Name
fname [(RetType rep, RetAls)]
restype [FParam rep]
params Body rep
body) =
Maybe EntryPoint
-> Attrs
-> Name
-> [(RetType (Aliases rep), RetAls)]
-> [FParam (Aliases rep)]
-> Body (Aliases rep)
-> FunDef (Aliases rep)
forall rep.
Maybe EntryPoint
-> Attrs
-> Name
-> [(RetType rep, RetAls)]
-> [FParam rep]
-> Body rep
-> FunDef rep
FunDef Maybe EntryPoint
entry Attrs
attrs Name
fname [(RetType rep, RetAls)]
[(RetType (Aliases rep), RetAls)]
restype [FParam rep]
[FParam (Aliases rep)]
params Body (Aliases rep)
body'
where
body' :: Body (Aliases rep)
body' = AliasTable -> Body rep -> Body (Aliases rep)
forall rep res.
(AliasableRep rep, IsResult res) =>
AliasTable -> GBody rep res -> GBody (Aliases rep) res
analyseBody AliasTable
forall a. Monoid a => a
mempty Body rep
body
analyseBody ::
(AliasableRep rep, IsResult res) =>
AliasTable ->
GBody rep res ->
GBody (Aliases rep) res
analyseBody :: forall rep res.
(AliasableRep rep, IsResult res) =>
AliasTable -> GBody rep res -> GBody (Aliases rep) res
analyseBody AliasTable
atable (Body BodyDec rep
rep Stms rep
stms [res]
result) =
let (Stms (Aliases rep)
stms', AliasesAndConsumed
_atable') = AliasTable -> Stms rep -> (Stms (Aliases rep), AliasesAndConsumed)
forall rep.
AliasableRep rep =>
AliasTable -> Stms rep -> (Stms (Aliases rep), AliasesAndConsumed)
analyseStms AliasTable
atable Stms rep
stms
in BodyDec rep
-> Stms (Aliases rep) -> [res] -> GBody (Aliases rep) res
forall rep res.
(ASTRep rep, AliasedOp (OpC rep),
ASTConstraints (OpC rep (Aliases rep)), IsResult res) =>
BodyDec rep
-> Stms (Aliases rep) -> [res] -> GBody (Aliases rep) res
mkAliasedBody BodyDec rep
rep Stms (Aliases rep)
stms' [res]
result
analyseStms ::
(AliasableRep rep) =>
AliasTable ->
Stms rep ->
(Stms (Aliases rep), AliasesAndConsumed)
analyseStms :: forall rep.
AliasableRep rep =>
AliasTable -> Stms rep -> (Stms (Aliases rep), AliasesAndConsumed)
analyseStms AliasTable
orig_aliases =
(Seq (Stm (Aliases rep)), AliasesAndConsumed)
-> (Seq (Stm (Aliases rep)), AliasesAndConsumed)
forall {t :: * -> *} {rep} {a}.
Foldable t =>
(t (Stm rep), (a, Names)) -> (t (Stm rep), (a, Names))
withoutBound ((Seq (Stm (Aliases rep)), AliasesAndConsumed)
-> (Seq (Stm (Aliases rep)), AliasesAndConsumed))
-> (Stms rep -> (Seq (Stm (Aliases rep)), AliasesAndConsumed))
-> Stms rep
-> (Seq (Stm (Aliases rep)), AliasesAndConsumed)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Seq (Stm (Aliases rep)), AliasesAndConsumed)
-> Stm rep -> (Seq (Stm (Aliases rep)), AliasesAndConsumed))
-> (Seq (Stm (Aliases rep)), AliasesAndConsumed)
-> [Stm rep]
-> (Seq (Stm (Aliases rep)), AliasesAndConsumed)
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
L.foldl' (Seq (Stm (Aliases rep)), AliasesAndConsumed)
-> Stm rep -> (Seq (Stm (Aliases rep)), AliasesAndConsumed)
forall {rep}.
(ASTRep rep, CanBeAliased (OpC rep), AliasedOp (OpC rep),
Ord (OpC rep (Aliases rep)), Show (OpC rep (Aliases rep)),
Rename (OpC rep (Aliases rep)), Substitute (OpC rep (Aliases rep)),
FreeIn (OpC rep (Aliases rep)), Pretty (OpC rep (Aliases rep))) =>
(Stms (Aliases rep), AliasesAndConsumed)
-> Stm rep -> (Stms (Aliases rep), AliasesAndConsumed)
f (Seq (Stm (Aliases rep))
forall a. Monoid a => a
mempty, (AliasTable
orig_aliases, Names
forall a. Monoid a => a
mempty)) ([Stm rep] -> (Seq (Stm (Aliases rep)), AliasesAndConsumed))
-> (Stms rep -> [Stm rep])
-> Stms rep
-> (Seq (Stm (Aliases rep)), AliasesAndConsumed)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Stms rep -> [Stm rep]
forall rep. Stms rep -> [Stm rep]
stmsToList
where
withoutBound :: (t (Stm rep), (a, Names)) -> (t (Stm rep), (a, Names))
withoutBound (t (Stm rep)
stms, (a
aliases, Names
consumed)) =
let bound :: Names
bound = (Stm rep -> Names) -> t (Stm rep) -> Names
forall m a. Monoid m => (a -> m) -> t a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap ([VName] -> Names
namesFromList ([VName] -> Names) -> (Stm rep -> [VName]) -> Stm rep -> Names
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pat (LetDec rep) -> [VName]
forall dec. Pat dec -> [VName]
patNames (Pat (LetDec rep) -> [VName])
-> (Stm rep -> Pat (LetDec rep)) -> Stm rep -> [VName]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Stm rep -> Pat (LetDec rep)
forall rep. Stm rep -> Pat (LetDec rep)
stmPat) t (Stm rep)
stms
consumed' :: Names
consumed' = Names
consumed Names -> Names -> Names
`namesSubtract` Names
bound
in (t (Stm rep)
stms, (a
aliases, Names
consumed'))
f :: (Stms (Aliases rep), AliasesAndConsumed)
-> Stm rep -> (Stms (Aliases rep), AliasesAndConsumed)
f (Stms (Aliases rep)
stms, AliasesAndConsumed
aliases) Stm rep
stm =
let stm' :: Stm (Aliases rep)
stm' = AliasTable -> Stm rep -> Stm (Aliases rep)
forall rep.
AliasableRep rep =>
AliasTable -> Stm rep -> Stm (Aliases rep)
analyseStm (AliasesAndConsumed -> AliasTable
forall a b. (a, b) -> a
fst AliasesAndConsumed
aliases) Stm rep
stm
atable' :: AliasesAndConsumed
atable' = AliasesAndConsumed -> Stm (Aliases rep) -> AliasesAndConsumed
forall rep.
Aliased rep =>
AliasesAndConsumed -> Stm rep -> AliasesAndConsumed
trackAliases AliasesAndConsumed
aliases Stm (Aliases rep)
stm'
in (Stms (Aliases rep)
stms Stms (Aliases rep) -> Stms (Aliases rep) -> Stms (Aliases rep)
forall a. Semigroup a => a -> a -> a
<> Stm (Aliases rep) -> Stms (Aliases rep)
forall rep. Stm rep -> Stms rep
oneStm Stm (Aliases rep)
stm', AliasesAndConsumed
atable')
analyseStm ::
(AliasableRep rep) =>
AliasTable ->
Stm rep ->
Stm (Aliases rep)
analyseStm :: forall rep.
AliasableRep rep =>
AliasTable -> Stm rep -> Stm (Aliases rep)
analyseStm AliasTable
aliases (Let Pat (LetDec rep)
pat StmAux (ExpDec rep)
aux Exp rep
e) =
let e' :: Exp (Aliases rep)
e' = AliasTable -> Exp rep -> Exp (Aliases rep)
forall rep.
AliasableRep rep =>
AliasTable -> Exp rep -> Exp (Aliases rep)
analyseExp AliasTable
aliases Exp rep
e
pat' :: Pat (VarAliases, LetDec rep)
pat' = Pat (LetDec rep)
-> Exp (Aliases rep) -> Pat (VarAliases, LetDec rep)
forall rep dec.
(Aliased rep, Typed dec) =>
Pat dec -> Exp rep -> Pat (VarAliases, dec)
mkAliasedPat Pat (LetDec rep)
pat Exp (Aliases rep)
e'
aux' :: StmAux (VarAliases, ExpDec rep)
aux' = (Names -> VarAliases
AliasDec (Exp (Aliases rep) -> Names
forall rep. Aliased rep => Exp rep -> Names
consumedInExp Exp (Aliases rep)
e'),) (ExpDec rep -> (VarAliases, ExpDec rep))
-> StmAux (ExpDec rep) -> StmAux (VarAliases, ExpDec rep)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StmAux (ExpDec rep)
aux
in Pat (LetDec (Aliases rep))
-> StmAux (ExpDec (Aliases rep))
-> Exp (Aliases rep)
-> Stm (Aliases rep)
forall rep.
Pat (LetDec rep) -> StmAux (ExpDec rep) -> Exp rep -> Stm rep
Let Pat (VarAliases, LetDec rep)
Pat (LetDec (Aliases rep))
pat' StmAux (VarAliases, ExpDec rep)
StmAux (ExpDec (Aliases rep))
aux' Exp (Aliases rep)
e'
analyseExp ::
(AliasableRep rep) =>
AliasTable ->
Exp rep ->
Exp (Aliases rep)
analyseExp :: forall rep.
AliasableRep rep =>
AliasTable -> Exp rep -> Exp (Aliases rep)
analyseExp AliasTable
aliases (Match [SubExp]
cond [Case (Body rep)]
cases Body rep
defbody MatchDec (BranchType rep)
matchdec) =
let cases' :: [Case (GBody (Aliases rep) SubExpRes)]
cases' = (Case (Body rep) -> Case (GBody (Aliases rep) SubExpRes))
-> [Case (Body rep)] -> [Case (GBody (Aliases rep) SubExpRes)]
forall a b. (a -> b) -> [a] -> [b]
map ((Body rep -> GBody (Aliases rep) SubExpRes)
-> Case (Body rep) -> Case (GBody (Aliases rep) SubExpRes)
forall a b. (a -> b) -> Case a -> Case b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Body rep -> GBody (Aliases rep) SubExpRes)
-> Case (Body rep) -> Case (GBody (Aliases rep) SubExpRes))
-> (Body rep -> GBody (Aliases rep) SubExpRes)
-> Case (Body rep)
-> Case (GBody (Aliases rep) SubExpRes)
forall a b. (a -> b) -> a -> b
$ AliasTable -> Body rep -> GBody (Aliases rep) SubExpRes
forall rep res.
(AliasableRep rep, IsResult res) =>
AliasTable -> GBody rep res -> GBody (Aliases rep) res
analyseBody AliasTable
aliases) [Case (Body rep)]
cases
defbody' :: GBody (Aliases rep) SubExpRes
defbody' = AliasTable -> Body rep -> GBody (Aliases rep) SubExpRes
forall rep res.
(AliasableRep rep, IsResult res) =>
AliasTable -> GBody rep res -> GBody (Aliases rep) res
analyseBody AliasTable
aliases Body rep
defbody
all_cons :: VarAliases
all_cons = (GBody (Aliases rep) SubExpRes -> VarAliases)
-> [GBody (Aliases rep) SubExpRes] -> VarAliases
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (([VarAliases], VarAliases) -> VarAliases
forall a b. (a, b) -> b
snd (([VarAliases], VarAliases) -> VarAliases)
-> (GBody (Aliases rep) SubExpRes -> ([VarAliases], VarAliases))
-> GBody (Aliases rep) SubExpRes
-> VarAliases
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (([VarAliases], VarAliases), BodyDec rep)
-> ([VarAliases], VarAliases)
forall a b. (a, b) -> a
fst ((([VarAliases], VarAliases), BodyDec rep)
-> ([VarAliases], VarAliases))
-> (GBody (Aliases rep) SubExpRes
-> (([VarAliases], VarAliases), BodyDec rep))
-> GBody (Aliases rep) SubExpRes
-> ([VarAliases], VarAliases)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GBody (Aliases rep) SubExpRes
-> (([VarAliases], VarAliases), BodyDec rep)
GBody (Aliases rep) SubExpRes -> BodyDec (Aliases rep)
forall rep res. GBody rep res -> BodyDec rep
bodyDec) ([GBody (Aliases rep) SubExpRes] -> VarAliases)
-> [GBody (Aliases rep) SubExpRes] -> VarAliases
forall a b. (a -> b) -> a -> b
$ GBody (Aliases rep) SubExpRes
defbody' GBody (Aliases rep) SubExpRes
-> [GBody (Aliases rep) SubExpRes]
-> [GBody (Aliases rep) SubExpRes]
forall a. a -> [a] -> [a]
: (Case (GBody (Aliases rep) SubExpRes)
-> GBody (Aliases rep) SubExpRes)
-> [Case (GBody (Aliases rep) SubExpRes)]
-> [GBody (Aliases rep) SubExpRes]
forall a b. (a -> b) -> [a] -> [b]
map Case (GBody (Aliases rep) SubExpRes)
-> GBody (Aliases rep) SubExpRes
forall body. Case body -> body
caseBody [Case (GBody (Aliases rep) SubExpRes)]
cases'
isConsumed :: VName -> Bool
isConsumed VName
v =
(VName -> Bool) -> [VName] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (VName -> Names -> Bool
`nameIn` VarAliases -> Names
unAliases VarAliases
all_cons) ([VName] -> Bool) -> [VName] -> Bool
forall a b. (a -> b) -> a -> b
$
VName
v VName -> [VName] -> [VName]
forall a. a -> [a] -> [a]
: Names -> [VName]
namesToList (Names -> VName -> AliasTable -> Names
forall k a. Ord k => a -> k -> Map k a -> a
M.findWithDefault Names
forall a. Monoid a => a
mempty VName
v AliasTable
aliases)
notConsumed :: VarAliases -> VarAliases
notConsumed =
Names -> VarAliases
AliasDec
(Names -> VarAliases)
-> (VarAliases -> Names) -> VarAliases -> VarAliases
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [VName] -> Names
namesFromList
([VName] -> Names)
-> (VarAliases -> [VName]) -> VarAliases -> Names
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (VName -> Bool) -> [VName] -> [VName]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (VName -> Bool) -> VName -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. VName -> Bool
isConsumed)
([VName] -> [VName])
-> (VarAliases -> [VName]) -> VarAliases -> [VName]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Names -> [VName]
namesToList
(Names -> [VName])
-> (VarAliases -> Names) -> VarAliases -> [VName]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. VarAliases -> Names
unAliases
onBody :: GBody (Aliases rep) SubExpRes -> GBody (Aliases rep) SubExpRes
onBody (Body (([VarAliases]
als, VarAliases
cons), BodyDec rep
dec) Stms (Aliases rep)
stms [SubExpRes]
res) =
BodyDec (Aliases rep)
-> Stms (Aliases rep)
-> [SubExpRes]
-> GBody (Aliases rep) SubExpRes
forall rep res. BodyDec rep -> Stms rep -> [res] -> GBody rep res
Body (((VarAliases -> VarAliases) -> [VarAliases] -> [VarAliases]
forall a b. (a -> b) -> [a] -> [b]
map VarAliases -> VarAliases
notConsumed [VarAliases]
als, VarAliases
cons), BodyDec rep
dec) Stms (Aliases rep)
stms [SubExpRes]
res
cases'' :: [Case (GBody (Aliases rep) SubExpRes)]
cases'' = (Case (GBody (Aliases rep) SubExpRes)
-> Case (GBody (Aliases rep) SubExpRes))
-> [Case (GBody (Aliases rep) SubExpRes)]
-> [Case (GBody (Aliases rep) SubExpRes)]
forall a b. (a -> b) -> [a] -> [b]
map ((GBody (Aliases rep) SubExpRes -> GBody (Aliases rep) SubExpRes)
-> Case (GBody (Aliases rep) SubExpRes)
-> Case (GBody (Aliases rep) SubExpRes)
forall a b. (a -> b) -> Case a -> Case b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap GBody (Aliases rep) SubExpRes -> GBody (Aliases rep) SubExpRes
onBody) [Case (GBody (Aliases rep) SubExpRes)]
cases'
defbody'' :: GBody (Aliases rep) SubExpRes
defbody'' = GBody (Aliases rep) SubExpRes -> GBody (Aliases rep) SubExpRes
onBody GBody (Aliases rep) SubExpRes
defbody'
in [SubExp]
-> [Case (GBody (Aliases rep) SubExpRes)]
-> GBody (Aliases rep) SubExpRes
-> MatchDec (BranchType (Aliases rep))
-> Exp (Aliases rep)
forall rep.
[SubExp]
-> [Case (Body rep)]
-> Body rep
-> MatchDec (BranchType rep)
-> Exp rep
Match [SubExp]
cond [Case (GBody (Aliases rep) SubExpRes)]
cases'' GBody (Aliases rep) SubExpRes
defbody'' MatchDec (BranchType rep)
MatchDec (BranchType (Aliases rep))
matchdec
analyseExp AliasTable
aliases Exp rep
e = Mapper rep (Aliases rep) Identity -> Exp rep -> Exp (Aliases rep)
forall frep trep. Mapper frep trep Identity -> Exp frep -> Exp trep
mapExp Mapper rep (Aliases rep) Identity
analyse Exp rep
e
where
analyse :: Mapper rep (Aliases rep) Identity
analyse =
Mapper
{ mapOnSubExp :: SubExp -> Identity SubExp
mapOnSubExp = SubExp -> Identity SubExp
forall a. a -> Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure,
mapOnVName :: VName -> Identity VName
mapOnVName = VName -> Identity VName
forall a. a -> Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure,
mapOnBody :: Scope (Aliases rep)
-> Body rep -> Identity (GBody (Aliases rep) SubExpRes)
mapOnBody = (Body rep -> Identity (GBody (Aliases rep) SubExpRes))
-> Scope (Aliases rep)
-> Body rep
-> Identity (GBody (Aliases rep) SubExpRes)
forall a b. a -> b -> a
const ((Body rep -> Identity (GBody (Aliases rep) SubExpRes))
-> Scope (Aliases rep)
-> Body rep
-> Identity (GBody (Aliases rep) SubExpRes))
-> (Body rep -> Identity (GBody (Aliases rep) SubExpRes))
-> Scope (Aliases rep)
-> Body rep
-> Identity (GBody (Aliases rep) SubExpRes)
forall a b. (a -> b) -> a -> b
$ GBody (Aliases rep) SubExpRes
-> Identity (GBody (Aliases rep) SubExpRes)
forall a. a -> Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (GBody (Aliases rep) SubExpRes
-> Identity (GBody (Aliases rep) SubExpRes))
-> (Body rep -> GBody (Aliases rep) SubExpRes)
-> Body rep
-> Identity (GBody (Aliases rep) SubExpRes)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AliasTable -> Body rep -> GBody (Aliases rep) SubExpRes
forall rep res.
(AliasableRep rep, IsResult res) =>
AliasTable -> GBody rep res -> GBody (Aliases rep) res
analyseBody AliasTable
aliases,
mapOnRetType :: RetType rep -> Identity (RetType (Aliases rep))
mapOnRetType = RetType rep -> Identity (RetType rep)
RetType rep -> Identity (RetType (Aliases rep))
forall a. a -> Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure,
mapOnBranchType :: BranchType rep -> Identity (BranchType (Aliases rep))
mapOnBranchType = BranchType rep -> Identity (BranchType rep)
BranchType rep -> Identity (BranchType (Aliases rep))
forall a. a -> Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure,
mapOnFParam :: FParam rep -> Identity (FParam (Aliases rep))
mapOnFParam = FParam rep -> Identity (FParam rep)
FParam rep -> Identity (FParam (Aliases rep))
forall a. a -> Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure,
mapOnLParam :: LParam rep -> Identity (LParam (Aliases rep))
mapOnLParam = LParam rep -> Identity (LParam rep)
LParam rep -> Identity (LParam (Aliases rep))
forall a. a -> Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure,
mapOnOp :: Op rep -> Identity (Op (Aliases rep))
mapOnOp = OpC rep (Aliases rep) -> Identity (OpC rep (Aliases rep))
forall a. a -> Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (OpC rep (Aliases rep) -> Identity (OpC rep (Aliases rep)))
-> (Op rep -> OpC rep (Aliases rep))
-> Op rep
-> Identity (OpC rep (Aliases rep))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AliasTable -> Op rep -> OpC rep (Aliases rep)
forall rep.
AliasableRep rep =>
AliasTable -> OpC rep rep -> OpC rep (Aliases rep)
forall (op :: * -> *) rep.
(CanBeAliased op, AliasableRep rep) =>
AliasTable -> op rep -> op (Aliases rep)
addOpAliases AliasTable
aliases
}
analyseLambda ::
(AliasableRep rep) =>
AliasTable ->
Lambda rep ->
Lambda (Aliases rep)
analyseLambda :: forall rep.
AliasableRep rep =>
AliasTable -> Lambda rep -> Lambda (Aliases rep)
analyseLambda AliasTable
aliases Lambda rep
lam =
let body :: GBody (Aliases rep) SubExpRes
body = AliasTable -> GBody rep SubExpRes -> GBody (Aliases rep) SubExpRes
forall rep res.
(AliasableRep rep, IsResult res) =>
AliasTable -> GBody rep res -> GBody (Aliases rep) res
analyseBody AliasTable
aliases (GBody rep SubExpRes -> GBody (Aliases rep) SubExpRes)
-> GBody rep SubExpRes -> GBody (Aliases rep) SubExpRes
forall a b. (a -> b) -> a -> b
$ Lambda rep -> GBody rep SubExpRes
forall rep. Lambda rep -> Body rep
lambdaBody Lambda rep
lam
in Lambda rep
lam
{ lambdaBody = body,
lambdaParams = lambdaParams lam
}