{-# LANGUAGE PartialTypeSignatures #-}
module H2JVM.Internal.IndexedMap (
IndexedMap,
Index,
indexValue,
empty,
singleton,
lookup,
lookupIndex,
lookupIndexWhere,
isEmpty,
insert,
lookupOrInsert,
lookupOrInsertM,
lookupOrInsertMOver,
toVector,
)
where
import Control.Lens (Lens', set, view)
import Control.Monad (forM_)
import Data.Vector (Vector)
import Data.Word (Word32)
import Effectful
import Effectful.State.Static.Local
import GHC.Exts (IsList (..))
import Prelude hiding (lookup)
import Data.IntMap qualified as IM
import Data.Map qualified as M
import Data.Vector qualified as V
newtype Index = Index Word32 deriving (Index -> Index -> Bool
(Index -> Index -> Bool) -> (Index -> Index -> Bool) -> Eq Index
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Index -> Index -> Bool
== :: Index -> Index -> Bool
$c/= :: Index -> Index -> Bool
/= :: Index -> Index -> Bool
Eq, Integer -> Index
Index -> Index
Index -> Index -> Index
(Index -> Index -> Index)
-> (Index -> Index -> Index)
-> (Index -> Index -> Index)
-> (Index -> Index)
-> (Index -> Index)
-> (Index -> Index)
-> (Integer -> Index)
-> Num Index
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
$c+ :: Index -> Index -> Index
+ :: Index -> Index -> Index
$c- :: Index -> Index -> Index
- :: Index -> Index -> Index
$c* :: Index -> Index -> Index
* :: Index -> Index -> Index
$cnegate :: Index -> Index
negate :: Index -> Index
$cabs :: Index -> Index
abs :: Index -> Index
$csignum :: Index -> Index
signum :: Index -> Index
$cfromInteger :: Integer -> Index
fromInteger :: Integer -> Index
Num, Eq Index
Eq Index =>
(Index -> Index -> Ordering)
-> (Index -> Index -> Bool)
-> (Index -> Index -> Bool)
-> (Index -> Index -> Bool)
-> (Index -> Index -> Bool)
-> (Index -> Index -> Index)
-> (Index -> Index -> Index)
-> Ord Index
Index -> Index -> Bool
Index -> Index -> Ordering
Index -> Index -> Index
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Index -> Index -> Ordering
compare :: Index -> Index -> Ordering
$c< :: Index -> Index -> Bool
< :: Index -> Index -> Bool
$c<= :: Index -> Index -> Bool
<= :: Index -> Index -> Bool
$c> :: Index -> Index -> Bool
> :: Index -> Index -> Bool
$c>= :: Index -> Index -> Bool
>= :: Index -> Index -> Bool
$cmax :: Index -> Index -> Index
max :: Index -> Index -> Index
$cmin :: Index -> Index -> Index
min :: Index -> Index -> Index
Ord, Int -> Index -> ShowS
[Index] -> ShowS
Index -> String
(Int -> Index -> ShowS)
-> (Index -> String) -> ([Index] -> ShowS) -> Show Index
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Index -> ShowS
showsPrec :: Int -> Index -> ShowS
$cshow :: Index -> String
show :: Index -> String
$cshowList :: [Index] -> ShowS
showList :: [Index] -> ShowS
Show)
indexValue :: Index -> Word32
indexValue :: Index -> Word32
indexValue (Index Word32
i) = Word32
i
data IndexedMap a = IndexedMap !(IM.IntMap a) !(M.Map a Int)
empty :: IndexedMap a
empty :: forall a. IndexedMap a
empty = IntMap a -> Map a Int -> IndexedMap a
forall a. IntMap a -> Map a Int -> IndexedMap a
IndexedMap IntMap a
forall a. IntMap a
IM.empty Map a Int
forall k a. Map k a
M.empty
singleton :: Ord a => a -> IndexedMap a
singleton :: forall a. Ord a => a -> IndexedMap a
singleton a
a = IntMap a -> Map a Int -> IndexedMap a
forall a. IntMap a -> Map a Int -> IndexedMap a
IndexedMap (Int -> a -> IntMap a
forall a. Int -> a -> IntMap a
IM.singleton Int
1 a
a) (a -> Int -> Map a Int
forall k a. k -> a -> Map k a
M.singleton a
a Int
1)
lookup :: Index -> IndexedMap a -> Maybe a
lookup :: forall a. Index -> IndexedMap a -> Maybe a
lookup (Index Word32
i) (IndexedMap IntMap a
m Map a Int
_) = Int -> IntMap a -> Maybe a
forall a. Int -> IntMap a -> Maybe a
IM.lookup (Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
i) IntMap a
m
lookupIndex :: Ord a => a -> IndexedMap a -> Maybe Index
lookupIndex :: forall a. Ord a => a -> IndexedMap a -> Maybe Index
lookupIndex a
a (IndexedMap IntMap a
_ Map a Int
m) = Word32 -> Index
Index (Word32 -> Index) -> (Int -> Word32) -> Int -> Index
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Index) -> Maybe Int -> Maybe Index
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> Map a Int -> Maybe Int
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup a
a Map a Int
m
lookupIndexWhere :: (a -> Bool) -> IndexedMap a -> Maybe Index
lookupIndexWhere :: forall a. (a -> Bool) -> IndexedMap a -> Maybe Index
lookupIndexWhere a -> Bool
f (IndexedMap IntMap a
m Map a Int
_) = Word32 -> Index
Index (Word32 -> Index) -> ((Int, a) -> Word32) -> (Int, a) -> Index
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word32) -> ((Int, a) -> Int) -> (Int, a) -> Word32
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int, a) -> Int
forall a b. (a, b) -> a
fst ((Int, a) -> Index) -> Maybe (Int, a) -> Maybe Index
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IntMap a -> Maybe (Int, a)
forall a. IntMap a -> Maybe (Int, a)
IM.lookupMin ((a -> Bool) -> IntMap a -> IntMap a
forall a. (a -> Bool) -> IntMap a -> IntMap a
IM.filter a -> Bool
f IntMap a
m)
insert :: Ord a => a -> IndexedMap a -> (Index, IndexedMap a)
insert :: forall a. Ord a => a -> IndexedMap a -> (Index, IndexedMap a)
insert a
a (IndexedMap IntMap a
m Map a Int
m') = (Word32 -> Index
Index (Word32 -> Index) -> Word32 -> Index
forall a b. (a -> b) -> a -> b
$ Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
i, IntMap a -> Map a Int -> IndexedMap a
forall a. IntMap a -> Map a Int -> IndexedMap a
IndexedMap (Int -> a -> IntMap a -> IntMap a
forall a. Int -> a -> IntMap a -> IntMap a
IM.insert Int
i a
a IntMap a
m) (a -> Int -> Map a Int -> Map a Int
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert a
a Int
i Map a Int
m'))
where
i :: Int
i = Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ IntMap a -> Int
forall a. IntMap a -> Int
IM.size IntMap a
m
lookupOrInsert :: Ord a => a -> IndexedMap a -> (Index, IndexedMap a)
lookupOrInsert :: forall a. Ord a => a -> IndexedMap a -> (Index, IndexedMap a)
lookupOrInsert a
a (IndexedMap IntMap a
m Map a Int
m') = case a -> Map a Int -> Maybe Int
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup a
a Map a Int
m' of
Just Int
i -> (Word32 -> Index
Index (Word32 -> Index) -> Word32 -> Index
forall a b. (a -> b) -> a -> b
$ Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
i, IntMap a -> Map a Int -> IndexedMap a
forall a. IntMap a -> Map a Int -> IndexedMap a
IndexedMap IntMap a
m Map a Int
m')
Maybe Int
Nothing -> a -> IndexedMap a -> (Index, IndexedMap a)
forall a. Ord a => a -> IndexedMap a -> (Index, IndexedMap a)
insert a
a (IntMap a -> Map a Int -> IndexedMap a
forall a. IntMap a -> Map a Int -> IndexedMap a
IndexedMap IntMap a
m Map a Int
m')
lookupOrInsertM :: (State (IndexedMap a) :> r, Ord a) => a -> Eff r Index
lookupOrInsertM :: forall a (r :: [Effect]).
(State (IndexedMap a) :> r, Ord a) =>
a -> Eff r Index
lookupOrInsertM = Lens' (IndexedMap a) (IndexedMap a) -> a -> Eff r Index
forall a (r :: [Effect]) b.
(State a :> r, Ord b) =>
Lens' a (IndexedMap b) -> b -> Eff r Index
lookupOrInsertMOver (IndexedMap a -> f (IndexedMap a))
-> IndexedMap a -> f (IndexedMap a)
forall a. a -> a
Lens' (IndexedMap a) (IndexedMap a)
id
lookupOrInsertMOver :: (State a :> r, Ord b) => Lens' a (IndexedMap b) -> b -> Eff r Index
lookupOrInsertMOver :: forall a (r :: [Effect]) b.
(State a :> r, Ord b) =>
Lens' a (IndexedMap b) -> b -> Eff r Index
lookupOrInsertMOver Lens' a (IndexedMap b)
lens b
a = do
i <- (a -> IndexedMap b) -> Eff r (IndexedMap b)
forall s (es :: [Effect]) a.
(HasCallStack, State s :> es) =>
(s -> a) -> Eff es a
gets (Getting (IndexedMap b) a (IndexedMap b) -> a -> IndexedMap b
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting (IndexedMap b) a (IndexedMap b)
Lens' a (IndexedMap b)
lens)
let (idx, new) = lookupOrInsert a i
modify (set lens new)
pure idx
isEmpty :: IndexedMap a -> Bool
isEmpty :: forall a. IndexedMap a -> Bool
isEmpty (IndexedMap IntMap a
m Map a Int
_) = IntMap a -> Bool
forall a. IntMap a -> Bool
IM.null IntMap a
m
toVector :: IndexedMap a -> Vector a
toVector :: forall a. IndexedMap a -> Vector a
toVector IndexedMap a
i | IndexedMap a -> Bool
forall a. IndexedMap a -> Bool
isEmpty IndexedMap a
i = Vector a
forall a. Vector a
V.empty
toVector (IndexedMap IntMap a
im Map a Int
_) = do
let (Int
maxIndex, a
_) = IntMap a -> (Int, a)
forall a. IntMap a -> (Int, a)
IM.findMax IntMap a
im
Int -> (Int -> a) -> Vector a
forall a. Int -> (Int -> a) -> Vector a
V.generate Int
maxIndex ((IntMap a
im IntMap a -> Int -> a
forall a. IntMap a -> Int -> a
IM.!) (Int -> a) -> (Int -> Int) -> Int -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+))
instance Show a => Show (IndexedMap a) where
show :: IndexedMap a -> String
show (IndexedMap IntMap a
im Map a Int
_) = IntMap a -> String
forall a. Show a => a -> String
show IntMap a
im
instance Eq a => Eq (IndexedMap a) where
(IndexedMap IntMap a
im Map a Int
_) == :: IndexedMap a -> IndexedMap a -> Bool
== (IndexedMap IntMap a
im' Map a Int
_) = IntMap a
im IntMap a -> IntMap a -> Bool
forall a. Eq a => a -> a -> Bool
== IntMap a
im'
instance Ord a => Ord (IndexedMap a) where
compare :: IndexedMap a -> IndexedMap a -> Ordering
compare (IndexedMap IntMap a
im Map a Int
_) (IndexedMap IntMap a
im' Map a Int
_) = IntMap a -> IntMap a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare IntMap a
im IntMap a
im'
instance Foldable IndexedMap where
foldMap :: forall m a. Monoid m => (a -> m) -> IndexedMap a -> m
foldMap a -> m
f (IndexedMap IntMap a
im Map a Int
_) = (a -> m) -> IntMap a -> m
forall m a. Monoid m => (a -> m) -> IntMap a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap a -> m
f IntMap a
im
instance Ord a => IsList (IndexedMap a) where
type Item (IndexedMap a) = a
fromList :: [Item (IndexedMap a)] -> IndexedMap a
fromList = (a -> IndexedMap a -> IndexedMap a)
-> IndexedMap a -> [a] -> IndexedMap a
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\a
a IndexedMap a
b -> (Index, IndexedMap a) -> IndexedMap a
forall a b. (a, b) -> b
snd ((Index, IndexedMap a) -> IndexedMap a)
-> (Index, IndexedMap a) -> IndexedMap a
forall a b. (a -> b) -> a -> b
$ a -> IndexedMap a -> (Index, IndexedMap a)
forall a. Ord a => a -> IndexedMap a -> (Index, IndexedMap a)
insert a
a IndexedMap a
b) IndexedMap a
forall a. IndexedMap a
empty
toList :: IndexedMap a -> [Item (IndexedMap a)]
toList = Vector a -> [a]
Vector a -> [Item (Vector a)]
forall l. IsList l => l -> [Item l]
toList (Vector a -> [a])
-> (IndexedMap a -> Vector a) -> IndexedMap a -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IndexedMap a -> Vector a
forall a. IndexedMap a -> Vector a
toVector
instance Ord a => Semigroup (IndexedMap a) where
IndexedMap a
l <> :: IndexedMap a -> IndexedMap a -> IndexedMap a
<> IndexedMap a
r =
Eff '[] (IndexedMap a) -> IndexedMap a
forall a. HasCallStack => Eff '[] a -> a
runPureEff (Eff '[] (IndexedMap a) -> IndexedMap a)
-> Eff '[] (IndexedMap a) -> IndexedMap a
forall a b. (a -> b) -> a -> b
$ IndexedMap a
-> Eff '[State (IndexedMap a)] () -> Eff '[] (IndexedMap a)
forall s (es :: [Effect]) a.
HasCallStack =>
s -> Eff (State s : es) a -> Eff es s
execState IndexedMap a
forall a. IndexedMap a
empty (Eff '[State (IndexedMap a)] () -> Eff '[] (IndexedMap a))
-> Eff '[State (IndexedMap a)] () -> Eff '[] (IndexedMap a)
forall a b. (a -> b) -> a -> b
$ do
Vector a
-> (a -> Eff '[State (IndexedMap a)] Index)
-> Eff '[State (IndexedMap a)] ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (IndexedMap a -> Vector a
forall a. IndexedMap a -> Vector a
toVector IndexedMap a
l) a -> Eff '[State (IndexedMap a)] Index
forall a (r :: [Effect]).
(State (IndexedMap a) :> r, Ord a) =>
a -> Eff r Index
lookupOrInsertM
Vector a
-> (a -> Eff '[State (IndexedMap a)] Index)
-> Eff '[State (IndexedMap a)] ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (IndexedMap a -> Vector a
forall a. IndexedMap a -> Vector a
toVector IndexedMap a
r) a -> Eff '[State (IndexedMap a)] Index
forall a (r :: [Effect]).
(State (IndexedMap a) :> r, Ord a) =>
a -> Eff r Index
lookupOrInsertM
instance Ord a => Monoid (IndexedMap a) where
mempty :: IndexedMap a
mempty = IndexedMap a
forall a. IndexedMap a
empty