{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
module Clash.Normalize.Transformations.ANF
( makeANF
, nonRepANF
) where
import Control.Arrow ((***))
import Control.Lens (_2)
import qualified Control.Lens as Lens
import qualified Control.Monad as Monad
import Control.Monad.State (StateT, lift, modify, runStateT)
import Control.Monad.Writer (listen)
import Data.Bifunctor (second)
import qualified Data.Monoid as Monoid (Any(..))
import qualified Data.Text.Extra as Text (showt)
import GHC.Stack (HasCallStack)
import Clash.Signal.Internal (Signal(..))
import Clash.Core.DataCon (DataCon(..))
import Clash.Core.HasFreeVars (disjointFreeVars)
import Clash.Core.HasType
import Clash.Core.Name (mkUnsafeSystemName, nameOcc)
import Clash.Core.Subst (deshadowLetExpr, freshenTm)
import Clash.Core.Term
( Alt, CoreContext(..), LetBinding, Pat(..), PrimInfo(..), Term(..)
, collectArgs, collectTicks, mkTicks, partitionTicks, stripTicks)
import Clash.Core.TermInfo (isCon, isLocalVar, isPrim, isVar)
import Clash.Core.TyCon (TyConMap)
import Clash.Core.Type (Type, TypeView(..), coreView, tyView)
import Clash.Core.Util (mkSelectorCase)
import Clash.Core.Var (Id)
import Clash.Core.VarEnv (InScopeSet, extendInScopeSet, extendInScopeSetList, mkVarSet)
import Clash.Netlist.Util (bindsExistentials)
import Clash.Normalize.Transformations.Specialize (specialize)
import Clash.Normalize.Types (NormRewrite, NormalizeSession)
import Clash.Rewrite.Combinators (bottomupR)
import Clash.Rewrite.Types
(Transform, TransformContext(..), tcCache)
import Clash.Rewrite.Util
(changed, isUntranslatable, mkDerivedName, mkTmBinderFor)
import Clash.Rewrite.WorkFree (isConstant, isConstantNotClockReset)
import Clash.Util (curLoc)
makeANF :: HasCallStack => NormRewrite
makeANF :: NormRewrite
makeANF (TransformContext InScopeSet
is0 Context
ctx) (Lam Id
bndr Term
e) = do
let ctx' :: TransformContext
ctx' = InScopeSet -> Context -> TransformContext
TransformContext (InScopeSet -> Id -> InScopeSet
forall a. InScopeSet -> Var a -> InScopeSet
extendInScopeSet InScopeSet
is0 Id
bndr) (Id -> CoreContext
LamBody Id
bndr CoreContext -> Context -> Context
forall a. a -> [a] -> [a]
: Context
ctx)
Term
e' <- HasCallStack => NormRewrite
NormRewrite
makeANF TransformContext
ctx' Term
e
Term -> RewriteMonad NormalizeState Term
forall (m :: Type -> Type) a. Monad m => a -> m a
return (Id -> Term -> Term
Lam Id
bndr Term
e')
makeANF TransformContext
_ e :: Term
e@(TyLam {}) = Term -> RewriteMonad NormalizeState Term
forall (m :: Type -> Type) a. Monad m => a -> m a
return Term
e
makeANF ctx :: TransformContext
ctx@(TransformContext InScopeSet
is0 Context
_) Term
e0 = do
let (InScopeSet
is2,Term
e1) = InScopeSet -> Term -> (InScopeSet, Term)
freshenTm InScopeSet
is0 Term
e0
((Term
e2,([LetBinding]
bndrs,InScopeSet
_)),Any -> Bool
Monoid.getAny -> Bool
hasChanged) <-
NormalizeSession (Term, ([LetBinding], InScopeSet))
-> NormalizeSession ((Term, ([LetBinding], InScopeSet)), Any)
forall w (m :: Type -> Type) a. MonadWriter w m => m a -> m (a, w)
listen (StateT ([LetBinding], InScopeSet) NormalizeSession Term
-> ([LetBinding], InScopeSet)
-> NormalizeSession (Term, ([LetBinding], InScopeSet))
forall s (m :: Type -> Type) a. StateT s m a -> s -> m (a, s)
runStateT (Transform (StateT ([LetBinding], InScopeSet) NormalizeSession)
-> Transform (StateT ([LetBinding], InScopeSet) NormalizeSession)
forall (m :: Type -> Type). Monad m => Transform m -> Transform m
bottomupR HasCallStack =>
Transform (StateT ([LetBinding], InScopeSet) NormalizeSession)
Transform (StateT ([LetBinding], InScopeSet) NormalizeSession)
collectANF TransformContext
ctx Term
e1) ([],InScopeSet
is2))
case [LetBinding]
bndrs of
[] -> if Bool
hasChanged then Term -> RewriteMonad NormalizeState Term
forall (m :: Type -> Type) a. Monad m => a -> m a
return Term
e2 else Term -> RewriteMonad NormalizeState Term
forall (m :: Type -> Type) a. Monad m => a -> m a
return Term
e0
[LetBinding]
_ -> do
let (Term
e3,[TickInfo]
ticks) = Term -> (Term, [TickInfo])
collectTicks Term
e2
([TickInfo]
srcTicks,[TickInfo]
nmTicks) = [TickInfo] -> ([TickInfo], [TickInfo])
partitionTicks [TickInfo]
ticks
Term -> RewriteMonad NormalizeState Term
forall a extra. a -> RewriteMonad extra a
changed (Term -> [TickInfo] -> Term
mkTicks ([LetBinding] -> Term -> Term
Letrec [LetBinding]
bndrs (Term -> [TickInfo] -> Term
mkTicks Term
e3 [TickInfo]
srcTicks)) [TickInfo]
nmTicks)
{-# SCC makeANF #-}
type NormRewriteW = Transform (StateT ([LetBinding],InScopeSet) NormalizeSession)
tellBinders :: [LetBinding] -> StateT ([LetBinding],InScopeSet) NormalizeSession ()
tellBinders :: [LetBinding]
-> StateT ([LetBinding], InScopeSet) NormalizeSession ()
tellBinders [LetBinding]
bs = (([LetBinding], InScopeSet) -> ([LetBinding], InScopeSet))
-> StateT ([LetBinding], InScopeSet) NormalizeSession ()
forall s (m :: Type -> Type). MonadState s m => (s -> s) -> m ()
modify (([LetBinding]
bs [LetBinding] -> [LetBinding] -> [LetBinding]
forall a. [a] -> [a] -> [a]
++) ([LetBinding] -> [LetBinding])
-> (InScopeSet -> InScopeSet)
-> ([LetBinding], InScopeSet)
-> ([LetBinding], InScopeSet)
forall (a :: Type -> Type -> Type) b c b' c'.
Arrow a =>
a b c -> a b' c' -> a (b, b') (c, c')
*** (InScopeSet -> [Id] -> InScopeSet
forall a. InScopeSet -> [Var a] -> InScopeSet
`extendInScopeSetList` ((LetBinding -> Id) -> [LetBinding] -> [Id]
forall a b. (a -> b) -> [a] -> [b]
map LetBinding -> Id
forall a b. (a, b) -> a
fst [LetBinding]
bs)))
notifyBinders :: Monad m => [LetBinding] -> StateT ([LetBinding],InScopeSet) m ()
notifyBinders :: [LetBinding] -> StateT ([LetBinding], InScopeSet) m ()
notifyBinders [LetBinding]
bs = (([LetBinding], InScopeSet) -> ([LetBinding], InScopeSet))
-> StateT ([LetBinding], InScopeSet) m ()
forall s (m :: Type -> Type). MonadState s m => (s -> s) -> m ()
modify ((InScopeSet -> InScopeSet)
-> ([LetBinding], InScopeSet) -> ([LetBinding], InScopeSet)
forall (p :: Type -> Type -> Type) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second (InScopeSet -> [Id] -> InScopeSet
forall a. InScopeSet -> [Var a] -> InScopeSet
`extendInScopeSetList` ((LetBinding -> Id) -> [LetBinding] -> [Id]
forall a b. (a -> b) -> [a] -> [b]
map LetBinding -> Id
forall a b. (a, b) -> a
fst [LetBinding]
bs)))
isSimIOTy
:: TyConMap
-> Type
-> Bool
isSimIOTy :: TyConMap -> Type -> Bool
isSimIOTy TyConMap
tcm Type
ty = case Type -> TypeView
tyView (TyConMap -> Type -> Type
coreView TyConMap
tcm Type
ty) of
TyConApp TyConName
tcNm [Type]
args
| TyConName -> OccName
forall a. Name a -> OccName
nameOcc TyConName
tcNm OccName -> OccName -> Bool
forall a. Eq a => a -> a -> Bool
== OccName
"Clash.Explicit.SimIO.SimIO"
-> Bool
True
| TyConName -> OccName
forall a. Name a -> OccName
nameOcc TyConName
tcNm OccName -> OccName -> Bool
forall a. Eq a => a -> a -> Bool
== OccName
"GHC.Prim.(#,#)"
, [Type
_,Type
_,Type
st,Type
_] <- [Type]
args
-> TyConMap -> Type -> Bool
isStateTokenTy TyConMap
tcm Type
st
FunTy Type
_ Type
res -> TyConMap -> Type -> Bool
isSimIOTy TyConMap
tcm Type
res
TypeView
_ -> Bool
False
isStateTokenTy
:: TyConMap
-> Type
-> Bool
isStateTokenTy :: TyConMap -> Type -> Bool
isStateTokenTy TyConMap
tcm Type
ty = case Type -> TypeView
tyView (TyConMap -> Type -> Type
coreView TyConMap
tcm Type
ty) of
TyConApp TyConName
tcNm [Type]
_ -> TyConName -> OccName
forall a. Name a -> OccName
nameOcc TyConName
tcNm OccName -> OccName -> Bool
forall a. Eq a => a -> a -> Bool
== OccName
"GHC.Prim.State#"
TypeView
_ -> Bool
False
collectANF :: HasCallStack => NormRewriteW
collectANF :: Transform (StateT ([LetBinding], InScopeSet) NormalizeSession)
collectANF TransformContext
ctx e :: Term
e@(App Term
appf Term
arg)
| (Term
conVarPrim, [Either Term Type]
_) <- Term -> (Term, [Either Term Type])
collectArgs Term
e
, Term -> Bool
isCon Term
conVarPrim Bool -> Bool -> Bool
|| Term -> Bool
isPrim Term
conVarPrim Bool -> Bool -> Bool
|| Term -> Bool
isVar Term
conVarPrim
= do
TyConMap
tcm <- Getting TyConMap RewriteEnv TyConMap
-> StateT ([LetBinding], InScopeSet) NormalizeSession TyConMap
forall s (m :: Type -> Type) a.
MonadReader s m =>
Getting a s a -> m a
Lens.view Getting TyConMap RewriteEnv TyConMap
Getter RewriteEnv TyConMap
tcCache
Bool
untranslatable <- RewriteMonad NormalizeState Bool
-> StateT ([LetBinding], InScopeSet) NormalizeSession Bool
forall (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (Bool -> Term -> RewriteMonad NormalizeState Bool
forall extra. Bool -> Term -> RewriteMonad extra Bool
isUntranslatable Bool
False Term
arg)
let localVar :: Bool
localVar = Term -> Bool
isLocalVar Term
arg
constantNoCR :: Bool
constantNoCR = TyConMap -> Term -> Bool
isConstantNotClockReset TyConMap
tcm Term
arg
case (Bool
untranslatable,Bool
localVar Bool -> Bool -> Bool
|| Bool
constantNoCR, Term -> Bool
isSimBind Term
conVarPrim,Term
arg) of
(Bool
False,Bool
False,Bool
False,Term
_) -> do
InScopeSet
is1 <- Getting InScopeSet ([LetBinding], InScopeSet) InScopeSet
-> StateT ([LetBinding], InScopeSet) NormalizeSession InScopeSet
forall s (m :: Type -> Type) a.
MonadState s m =>
Getting a s a -> m a
Lens.use Getting InScopeSet ([LetBinding], InScopeSet) InScopeSet
forall s t a b. Field2 s t a b => Lens s t a b
_2
Id
argId <- NormalizeSession Id
-> StateT ([LetBinding], InScopeSet) NormalizeSession Id
forall (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (InScopeSet -> TyConMap -> Name Term -> Term -> NormalizeSession Id
forall (m :: Type -> Type) a.
MonadUnique m =>
InScopeSet -> TyConMap -> Name a -> Term -> m Id
mkTmBinderFor InScopeSet
is1 TyConMap
tcm (TransformContext -> OccName -> Name Term
mkDerivedName TransformContext
ctx OccName
"app_arg") Term
arg)
[LetBinding]
-> StateT ([LetBinding], InScopeSet) NormalizeSession ()
tellBinders [(Id
argId,Term
arg)]
Term -> StateT ([LetBinding], InScopeSet) NormalizeSession Term
forall (m :: Type -> Type) a. Monad m => a -> m a
return (Term -> Term -> Term
App Term
appf (Id -> Term
Var Id
argId))
(Bool
True,Bool
False,Bool
_,Letrec [LetBinding]
binds Term
body) -> do
[LetBinding]
-> StateT ([LetBinding], InScopeSet) NormalizeSession ()
tellBinders [LetBinding]
binds
Term -> StateT ([LetBinding], InScopeSet) NormalizeSession Term
forall (m :: Type -> Type) a. Monad m => a -> m a
return (Term -> Term -> Term
App Term
appf Term
body)
(Bool, Bool, Bool, Term)
_ -> Term -> StateT ([LetBinding], InScopeSet) NormalizeSession Term
forall (m :: Type -> Type) a. Monad m => a -> m a
return Term
e
where
isSimBind :: Term -> Bool
isSimBind (Prim PrimInfo
p) = PrimInfo -> OccName
primName PrimInfo
p OccName -> OccName -> Bool
forall a. Eq a => a -> a -> Bool
== OccName
"Clash.Explicit.SimIO.bindSimIO#"
isSimBind Term
_ = Bool
False
collectANF TransformContext
_ (Letrec [LetBinding]
binds Term
body) = do
TyConMap
tcm <- Getting TyConMap RewriteEnv TyConMap
-> StateT ([LetBinding], InScopeSet) NormalizeSession TyConMap
forall s (m :: Type -> Type) a.
MonadReader s m =>
Getting a s a -> m a
Lens.view Getting TyConMap RewriteEnv TyConMap
Getter RewriteEnv TyConMap
tcCache
let isSimIO :: Bool
isSimIO = TyConMap -> Type -> Bool
isSimIOTy TyConMap
tcm (TyConMap -> Term -> Type
forall a. InferType a => TyConMap -> a -> Type
inferCoreTypeOf TyConMap
tcm Term
body)
Bool
untranslatable <- RewriteMonad NormalizeState Bool
-> StateT ([LetBinding], InScopeSet) NormalizeSession Bool
forall (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (Bool -> Term -> RewriteMonad NormalizeState Bool
forall extra. Bool -> Term -> RewriteMonad extra Bool
isUntranslatable Bool
False Term
body)
let localVar :: Bool
localVar = Term -> Bool
isLocalVar Term
body
if Bool
localVar Bool -> Bool -> Bool
|| Bool
untranslatable Bool -> Bool -> Bool
|| Bool
isSimIO
then do
[LetBinding]
-> StateT ([LetBinding], InScopeSet) NormalizeSession ()
tellBinders [LetBinding]
binds
Term -> StateT ([LetBinding], InScopeSet) NormalizeSession Term
forall (m :: Type -> Type) a. Monad m => a -> m a
return Term
body
else do
InScopeSet
is1 <- Getting InScopeSet ([LetBinding], InScopeSet) InScopeSet
-> StateT ([LetBinding], InScopeSet) NormalizeSession InScopeSet
forall s (m :: Type -> Type) a.
MonadState s m =>
Getting a s a -> m a
Lens.use Getting InScopeSet ([LetBinding], InScopeSet) InScopeSet
forall s t a b. Field2 s t a b => Lens s t a b
_2
Id
argId <- NormalizeSession Id
-> StateT ([LetBinding], InScopeSet) NormalizeSession Id
forall (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (InScopeSet -> TyConMap -> Name Any -> Term -> NormalizeSession Id
forall (m :: Type -> Type) a.
MonadUnique m =>
InScopeSet -> TyConMap -> Name a -> Term -> m Id
mkTmBinderFor InScopeSet
is1 TyConMap
tcm (OccName -> Unique -> Name Any
forall a. OccName -> Unique -> Name a
mkUnsafeSystemName OccName
"result" Unique
0) Term
body)
[LetBinding]
-> StateT ([LetBinding], InScopeSet) NormalizeSession ()
tellBinders [(Id
argId,Term
body)]
[LetBinding]
-> StateT ([LetBinding], InScopeSet) NormalizeSession ()
tellBinders [LetBinding]
binds
Term -> StateT ([LetBinding], InScopeSet) NormalizeSession Term
forall (m :: Type -> Type) a. Monad m => a -> m a
return (Id -> Term
Var Id
argId)
collectANF TransformContext
_ e :: Term
e@(Case Term
_ Type
_ [(DataPat DataCon
dc [TyVar]
_ [Id]
_,Term
_)])
| Name DataCon -> OccName
forall a. Name a -> OccName
nameOcc (DataCon -> Name DataCon
dcName DataCon
dc) OccName -> OccName -> Bool
forall a. Eq a => a -> a -> Bool
== Name -> OccName
forall a. Show a => a -> OccName
Text.showt '(:-) = Term -> StateT ([LetBinding], InScopeSet) NormalizeSession Term
forall (m :: Type -> Type) a. Monad m => a -> m a
return Term
e
collectANF TransformContext
ctx (Case Term
subj Type
ty [Alt]
alts) = do
let localVar :: Bool
localVar = Term -> Bool
isLocalVar Term
subj
let isConstantSubj :: Bool
isConstantSubj = Term -> Bool
isConstant Term
subj
(Term
subj',[LetBinding]
subjBinders) <- if Bool
localVar Bool -> Bool -> Bool
|| Bool
isConstantSubj
then (Term, [LetBinding])
-> StateT
([LetBinding], InScopeSet) NormalizeSession (Term, [LetBinding])
forall (m :: Type -> Type) a. Monad m => a -> m a
return (Term
subj,[])
else do
TyConMap
tcm <- Getting TyConMap RewriteEnv TyConMap
-> StateT ([LetBinding], InScopeSet) NormalizeSession TyConMap
forall s (m :: Type -> Type) a.
MonadReader s m =>
Getting a s a -> m a
Lens.view Getting TyConMap RewriteEnv TyConMap
Getter RewriteEnv TyConMap
tcCache
InScopeSet
is1 <- Getting InScopeSet ([LetBinding], InScopeSet) InScopeSet
-> StateT ([LetBinding], InScopeSet) NormalizeSession InScopeSet
forall s (m :: Type -> Type) a.
MonadState s m =>
Getting a s a -> m a
Lens.use Getting InScopeSet ([LetBinding], InScopeSet) InScopeSet
forall s t a b. Field2 s t a b => Lens s t a b
_2
Id
argId <- NormalizeSession Id
-> StateT ([LetBinding], InScopeSet) NormalizeSession Id
forall (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (InScopeSet -> TyConMap -> Name Term -> Term -> NormalizeSession Id
forall (m :: Type -> Type) a.
MonadUnique m =>
InScopeSet -> TyConMap -> Name a -> Term -> m Id
mkTmBinderFor InScopeSet
is1 TyConMap
tcm (TransformContext -> OccName -> Name Term
mkDerivedName TransformContext
ctx OccName
"case_scrut") Term
subj)
[LetBinding]
-> StateT ([LetBinding], InScopeSet) NormalizeSession ()
forall (m :: Type -> Type).
Monad m =>
[LetBinding] -> StateT ([LetBinding], InScopeSet) m ()
notifyBinders [(Id
argId,Term
subj)]
(Term, [LetBinding])
-> StateT
([LetBinding], InScopeSet) NormalizeSession (Term, [LetBinding])
forall (m :: Type -> Type) a. Monad m => a -> m a
return (Id -> Term
Var Id
argId,[(Id
argId,Term
subj)])
TyConMap
tcm <- Getting TyConMap RewriteEnv TyConMap
-> StateT ([LetBinding], InScopeSet) NormalizeSession TyConMap
forall s (m :: Type -> Type) a.
MonadReader s m =>
Getting a s a -> m a
Lens.view Getting TyConMap RewriteEnv TyConMap
Getter RewriteEnv TyConMap
tcCache
let isSimIOAlt :: Bool
isSimIOAlt = TyConMap -> Type -> Bool
isSimIOTy TyConMap
tcm Type
ty
[Alt]
alts' <- (Alt -> StateT ([LetBinding], InScopeSet) NormalizeSession Alt)
-> [Alt]
-> StateT ([LetBinding], InScopeSet) NormalizeSession [Alt]
forall (t :: Type -> Type) (m :: Type -> Type) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (Bool
-> Term
-> Alt
-> StateT ([LetBinding], InScopeSet) NormalizeSession Alt
doAlt Bool
isSimIOAlt Term
subj') [Alt]
alts
[LetBinding]
-> StateT ([LetBinding], InScopeSet) NormalizeSession ()
tellBinders [LetBinding]
subjBinders
case [Alt]
alts' of
[(DataPat DataCon
_ [] [Id]
xs,Term
altExpr)]
| [Id] -> VarSet
forall a. [Var a] -> VarSet
mkVarSet [Id]
xs VarSet -> Term -> Bool
forall a. HasFreeVars a => VarSet -> a -> Bool
`disjointFreeVars` Term
altExpr Bool -> Bool -> Bool
|| Bool
isSimIOAlt
-> Term -> StateT ([LetBinding], InScopeSet) NormalizeSession Term
forall (m :: Type -> Type) a. Monad m => a -> m a
return Term
altExpr
[Alt]
_ -> Term -> StateT ([LetBinding], InScopeSet) NormalizeSession Term
forall (m :: Type -> Type) a. Monad m => a -> m a
return (Term -> Type -> [Alt] -> Term
Case Term
subj' Type
ty [Alt]
alts')
where
doAlt :: Bool -> Term -> Alt -> StateT ([LetBinding],InScopeSet) NormalizeSession Alt
doAlt :: Bool
-> Term
-> Alt
-> StateT ([LetBinding], InScopeSet) NormalizeSession Alt
doAlt Bool
isSimIOAlt Term
subj' alt :: Alt
alt@(DataPat DataCon
dc [TyVar]
exts [Id]
xs,Term
altExpr) | Bool -> Bool
not ([TyVar] -> [Id] -> Bool
forall a. [TyVar] -> [Var a] -> Bool
bindsExistentials [TyVar]
exts [Id]
xs) = do
let lv :: Bool
lv = Term -> Bool
isLocalVar Term
altExpr
[LetBinding]
patSels <- (Id
-> Unique
-> StateT ([LetBinding], InScopeSet) NormalizeSession LetBinding)
-> [Id]
-> [Unique]
-> StateT ([LetBinding], InScopeSet) NormalizeSession [LetBinding]
forall (m :: Type -> Type) a b c.
Applicative m =>
(a -> b -> m c) -> [a] -> [b] -> m [c]
Monad.zipWithM (Term
-> DataCon
-> Id
-> Unique
-> StateT ([LetBinding], InScopeSet) NormalizeSession LetBinding
doPatBndr Term
subj' DataCon
dc) [Id]
xs [Unique
0..]
let altExprIsConstant :: Bool
altExprIsConstant = Term -> Bool
isConstant Term
altExpr
let usesXs :: Term -> Bool
usesXs (Var Id
n) = (Id -> Bool) -> [Id] -> Bool
forall (t :: Type -> Type) a.
Foldable t =>
(a -> Bool) -> t a -> Bool
any (Id -> Id -> Bool
forall a. Eq a => a -> a -> Bool
== Id
n) [Id]
xs
usesXs Term
_ = Bool
False
if [Bool] -> Bool
forall (t :: Type -> Type). Foldable t => t Bool -> Bool
or [Bool
isSimIOAlt, Bool
lv Bool -> Bool -> Bool
&& (Bool -> Bool
not (Term -> Bool
usesXs Term
altExpr) Bool -> Bool -> Bool
|| [Alt] -> Unique
forall (t :: Type -> Type) a. Foldable t => t a -> Unique
length [Alt]
alts Unique -> Unique -> Bool
forall a. Eq a => a -> a -> Bool
== Unique
1), Bool
altExprIsConstant]
then do
[LetBinding]
-> StateT ([LetBinding], InScopeSet) NormalizeSession ()
tellBinders [LetBinding]
patSels
Alt -> StateT ([LetBinding], InScopeSet) NormalizeSession Alt
forall (m :: Type -> Type) a. Monad m => a -> m a
return Alt
alt
else do
TyConMap
tcm <- Getting TyConMap RewriteEnv TyConMap
-> StateT ([LetBinding], InScopeSet) NormalizeSession TyConMap
forall s (m :: Type -> Type) a.
MonadReader s m =>
Getting a s a -> m a
Lens.view Getting TyConMap RewriteEnv TyConMap
Getter RewriteEnv TyConMap
tcCache
InScopeSet
is1 <- Getting InScopeSet ([LetBinding], InScopeSet) InScopeSet
-> StateT ([LetBinding], InScopeSet) NormalizeSession InScopeSet
forall s (m :: Type -> Type) a.
MonadState s m =>
Getting a s a -> m a
Lens.use Getting InScopeSet ([LetBinding], InScopeSet) InScopeSet
forall s t a b. Field2 s t a b => Lens s t a b
_2
Id
altId <- NormalizeSession Id
-> StateT ([LetBinding], InScopeSet) NormalizeSession Id
forall (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (InScopeSet -> TyConMap -> Name Term -> Term -> NormalizeSession Id
forall (m :: Type -> Type) a.
MonadUnique m =>
InScopeSet -> TyConMap -> Name a -> Term -> m Id
mkTmBinderFor InScopeSet
is1 TyConMap
tcm (TransformContext -> OccName -> Name Term
mkDerivedName TransformContext
ctx OccName
"case_alt") Term
altExpr)
[LetBinding]
-> StateT ([LetBinding], InScopeSet) NormalizeSession ()
tellBinders ([LetBinding]
patSels [LetBinding] -> [LetBinding] -> [LetBinding]
forall a. [a] -> [a] -> [a]
++ [(Id
altId,Term
altExpr)])
Alt -> StateT ([LetBinding], InScopeSet) NormalizeSession Alt
forall (m :: Type -> Type) a. Monad m => a -> m a
return (DataCon -> [TyVar] -> [Id] -> Pat
DataPat DataCon
dc [TyVar]
exts [Id]
xs,Id -> Term
Var Id
altId)
doAlt Bool
_ Term
_ alt :: Alt
alt@(DataPat {}, Term
_) = Alt -> StateT ([LetBinding], InScopeSet) NormalizeSession Alt
forall (m :: Type -> Type) a. Monad m => a -> m a
return Alt
alt
doAlt Bool
isSimIOAlt Term
_ alt :: Alt
alt@(Pat
pat,Term
altExpr) = do
let lv :: Bool
lv = Term -> Bool
isLocalVar Term
altExpr
let altExprIsConstant :: Bool
altExprIsConstant = Term -> Bool
isConstant Term
altExpr
if Bool
isSimIOAlt Bool -> Bool -> Bool
|| Bool
lv Bool -> Bool -> Bool
|| Bool
altExprIsConstant
then Alt -> StateT ([LetBinding], InScopeSet) NormalizeSession Alt
forall (m :: Type -> Type) a. Monad m => a -> m a
return Alt
alt
else do
TyConMap
tcm <- Getting TyConMap RewriteEnv TyConMap
-> StateT ([LetBinding], InScopeSet) NormalizeSession TyConMap
forall s (m :: Type -> Type) a.
MonadReader s m =>
Getting a s a -> m a
Lens.view Getting TyConMap RewriteEnv TyConMap
Getter RewriteEnv TyConMap
tcCache
InScopeSet
is1 <- Getting InScopeSet ([LetBinding], InScopeSet) InScopeSet
-> StateT ([LetBinding], InScopeSet) NormalizeSession InScopeSet
forall s (m :: Type -> Type) a.
MonadState s m =>
Getting a s a -> m a
Lens.use Getting InScopeSet ([LetBinding], InScopeSet) InScopeSet
forall s t a b. Field2 s t a b => Lens s t a b
_2
Id
altId <- NormalizeSession Id
-> StateT ([LetBinding], InScopeSet) NormalizeSession Id
forall (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (InScopeSet -> TyConMap -> Name Term -> Term -> NormalizeSession Id
forall (m :: Type -> Type) a.
MonadUnique m =>
InScopeSet -> TyConMap -> Name a -> Term -> m Id
mkTmBinderFor InScopeSet
is1 TyConMap
tcm (TransformContext -> OccName -> Name Term
mkDerivedName TransformContext
ctx OccName
"case_alt") Term
altExpr)
[LetBinding]
-> StateT ([LetBinding], InScopeSet) NormalizeSession ()
tellBinders [(Id
altId,Term
altExpr)]
Alt -> StateT ([LetBinding], InScopeSet) NormalizeSession Alt
forall (m :: Type -> Type) a. Monad m => a -> m a
return (Pat
pat,Id -> Term
Var Id
altId)
doPatBndr :: Term -> DataCon -> Id -> Int -> StateT ([LetBinding],InScopeSet) NormalizeSession LetBinding
doPatBndr :: Term
-> DataCon
-> Id
-> Unique
-> StateT ([LetBinding], InScopeSet) NormalizeSession LetBinding
doPatBndr Term
subj' DataCon
dc Id
pId Unique
i = do
TyConMap
tcm <- Getting TyConMap RewriteEnv TyConMap
-> StateT ([LetBinding], InScopeSet) NormalizeSession TyConMap
forall s (m :: Type -> Type) a.
MonadReader s m =>
Getting a s a -> m a
Lens.view Getting TyConMap RewriteEnv TyConMap
Getter RewriteEnv TyConMap
tcCache
InScopeSet
is1 <- Getting InScopeSet ([LetBinding], InScopeSet) InScopeSet
-> StateT ([LetBinding], InScopeSet) NormalizeSession InScopeSet
forall s (m :: Type -> Type) a.
MonadState s m =>
Getting a s a -> m a
Lens.use Getting InScopeSet ([LetBinding], InScopeSet) InScopeSet
forall s t a b. Field2 s t a b => Lens s t a b
_2
Term
patExpr <- RewriteMonad NormalizeState Term
-> StateT ([LetBinding], InScopeSet) NormalizeSession Term
forall (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (String
-> InScopeSet
-> TyConMap
-> Term
-> Unique
-> Unique
-> RewriteMonad NormalizeState Term
forall (m :: Type -> Type).
(HasCallStack, MonadUnique m) =>
String
-> InScopeSet -> TyConMap -> Term -> Unique -> Unique -> m Term
mkSelectorCase ($(String
curLoc) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"doPatBndr") InScopeSet
is1 TyConMap
tcm Term
subj' (DataCon -> Unique
dcTag DataCon
dc) Unique
i)
LetBinding
-> StateT ([LetBinding], InScopeSet) NormalizeSession LetBinding
forall (m :: Type -> Type) a. Monad m => a -> m a
return (Id
pId,Term
patExpr)
collectANF TransformContext
_ Term
e = Term -> StateT ([LetBinding], InScopeSet) NormalizeSession Term
forall (m :: Type -> Type) a. Monad m => a -> m a
return Term
e
{-# SCC collectANF #-}
nonRepANF :: HasCallStack => NormRewrite
nonRepANF :: NormRewrite
nonRepANF ctx :: TransformContext
ctx@(TransformContext InScopeSet
is0 Context
_) e :: Term
e@(App Term
appConPrim Term
arg)
| (Term
conPrim, [Either Term Type]
_) <- Term -> (Term, [Either Term Type])
collectArgs Term
e
, Term -> Bool
isCon Term
conPrim Bool -> Bool -> Bool
|| Term -> Bool
isPrim Term
conPrim
= do
Bool
untranslatable <- Bool -> Term -> RewriteMonad NormalizeState Bool
forall extra. Bool -> Term -> RewriteMonad extra Bool
isUntranslatable Bool
False Term
arg
case (Bool
untranslatable,Term -> Term
stripTicks Term
arg) of
(Bool
True,Let Bind Term
binds Term
body) ->
let (Bind Term
binds1,Term
body1) = HasCallStack =>
InScopeSet -> Bind Term -> Term -> (Bind Term, Term)
InScopeSet -> Bind Term -> Term -> (Bind Term, Term)
deshadowLetExpr InScopeSet
is0 Bind Term
binds Term
body
in Term -> RewriteMonad NormalizeState Term
forall a extra. a -> RewriteMonad extra a
changed (Bind Term -> Term -> Term
Let Bind Term
binds1 (Term -> Term -> Term
App Term
appConPrim Term
body1))
(Bool
True,Case {}) -> NormRewrite
specialize TransformContext
ctx Term
e
(Bool
True,Lam {}) -> NormRewrite
specialize TransformContext
ctx Term
e
(Bool
True,TyLam {}) -> NormRewrite
specialize TransformContext
ctx Term
e
(Bool, Term)
_ -> Term -> RewriteMonad NormalizeState Term
forall (m :: Type -> Type) a. Monad m => a -> m a
return Term
e
nonRepANF TransformContext
_ Term
e = Term -> RewriteMonad NormalizeState Term
forall (m :: Type -> Type) a. Monad m => a -> m a
return Term
e
{-# SCC nonRepANF #-}