{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TupleSections #-}
module IR.InsertRefCounting (insertRefCounting) where
import qualified Common.Compiler as Compiler
import Common.Identifiers
import Control.Monad.State.Lazy (
MonadState (..),
StateT (..),
forM,
modify,
)
import qualified IR.MangleNames as I
import qualified IR.IR as I
import qualified IR.Types as I
import qualified Data.Map as M
insertRefCounting :: I.Program I.Type -> Compiler.Pass (I.Program I.Type)
insertRefCounting :: Program Type -> Pass (Program Type)
insertRefCounting p :: Program Type
p@I.Program{symTable :: forall t. Program t -> Map VarId (SymInfo t)
I.symTable = Map VarId (SymInfo Type)
symTable, programDefs :: forall t. Program t -> [(Binder t, Expr t)]
I.programDefs = [(Binder Type, Expr Type)]
defs} = do
([(Binder Type, Expr Type)]
defs', Map VarId (SymInfo Type)
symTable') <- StateT (Map VarId (SymInfo Type)) Pass [(Binder Type, Expr Type)]
-> Map VarId (SymInfo Type)
-> Pass ([(Binder Type, Expr Type)], Map VarId (SymInfo Type))
forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
runStateT (((Binder Type, Expr Type)
-> StateT (Map VarId (SymInfo Type)) Pass (Binder Type, Expr Type))
-> [(Binder Type, Expr Type)]
-> StateT
(Map VarId (SymInfo Type)) Pass [(Binder Type, Expr Type)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (Binder Type, Expr Type)
-> StateT (Map VarId (SymInfo Type)) Pass (Binder Type, Expr Type)
insertTop [(Binder Type, Expr Type)]
defs) Map VarId (SymInfo Type)
symTable
Program Type -> Pass (Program Type)
forall (m :: * -> *) a. Monad m => a -> m a
return (Program Type -> Pass (Program Type))
-> Program Type -> Pass (Program Type)
forall a b. (a -> b) -> a -> b
$ Program Type
p{ symTable :: Map VarId (SymInfo Type)
I.symTable = Map VarId (SymInfo Type)
symTable', programDefs :: [(Binder Type, Expr Type)]
I.programDefs = [(Binder Type, Expr Type)]
defs' }
type Fresh = StateT (I.SymTable I.Type) Compiler.Pass
getFresh :: String -> I.Type -> Fresh I.VarId
getFresh :: String -> Type -> Fresh VarId
getFresh String
seed Type
t = do
Map VarId (SymInfo Type)
symTable <- StateT (Map VarId (SymInfo Type)) Pass (Map VarId (SymInfo Type))
forall s (m :: * -> *). MonadState s m => m s
get
let str :: VarId
str = String -> VarId
forall a. IsString a => String -> a
fromString (String -> VarId) -> String -> VarId
forall a b. (a -> b) -> a -> b
$ String
"__dupdrop_anon_" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
seed
i :: VarId
i = Map VarId (SymInfo Type) -> VarId -> VarId
forall t. Map VarId t -> VarId -> VarId
I.pickId Map VarId (SymInfo Type)
symTable VarId
str
(Map VarId (SymInfo Type) -> Map VarId (SymInfo Type))
-> StateT (Map VarId (SymInfo Type)) Pass ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((Map VarId (SymInfo Type) -> Map VarId (SymInfo Type))
-> StateT (Map VarId (SymInfo Type)) Pass ())
-> (Map VarId (SymInfo Type) -> Map VarId (SymInfo Type))
-> StateT (Map VarId (SymInfo Type)) Pass ()
forall a b. (a -> b) -> a -> b
$ VarId
-> SymInfo Type
-> Map VarId (SymInfo Type)
-> Map VarId (SymInfo Type)
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert VarId
i (SymInfo Type
-> Map VarId (SymInfo Type) -> Map VarId (SymInfo Type))
-> SymInfo Type
-> Map VarId (SymInfo Type)
-> Map VarId (SymInfo Type)
forall a b. (a -> b) -> a -> b
$ SymInfo :: forall t. VarId -> t -> SymInfo t
I.SymInfo{ symOrigin :: VarId
I.symOrigin = VarId
str, symType :: Type
I.symType = Type
t }
VarId -> Fresh VarId
forall (m :: * -> *) a. Monad m => a -> m a
return VarId
i
makeDup
:: I.Expr I.Type
-> I.Expr I.Type
makeDup :: Expr Type -> Expr Type
makeDup Expr Type
e = Primitive -> [Expr Type] -> Type -> Expr Type
forall t. Primitive -> [Expr t] -> t -> Expr t
I.Prim Primitive
I.Dup [Expr Type
e] (Type -> Expr Type) -> Type -> Expr Type
forall a b. (a -> b) -> a -> b
$ Expr Type -> Type
forall (c :: * -> *) a. Carrier c => c a -> a
I.extract Expr Type
e
makeDrop
:: I.Expr I.Type
-> I.Expr I.Type
-> I.Expr I.Type
makeDrop :: Expr Type -> Expr Type -> Expr Type
makeDrop Expr Type
r Expr Type
e = Primitive -> [Expr Type] -> Type -> Expr Type
forall t. Primitive -> [Expr t] -> t -> Expr t
I.Prim Primitive
I.Drop [Expr Type
e, Expr Type
r] Type
I.Unit
insertTop :: (I.Binder I.Type, I.Expr I.Type) -> Fresh (I.Binder I.Type, I.Expr I.Type)
insertTop :: (Binder Type, Expr Type)
-> StateT (Map VarId (SymInfo Type)) Pass (Binder Type, Expr Type)
insertTop (Binder Type
var, Expr Type
expr) = (Binder Type
var,) (Expr Type -> (Binder Type, Expr Type))
-> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
-> StateT (Map VarId (SymInfo Type)) Pass (Binder Type, Expr Type)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
insertExpr Expr Type
expr
insertExpr :: I.Expr I.Type -> Fresh (I.Expr I.Type)
insertExpr :: Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
insertExpr dcon :: Expr Type
dcon@I.Data{} = Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
forall (m :: * -> *) a. Monad m => a -> m a
return Expr Type
dcon
insertExpr lit :: Expr Type
lit@I.Lit{} = Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
forall (m :: * -> *) a. Monad m => a -> m a
return Expr Type
lit
insertExpr var :: Expr Type
var@I.Var{} = Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
forall (m :: * -> *) a. Monad m => a -> m a
return (Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type))
-> Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
forall a b. (a -> b) -> a -> b
$ Expr Type -> Expr Type
makeDup Expr Type
var
insertExpr (I.App Expr Type
f Expr Type
x Type
t) = Expr Type -> Expr Type -> Type -> Expr Type
forall t. Expr t -> Expr t -> t -> Expr t
I.App (Expr Type -> Expr Type -> Type -> Expr Type)
-> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
-> StateT
(Map VarId (SymInfo Type)) Pass (Expr Type -> Type -> Expr Type)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
insertExpr Expr Type
f StateT
(Map VarId (SymInfo Type)) Pass (Expr Type -> Type -> Expr Type)
-> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
-> StateT (Map VarId (SymInfo Type)) Pass (Type -> Expr Type)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
insertExpr Expr Type
x StateT (Map VarId (SymInfo Type)) Pass (Type -> Expr Type)
-> StateT (Map VarId (SymInfo Type)) Pass Type
-> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Type -> StateT (Map VarId (SymInfo Type)) Pass Type
forall (f :: * -> *) a. Applicative f => a -> f a
pure Type
t
insertExpr (I.Prim Primitive
p [Expr Type]
es Type
typ) = Primitive -> [Expr Type] -> Type -> Expr Type
forall t. Primitive -> [Expr t] -> t -> Expr t
I.Prim Primitive
p ([Expr Type] -> Type -> Expr Type)
-> StateT (Map VarId (SymInfo Type)) Pass [Expr Type]
-> StateT (Map VarId (SymInfo Type)) Pass (Type -> Expr Type)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type))
-> [Expr Type]
-> StateT (Map VarId (SymInfo Type)) Pass [Expr Type]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
insertExpr [Expr Type]
es StateT (Map VarId (SymInfo Type)) Pass (Type -> Expr Type)
-> StateT (Map VarId (SymInfo Type)) Pass Type
-> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Type -> StateT (Map VarId (SymInfo Type)) Pass Type
forall (f :: * -> *) a. Applicative f => a -> f a
pure Type
typ
insertExpr (I.Let [(Binder Type, Expr Type)]
bins Expr Type
expr Type
typ) = do
[(VarId, Type, Expr Type)]
bins' <- [(Binder Type, Expr Type)]
-> ((Binder Type, Expr Type)
-> StateT (Map VarId (SymInfo Type)) Pass (VarId, Type, Expr Type))
-> StateT
(Map VarId (SymInfo Type)) Pass [(VarId, Type, Expr Type)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [(Binder Type, Expr Type)]
bins (Binder Type, Expr Type)
-> StateT (Map VarId (SymInfo Type)) Pass (VarId, Type, Expr Type)
droppedBinder
Expr Type
expr' <- Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
insertExpr Expr Type
expr
Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
forall (m :: * -> *) a. Monad m => a -> m a
return (Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type))
-> Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
forall a b. (a -> b) -> a -> b
$ [(Binder Type, Expr Type)] -> Expr Type -> Type -> Expr Type
forall t. [(Binder t, Expr t)] -> Expr t -> t -> Expr t
I.Let (((VarId, Type, Expr Type) -> (Binder Type, Expr Type))
-> [(VarId, Type, Expr Type)] -> [(Binder Type, Expr Type)]
forall a b. (a -> b) -> [a] -> [b]
map (VarId, Type, Expr Type) -> (Binder Type, Expr Type)
forall t b. (VarId, t, b) -> (Binder t, b)
defFromBind [(VarId, Type, Expr Type)]
bins') (((VarId, Type, Expr Type) -> Expr Type -> Expr Type)
-> Expr Type -> [(VarId, Type, Expr Type)] -> Expr Type
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (Expr Type -> Expr Type -> Expr Type
makeDrop (Expr Type -> Expr Type -> Expr Type)
-> ((VarId, Type, Expr Type) -> Expr Type)
-> (VarId, Type, Expr Type)
-> Expr Type
-> Expr Type
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (VarId, Type, Expr Type) -> Expr Type
forall t c. (VarId, t, c) -> Expr t
varFromBind) Expr Type
expr' [(VarId, Type, Expr Type)]
bins') Type
typ
where
varFromBind :: (VarId, t, c) -> Expr t
varFromBind (VarId
v, t
t, c
_) = VarId -> t -> Expr t
forall t. VarId -> t -> Expr t
I.Var VarId
v t
t
defFromBind :: (VarId, t, b) -> (Binder t, b)
defFromBind (VarId
v, t
t, b
d) = (VarId -> t -> Binder t
forall t. VarId -> t -> Binder t
I.BindVar VarId
v t
t, b
d)
droppedBinder :: (Binder Type, Expr Type)
-> StateT (Map VarId (SymInfo Type)) Pass (VarId, Type, Expr Type)
droppedBinder (I.BindAnon Type
t, Expr Type
d) = do
VarId
temp <- String -> Type -> Fresh VarId
getFresh String
"underscore" Type
t
Expr Type
d' <- Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
insertExpr Expr Type
d
(VarId, Type, Expr Type)
-> StateT (Map VarId (SymInfo Type)) Pass (VarId, Type, Expr Type)
forall (m :: * -> *) a. Monad m => a -> m a
return (VarId
temp, Type
t, Expr Type
d')
droppedBinder (I.BindVar VarId
v Type
t, Expr Type
d) = do
Expr Type
d' <- Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
insertExpr Expr Type
d
(VarId, Type, Expr Type)
-> StateT (Map VarId (SymInfo Type)) Pass (VarId, Type, Expr Type)
forall (m :: * -> *) a. Monad m => a -> m a
return (VarId
v, Type
t, Expr Type
d')
insertExpr lam :: Expr Type
lam@I.Lambda{} = do
let ([Binder Type]
args, Expr Type
body) = Expr Type -> ([Binder Type], Expr Type)
forall t. Expr t -> ([Binder t], Expr t)
I.unfoldLambda Expr Type
lam
[(VarId, Type)]
args' <- [Binder Type]
-> (Binder Type
-> StateT (Map VarId (SymInfo Type)) Pass (VarId, Type))
-> StateT (Map VarId (SymInfo Type)) Pass [(VarId, Type)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [Binder Type]
args ((Binder Type
-> StateT (Map VarId (SymInfo Type)) Pass (VarId, Type))
-> StateT (Map VarId (SymInfo Type)) Pass [(VarId, Type)])
-> (Binder Type
-> StateT (Map VarId (SymInfo Type)) Pass (VarId, Type))
-> StateT (Map VarId (SymInfo Type)) Pass [(VarId, Type)]
forall a b. (a -> b) -> a -> b
$ \case
I.BindAnon Type
t -> do
VarId
v <- String -> Type -> Fresh VarId
getFresh String
"arg" Type
t
(VarId, Type)
-> StateT (Map VarId (SymInfo Type)) Pass (VarId, Type)
forall (m :: * -> *) a. Monad m => a -> m a
return (VarId
v, Type
t)
I.BindVar VarId
v Type
t -> (VarId, Type)
-> StateT (Map VarId (SymInfo Type)) Pass (VarId, Type)
forall (m :: * -> *) a. Monad m => a -> m a
return (VarId
v, Type
t)
let argBinders :: [Binder Type]
argBinders = (VarId -> Type -> Binder Type) -> (VarId, Type) -> Binder Type
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry VarId -> Type -> Binder Type
forall t. VarId -> t -> Binder t
I.BindVar ((VarId, Type) -> Binder Type) -> [(VarId, Type)] -> [Binder Type]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(VarId, Type)]
args'
argVars :: [Expr Type]
argVars = (VarId -> Type -> Expr Type) -> (VarId, Type) -> Expr Type
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry VarId -> Type -> Expr Type
forall t. VarId -> t -> Expr t
I.Var ((VarId, Type) -> Expr Type) -> [(VarId, Type)] -> [Expr Type]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(VarId, Type)]
args'
Expr Type
body' <- Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
insertExpr Expr Type
body
Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
forall (m :: * -> *) a. Monad m => a -> m a
return (Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type))
-> Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
forall a b. (a -> b) -> a -> b
$ [Binder Type] -> Expr Type -> Expr Type
I.foldLambda [Binder Type]
argBinders (Expr Type -> Expr Type) -> Expr Type -> Expr Type
forall a b. (a -> b) -> a -> b
$ (Expr Type -> Expr Type -> Expr Type)
-> Expr Type -> [Expr Type] -> Expr Type
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Expr Type -> Expr Type -> Expr Type
makeDrop Expr Type
body' [Expr Type]
argVars
insertExpr (I.Match v :: Expr Type
v@I.Var{} [(Alt Type, Expr Type)]
alts Type
typ) = do
[(Alt Type, Expr Type)]
alts' <- [(Alt Type, Expr Type)]
-> ((Alt Type, Expr Type)
-> StateT (Map VarId (SymInfo Type)) Pass (Alt Type, Expr Type))
-> StateT (Map VarId (SymInfo Type)) Pass [(Alt Type, Expr Type)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [(Alt Type, Expr Type)]
alts (Alt Type, Expr Type)
-> StateT (Map VarId (SymInfo Type)) Pass (Alt Type, Expr Type)
insertAlt
Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
forall (m :: * -> *) a. Monad m => a -> m a
return (Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type))
-> Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
forall a b. (a -> b) -> a -> b
$ Expr Type -> [(Alt Type, Expr Type)] -> Type -> Expr Type
forall t. Expr t -> [(Alt t, Expr t)] -> t -> Expr t
I.Match Expr Type
v [(Alt Type, Expr Type)]
alts' Type
typ
insertExpr (I.Match Expr Type
scrutExpr [(Alt Type, Expr Type)]
alts Type
typ) = do
let scrutType :: Type
scrutType = Expr Type -> Type
forall (c :: * -> *) a. Carrier c => c a -> a
I.extract Expr Type
scrutExpr
VarId
scrutVar <- String -> Type -> Fresh VarId
getFresh String
"scrutinee" Type
scrutType
Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
insertExpr (Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type))
-> Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
forall a b. (a -> b) -> a -> b
$
[(Binder Type, Expr Type)] -> Expr Type -> Type -> Expr Type
forall t. [(Binder t, Expr t)] -> Expr t -> t -> Expr t
I.Let
[(VarId -> Type -> Binder Type
forall t. VarId -> t -> Binder t
I.BindVar VarId
scrutVar Type
scrutType, Expr Type
scrutExpr)]
(Expr Type -> [(Alt Type, Expr Type)] -> Type -> Expr Type
forall t. Expr t -> [(Alt t, Expr t)] -> t -> Expr t
I.Match (VarId -> Type -> Expr Type
forall t. VarId -> t -> Expr t
I.Var VarId
scrutVar Type
scrutType) [(Alt Type, Expr Type)]
alts Type
typ)
Type
typ
insertExpr e :: Expr Type
e@(I.Exception ExceptType
_ Type
_) = Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
forall (m :: * -> *) a. Monad m => a -> m a
return Expr Type
e
insertAlt :: (I.Alt I.Type, I.Expr I.Type) -> Fresh (I.Alt I.Type, I.Expr I.Type)
insertAlt :: (Alt Type, Expr Type)
-> StateT (Map VarId (SymInfo Type)) Pass (Alt Type, Expr Type)
insertAlt (I.AltBinder Binder Type
v, Expr Type
e) = (Binder Type -> Alt Type
forall t. Binder t -> Alt t
I.AltBinder Binder Type
v,) (Expr Type -> (Alt Type, Expr Type))
-> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
-> StateT (Map VarId (SymInfo Type)) Pass (Alt Type, Expr Type)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
insertExpr Expr Type
e
insertAlt (I.AltLit Literal
l Type
t, Expr Type
e) = (Literal -> Type -> Alt Type
forall t. Literal -> t -> Alt t
I.AltLit Literal
l Type
t,) (Expr Type -> (Alt Type, Expr Type))
-> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
-> StateT (Map VarId (SymInfo Type)) Pass (Alt Type, Expr Type)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
insertExpr Expr Type
e
insertAlt (I.AltData DConId
dcon [Alt Type]
binds Type
t, Expr Type
body) = do
Expr Type
body' <- Expr Type -> StateT (Map VarId (SymInfo Type)) Pass (Expr Type)
insertExpr Expr Type
body
(Alt Type, Expr Type)
-> StateT (Map VarId (SymInfo Type)) Pass (Alt Type, Expr Type)
forall (m :: * -> *) a. Monad m => a -> m a
return (DConId -> [Alt Type] -> Type -> Alt Type
forall t. DConId -> [Alt t] -> t -> Alt t
I.AltData DConId
dcon [Alt Type]
binds Type
t, (Binder Type -> Expr Type -> Expr Type)
-> Expr Type -> [Binder Type] -> Expr Type
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Binder Type -> Expr Type -> Expr Type
dropDupLet Expr Type
body' ([Binder Type] -> Expr Type) -> [Binder Type] -> Expr Type
forall a b. (a -> b) -> a -> b
$ (Alt Type -> [Binder Type]) -> [Alt Type] -> [Binder Type]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Alt Type -> [Binder Type]
forall t. Alt t -> [Binder t]
I.altBinders [Alt Type]
binds)
where
dropDupLet :: Binder Type -> Expr Type -> Expr Type
dropDupLet (I.BindAnon Type
_) Expr Type
e = Expr Type
e
dropDupLet (I.BindVar VarId
v Type
t') Expr Type
e =
let varExpr :: Expr Type
varExpr = VarId -> Type -> Expr Type
forall t. VarId -> t -> Expr t
I.Var VarId
v Type
t'
dupExpr :: Expr Type
dupExpr = Expr Type -> Expr Type
makeDup Expr Type
varExpr
in Expr Type -> Expr Type -> Expr Type
makeDrop Expr Type
varExpr ([(Binder Type, Expr Type)] -> Expr Type -> Type -> Expr Type
forall t. [(Binder t, Expr t)] -> Expr t -> t -> Expr t
I.Let [(Type -> Binder Type
forall t. t -> Binder t
I.BindAnon (Type -> Binder Type) -> Type -> Binder Type
forall a b. (a -> b) -> a -> b
$ Expr Type -> Type
forall (c :: * -> *) a. Carrier c => c a -> a
I.extract Expr Type
dupExpr, Expr Type
dupExpr)] Expr Type
e (Expr Type -> Type
forall (c :: * -> *) a. Carrier c => c a -> a
I.extract Expr Type
e))