{-# LANGUAGE CPP #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
module Clash.Unique
(
Unique
, Uniquable (..)
, UniqMap
, nullUniqMap
, lookupUniqMap
, lookupUniqMap'
, emptyUniqMap
, unitUniqMap
, extendUniqMap
, extendUniqMapWith
, extendListUniqMap
, delUniqMap
, delListUniqMap
, unionUniqMap
, unionUniqMapWith
, differenceUniqMap
, mapUniqMap
, mapMaybeUniqMap
, filterUniqMap
, elemUniqMap
, notElemUniqMap
, elemUniqMapDirectly
, foldrWithUnique
, foldlWithUnique'
, eltsUniqMap
, keysUniqMap
, listToUniqMap
, toListUniqMap
, uniqMapToUniqSet
, UniqSet
, lookupUniqSet
, emptyUniqSet
, unitUniqSet
, extendUniqSet
, unionUniqSet
, delUniqSetDirectly
, elemUniqSet
, notElemUniqSet
, elemUniqSetDirectly
, subsetUniqSet
, mkUniqSet
, eltsUniqSet
)
where
import Control.DeepSeq (NFData)
import Data.Binary (Binary)
import Data.IntMap (IntMap)
import qualified Data.IntMap as IntMap
import qualified Data.List as List
import Data.Text.Prettyprint.Doc
#if !MIN_VERSION_base(4,11,0)
import Data.Semigroup
#endif
import GHC.Stack
import Clash.Pretty
type Unique = Int
class Uniquable a where
getUnique :: a -> Unique
setUnique :: a -> Unique -> a
instance Uniquable Int where
getUnique i = i
setUnique _i0 i1 = i1
newtype UniqMap a = UniqMap (IntMap a)
deriving (Functor, Foldable, Traversable, Semigroup, Monoid, NFData, Binary)
instance ClashPretty a => ClashPretty (UniqMap a) where
clashPretty (UniqMap env) =
brackets $ fillSep $ punctuate comma $
[ fromPretty uq <+> ":->" <+> clashPretty elt
| (uq,elt) <- IntMap.toList env
]
instance ClashPretty a => Show (UniqMap a) where
show = showDoc . clashPretty
emptyUniqMap
:: UniqMap a
emptyUniqMap = UniqMap IntMap.empty
unitUniqMap
:: Uniquable a
=> a
-> b
-> UniqMap b
unitUniqMap k v = UniqMap (IntMap.singleton (getUnique k) v)
nullUniqMap
:: UniqMap a
-> Bool
nullUniqMap (UniqMap m) = IntMap.null m
extendUniqMap
:: Uniquable a
=> a
-> b
-> UniqMap b
-> UniqMap b
extendUniqMap k x (UniqMap m) = UniqMap (IntMap.insert (getUnique k) x m)
extendUniqMapWith
:: Uniquable a
=> a
-> b
-> (b -> b -> b)
-> UniqMap b
-> UniqMap b
extendUniqMapWith k x f (UniqMap m) =
UniqMap (IntMap.insertWith f (getUnique k) x m)
extendListUniqMap
:: Uniquable a
=> UniqMap b
-> [(a, b)]
-> UniqMap b
extendListUniqMap (UniqMap env) xs =
UniqMap (List.foldl' (\m (k, v) -> IntMap.insert (getUnique k) v m) env xs)
lookupUniqMap
:: Uniquable a
=> a
-> UniqMap b
-> Maybe b
lookupUniqMap k (UniqMap m) = IntMap.lookup (getUnique k) m
lookupUniqMap'
:: (HasCallStack, Uniquable a)
=> UniqMap b
-> a
-> b
lookupUniqMap' (UniqMap m) k =
IntMap.findWithDefault d k' m
where
k' = getUnique k
d = error ("lookupUniqMap': key " ++ show k' ++ " is not an element of the map")
elemUniqMap
:: Uniquable a
=> a
-> UniqMap b
-> Bool
elemUniqMap k = elemUniqMapDirectly (getUnique k)
elemUniqMapDirectly
:: Unique
-> UniqMap b
-> Bool
elemUniqMapDirectly k (UniqMap m) = k `IntMap.member` m
{-# INLINE elemUniqMapDirectly #-}
notElemUniqMap
:: Uniquable a
=> a
-> UniqMap b
-> Bool
notElemUniqMap k (UniqMap m) = IntMap.notMember (getUnique k) m
filterUniqMap
:: (b -> Bool)
-> UniqMap b
-> UniqMap b
filterUniqMap f (UniqMap m) = UniqMap (IntMap.filter f m)
delUniqMap
:: Uniquable a
=> UniqMap b
-> a
-> UniqMap b
delUniqMap (UniqMap env) v = UniqMap (IntMap.delete (getUnique v) env)
delListUniqMap
:: Uniquable a
=> UniqMap b
-> [a]
-> UniqMap b
delListUniqMap (UniqMap env) vs =
UniqMap (List.foldl' (\m v -> IntMap.delete (getUnique v) m) env vs)
unionUniqMap
:: UniqMap a
-> UniqMap a
-> UniqMap a
unionUniqMap (UniqMap m1) (UniqMap m2) = UniqMap (IntMap.union m1 m2)
unionUniqMapWith
:: (a -> a -> a)
-> UniqMap a
-> UniqMap a
-> UniqMap a
unionUniqMapWith f (UniqMap m1) (UniqMap m2) = UniqMap (IntMap.unionWith f m1 m2)
differenceUniqMap
:: UniqMap a
-> UniqMap a
-> UniqMap a
differenceUniqMap (UniqMap m1) (UniqMap m2) = UniqMap (IntMap.difference m1 m2)
listToUniqMap
:: Uniquable a
=> [(a,b)]
-> UniqMap b
listToUniqMap xs =
UniqMap (List.foldl' (\m (k, v) -> IntMap.insert (getUnique k) v m) IntMap.empty xs)
toListUniqMap
:: UniqMap a
-> [(Unique,a)]
toListUniqMap (UniqMap m) = IntMap.toList m
eltsUniqMap
:: UniqMap a
-> [a]
eltsUniqMap (UniqMap m) = IntMap.elems m
mapUniqMap
:: (a -> b)
-> UniqMap a
-> UniqMap b
mapUniqMap f (UniqMap m) = UniqMap (IntMap.map f m)
keysUniqMap
:: UniqMap a
-> [Unique]
keysUniqMap (UniqMap m) = IntMap.keys m
mapMaybeUniqMap
:: (a -> Maybe b)
-> UniqMap a
-> UniqMap b
mapMaybeUniqMap f (UniqMap m) = UniqMap (IntMap.mapMaybe f m)
foldrWithUnique
:: (Unique -> a -> b -> b)
-> b
-> UniqMap a
-> b
foldrWithUnique f s (UniqMap m) = IntMap.foldrWithKey f s m
foldlWithUnique'
:: (a -> Unique -> b -> a)
-> a
-> UniqMap b
-> a
foldlWithUnique' f s (UniqMap m) = IntMap.foldlWithKey' f s m
newtype UniqSet a = UniqSet (IntMap a)
deriving (Foldable, Semigroup, Monoid, Binary)
instance ClashPretty a => ClashPretty (UniqSet a) where
clashPretty (UniqSet env) =
braces (fillSep (map clashPretty (IntMap.elems env)))
emptyUniqSet
:: UniqSet a
emptyUniqSet = UniqSet IntMap.empty
unitUniqSet
:: Uniquable a
=> a
-> UniqSet a
unitUniqSet a = UniqSet (IntMap.singleton (getUnique a) a)
extendUniqSet
:: Uniquable a
=> UniqSet a
-> a
-> UniqSet a
extendUniqSet (UniqSet env) a = UniqSet (IntMap.insert (getUnique a) a env)
unionUniqSet
:: UniqSet a
-> UniqSet a
-> UniqSet a
unionUniqSet (UniqSet env1) (UniqSet env2) = UniqSet (IntMap.union env1 env2)
elemUniqSet
:: Uniquable a
=> a
-> UniqSet a
-> Bool
elemUniqSet a (UniqSet env) = IntMap.member (getUnique a) env
notElemUniqSet
:: Uniquable a
=> a
-> UniqSet a
-> Bool
notElemUniqSet a (UniqSet env) = IntMap.notMember (getUnique a) env
elemUniqSetDirectly
:: Unique
-> UniqSet a
-> Bool
elemUniqSetDirectly k (UniqSet m) = k `IntMap.member` m
lookupUniqSet
:: Uniquable a
=> a
-> UniqSet b
-> Maybe b
lookupUniqSet a (UniqSet env) = IntMap.lookup (getUnique a) env
delUniqSetDirectly
:: Unique
-> UniqSet b
-> UniqSet b
delUniqSetDirectly k (UniqSet env) = UniqSet (IntMap.delete k env)
eltsUniqSet
:: UniqSet a
-> [a]
eltsUniqSet (UniqSet env) = IntMap.elems env
mkUniqSet
:: Uniquable a
=> [a]
-> UniqSet a
mkUniqSet m = UniqSet (IntMap.fromList (map (\x -> (getUnique x,x)) m))
uniqMapToUniqSet
:: UniqMap a
-> UniqSet a
uniqMapToUniqSet (UniqMap m) = UniqSet m
subsetUniqSet
:: UniqSet a
-> UniqSet a
-> Bool
subsetUniqSet (UniqSet e1) (UniqSet e2) = IntMap.null (IntMap.difference e1 e2)