{-# LANGUAGE DeriveAnyClass    #-}
{-# LANGUAGE DeriveGeneric     #-}
{-# LANGUAGE OverloadedStrings #-}

module Kempe.Asm.Type ( ControlAnn (..)
                      , Liveness (..)
                      ) where

import           Control.DeepSeq (NFData)
import qualified Data.IntSet     as IS
import           Data.Semigroup  ((<>))
import           GHC.Generics    (Generic)
import           Prettyprinter   (Pretty (pretty), braces, punctuate, (<+>))

data Liveness = Liveness { Liveness -> IntSet
ins :: !IS.IntSet, Liveness -> IntSet
out :: !IS.IntSet } -- strictness annotations make it perform better
    deriving (Liveness -> Liveness -> Bool
(Liveness -> Liveness -> Bool)
-> (Liveness -> Liveness -> Bool) -> Eq Liveness
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Liveness -> Liveness -> Bool
$c/= :: Liveness -> Liveness -> Bool
== :: Liveness -> Liveness -> Bool
$c== :: Liveness -> Liveness -> Bool
Eq, (forall x. Liveness -> Rep Liveness x)
-> (forall x. Rep Liveness x -> Liveness) -> Generic Liveness
forall x. Rep Liveness x -> Liveness
forall x. Liveness -> Rep Liveness x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Liveness x -> Liveness
$cfrom :: forall x. Liveness -> Rep Liveness x
Generic, Liveness -> ()
(Liveness -> ()) -> NFData Liveness
forall a. (a -> ()) -> NFData a
rnf :: Liveness -> ()
$crnf :: Liveness -> ()
NFData)

instance Pretty Liveness where
    pretty :: Liveness -> Doc ann
pretty (Liveness IntSet
is IntSet
os) = Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann
braces (IntSet -> Doc ann
forall ann. IntSet -> Doc ann
pp IntSet
is Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann
";" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> IntSet -> Doc ann
forall ann. IntSet -> Doc ann
pp IntSet
os)
        where pp :: IntSet -> Doc ann
pp = [Doc ann] -> Doc ann
forall a. Monoid a => [a] -> a
mconcat ([Doc ann] -> Doc ann)
-> (IntSet -> [Doc ann]) -> IntSet -> Doc ann
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc ann -> [Doc ann] -> [Doc ann]
forall ann. Doc ann -> [Doc ann] -> [Doc ann]
punctuate Doc ann
"," ([Doc ann] -> [Doc ann])
-> (IntSet -> [Doc ann]) -> IntSet -> [Doc ann]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Key -> Doc ann) -> [Key] -> [Doc ann]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Key -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty ([Key] -> [Doc ann]) -> (IntSet -> [Key]) -> IntSet -> [Doc ann]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IntSet -> [Key]
IS.toList

-- | Control-flow annotations
data ControlAnn = ControlAnn { ControlAnn -> Key
node     :: !Int
                             , ControlAnn -> [Key]
conn     :: [Int]
                             , ControlAnn -> IntSet
usesNode :: IS.IntSet
                             , ControlAnn -> IntSet
defsNode :: IS.IntSet
                             } deriving ((forall x. ControlAnn -> Rep ControlAnn x)
-> (forall x. Rep ControlAnn x -> ControlAnn) -> Generic ControlAnn
forall x. Rep ControlAnn x -> ControlAnn
forall x. ControlAnn -> Rep ControlAnn x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep ControlAnn x -> ControlAnn
$cfrom :: forall x. ControlAnn -> Rep ControlAnn x
Generic, ControlAnn -> ()
(ControlAnn -> ()) -> NFData ControlAnn
forall a. (a -> ()) -> NFData a
rnf :: ControlAnn -> ()
$crnf :: ControlAnn -> ()
NFData)