{-# LANGUAGE CPP #-}
module CoreArity (
manifestArity, joinRhsArity, exprArity, typeArity,
exprEtaExpandArity, findRhsArity, etaExpand,
etaExpandToJoinPoint, etaExpandToJoinPointRule,
exprBotStrictness_maybe
) where
#include "HsVersions.h"
import GhcPrelude
import CoreSyn
import CoreFVs
import CoreUtils
import CoreSubst
import Demand
import Var
import VarEnv
import Id
import Type
import TyCon ( initRecTc, checkRecTc )
import Coercion
import BasicTypes
import Unique
import DynFlags ( DynFlags, GeneralFlag(..), gopt )
import Outputable
import FastString
import Pair
import Util ( debugIsOn )
manifestArity :: CoreExpr -> Arity
manifestArity :: CoreExpr -> Arity
manifestArity (Lam v :: CoreBndr
v e :: CoreExpr
e) | CoreBndr -> Bool
isId CoreBndr
v = 1 Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
+ CoreExpr -> Arity
manifestArity CoreExpr
e
| Bool
otherwise = CoreExpr -> Arity
manifestArity CoreExpr
e
manifestArity (Tick t :: Tickish CoreBndr
t e :: CoreExpr
e) | Bool -> Bool
not (Tickish CoreBndr -> Bool
forall id. Tickish id -> Bool
tickishIsCode Tickish CoreBndr
t) = CoreExpr -> Arity
manifestArity CoreExpr
e
manifestArity (Cast e :: CoreExpr
e _) = CoreExpr -> Arity
manifestArity CoreExpr
e
manifestArity _ = 0
joinRhsArity :: CoreExpr -> JoinArity
joinRhsArity :: CoreExpr -> Arity
joinRhsArity (Lam _ e :: CoreExpr
e) = 1 Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
+ CoreExpr -> Arity
joinRhsArity CoreExpr
e
joinRhsArity _ = 0
exprArity :: CoreExpr -> Arity
exprArity :: CoreExpr -> Arity
exprArity e :: CoreExpr
e = CoreExpr -> Arity
go CoreExpr
e
where
go :: CoreExpr -> Arity
go (Var v :: CoreBndr
v) = CoreBndr -> Arity
idArity CoreBndr
v
go (Lam x :: CoreBndr
x e :: CoreExpr
e) | CoreBndr -> Bool
isId CoreBndr
x = CoreExpr -> Arity
go CoreExpr
e Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
+ 1
| Bool
otherwise = CoreExpr -> Arity
go CoreExpr
e
go (Tick t :: Tickish CoreBndr
t e :: CoreExpr
e) | Bool -> Bool
not (Tickish CoreBndr -> Bool
forall id. Tickish id -> Bool
tickishIsCode Tickish CoreBndr
t) = CoreExpr -> Arity
go CoreExpr
e
go (Cast e :: CoreExpr
e co :: Coercion
co) = Arity -> Type -> Arity
trim_arity (CoreExpr -> Arity
go CoreExpr
e) (Pair Type -> Type
forall a. Pair a -> a
pSnd (Coercion -> Pair Type
coercionKind Coercion
co))
go (App e :: CoreExpr
e (Type _)) = CoreExpr -> Arity
go CoreExpr
e
go (App f :: CoreExpr
f a :: CoreExpr
a) | CoreExpr -> Bool
exprIsTrivial CoreExpr
a = (CoreExpr -> Arity
go CoreExpr
f Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
- 1) Arity -> Arity -> Arity
forall a. Ord a => a -> a -> a
`max` 0
go _ = 0
trim_arity :: Arity -> Type -> Arity
trim_arity :: Arity -> Type -> Arity
trim_arity arity :: Arity
arity ty :: Type
ty = Arity
arity Arity -> Arity -> Arity
forall a. Ord a => a -> a -> a
`min` [OneShotInfo] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length (Type -> [OneShotInfo]
typeArity Type
ty)
typeArity :: Type -> [OneShotInfo]
typeArity :: Type -> [OneShotInfo]
typeArity ty :: Type
ty
= RecTcChecker -> Type -> [OneShotInfo]
go RecTcChecker
initRecTc Type
ty
where
go :: RecTcChecker -> Type -> [OneShotInfo]
go rec_nts :: RecTcChecker
rec_nts ty :: Type
ty
| Just (_, ty' :: Type
ty') <- Type -> Maybe (CoreBndr, Type)
splitForAllTy_maybe Type
ty
= RecTcChecker -> Type -> [OneShotInfo]
go RecTcChecker
rec_nts Type
ty'
| Just (arg :: Type
arg,res :: Type
res) <- Type -> Maybe (Type, Type)
splitFunTy_maybe Type
ty
= Type -> OneShotInfo
typeOneShot Type
arg OneShotInfo -> [OneShotInfo] -> [OneShotInfo]
forall a. a -> [a] -> [a]
: RecTcChecker -> Type -> [OneShotInfo]
go RecTcChecker
rec_nts Type
res
| Just (tc :: TyCon
tc,tys :: [Type]
tys) <- HasDebugCallStack => Type -> Maybe (TyCon, [Type])
Type -> Maybe (TyCon, [Type])
splitTyConApp_maybe Type
ty
, Just (ty' :: Type
ty', _) <- TyCon -> [Type] -> Maybe (Type, Coercion)
instNewTyCon_maybe TyCon
tc [Type]
tys
, Just rec_nts' :: RecTcChecker
rec_nts' <- RecTcChecker -> TyCon -> Maybe RecTcChecker
checkRecTc RecTcChecker
rec_nts TyCon
tc
= RecTcChecker -> Type -> [OneShotInfo]
go RecTcChecker
rec_nts' Type
ty'
| Bool
otherwise
= []
exprBotStrictness_maybe :: CoreExpr -> Maybe (Arity, StrictSig)
exprBotStrictness_maybe :: CoreExpr -> Maybe (Arity, StrictSig)
exprBotStrictness_maybe e :: CoreExpr
e
= case ArityType -> Maybe Arity
getBotArity (ArityEnv -> CoreExpr -> ArityType
arityType ArityEnv
env CoreExpr
e) of
Nothing -> Maybe (Arity, StrictSig)
forall a. Maybe a
Nothing
Just ar :: Arity
ar -> (Arity, StrictSig) -> Maybe (Arity, StrictSig)
forall a. a -> Maybe a
Just (Arity
ar, Arity -> StrictSig
sig Arity
ar)
where
env :: ArityEnv
env = AE :: CheapFun -> Bool -> ArityEnv
AE { ae_ped_bot :: Bool
ae_ped_bot = Bool
True, ae_cheap_fn :: CheapFun
ae_cheap_fn = \ _ _ -> Bool
False }
sig :: Arity -> StrictSig
sig ar :: Arity
ar = [Demand] -> DmdResult -> StrictSig
mkClosedStrictSig (Arity -> Demand -> [Demand]
forall a. Arity -> a -> [a]
replicate Arity
ar Demand
topDmd) DmdResult
exnRes
data ArityType = ATop [OneShotInfo] | ABot Arity
instance Outputable ArityType where
ppr :: ArityType -> SDoc
ppr (ATop os :: [OneShotInfo]
os) = String -> SDoc
text "ATop" SDoc -> SDoc -> SDoc
<> SDoc -> SDoc
parens (Arity -> SDoc
forall a. Outputable a => a -> SDoc
ppr ([OneShotInfo] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length [OneShotInfo]
os))
ppr (ABot n :: Arity
n) = String -> SDoc
text "ABot" SDoc -> SDoc -> SDoc
<> SDoc -> SDoc
parens (Arity -> SDoc
forall a. Outputable a => a -> SDoc
ppr Arity
n)
vanillaArityType :: ArityType
vanillaArityType :: ArityType
vanillaArityType = [OneShotInfo] -> ArityType
ATop []
exprEtaExpandArity :: DynFlags -> CoreExpr -> Arity
exprEtaExpandArity :: DynFlags -> CoreExpr -> Arity
exprEtaExpandArity dflags :: DynFlags
dflags e :: CoreExpr
e
= case (ArityEnv -> CoreExpr -> ArityType
arityType ArityEnv
env CoreExpr
e) of
ATop oss :: [OneShotInfo]
oss -> [OneShotInfo] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length [OneShotInfo]
oss
ABot n :: Arity
n -> Arity
n
where
env :: ArityEnv
env = AE :: CheapFun -> Bool -> ArityEnv
AE { ae_cheap_fn :: CheapFun
ae_cheap_fn = DynFlags -> CheapAppFun -> CheapFun
mk_cheap_fn DynFlags
dflags CheapAppFun
isCheapApp
, ae_ped_bot :: Bool
ae_ped_bot = GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_PedanticBottoms DynFlags
dflags }
getBotArity :: ArityType -> Maybe Arity
getBotArity :: ArityType -> Maybe Arity
getBotArity (ABot n :: Arity
n) = Arity -> Maybe Arity
forall a. a -> Maybe a
Just Arity
n
getBotArity _ = Maybe Arity
forall a. Maybe a
Nothing
mk_cheap_fn :: DynFlags -> CheapAppFun -> CheapFun
mk_cheap_fn :: DynFlags -> CheapAppFun -> CheapFun
mk_cheap_fn dflags :: DynFlags
dflags cheap_app :: CheapAppFun
cheap_app
| Bool -> Bool
not (GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_DictsCheap DynFlags
dflags)
= \e :: CoreExpr
e _ -> CheapAppFun -> CoreExpr -> Bool
exprIsCheapX CheapAppFun
cheap_app CoreExpr
e
| Bool
otherwise
= \e :: CoreExpr
e mb_ty :: Maybe Type
mb_ty -> CheapAppFun -> CoreExpr -> Bool
exprIsCheapX CheapAppFun
cheap_app CoreExpr
e
Bool -> Bool -> Bool
|| case Maybe Type
mb_ty of
Nothing -> Bool
False
Just ty :: Type
ty -> Type -> Bool
isDictLikeTy Type
ty
findRhsArity :: DynFlags -> Id -> CoreExpr -> Arity -> (Arity, Bool)
findRhsArity :: DynFlags -> CoreBndr -> CoreExpr -> Arity -> (Arity, Bool)
findRhsArity dflags :: DynFlags
dflags bndr :: CoreBndr
bndr rhs :: CoreExpr
rhs old_arity :: Arity
old_arity
= (Arity, Bool) -> (Arity, Bool)
go (CheapAppFun -> (Arity, Bool)
get_arity CheapAppFun
init_cheap_app)
where
is_lam :: Bool
is_lam = CoreExpr -> Bool
has_lam CoreExpr
rhs
has_lam :: CoreExpr -> Bool
has_lam (Tick _ e :: CoreExpr
e) = CoreExpr -> Bool
has_lam CoreExpr
e
has_lam (Lam b :: CoreBndr
b e :: CoreExpr
e) = CoreBndr -> Bool
isId CoreBndr
b Bool -> Bool -> Bool
|| CoreExpr -> Bool
has_lam CoreExpr
e
has_lam _ = Bool
False
init_cheap_app :: CheapAppFun
init_cheap_app :: CheapAppFun
init_cheap_app fn :: CoreBndr
fn n_val_args :: Arity
n_val_args
| CoreBndr
fn CoreBndr -> CoreBndr -> Bool
forall a. Eq a => a -> a -> Bool
== CoreBndr
bndr = Bool
True
| Bool
otherwise = CheapAppFun
isCheapApp CoreBndr
fn Arity
n_val_args
go :: (Arity, Bool) -> (Arity, Bool)
go :: (Arity, Bool) -> (Arity, Bool)
go cur_info :: (Arity, Bool)
cur_info@(cur_arity :: Arity
cur_arity, _)
| Arity
cur_arity Arity -> Arity -> Bool
forall a. Ord a => a -> a -> Bool
<= Arity
old_arity = (Arity, Bool)
cur_info
| Arity
new_arity Arity -> Arity -> Bool
forall a. Eq a => a -> a -> Bool
== Arity
cur_arity = (Arity, Bool)
cur_info
| Bool
otherwise = ASSERT( new_arity < cur_arity )
#if defined(DEBUG)
pprTrace "Exciting arity"
(vcat [ ppr bndr <+> ppr cur_arity <+> ppr new_arity
, ppr rhs])
#endif
(Arity, Bool) -> (Arity, Bool)
go (Arity, Bool)
new_info
where
new_info :: (Arity, Bool)
new_info@(new_arity :: Arity
new_arity, _) = CheapAppFun -> (Arity, Bool)
get_arity CheapAppFun
cheap_app
cheap_app :: CheapAppFun
cheap_app :: CheapAppFun
cheap_app fn :: CoreBndr
fn n_val_args :: Arity
n_val_args
| CoreBndr
fn CoreBndr -> CoreBndr -> Bool
forall a. Eq a => a -> a -> Bool
== CoreBndr
bndr = Arity
n_val_args Arity -> Arity -> Bool
forall a. Ord a => a -> a -> Bool
< Arity
cur_arity
| Bool
otherwise = CheapAppFun
isCheapApp CoreBndr
fn Arity
n_val_args
get_arity :: CheapAppFun -> (Arity, Bool)
get_arity :: CheapAppFun -> (Arity, Bool)
get_arity cheap_app :: CheapAppFun
cheap_app
= case (ArityEnv -> CoreExpr -> ArityType
arityType ArityEnv
env CoreExpr
rhs) of
ABot n :: Arity
n -> (Arity
n, Bool
True)
ATop (os :: OneShotInfo
os:oss :: [OneShotInfo]
oss) | OneShotInfo -> Bool
isOneShotInfo OneShotInfo
os Bool -> Bool -> Bool
|| Bool
is_lam
-> (1 Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
+ [OneShotInfo] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length [OneShotInfo]
oss, Bool
False)
ATop _ -> (0, Bool
False)
where
env :: ArityEnv
env = AE :: CheapFun -> Bool -> ArityEnv
AE { ae_cheap_fn :: CheapFun
ae_cheap_fn = DynFlags -> CheapAppFun -> CheapFun
mk_cheap_fn DynFlags
dflags CheapAppFun
cheap_app
, ae_ped_bot :: Bool
ae_ped_bot = GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_PedanticBottoms DynFlags
dflags }
arityLam :: Id -> ArityType -> ArityType
arityLam :: CoreBndr -> ArityType -> ArityType
arityLam id :: CoreBndr
id (ATop as :: [OneShotInfo]
as) = [OneShotInfo] -> ArityType
ATop (CoreBndr -> OneShotInfo
idStateHackOneShotInfo CoreBndr
id OneShotInfo -> [OneShotInfo] -> [OneShotInfo]
forall a. a -> [a] -> [a]
: [OneShotInfo]
as)
arityLam _ (ABot n :: Arity
n) = Arity -> ArityType
ABot (Arity
nArity -> Arity -> Arity
forall a. Num a => a -> a -> a
+1)
floatIn :: Bool -> ArityType -> ArityType
floatIn :: Bool -> ArityType -> ArityType
floatIn _ (ABot n :: Arity
n) = Arity -> ArityType
ABot Arity
n
floatIn True (ATop as :: [OneShotInfo]
as) = [OneShotInfo] -> ArityType
ATop [OneShotInfo]
as
floatIn False (ATop as :: [OneShotInfo]
as) = [OneShotInfo] -> ArityType
ATop ((OneShotInfo -> Bool) -> [OneShotInfo] -> [OneShotInfo]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile OneShotInfo -> Bool
isOneShotInfo [OneShotInfo]
as)
arityApp :: ArityType -> Bool -> ArityType
arityApp :: ArityType -> Bool -> ArityType
arityApp (ABot 0) _ = Arity -> ArityType
ABot 0
arityApp (ABot n :: Arity
n) _ = Arity -> ArityType
ABot (Arity
nArity -> Arity -> Arity
forall a. Num a => a -> a -> a
-1)
arityApp (ATop []) _ = [OneShotInfo] -> ArityType
ATop []
arityApp (ATop (_:as :: [OneShotInfo]
as)) cheap :: Bool
cheap = Bool -> ArityType -> ArityType
floatIn Bool
cheap ([OneShotInfo] -> ArityType
ATop [OneShotInfo]
as)
andArityType :: ArityType -> ArityType -> ArityType
andArityType :: ArityType -> ArityType -> ArityType
andArityType (ABot n1 :: Arity
n1) (ABot n2 :: Arity
n2) = Arity -> ArityType
ABot (Arity
n1 Arity -> Arity -> Arity
forall a. Ord a => a -> a -> a
`max` Arity
n2)
andArityType (ATop as :: [OneShotInfo]
as) (ABot _) = [OneShotInfo] -> ArityType
ATop [OneShotInfo]
as
andArityType (ABot _) (ATop bs :: [OneShotInfo]
bs) = [OneShotInfo] -> ArityType
ATop [OneShotInfo]
bs
andArityType (ATop as :: [OneShotInfo]
as) (ATop bs :: [OneShotInfo]
bs) = [OneShotInfo] -> ArityType
ATop ([OneShotInfo]
as [OneShotInfo] -> [OneShotInfo] -> [OneShotInfo]
`combine` [OneShotInfo]
bs)
where
combine :: [OneShotInfo] -> [OneShotInfo] -> [OneShotInfo]
combine (a :: OneShotInfo
a:as :: [OneShotInfo]
as) (b :: OneShotInfo
b:bs :: [OneShotInfo]
bs) = (OneShotInfo
a OneShotInfo -> OneShotInfo -> OneShotInfo
`bestOneShot` OneShotInfo
b) OneShotInfo -> [OneShotInfo] -> [OneShotInfo]
forall a. a -> [a] -> [a]
: [OneShotInfo] -> [OneShotInfo] -> [OneShotInfo]
combine [OneShotInfo]
as [OneShotInfo]
bs
combine [] bs :: [OneShotInfo]
bs = (OneShotInfo -> Bool) -> [OneShotInfo] -> [OneShotInfo]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile OneShotInfo -> Bool
isOneShotInfo [OneShotInfo]
bs
combine as :: [OneShotInfo]
as [] = (OneShotInfo -> Bool) -> [OneShotInfo] -> [OneShotInfo]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile OneShotInfo -> Bool
isOneShotInfo [OneShotInfo]
as
type CheapFun = CoreExpr -> Maybe Type -> Bool
data ArityEnv
= AE { ArityEnv -> CheapFun
ae_cheap_fn :: CheapFun
, ArityEnv -> Bool
ae_ped_bot :: Bool
}
arityType :: ArityEnv -> CoreExpr -> ArityType
arityType :: ArityEnv -> CoreExpr -> ArityType
arityType env :: ArityEnv
env (Cast e :: CoreExpr
e co :: Coercion
co)
= case ArityEnv -> CoreExpr -> ArityType
arityType ArityEnv
env CoreExpr
e of
ATop os :: [OneShotInfo]
os -> [OneShotInfo] -> ArityType
ATop (Arity -> [OneShotInfo] -> [OneShotInfo]
forall a. Arity -> [a] -> [a]
take Arity
co_arity [OneShotInfo]
os)
ABot n :: Arity
n | Arity
co_arity Arity -> Arity -> Bool
forall a. Ord a => a -> a -> Bool
< Arity
n -> [OneShotInfo] -> ArityType
ATop (Arity -> OneShotInfo -> [OneShotInfo]
forall a. Arity -> a -> [a]
replicate Arity
co_arity OneShotInfo
noOneShotInfo)
| Bool
otherwise -> Arity -> ArityType
ABot Arity
n
where
co_arity :: Arity
co_arity = [OneShotInfo] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length (Type -> [OneShotInfo]
typeArity (Pair Type -> Type
forall a. Pair a -> a
pSnd (Coercion -> Pair Type
coercionKind Coercion
co)))
arityType _ (Var v :: CoreBndr
v)
| StrictSig
strict_sig <- CoreBndr -> StrictSig
idStrictness CoreBndr
v
, Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ StrictSig -> Bool
isTopSig StrictSig
strict_sig
, (ds :: [Demand]
ds, res :: DmdResult
res) <- StrictSig -> ([Demand], DmdResult)
splitStrictSig StrictSig
strict_sig
, let arity :: Arity
arity = [Demand] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length [Demand]
ds
= if DmdResult -> Bool
isBotRes DmdResult
res then Arity -> ArityType
ABot Arity
arity
else [OneShotInfo] -> ArityType
ATop (Arity -> [OneShotInfo] -> [OneShotInfo]
forall a. Arity -> [a] -> [a]
take Arity
arity [OneShotInfo]
one_shots)
| Bool
otherwise
= [OneShotInfo] -> ArityType
ATop (Arity -> [OneShotInfo] -> [OneShotInfo]
forall a. Arity -> [a] -> [a]
take (CoreBndr -> Arity
idArity CoreBndr
v) [OneShotInfo]
one_shots)
where
one_shots :: [OneShotInfo]
one_shots :: [OneShotInfo]
one_shots = Type -> [OneShotInfo]
typeArity (CoreBndr -> Type
idType CoreBndr
v)
arityType env :: ArityEnv
env (Lam x :: CoreBndr
x e :: CoreExpr
e)
| CoreBndr -> Bool
isId CoreBndr
x = CoreBndr -> ArityType -> ArityType
arityLam CoreBndr
x (ArityEnv -> CoreExpr -> ArityType
arityType ArityEnv
env CoreExpr
e)
| Bool
otherwise = ArityEnv -> CoreExpr -> ArityType
arityType ArityEnv
env CoreExpr
e
arityType env :: ArityEnv
env (App fun :: CoreExpr
fun (Type _))
= ArityEnv -> CoreExpr -> ArityType
arityType ArityEnv
env CoreExpr
fun
arityType env :: ArityEnv
env (App fun :: CoreExpr
fun arg :: CoreExpr
arg )
= ArityType -> Bool -> ArityType
arityApp (ArityEnv -> CoreExpr -> ArityType
arityType ArityEnv
env CoreExpr
fun) (ArityEnv -> CheapFun
ae_cheap_fn ArityEnv
env CoreExpr
arg Maybe Type
forall a. Maybe a
Nothing)
arityType env :: ArityEnv
env (Case scrut :: CoreExpr
scrut _ _ alts :: [Alt CoreBndr]
alts)
| CoreExpr -> Bool
exprIsBottom CoreExpr
scrut Bool -> Bool -> Bool
|| [Alt CoreBndr] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Alt CoreBndr]
alts
= Arity -> ArityType
ABot 0
| Bool
otherwise
= case ArityType
alts_type of
ABot n :: Arity
n | Arity
nArity -> Arity -> Bool
forall a. Ord a => a -> a -> Bool
>0 -> [OneShotInfo] -> ArityType
ATop []
| Bool
otherwise -> Arity -> ArityType
ABot 0
ATop as :: [OneShotInfo]
as | Bool -> Bool
not (ArityEnv -> Bool
ae_ped_bot ArityEnv
env)
, ArityEnv -> CheapFun
ae_cheap_fn ArityEnv
env CoreExpr
scrut Maybe Type
forall a. Maybe a
Nothing -> [OneShotInfo] -> ArityType
ATop [OneShotInfo]
as
| CoreExpr -> Bool
exprOkForSpeculation CoreExpr
scrut -> [OneShotInfo] -> ArityType
ATop [OneShotInfo]
as
| Bool
otherwise -> [OneShotInfo] -> ArityType
ATop ((OneShotInfo -> Bool) -> [OneShotInfo] -> [OneShotInfo]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile OneShotInfo -> Bool
isOneShotInfo [OneShotInfo]
as)
where
alts_type :: ArityType
alts_type = (ArityType -> ArityType -> ArityType) -> [ArityType] -> ArityType
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 ArityType -> ArityType -> ArityType
andArityType [ArityEnv -> CoreExpr -> ArityType
arityType ArityEnv
env CoreExpr
rhs | (_,_,rhs :: CoreExpr
rhs) <- [Alt CoreBndr]
alts]
arityType env :: ArityEnv
env (Let b :: Bind CoreBndr
b e :: CoreExpr
e)
= Bool -> ArityType -> ArityType
floatIn (Bind CoreBndr -> Bool
cheap_bind Bind CoreBndr
b) (ArityEnv -> CoreExpr -> ArityType
arityType ArityEnv
env CoreExpr
e)
where
cheap_bind :: Bind CoreBndr -> Bool
cheap_bind (NonRec b :: CoreBndr
b e :: CoreExpr
e) = (CoreBndr, CoreExpr) -> Bool
is_cheap (CoreBndr
b,CoreExpr
e)
cheap_bind (Rec prs :: [(CoreBndr, CoreExpr)]
prs) = ((CoreBndr, CoreExpr) -> Bool) -> [(CoreBndr, CoreExpr)] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (CoreBndr, CoreExpr) -> Bool
is_cheap [(CoreBndr, CoreExpr)]
prs
is_cheap :: (CoreBndr, CoreExpr) -> Bool
is_cheap (b :: CoreBndr
b,e :: CoreExpr
e) = ArityEnv -> CheapFun
ae_cheap_fn ArityEnv
env CoreExpr
e (Type -> Maybe Type
forall a. a -> Maybe a
Just (CoreBndr -> Type
idType CoreBndr
b))
arityType env :: ArityEnv
env (Tick t :: Tickish CoreBndr
t e :: CoreExpr
e)
| Bool -> Bool
not (Tickish CoreBndr -> Bool
forall id. Tickish id -> Bool
tickishIsCode Tickish CoreBndr
t) = ArityEnv -> CoreExpr -> ArityType
arityType ArityEnv
env CoreExpr
e
arityType _ _ = ArityType
vanillaArityType
etaExpand :: Arity
-> CoreExpr
-> CoreExpr
etaExpand :: Arity -> CoreExpr -> CoreExpr
etaExpand n :: Arity
n orig_expr :: CoreExpr
orig_expr
= Arity -> CoreExpr -> CoreExpr
go Arity
n CoreExpr
orig_expr
where
go :: Arity -> CoreExpr -> CoreExpr
go 0 expr :: CoreExpr
expr = CoreExpr
expr
go n :: Arity
n (Lam v :: CoreBndr
v body :: CoreExpr
body) | CoreBndr -> Bool
isTyVar CoreBndr
v = CoreBndr -> CoreExpr -> CoreExpr
forall b. b -> Expr b -> Expr b
Lam CoreBndr
v (Arity -> CoreExpr -> CoreExpr
go Arity
n CoreExpr
body)
| Bool
otherwise = CoreBndr -> CoreExpr -> CoreExpr
forall b. b -> Expr b -> Expr b
Lam CoreBndr
v (Arity -> CoreExpr -> CoreExpr
go (Arity
nArity -> Arity -> Arity
forall a. Num a => a -> a -> a
-1) CoreExpr
body)
go n :: Arity
n (Cast expr :: CoreExpr
expr co :: Coercion
co) = CoreExpr -> Coercion -> CoreExpr
forall b. Expr b -> Coercion -> Expr b
Cast (Arity -> CoreExpr -> CoreExpr
go Arity
n CoreExpr
expr) Coercion
co
go n :: Arity
n expr :: CoreExpr
expr
=
CoreExpr -> CoreExpr
retick (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall a b. (a -> b) -> a -> b
$ [EtaInfo] -> CoreExpr -> CoreExpr
etaInfoAbs [EtaInfo]
etas (Subst -> CoreExpr -> [EtaInfo] -> CoreExpr
etaInfoApp Subst
subst' CoreExpr
sexpr [EtaInfo]
etas)
where
in_scope :: InScopeSet
in_scope = VarSet -> InScopeSet
mkInScopeSet (CoreExpr -> VarSet
exprFreeVars CoreExpr
expr)
(in_scope' :: InScopeSet
in_scope', etas :: [EtaInfo]
etas) = Arity -> CoreExpr -> InScopeSet -> Type -> (InScopeSet, [EtaInfo])
mkEtaWW Arity
n CoreExpr
orig_expr InScopeSet
in_scope (CoreExpr -> Type
exprType CoreExpr
expr)
subst' :: Subst
subst' = InScopeSet -> Subst
mkEmptySubst InScopeSet
in_scope'
(expr' :: CoreExpr
expr', args :: [CoreExpr]
args) = CoreExpr -> (CoreExpr, [CoreExpr])
forall b. Expr b -> (Expr b, [Expr b])
collectArgs CoreExpr
expr
(ticks :: [Tickish CoreBndr]
ticks, expr'' :: CoreExpr
expr'') = (Tickish CoreBndr -> Bool)
-> CoreExpr -> ([Tickish CoreBndr], CoreExpr)
forall b.
(Tickish CoreBndr -> Bool)
-> Expr b -> ([Tickish CoreBndr], Expr b)
stripTicksTop Tickish CoreBndr -> Bool
forall id. Tickish id -> Bool
tickishFloatable CoreExpr
expr'
sexpr :: CoreExpr
sexpr = (CoreExpr -> CoreExpr -> CoreExpr)
-> CoreExpr -> [CoreExpr] -> CoreExpr
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' CoreExpr -> CoreExpr -> CoreExpr
forall b. Expr b -> Expr b -> Expr b
App CoreExpr
expr'' [CoreExpr]
args
retick :: CoreExpr -> CoreExpr
retick expr :: CoreExpr
expr = (Tickish CoreBndr -> CoreExpr -> CoreExpr)
-> CoreExpr -> [Tickish CoreBndr] -> CoreExpr
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Tickish CoreBndr -> CoreExpr -> CoreExpr
mkTick CoreExpr
expr [Tickish CoreBndr]
ticks
data EtaInfo = EtaVar Var
| EtaCo Coercion
instance Outputable EtaInfo where
ppr :: EtaInfo -> SDoc
ppr (EtaVar v :: CoreBndr
v) = String -> SDoc
text "EtaVar" SDoc -> SDoc -> SDoc
<+> CoreBndr -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreBndr
v
ppr (EtaCo co :: Coercion
co) = String -> SDoc
text "EtaCo" SDoc -> SDoc -> SDoc
<+> Coercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr Coercion
co
pushCoercion :: Coercion -> [EtaInfo] -> [EtaInfo]
pushCoercion :: Coercion -> [EtaInfo] -> [EtaInfo]
pushCoercion co1 :: Coercion
co1 (EtaCo co2 :: Coercion
co2 : eis :: [EtaInfo]
eis)
| Coercion -> Bool
isReflCo Coercion
co = [EtaInfo]
eis
| Bool
otherwise = Coercion -> EtaInfo
EtaCo Coercion
co EtaInfo -> [EtaInfo] -> [EtaInfo]
forall a. a -> [a] -> [a]
: [EtaInfo]
eis
where
co :: Coercion
co = Coercion
co1 Coercion -> Coercion -> Coercion
`mkTransCo` Coercion
co2
pushCoercion co :: Coercion
co eis :: [EtaInfo]
eis = Coercion -> EtaInfo
EtaCo Coercion
co EtaInfo -> [EtaInfo] -> [EtaInfo]
forall a. a -> [a] -> [a]
: [EtaInfo]
eis
etaInfoAbs :: [EtaInfo] -> CoreExpr -> CoreExpr
etaInfoAbs :: [EtaInfo] -> CoreExpr -> CoreExpr
etaInfoAbs [] expr :: CoreExpr
expr = CoreExpr
expr
etaInfoAbs (EtaVar v :: CoreBndr
v : eis :: [EtaInfo]
eis) expr :: CoreExpr
expr = CoreBndr -> CoreExpr -> CoreExpr
forall b. b -> Expr b -> Expr b
Lam CoreBndr
v ([EtaInfo] -> CoreExpr -> CoreExpr
etaInfoAbs [EtaInfo]
eis CoreExpr
expr)
etaInfoAbs (EtaCo co :: Coercion
co : eis :: [EtaInfo]
eis) expr :: CoreExpr
expr = CoreExpr -> Coercion -> CoreExpr
forall b. Expr b -> Coercion -> Expr b
Cast ([EtaInfo] -> CoreExpr -> CoreExpr
etaInfoAbs [EtaInfo]
eis CoreExpr
expr) (Coercion -> Coercion
mkSymCo Coercion
co)
etaInfoApp :: Subst -> CoreExpr -> [EtaInfo] -> CoreExpr
etaInfoApp :: Subst -> CoreExpr -> [EtaInfo] -> CoreExpr
etaInfoApp subst :: Subst
subst (Lam v1 :: CoreBndr
v1 e :: CoreExpr
e) (EtaVar v2 :: CoreBndr
v2 : eis :: [EtaInfo]
eis)
= Subst -> CoreExpr -> [EtaInfo] -> CoreExpr
etaInfoApp (Subst -> CoreBndr -> CoreBndr -> Subst
CoreSubst.extendSubstWithVar Subst
subst CoreBndr
v1 CoreBndr
v2) CoreExpr
e [EtaInfo]
eis
etaInfoApp subst :: Subst
subst (Cast e :: CoreExpr
e co1 :: Coercion
co1) eis :: [EtaInfo]
eis
= Subst -> CoreExpr -> [EtaInfo] -> CoreExpr
etaInfoApp Subst
subst CoreExpr
e (Coercion -> [EtaInfo] -> [EtaInfo]
pushCoercion Coercion
co' [EtaInfo]
eis)
where
co' :: Coercion
co' = Subst -> Coercion -> Coercion
CoreSubst.substCo Subst
subst Coercion
co1
etaInfoApp subst :: Subst
subst (Case e :: CoreExpr
e b :: CoreBndr
b ty :: Type
ty alts :: [Alt CoreBndr]
alts) eis :: [EtaInfo]
eis
= CoreExpr -> CoreBndr -> Type -> [Alt CoreBndr] -> CoreExpr
forall b. Expr b -> b -> Type -> [Alt b] -> Expr b
Case (Subst -> CoreExpr -> CoreExpr
subst_expr Subst
subst CoreExpr
e) CoreBndr
b1 Type
ty' [Alt CoreBndr]
alts'
where
(subst1 :: Subst
subst1, b1 :: CoreBndr
b1) = Subst -> CoreBndr -> (Subst, CoreBndr)
substBndr Subst
subst CoreBndr
b
alts' :: [Alt CoreBndr]
alts' = (Alt CoreBndr -> Alt CoreBndr) -> [Alt CoreBndr] -> [Alt CoreBndr]
forall a b. (a -> b) -> [a] -> [b]
map Alt CoreBndr -> Alt CoreBndr
forall a. (a, [CoreBndr], CoreExpr) -> (a, [CoreBndr], CoreExpr)
subst_alt [Alt CoreBndr]
alts
ty' :: Type
ty' = Type -> [EtaInfo] -> Type
etaInfoAppTy (Subst -> Type -> Type
CoreSubst.substTy Subst
subst Type
ty) [EtaInfo]
eis
subst_alt :: (a, [CoreBndr], CoreExpr) -> (a, [CoreBndr], CoreExpr)
subst_alt (con :: a
con, bs :: [CoreBndr]
bs, rhs :: CoreExpr
rhs) = (a
con, [CoreBndr]
bs', Subst -> CoreExpr -> [EtaInfo] -> CoreExpr
etaInfoApp Subst
subst2 CoreExpr
rhs [EtaInfo]
eis)
where
(subst2 :: Subst
subst2,bs' :: [CoreBndr]
bs') = Subst -> [CoreBndr] -> (Subst, [CoreBndr])
substBndrs Subst
subst1 [CoreBndr]
bs
etaInfoApp subst :: Subst
subst (Let b :: Bind CoreBndr
b e :: CoreExpr
e) eis :: [EtaInfo]
eis
| Bool -> Bool
not (Bind CoreBndr -> Bool
isJoinBind Bind CoreBndr
b)
= Bind CoreBndr -> CoreExpr -> CoreExpr
forall b. Bind b -> Expr b -> Expr b
Let Bind CoreBndr
b' (Subst -> CoreExpr -> [EtaInfo] -> CoreExpr
etaInfoApp Subst
subst' CoreExpr
e [EtaInfo]
eis)
where
(subst' :: Subst
subst', b' :: Bind CoreBndr
b') = Subst -> Bind CoreBndr -> (Subst, Bind CoreBndr)
substBindSC Subst
subst Bind CoreBndr
b
etaInfoApp subst :: Subst
subst (Tick t :: Tickish CoreBndr
t e :: CoreExpr
e) eis :: [EtaInfo]
eis
= Tickish CoreBndr -> CoreExpr -> CoreExpr
forall b. Tickish CoreBndr -> Expr b -> Expr b
Tick (Subst -> Tickish CoreBndr -> Tickish CoreBndr
substTickish Subst
subst Tickish CoreBndr
t) (Subst -> CoreExpr -> [EtaInfo] -> CoreExpr
etaInfoApp Subst
subst CoreExpr
e [EtaInfo]
eis)
etaInfoApp subst :: Subst
subst expr :: CoreExpr
expr _
| (Var fun :: CoreBndr
fun, _) <- CoreExpr -> (CoreExpr, [CoreExpr])
forall b. Expr b -> (Expr b, [Expr b])
collectArgs CoreExpr
expr
, Var fun' :: CoreBndr
fun' <- SDoc -> Subst -> CoreBndr -> CoreExpr
lookupIdSubst (String -> SDoc
text "etaInfoApp" SDoc -> SDoc -> SDoc
<+> CoreBndr -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreBndr
fun) Subst
subst CoreBndr
fun
, CoreBndr -> Bool
isJoinId CoreBndr
fun'
= Subst -> CoreExpr -> CoreExpr
subst_expr Subst
subst CoreExpr
expr
etaInfoApp subst :: Subst
subst e :: CoreExpr
e eis :: [EtaInfo]
eis
= CoreExpr -> [EtaInfo] -> CoreExpr
forall b. Expr b -> [EtaInfo] -> Expr b
go (Subst -> CoreExpr -> CoreExpr
subst_expr Subst
subst CoreExpr
e) [EtaInfo]
eis
where
go :: Expr b -> [EtaInfo] -> Expr b
go e :: Expr b
e [] = Expr b
e
go e :: Expr b
e (EtaVar v :: CoreBndr
v : eis :: [EtaInfo]
eis) = Expr b -> [EtaInfo] -> Expr b
go (Expr b -> Expr b -> Expr b
forall b. Expr b -> Expr b -> Expr b
App Expr b
e (CoreBndr -> Expr b
forall b. CoreBndr -> Expr b
varToCoreExpr CoreBndr
v)) [EtaInfo]
eis
go e :: Expr b
e (EtaCo co :: Coercion
co : eis :: [EtaInfo]
eis) = Expr b -> [EtaInfo] -> Expr b
go (Expr b -> Coercion -> Expr b
forall b. Expr b -> Coercion -> Expr b
Cast Expr b
e Coercion
co) [EtaInfo]
eis
etaInfoAppTy :: Type -> [EtaInfo] -> Type
etaInfoAppTy :: Type -> [EtaInfo] -> Type
etaInfoAppTy ty :: Type
ty [] = Type
ty
etaInfoAppTy ty :: Type
ty (EtaVar v :: CoreBndr
v : eis :: [EtaInfo]
eis) = Type -> [EtaInfo] -> Type
etaInfoAppTy (Type -> CoreExpr -> Type
applyTypeToArg Type
ty (CoreBndr -> CoreExpr
forall b. CoreBndr -> Expr b
varToCoreExpr CoreBndr
v)) [EtaInfo]
eis
etaInfoAppTy _ (EtaCo co :: Coercion
co : eis :: [EtaInfo]
eis) = Type -> [EtaInfo] -> Type
etaInfoAppTy (Pair Type -> Type
forall a. Pair a -> a
pSnd (Coercion -> Pair Type
coercionKind Coercion
co)) [EtaInfo]
eis
mkEtaWW :: Arity -> CoreExpr -> InScopeSet -> Type
-> (InScopeSet, [EtaInfo])
mkEtaWW :: Arity -> CoreExpr -> InScopeSet -> Type -> (InScopeSet, [EtaInfo])
mkEtaWW orig_n :: Arity
orig_n orig_expr :: CoreExpr
orig_expr in_scope :: InScopeSet
in_scope orig_ty :: Type
orig_ty
= Arity -> TCvSubst -> Type -> [EtaInfo] -> (InScopeSet, [EtaInfo])
go Arity
orig_n TCvSubst
empty_subst Type
orig_ty []
where
empty_subst :: TCvSubst
empty_subst = InScopeSet -> TCvSubst
mkEmptyTCvSubst InScopeSet
in_scope
go :: Arity
-> TCvSubst -> Type
-> [EtaInfo]
-> (InScopeSet, [EtaInfo])
go :: Arity -> TCvSubst -> Type -> [EtaInfo] -> (InScopeSet, [EtaInfo])
go n :: Arity
n subst :: TCvSubst
subst ty :: Type
ty eis :: [EtaInfo]
eis
| Arity
n Arity -> Arity -> Bool
forall a. Eq a => a -> a -> Bool
== 0
= (TCvSubst -> InScopeSet
getTCvInScope TCvSubst
subst, [EtaInfo] -> [EtaInfo]
forall a. [a] -> [a]
reverse [EtaInfo]
eis)
| Just (tcv :: CoreBndr
tcv,ty' :: Type
ty') <- Type -> Maybe (CoreBndr, Type)
splitForAllTy_maybe Type
ty
, let (subst' :: TCvSubst
subst', tcv' :: CoreBndr
tcv') = HasCallStack => TCvSubst -> CoreBndr -> (TCvSubst, CoreBndr)
TCvSubst -> CoreBndr -> (TCvSubst, CoreBndr)
Type.substVarBndr TCvSubst
subst CoreBndr
tcv
= let ((n_subst :: TCvSubst
n_subst, n_tcv :: CoreBndr
n_tcv), n_n :: Arity
n_n)
| CoreBndr -> Bool
isTyVar CoreBndr
tcv = ((TCvSubst
subst', CoreBndr
tcv'), Arity
n)
| Bool
otherwise = (Arity -> TCvSubst -> Type -> (TCvSubst, CoreBndr)
freshEtaId Arity
n TCvSubst
subst' (CoreBndr -> Type
varType CoreBndr
tcv'), Arity
nArity -> Arity -> Arity
forall a. Num a => a -> a -> a
-1)
in Arity -> TCvSubst -> Type -> [EtaInfo] -> (InScopeSet, [EtaInfo])
go Arity
n_n TCvSubst
n_subst Type
ty' (CoreBndr -> EtaInfo
EtaVar CoreBndr
n_tcv EtaInfo -> [EtaInfo] -> [EtaInfo]
forall a. a -> [a] -> [a]
: [EtaInfo]
eis)
| Just (arg_ty :: Type
arg_ty, res_ty :: Type
res_ty) <- Type -> Maybe (Type, Type)
splitFunTy_maybe Type
ty
, Bool -> Bool
not (Type -> Bool
isTypeLevPoly Type
arg_ty)
, let (subst' :: TCvSubst
subst', eta_id' :: CoreBndr
eta_id') = Arity -> TCvSubst -> Type -> (TCvSubst, CoreBndr)
freshEtaId Arity
n TCvSubst
subst Type
arg_ty
= Arity -> TCvSubst -> Type -> [EtaInfo] -> (InScopeSet, [EtaInfo])
go (Arity
nArity -> Arity -> Arity
forall a. Num a => a -> a -> a
-1) TCvSubst
subst' Type
res_ty (CoreBndr -> EtaInfo
EtaVar CoreBndr
eta_id' EtaInfo -> [EtaInfo] -> [EtaInfo]
forall a. a -> [a] -> [a]
: [EtaInfo]
eis)
| Just (co :: Coercion
co, ty' :: Type
ty') <- Type -> Maybe (Coercion, Type)
topNormaliseNewType_maybe Type
ty
, let co' :: Coercion
co' = HasCallStack => TCvSubst -> Coercion -> Coercion
TCvSubst -> Coercion -> Coercion
Coercion.substCo TCvSubst
subst Coercion
co
= Arity -> TCvSubst -> Type -> [EtaInfo] -> (InScopeSet, [EtaInfo])
go Arity
n TCvSubst
subst Type
ty' (Coercion -> [EtaInfo] -> [EtaInfo]
pushCoercion Coercion
co' [EtaInfo]
eis)
| Bool
otherwise
= WARN( True, (ppr orig_n <+> ppr orig_ty) $$ ppr orig_expr )
(TCvSubst -> InScopeSet
getTCvInScope TCvSubst
subst, [EtaInfo] -> [EtaInfo]
forall a. [a] -> [a]
reverse [EtaInfo]
eis)
subst_expr :: Subst -> CoreExpr -> CoreExpr
subst_expr :: Subst -> CoreExpr -> CoreExpr
subst_expr = SDoc -> Subst -> CoreExpr -> CoreExpr
substExpr (String -> SDoc
text "CoreArity:substExpr")
etaExpandToJoinPoint :: JoinArity -> CoreExpr -> ([CoreBndr], CoreExpr)
etaExpandToJoinPoint :: Arity -> CoreExpr -> ([CoreBndr], CoreExpr)
etaExpandToJoinPoint join_arity :: Arity
join_arity expr :: CoreExpr
expr
= Arity -> [CoreBndr] -> CoreExpr -> ([CoreBndr], CoreExpr)
go Arity
join_arity [] CoreExpr
expr
where
go :: Arity -> [CoreBndr] -> CoreExpr -> ([CoreBndr], CoreExpr)
go 0 rev_bs :: [CoreBndr]
rev_bs e :: CoreExpr
e = ([CoreBndr] -> [CoreBndr]
forall a. [a] -> [a]
reverse [CoreBndr]
rev_bs, CoreExpr
e)
go n :: Arity
n rev_bs :: [CoreBndr]
rev_bs (Lam b :: CoreBndr
b e :: CoreExpr
e) = Arity -> [CoreBndr] -> CoreExpr -> ([CoreBndr], CoreExpr)
go (Arity
nArity -> Arity -> Arity
forall a. Num a => a -> a -> a
-1) (CoreBndr
b CoreBndr -> [CoreBndr] -> [CoreBndr]
forall a. a -> [a] -> [a]
: [CoreBndr]
rev_bs) CoreExpr
e
go n :: Arity
n rev_bs :: [CoreBndr]
rev_bs e :: CoreExpr
e = case Arity -> CoreExpr -> ([CoreBndr], CoreExpr)
etaBodyForJoinPoint Arity
n CoreExpr
e of
(bs :: [CoreBndr]
bs, e' :: CoreExpr
e') -> ([CoreBndr] -> [CoreBndr]
forall a. [a] -> [a]
reverse [CoreBndr]
rev_bs [CoreBndr] -> [CoreBndr] -> [CoreBndr]
forall a. [a] -> [a] -> [a]
++ [CoreBndr]
bs, CoreExpr
e')
etaExpandToJoinPointRule :: JoinArity -> CoreRule -> CoreRule
etaExpandToJoinPointRule :: Arity -> CoreRule -> CoreRule
etaExpandToJoinPointRule _ rule :: CoreRule
rule@(BuiltinRule {})
= WARN(True, (sep [text "Can't eta-expand built-in rule:", ppr rule]))
CoreRule
rule
etaExpandToJoinPointRule join_arity :: Arity
join_arity rule :: CoreRule
rule@(Rule { ru_bndrs :: CoreRule -> [CoreBndr]
ru_bndrs = [CoreBndr]
bndrs, ru_rhs :: CoreRule -> CoreExpr
ru_rhs = CoreExpr
rhs
, ru_args :: CoreRule -> [CoreExpr]
ru_args = [CoreExpr]
args })
| Arity
need_args Arity -> Arity -> Bool
forall a. Eq a => a -> a -> Bool
== 0
= CoreRule
rule
| Arity
need_args Arity -> Arity -> Bool
forall a. Ord a => a -> a -> Bool
< 0
= String -> SDoc -> CoreRule
forall a. HasCallStack => String -> SDoc -> a
pprPanic "etaExpandToJoinPointRule" (Arity -> SDoc
forall a. Outputable a => a -> SDoc
ppr Arity
join_arity SDoc -> SDoc -> SDoc
$$ CoreRule -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreRule
rule)
| Bool
otherwise
= CoreRule
rule { ru_bndrs :: [CoreBndr]
ru_bndrs = [CoreBndr]
bndrs [CoreBndr] -> [CoreBndr] -> [CoreBndr]
forall a. [a] -> [a] -> [a]
++ [CoreBndr]
new_bndrs, ru_args :: [CoreExpr]
ru_args = [CoreExpr]
args [CoreExpr] -> [CoreExpr] -> [CoreExpr]
forall a. [a] -> [a] -> [a]
++ [CoreExpr]
forall b. [Expr b]
new_args
, ru_rhs :: CoreExpr
ru_rhs = CoreExpr
new_rhs }
where
need_args :: Arity
need_args = Arity
join_arity Arity -> Arity -> Arity
forall a. Num a => a -> a -> a
- [CoreExpr] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length [CoreExpr]
args
(new_bndrs :: [CoreBndr]
new_bndrs, new_rhs :: CoreExpr
new_rhs) = Arity -> CoreExpr -> ([CoreBndr], CoreExpr)
etaBodyForJoinPoint Arity
need_args CoreExpr
rhs
new_args :: [Expr b]
new_args = [CoreBndr] -> [Expr b]
forall b. [CoreBndr] -> [Expr b]
varsToCoreExprs [CoreBndr]
new_bndrs
etaBodyForJoinPoint :: Int -> CoreExpr -> ([CoreBndr], CoreExpr)
etaBodyForJoinPoint :: Arity -> CoreExpr -> ([CoreBndr], CoreExpr)
etaBodyForJoinPoint need_args :: Arity
need_args body :: CoreExpr
body
= Arity
-> Type
-> TCvSubst
-> [CoreBndr]
-> CoreExpr
-> ([CoreBndr], CoreExpr)
forall b.
Arity
-> Type -> TCvSubst -> [CoreBndr] -> Expr b -> ([CoreBndr], Expr b)
go Arity
need_args (CoreExpr -> Type
exprType CoreExpr
body) (CoreExpr -> TCvSubst
init_subst CoreExpr
body) [] CoreExpr
body
where
go :: Arity
-> Type -> TCvSubst -> [CoreBndr] -> Expr b -> ([CoreBndr], Expr b)
go 0 _ _ rev_bs :: [CoreBndr]
rev_bs e :: Expr b
e
= ([CoreBndr] -> [CoreBndr]
forall a. [a] -> [a]
reverse [CoreBndr]
rev_bs, Expr b
e)
go n :: Arity
n ty :: Type
ty subst :: TCvSubst
subst rev_bs :: [CoreBndr]
rev_bs e :: Expr b
e
| Just (tv :: CoreBndr
tv, res_ty :: Type
res_ty) <- Type -> Maybe (CoreBndr, Type)
splitForAllTy_maybe Type
ty
, let (subst' :: TCvSubst
subst', tv' :: CoreBndr
tv') = HasCallStack => TCvSubst -> CoreBndr -> (TCvSubst, CoreBndr)
TCvSubst -> CoreBndr -> (TCvSubst, CoreBndr)
Type.substVarBndr TCvSubst
subst CoreBndr
tv
= Arity
-> Type -> TCvSubst -> [CoreBndr] -> Expr b -> ([CoreBndr], Expr b)
go (Arity
nArity -> Arity -> Arity
forall a. Num a => a -> a -> a
-1) Type
res_ty TCvSubst
subst' (CoreBndr
tv' CoreBndr -> [CoreBndr] -> [CoreBndr]
forall a. a -> [a] -> [a]
: [CoreBndr]
rev_bs) (Expr b
e Expr b -> Expr b -> Expr b
forall b. Expr b -> Expr b -> Expr b
`App` CoreBndr -> Expr b
forall b. CoreBndr -> Expr b
varToCoreExpr CoreBndr
tv')
| Just (arg_ty :: Type
arg_ty, res_ty :: Type
res_ty) <- Type -> Maybe (Type, Type)
splitFunTy_maybe Type
ty
, let (subst' :: TCvSubst
subst', b :: CoreBndr
b) = Arity -> TCvSubst -> Type -> (TCvSubst, CoreBndr)
freshEtaId Arity
n TCvSubst
subst Type
arg_ty
= Arity
-> Type -> TCvSubst -> [CoreBndr] -> Expr b -> ([CoreBndr], Expr b)
go (Arity
nArity -> Arity -> Arity
forall a. Num a => a -> a -> a
-1) Type
res_ty TCvSubst
subst' (CoreBndr
b CoreBndr -> [CoreBndr] -> [CoreBndr]
forall a. a -> [a] -> [a]
: [CoreBndr]
rev_bs) (Expr b
e Expr b -> Expr b -> Expr b
forall b. Expr b -> Expr b -> Expr b
`App` CoreBndr -> Expr b
forall b. CoreBndr -> Expr b
Var CoreBndr
b)
| Bool
otherwise
= String -> SDoc -> ([CoreBndr], Expr b)
forall a. HasCallStack => String -> SDoc -> a
pprPanic "etaBodyForJoinPoint" (SDoc -> ([CoreBndr], Expr b)) -> SDoc -> ([CoreBndr], Expr b)
forall a b. (a -> b) -> a -> b
$ Arity -> SDoc
int Arity
need_args SDoc -> SDoc -> SDoc
$$
CoreExpr -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreExpr
body SDoc -> SDoc -> SDoc
$$ Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr (CoreExpr -> Type
exprType CoreExpr
body)
init_subst :: CoreExpr -> TCvSubst
init_subst e :: CoreExpr
e = InScopeSet -> TCvSubst
mkEmptyTCvSubst (VarSet -> InScopeSet
mkInScopeSet (CoreExpr -> VarSet
exprFreeVars CoreExpr
e))
freshEtaId :: Int -> TCvSubst -> Type -> (TCvSubst, Id)
freshEtaId :: Arity -> TCvSubst -> Type -> (TCvSubst, CoreBndr)
freshEtaId n :: Arity
n subst :: TCvSubst
subst ty :: Type
ty
= (TCvSubst
subst', CoreBndr
eta_id')
where
ty' :: Type
ty' = HasCallStack => TCvSubst -> Type -> Type
TCvSubst -> Type -> Type
Type.substTy TCvSubst
subst Type
ty
eta_id' :: CoreBndr
eta_id' = InScopeSet -> CoreBndr -> CoreBndr
uniqAway (TCvSubst -> InScopeSet
getTCvInScope TCvSubst
subst) (CoreBndr -> CoreBndr) -> CoreBndr -> CoreBndr
forall a b. (a -> b) -> a -> b
$
FastString -> Unique -> Type -> CoreBndr
mkSysLocalOrCoVar (String -> FastString
fsLit "eta") (Arity -> Unique
mkBuiltinUnique Arity
n) Type
ty'
subst' :: TCvSubst
subst' = TCvSubst -> CoreBndr -> TCvSubst
extendTCvInScope TCvSubst
subst CoreBndr
eta_id'