{-# LANGUAGE GeneralisedNewtypeDeriving #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE PatternSynonyms #-}
module GHC.Types.Cpr (
Cpr (ConCpr), topCpr, botCpr, flatConCpr, asConCpr,
CprType (..), topCprType, botCprType, flatConCprType,
lubCprType, applyCprTy, abstractCprTy, trimCprTy,
UnpackConFieldsResult (..), unpackConFieldsCpr,
CprSig (..), topCprSig, isTopCprSig, mkCprSigForArity, mkCprSig,
seqCprSig, prependArgsCprSig
) where
import GHC.Prelude
import GHC.Core.DataCon
import GHC.Types.Basic
import GHC.Utils.Binary
import GHC.Utils.Misc
import GHC.Utils.Outputable
import GHC.Utils.Panic
data Cpr
= BotCpr
| ConCpr_ !ConTag ![Cpr]
| FlatConCpr !ConTag
| TopCpr
deriving Cpr -> Cpr -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Cpr -> Cpr -> Bool
$c/= :: Cpr -> Cpr -> Bool
== :: Cpr -> Cpr -> Bool
$c== :: Cpr -> Cpr -> Bool
Eq
pattern ConCpr :: ConTag -> [Cpr] -> Cpr
pattern $bConCpr :: Arity -> [Cpr] -> Cpr
$mConCpr :: forall {r}. Cpr -> (Arity -> [Cpr] -> r) -> ((# #) -> r) -> r
ConCpr t cs <- ConCpr_ t cs where
ConCpr Arity
t [Cpr]
cs
| forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (forall a. Eq a => a -> a -> Bool
== Cpr
TopCpr) [Cpr]
cs = Arity -> Cpr
FlatConCpr Arity
t
| Bool
otherwise = Arity -> [Cpr] -> Cpr
ConCpr_ Arity
t [Cpr]
cs
{-# COMPLETE BotCpr, TopCpr, FlatConCpr, ConCpr #-}
viewConTag :: Cpr -> Maybe ConTag
viewConTag :: Cpr -> Maybe Arity
viewConTag (FlatConCpr Arity
t) = forall a. a -> Maybe a
Just Arity
t
viewConTag (ConCpr Arity
t [Cpr]
_) = forall a. a -> Maybe a
Just Arity
t
viewConTag Cpr
_ = forall a. Maybe a
Nothing
{-# INLINE viewConTag #-}
lubCpr :: Cpr -> Cpr -> Cpr
lubCpr :: Cpr -> Cpr -> Cpr
lubCpr Cpr
BotCpr Cpr
cpr = Cpr
cpr
lubCpr Cpr
cpr Cpr
BotCpr = Cpr
cpr
lubCpr (FlatConCpr Arity
t1) (Cpr -> Maybe Arity
viewConTag -> Just Arity
t2)
| Arity
t1 forall a. Eq a => a -> a -> Bool
== Arity
t2 = Arity -> Cpr
FlatConCpr Arity
t1
lubCpr (Cpr -> Maybe Arity
viewConTag -> Just Arity
t1) (FlatConCpr Arity
t2)
| Arity
t1 forall a. Eq a => a -> a -> Bool
== Arity
t2 = Arity -> Cpr
FlatConCpr Arity
t2
lubCpr (ConCpr Arity
t1 [Cpr]
cs1) (ConCpr Arity
t2 [Cpr]
cs2)
| Arity
t1 forall a. Eq a => a -> a -> Bool
== Arity
t2 = Arity -> [Cpr] -> Cpr
ConCpr Arity
t1 ([Cpr] -> [Cpr] -> [Cpr]
lubFieldCprs [Cpr]
cs1 [Cpr]
cs2)
lubCpr Cpr
_ Cpr
_ = Cpr
TopCpr
lubFieldCprs :: [Cpr] -> [Cpr] -> [Cpr]
lubFieldCprs :: [Cpr] -> [Cpr] -> [Cpr]
lubFieldCprs [Cpr]
as [Cpr]
bs
| [Cpr]
as forall a b. [a] -> [b] -> Bool
`equalLength` [Cpr]
bs = forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Cpr -> Cpr -> Cpr
lubCpr [Cpr]
as [Cpr]
bs
| Bool
otherwise = []
topCpr :: Cpr
topCpr :: Cpr
topCpr = Cpr
TopCpr
botCpr :: Cpr
botCpr :: Cpr
botCpr = Cpr
BotCpr
flatConCpr :: ConTag -> Cpr
flatConCpr :: Arity -> Cpr
flatConCpr Arity
t = Arity -> Cpr
FlatConCpr Arity
t
trimCpr :: Cpr -> Cpr
trimCpr :: Cpr -> Cpr
trimCpr Cpr
BotCpr = Cpr
botCpr
trimCpr Cpr
_ = Cpr
topCpr
asConCpr :: Cpr -> Maybe (ConTag, [Cpr])
asConCpr :: Cpr -> Maybe (Arity, [Cpr])
asConCpr (ConCpr Arity
t [Cpr]
cs) = forall a. a -> Maybe a
Just (Arity
t, [Cpr]
cs)
asConCpr (FlatConCpr Arity
t) = forall a. a -> Maybe a
Just (Arity
t, [])
asConCpr Cpr
TopCpr = forall a. Maybe a
Nothing
asConCpr Cpr
BotCpr = forall a. Maybe a
Nothing
seqCpr :: Cpr -> ()
seqCpr :: Cpr -> ()
seqCpr (ConCpr Arity
_ [Cpr]
cs) = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (seq :: forall a b. a -> b -> b
seq forall b c a. (b -> c) -> (a -> b) -> a -> c
. Cpr -> ()
seqCpr) () [Cpr]
cs
seqCpr Cpr
_ = ()
data CprType
= CprType
{ CprType -> Arity
ct_arty :: !Arity
, CprType -> Cpr
ct_cpr :: !Cpr
}
instance Eq CprType where
CprType
a == :: CprType -> CprType -> Bool
== CprType
b = CprType -> Cpr
ct_cpr CprType
a forall a. Eq a => a -> a -> Bool
== CprType -> Cpr
ct_cpr CprType
b
Bool -> Bool -> Bool
&& (CprType -> Arity
ct_arty CprType
a forall a. Eq a => a -> a -> Bool
== CprType -> Arity
ct_arty CprType
b Bool -> Bool -> Bool
|| CprType -> Cpr
ct_cpr CprType
a forall a. Eq a => a -> a -> Bool
== Cpr
topCpr)
topCprType :: CprType
topCprType :: CprType
topCprType = Arity -> Cpr -> CprType
CprType Arity
0 Cpr
topCpr
botCprType :: CprType
botCprType :: CprType
botCprType = Arity -> Cpr -> CprType
CprType Arity
0 Cpr
botCpr
flatConCprType :: ConTag -> CprType
flatConCprType :: Arity -> CprType
flatConCprType Arity
con_tag = CprType { ct_arty :: Arity
ct_arty = Arity
0, ct_cpr :: Cpr
ct_cpr = Arity -> Cpr
flatConCpr Arity
con_tag }
lubCprType :: CprType -> CprType -> CprType
lubCprType :: CprType -> CprType -> CprType
lubCprType ty1 :: CprType
ty1@(CprType Arity
n1 Cpr
cpr1) ty2 :: CprType
ty2@(CprType Arity
n2 Cpr
cpr2)
| Cpr
cpr1 forall a. Eq a => a -> a -> Bool
== Cpr
botCpr Bool -> Bool -> Bool
&& Arity
n1 forall a. Ord a => a -> a -> Bool
<= Arity
n2 = CprType
ty2
| Cpr
cpr2 forall a. Eq a => a -> a -> Bool
== Cpr
botCpr Bool -> Bool -> Bool
&& Arity
n2 forall a. Ord a => a -> a -> Bool
<= Arity
n1 = CprType
ty1
| Arity
n1 forall a. Eq a => a -> a -> Bool
== Arity
n2 = Arity -> Cpr -> CprType
CprType Arity
n1 (Cpr -> Cpr -> Cpr
lubCpr Cpr
cpr1 Cpr
cpr2)
| Bool
otherwise = CprType
topCprType
applyCprTy :: CprType -> Arity -> CprType
applyCprTy :: CprType -> Arity -> CprType
applyCprTy (CprType Arity
n Cpr
res) Arity
k
| Arity
n forall a. Ord a => a -> a -> Bool
>= Arity
k = Arity -> Cpr -> CprType
CprType (Arity
nforall a. Num a => a -> a -> a
-Arity
k) Cpr
res
| Cpr
res forall a. Eq a => a -> a -> Bool
== Cpr
botCpr = CprType
botCprType
| Bool
otherwise = CprType
topCprType
abstractCprTy :: CprType -> CprType
abstractCprTy :: CprType -> CprType
abstractCprTy (CprType Arity
n Cpr
res)
| Cpr
res forall a. Eq a => a -> a -> Bool
== Cpr
topCpr = CprType
topCprType
| Bool
otherwise = Arity -> Cpr -> CprType
CprType (Arity
nforall a. Num a => a -> a -> a
+Arity
1) Cpr
res
trimCprTy :: CprType -> CprType
trimCprTy :: CprType -> CprType
trimCprTy (CprType Arity
arty Cpr
res) = Arity -> Cpr -> CprType
CprType Arity
arty (Cpr -> Cpr
trimCpr Cpr
res)
data UnpackConFieldsResult
= AllFieldsSame !Cpr
| ForeachField ![Cpr]
unpackConFieldsCpr :: DataCon -> Cpr -> UnpackConFieldsResult
unpackConFieldsCpr :: DataCon -> Cpr -> UnpackConFieldsResult
unpackConFieldsCpr DataCon
dc (ConCpr Arity
t [Cpr]
cs)
| Arity
t forall a. Eq a => a -> a -> Bool
== DataCon -> Arity
dataConTag DataCon
dc, [Cpr]
cs forall a. [a] -> Arity -> Bool
`lengthIs` DataCon -> Arity
dataConRepArity DataCon
dc
= [Cpr] -> UnpackConFieldsResult
ForeachField [Cpr]
cs
unpackConFieldsCpr DataCon
_ Cpr
BotCpr = Cpr -> UnpackConFieldsResult
AllFieldsSame Cpr
BotCpr
unpackConFieldsCpr DataCon
_ Cpr
_ = Cpr -> UnpackConFieldsResult
AllFieldsSame Cpr
TopCpr
{-# INLINE unpackConFieldsCpr #-}
seqCprTy :: CprType -> ()
seqCprTy :: CprType -> ()
seqCprTy (CprType Arity
_ Cpr
cpr) = Cpr -> ()
seqCpr Cpr
cpr
newtype CprSig = CprSig { CprSig -> CprType
getCprSig :: CprType }
deriving (CprSig -> CprSig -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CprSig -> CprSig -> Bool
$c/= :: CprSig -> CprSig -> Bool
== :: CprSig -> CprSig -> Bool
$c== :: CprSig -> CprSig -> Bool
Eq, BinHandle -> IO CprSig
BinHandle -> CprSig -> IO ()
BinHandle -> CprSig -> IO (Bin CprSig)
forall a.
(BinHandle -> a -> IO ())
-> (BinHandle -> a -> IO (Bin a))
-> (BinHandle -> IO a)
-> Binary a
get :: BinHandle -> IO CprSig
$cget :: BinHandle -> IO CprSig
put :: BinHandle -> CprSig -> IO (Bin CprSig)
$cput :: BinHandle -> CprSig -> IO (Bin CprSig)
put_ :: BinHandle -> CprSig -> IO ()
$cput_ :: BinHandle -> CprSig -> IO ()
Binary)
mkCprSigForArity :: Arity -> CprType -> CprSig
mkCprSigForArity :: Arity -> CprType -> CprSig
mkCprSigForArity Arity
arty ty :: CprType
ty@(CprType Arity
n Cpr
_)
| Arity
arty forall a. Eq a => a -> a -> Bool
/= Arity
n = CprSig
topCprSig
| Bool
otherwise = CprType -> CprSig
CprSig CprType
ty
topCprSig :: CprSig
topCprSig :: CprSig
topCprSig = CprType -> CprSig
CprSig CprType
topCprType
isTopCprSig :: CprSig -> Bool
isTopCprSig :: CprSig -> Bool
isTopCprSig (CprSig CprType
ty) = CprType -> Cpr
ct_cpr CprType
ty forall a. Eq a => a -> a -> Bool
== Cpr
topCpr
mkCprSig :: Arity -> Cpr -> CprSig
mkCprSig :: Arity -> Cpr -> CprSig
mkCprSig Arity
arty Cpr
cpr = CprType -> CprSig
CprSig (Arity -> Cpr -> CprType
CprType Arity
arty Cpr
cpr)
seqCprSig :: CprSig -> ()
seqCprSig :: CprSig -> ()
seqCprSig (CprSig CprType
ty) = CprType -> ()
seqCprTy CprType
ty
prependArgsCprSig :: Arity -> CprSig -> CprSig
prependArgsCprSig :: Arity -> CprSig -> CprSig
prependArgsCprSig Arity
n_extra cpr_sig :: CprSig
cpr_sig@(CprSig (CprType Arity
arity Cpr
cpr))
| Arity
n_extra forall a. Eq a => a -> a -> Bool
== Arity
0 = CprSig
cpr_sig
| Bool
otherwise = forall a. HasCallStack => Bool -> SDoc -> a -> a
assertPpr (Arity
n_extra forall a. Ord a => a -> a -> Bool
> Arity
0) (forall a. Outputable a => a -> SDoc
ppr Arity
n_extra) forall a b. (a -> b) -> a -> b
$
CprType -> CprSig
CprSig (Arity -> Cpr -> CprType
CprType (Arity
arity forall a. Num a => a -> a -> a
+ Arity
n_extra) Cpr
cpr)
instance Outputable Cpr where
ppr :: Cpr -> SDoc
ppr Cpr
TopCpr = forall doc. IsOutput doc => doc
empty
ppr (FlatConCpr Arity
n) = forall doc. IsLine doc => Arity -> doc
int Arity
n
ppr (ConCpr Arity
n [Cpr]
cs) = forall doc. IsLine doc => Arity -> doc
int Arity
n forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc -> doc
parens (forall a. (a -> SDoc) -> [a] -> SDoc
pprWithCommas forall a. Outputable a => a -> SDoc
ppr [Cpr]
cs)
ppr Cpr
BotCpr = forall doc. IsLine doc => Char -> doc
char Char
'b'
instance Outputable CprType where
ppr :: CprType -> SDoc
ppr (CprType Arity
arty Cpr
res)
| Arity
0 <- Arity
arty = forall a. Outputable a => a -> SDoc
ppr Cpr
res
| Bool
otherwise = forall doc. IsLine doc => Char -> doc
char Char
'\\' forall doc. IsLine doc => doc -> doc -> doc
<> forall a. Outputable a => a -> SDoc
ppr Arity
arty forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Char -> doc
char Char
'.' forall doc. IsLine doc => doc -> doc -> doc
<> forall a. Outputable a => a -> SDoc
ppr Cpr
res
instance Outputable CprSig where
ppr :: CprSig -> SDoc
ppr (CprSig CprType
ty) = forall a. Outputable a => a -> SDoc
ppr (CprType -> Cpr
ct_cpr CprType
ty)
instance Binary Cpr where
put_ :: BinHandle -> Cpr -> IO ()
put_ BinHandle
bh Cpr
TopCpr = BinHandle -> Word8 -> IO ()
putByte BinHandle
bh Word8
0
put_ BinHandle
bh Cpr
BotCpr = BinHandle -> Word8 -> IO ()
putByte BinHandle
bh Word8
1
put_ BinHandle
bh (FlatConCpr Arity
n) = BinHandle -> Word8 -> IO ()
putByte BinHandle
bh Word8
2 forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall a. Binary a => BinHandle -> a -> IO ()
put_ BinHandle
bh Arity
n
put_ BinHandle
bh (ConCpr Arity
n [Cpr]
cs) = BinHandle -> Word8 -> IO ()
putByte BinHandle
bh Word8
3 forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall a. Binary a => BinHandle -> a -> IO ()
put_ BinHandle
bh Arity
n forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall a. Binary a => BinHandle -> a -> IO ()
put_ BinHandle
bh [Cpr]
cs
get :: BinHandle -> IO Cpr
get BinHandle
bh = do
Word8
h <- BinHandle -> IO Word8
getByte BinHandle
bh
case Word8
h of
Word8
0 -> forall (m :: * -> *) a. Monad m => a -> m a
return Cpr
TopCpr
Word8
1 -> forall (m :: * -> *) a. Monad m => a -> m a
return Cpr
BotCpr
Word8
2 -> Arity -> Cpr
FlatConCpr forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Binary a => BinHandle -> IO a
get BinHandle
bh
Word8
3 -> Arity -> [Cpr] -> Cpr
ConCpr forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Binary a => BinHandle -> IO a
get BinHandle
bh forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. Binary a => BinHandle -> IO a
get BinHandle
bh
Word8
_ -> forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"Binary Cpr: Invalid tag" (forall doc. IsLine doc => Arity -> doc
int (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
h))
instance Binary CprType where
put_ :: BinHandle -> CprType -> IO ()
put_ BinHandle
bh (CprType Arity
arty Cpr
cpr) = forall a. Binary a => BinHandle -> a -> IO ()
put_ BinHandle
bh Arity
arty forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall a. Binary a => BinHandle -> a -> IO ()
put_ BinHandle
bh Cpr
cpr
get :: BinHandle -> IO CprType
get BinHandle
bh = Arity -> Cpr -> CprType
CprType forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Binary a => BinHandle -> IO a
get BinHandle
bh forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. Binary a => BinHandle -> IO a
get BinHandle
bh