module Erebos.Storage.Merge (
    Mergeable(..),
    merge, storeMerge,

    Generation,
    showGeneration,
    compareGeneration, generationMax,
    storedGeneration,

    generations,
    ancestors,
    precedes,
    filterAncestors,
    storedRoots,
    walkAncestors,

    findProperty,
    findPropertyFirst,
) where

import Control.Concurrent.MVar

import Data.ByteString.Char8 qualified as BC
import Data.HashTable.IO qualified as HT
import Data.Kind
import Data.List
import Data.Maybe
import Data.Set (Set)
import Data.Set qualified as S

import System.IO.Unsafe (unsafePerformIO)

import Erebos.Storage
import Erebos.Storage.Internal
import Erebos.Util

class Storable (Component a) => Mergeable a where
    type Component a :: Type
    mergeSorted :: [Stored (Component a)] -> a
    toComponents :: a -> [Stored (Component a)]

instance Mergeable [Stored Object] where
    type Component [Stored Object] = Object
    mergeSorted :: [Stored (Component [Stored Object])] -> [Stored Object]
mergeSorted = [Stored Object] -> [Stored Object]
[Stored (Component [Stored Object])] -> [Stored Object]
forall a. a -> a
id
    toComponents :: [Stored Object] -> [Stored (Component [Stored Object])]
toComponents = [Stored Object] -> [Stored Object]
[Stored Object] -> [Stored (Component [Stored Object])]
forall a. a -> a
id

merge :: Mergeable a => [Stored (Component a)] -> a
merge :: forall a. Mergeable a => [Stored (Component a)] -> a
merge [] = [Char] -> a
forall a. HasCallStack => [Char] -> a
error [Char]
"merge: empty list"
merge [Stored (Component a)]
xs = [Stored (Component a)] -> a
forall a. Mergeable a => [Stored (Component a)] -> a
mergeSorted ([Stored (Component a)] -> a) -> [Stored (Component a)] -> a
forall a b. (a -> b) -> a -> b
$ [Stored (Component a)] -> [Stored (Component a)]
forall a. Storable a => [Stored a] -> [Stored a]
filterAncestors [Stored (Component a)]
xs

storeMerge :: (Mergeable a, Storable a) => [Stored (Component a)] -> IO (Stored a)
storeMerge :: forall a.
(Mergeable a, Storable a) =>
[Stored (Component a)] -> IO (Stored a)
storeMerge [] = [Char] -> IO (Stored a)
forall a. HasCallStack => [Char] -> a
error [Char]
"merge: empty list"
storeMerge xs :: [Stored (Component a)]
xs@(Stored Ref' Complete
ref Component a
_ : [Stored (Component a)]
_) = Storage -> a -> IO (Stored a)
forall (m :: * -> *) a.
(MonadIO m, Storable a) =>
Storage -> a -> m (Stored a)
wrappedStore (Ref' Complete -> Storage
forall (c :: * -> *). Ref' c -> Storage' c
refStorage Ref' Complete
ref) (a -> IO (Stored a)) -> a -> IO (Stored a)
forall a b. (a -> b) -> a -> b
$ [Stored (Component a)] -> a
forall a. Mergeable a => [Stored (Component a)] -> a
mergeSorted ([Stored (Component a)] -> a) -> [Stored (Component a)] -> a
forall a b. (a -> b) -> a -> b
$ [Stored (Component a)] -> [Stored (Component a)]
forall a. Storable a => [Stored a] -> [Stored a]
filterAncestors [Stored (Component a)]
xs

previous :: Storable a => Stored a -> [Stored a]
previous :: forall a. Storable a => Stored a -> [Stored a]
previous (Stored Ref' Complete
ref a
_) = case Ref' Complete -> Object
forall a. Storable a => Ref' Complete -> a
load Ref' Complete
ref of
    Rec [(ByteString, RecItem' Complete)]
items | Just (RecRef Ref' Complete
dref) <- ByteString
-> [(ByteString, RecItem' Complete)] -> Maybe (RecItem' Complete)
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup ([Char] -> ByteString
BC.pack [Char]
"SDATA") [(ByteString, RecItem' Complete)]
items
              , Rec [(ByteString, RecItem' Complete)]
ditems <- Ref' Complete -> Object
forall a. Storable a => Ref' Complete -> a
load Ref' Complete
dref ->
                    (Ref' Complete -> Stored' Complete a)
-> [Ref' Complete] -> [Stored' Complete a]
forall a b. (a -> b) -> [a] -> [b]
map Ref' Complete -> Stored' Complete a
forall a. Storable a => Ref' Complete -> Stored a
wrappedLoad ([Ref' Complete] -> [Stored' Complete a])
-> [Ref' Complete] -> [Stored' Complete a]
forall a b. (a -> b) -> a -> b
$ [Maybe (Ref' Complete)] -> [Ref' Complete]
forall a. [Maybe a] -> [a]
catMaybes ([Maybe (Ref' Complete)] -> [Ref' Complete])
-> [Maybe (Ref' Complete)] -> [Ref' Complete]
forall a b. (a -> b) -> a -> b
$ (RecItem' Complete -> Maybe (Ref' Complete))
-> [RecItem' Complete] -> [Maybe (Ref' Complete)]
forall a b. (a -> b) -> [a] -> [b]
map (\case RecRef Ref' Complete
r -> Ref' Complete -> Maybe (Ref' Complete)
forall a. a -> Maybe a
Just Ref' Complete
r; RecItem' Complete
_ -> Maybe (Ref' Complete)
forall a. Maybe a
Nothing) ([RecItem' Complete] -> [Maybe (Ref' Complete)])
-> [RecItem' Complete] -> [Maybe (Ref' Complete)]
forall a b. (a -> b) -> a -> b
$
                        ((ByteString, RecItem' Complete) -> RecItem' Complete)
-> [(ByteString, RecItem' Complete)] -> [RecItem' Complete]
forall a b. (a -> b) -> [a] -> [b]
map (ByteString, RecItem' Complete) -> RecItem' Complete
forall a b. (a, b) -> b
snd ([(ByteString, RecItem' Complete)] -> [RecItem' Complete])
-> [(ByteString, RecItem' Complete)] -> [RecItem' Complete]
forall a b. (a -> b) -> a -> b
$ ((ByteString, RecItem' Complete) -> Bool)
-> [(ByteString, RecItem' Complete)]
-> [(ByteString, RecItem' Complete)]
forall a. (a -> Bool) -> [a] -> [a]
filter ((ByteString -> [ByteString] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ [Char] -> ByteString
BC.pack [Char]
"SPREV", [Char] -> ByteString
BC.pack [Char]
"SBASE" ]) (ByteString -> Bool)
-> ((ByteString, RecItem' Complete) -> ByteString)
-> (ByteString, RecItem' Complete)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString, RecItem' Complete) -> ByteString
forall a b. (a, b) -> a
fst) [(ByteString, RecItem' Complete)]
ditems

              | Bool
otherwise ->
                    (Ref' Complete -> Stored' Complete a)
-> [Ref' Complete] -> [Stored' Complete a]
forall a b. (a -> b) -> [a] -> [b]
map Ref' Complete -> Stored' Complete a
forall a. Storable a => Ref' Complete -> Stored a
wrappedLoad ([Ref' Complete] -> [Stored' Complete a])
-> [Ref' Complete] -> [Stored' Complete a]
forall a b. (a -> b) -> a -> b
$ [Maybe (Ref' Complete)] -> [Ref' Complete]
forall a. [Maybe a] -> [a]
catMaybes ([Maybe (Ref' Complete)] -> [Ref' Complete])
-> [Maybe (Ref' Complete)] -> [Ref' Complete]
forall a b. (a -> b) -> a -> b
$ (RecItem' Complete -> Maybe (Ref' Complete))
-> [RecItem' Complete] -> [Maybe (Ref' Complete)]
forall a b. (a -> b) -> [a] -> [b]
map (\case RecRef Ref' Complete
r -> Ref' Complete -> Maybe (Ref' Complete)
forall a. a -> Maybe a
Just Ref' Complete
r; RecItem' Complete
_ -> Maybe (Ref' Complete)
forall a. Maybe a
Nothing) ([RecItem' Complete] -> [Maybe (Ref' Complete)])
-> [RecItem' Complete] -> [Maybe (Ref' Complete)]
forall a b. (a -> b) -> a -> b
$
                        ((ByteString, RecItem' Complete) -> RecItem' Complete)
-> [(ByteString, RecItem' Complete)] -> [RecItem' Complete]
forall a b. (a -> b) -> [a] -> [b]
map (ByteString, RecItem' Complete) -> RecItem' Complete
forall a b. (a, b) -> b
snd ([(ByteString, RecItem' Complete)] -> [RecItem' Complete])
-> [(ByteString, RecItem' Complete)] -> [RecItem' Complete]
forall a b. (a -> b) -> a -> b
$ ((ByteString, RecItem' Complete) -> Bool)
-> [(ByteString, RecItem' Complete)]
-> [(ByteString, RecItem' Complete)]
forall a. (a -> Bool) -> [a] -> [a]
filter ((ByteString -> [ByteString] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ [Char] -> ByteString
BC.pack [Char]
"PREV", [Char] -> ByteString
BC.pack [Char]
"BASE" ]) (ByteString -> Bool)
-> ((ByteString, RecItem' Complete) -> ByteString)
-> (ByteString, RecItem' Complete)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString, RecItem' Complete) -> ByteString
forall a b. (a, b) -> a
fst) [(ByteString, RecItem' Complete)]
items
    Object
_ -> []


nextGeneration :: [Generation] -> Generation
nextGeneration :: [Generation] -> Generation
nextGeneration = (Generation -> Generation -> Generation)
-> Generation -> [Generation] -> Generation
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Generation -> Generation -> Generation
helper (Int -> Generation
Generation Int
0)
    where helper :: Generation -> Generation -> Generation
helper (Generation Int
c) (Generation Int
n) | Int
c Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
n    = Int -> Generation
Generation (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
                                               | Bool
otherwise = Int -> Generation
Generation Int
c

showGeneration :: Generation -> String
showGeneration :: Generation -> [Char]
showGeneration (Generation Int
x) = Int -> [Char]
forall a. Show a => a -> [Char]
show Int
x

compareGeneration :: Generation -> Generation -> Maybe Ordering
compareGeneration :: Generation -> Generation -> Maybe Ordering
compareGeneration (Generation Int
x) (Generation Int
y) = Ordering -> Maybe Ordering
forall a. a -> Maybe a
Just (Ordering -> Maybe Ordering) -> Ordering -> Maybe Ordering
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Int
x Int
y

generationMax :: Storable a => [Stored a] -> Maybe (Stored a)
generationMax :: forall a. Storable a => [Stored a] -> Maybe (Stored a)
generationMax (Stored a
x : [Stored a]
xs) = Stored a -> Maybe (Stored a)
forall a. a -> Maybe a
Just (Stored a -> Maybe (Stored a)) -> Stored a -> Maybe (Stored a)
forall a b. (a -> b) -> a -> b
$ (Generation, Stored a) -> Stored a
forall a b. (a, b) -> b
snd ((Generation, Stored a) -> Stored a)
-> (Generation, Stored a) -> Stored a
forall a b. (a -> b) -> a -> b
$ ((Generation, Stored a) -> Stored a -> (Generation, Stored a))
-> (Generation, Stored a) -> [Stored a] -> (Generation, Stored a)
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (Generation, Stored a) -> Stored a -> (Generation, Stored a)
forall {a}.
Storable a =>
(Generation, Stored a) -> Stored a -> (Generation, Stored a)
helper (Stored a -> Generation
forall a. Storable a => Stored a -> Generation
storedGeneration Stored a
x, Stored a
x) [Stored a]
xs
    where helper :: (Generation, Stored a) -> Stored a -> (Generation, Stored a)
helper (Generation
mg, Stored a
mx) Stored a
y = let yg :: Generation
yg = Stored a -> Generation
forall a. Storable a => Stored a -> Generation
storedGeneration Stored a
y
                               in case Generation -> Generation -> Maybe Ordering
compareGeneration Generation
mg Generation
yg of
                                       Just Ordering
LT -> (Generation
yg, Stored a
y)
                                       Maybe Ordering
_       -> (Generation
mg, Stored a
mx)
generationMax [] = Maybe (Stored a)
forall a. Maybe a
Nothing

storedGeneration :: Storable a => Stored a -> Generation
storedGeneration :: forall a. Storable a => Stored a -> Generation
storedGeneration Stored a
x =
    IO Generation -> Generation
forall a. IO a -> a
unsafePerformIO (IO Generation -> Generation) -> IO Generation -> Generation
forall a b. (a -> b) -> a -> b
$ MVar (HashTable RealWorld RefDigest Generation)
-> (HashTable RealWorld RefDigest Generation -> IO Generation)
-> IO Generation
forall a b. MVar a -> (a -> IO b) -> IO b
withMVar (Storage -> MVar (BasicHashTable RefDigest Generation)
forall (c :: * -> *).
Storage' c -> MVar (BasicHashTable RefDigest Generation)
stRefGeneration (Storage -> MVar (BasicHashTable RefDigest Generation))
-> Storage -> MVar (BasicHashTable RefDigest Generation)
forall a b. (a -> b) -> a -> b
$ Ref' Complete -> Storage
forall (c :: * -> *). Ref' c -> Storage' c
refStorage (Ref' Complete -> Storage) -> Ref' Complete -> Storage
forall a b. (a -> b) -> a -> b
$ Stored a -> Ref' Complete
forall a. Stored a -> Ref' Complete
storedRef Stored a
x) ((HashTable RealWorld RefDigest Generation -> IO Generation)
 -> IO Generation)
-> (HashTable RealWorld RefDigest Generation -> IO Generation)
-> IO Generation
forall a b. (a -> b) -> a -> b
$ \HashTable RealWorld RefDigest Generation
ht -> do
        let doLookup :: Stored a -> IO Generation
doLookup Stored a
y = BasicHashTable RefDigest Generation
-> RefDigest -> IO (Maybe Generation)
forall (h :: * -> * -> * -> *) k v.
(HashTable h, Eq k, Hashable k) =>
IOHashTable h k v -> k -> IO (Maybe v)
HT.lookup HashTable RealWorld RefDigest Generation
BasicHashTable RefDigest Generation
ht (Ref' Complete -> RefDigest
forall (c :: * -> *). Ref' c -> RefDigest
refDigest (Ref' Complete -> RefDigest) -> Ref' Complete -> RefDigest
forall a b. (a -> b) -> a -> b
$ Stored a -> Ref' Complete
forall a. Stored a -> Ref' Complete
storedRef Stored a
y) IO (Maybe Generation)
-> (Maybe Generation -> IO Generation) -> IO Generation
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
                Just Generation
gen -> Generation -> IO Generation
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Generation
gen
                Maybe Generation
Nothing -> do
                    Generation
gen <- [Generation] -> Generation
nextGeneration ([Generation] -> Generation) -> IO [Generation] -> IO Generation
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Stored a -> IO Generation) -> [Stored a] -> IO [Generation]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM Stored a -> IO Generation
doLookup (Stored a -> [Stored a]
forall a. Storable a => Stored a -> [Stored a]
previous Stored a
y)
                    BasicHashTable RefDigest Generation
-> RefDigest -> Generation -> IO ()
forall (h :: * -> * -> * -> *) k v.
(HashTable h, Eq k, Hashable k) =>
IOHashTable h k v -> k -> v -> IO ()
HT.insert HashTable RealWorld RefDigest Generation
BasicHashTable RefDigest Generation
ht (Ref' Complete -> RefDigest
forall (c :: * -> *). Ref' c -> RefDigest
refDigest (Ref' Complete -> RefDigest) -> Ref' Complete -> RefDigest
forall a b. (a -> b) -> a -> b
$ Stored a -> Ref' Complete
forall a. Stored a -> Ref' Complete
storedRef Stored a
y) Generation
gen
                    Generation -> IO Generation
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Generation
gen
        Stored a -> IO Generation
doLookup Stored a
x


generations :: Storable a => [Stored a] -> [Set (Stored a)]
generations :: forall a. Storable a => [Stored a] -> [Set (Stored a)]
generations = (([Stored a], Set (Stored a))
 -> Maybe (Set (Stored a), ([Stored a], Set (Stored a))))
-> ([Stored a], Set (Stored a)) -> [Set (Stored a)]
forall b a. (b -> Maybe (a, b)) -> b -> [a]
unfoldr ([Stored a], Set (Stored a))
-> Maybe (Set (Stored a), ([Stored a], Set (Stored a)))
forall {a}.
Storable a =>
([Stored a], Set (Stored a))
-> Maybe (Set (Stored a), ([Stored a], Set (Stored a)))
gen (([Stored a], Set (Stored a)) -> [Set (Stored a)])
-> ([Stored a] -> ([Stored a], Set (Stored a)))
-> [Stored a]
-> [Set (Stored a)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (,Set (Stored a)
forall a. Set a
S.empty)
    where gen :: ([Stored a], Set (Stored a))
-> Maybe (Set (Stored a), ([Stored a], Set (Stored a)))
gen ([Stored a]
hs, Set (Stored a)
cur) = case (Stored a -> Bool) -> [Stored a] -> [Stored a]
forall a. (a -> Bool) -> [a] -> [a]
filter (Stored a -> Set (Stored a) -> Bool
forall a. Ord a => a -> Set a -> Bool
`S.notMember` Set (Stored a)
cur) ([Stored a] -> [Stored a]) -> [Stored a] -> [Stored a]
forall a b. (a -> b) -> a -> b
$ Stored a -> [Stored a]
forall a. Storable a => Stored a -> [Stored a]
previous (Stored a -> [Stored a]) -> [Stored a] -> [Stored a]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< [Stored a]
hs of
              []    -> Maybe (Set (Stored a), ([Stored a], Set (Stored a)))
forall a. Maybe a
Nothing
              [Stored a]
added -> let next :: Set (Stored a)
next = (Stored a -> Set (Stored a) -> Set (Stored a))
-> Set (Stored a) -> [Stored a] -> Set (Stored a)
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Stored a -> Set (Stored a) -> Set (Stored a)
forall a. Ord a => a -> Set a -> Set a
S.insert Set (Stored a)
cur [Stored a]
added
                        in (Set (Stored a), ([Stored a], Set (Stored a)))
-> Maybe (Set (Stored a), ([Stored a], Set (Stored a)))
forall a. a -> Maybe a
Just (Set (Stored a)
next, ([Stored a]
added, Set (Stored a)
next))

ancestors :: Storable a => [Stored a] -> Set (Stored a)
ancestors :: forall a. Storable a => [Stored a] -> Set (Stored a)
ancestors = [Set (Stored a)] -> Set (Stored a)
forall a. HasCallStack => [a] -> a
last ([Set (Stored a)] -> Set (Stored a))
-> ([Stored a] -> [Set (Stored a)]) -> [Stored a] -> Set (Stored a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Set (Stored a)
forall a. Set a
S.emptySet (Stored a) -> [Set (Stored a)] -> [Set (Stored a)]
forall a. a -> [a] -> [a]
:) ([Set (Stored a)] -> [Set (Stored a)])
-> ([Stored a] -> [Set (Stored a)])
-> [Stored a]
-> [Set (Stored a)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Stored a] -> [Set (Stored a)]
forall a. Storable a => [Stored a] -> [Set (Stored a)]
generations

precedes :: Storable a => Stored a -> Stored a -> Bool
precedes :: forall a. Storable a => Stored a -> Stored a -> Bool
precedes Stored a
x Stored a
y = Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Stored a
x Stored a -> [Stored a] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Stored a] -> [Stored a]
forall a. Storable a => [Stored a] -> [Stored a]
filterAncestors [Stored a
x, Stored a
y]

filterAncestors :: Storable a => [Stored a] -> [Stored a]
filterAncestors :: forall a. Storable a => [Stored a] -> [Stored a]
filterAncestors [Stored a
x] = [Stored a
x]
filterAncestors [Stored a]
xs = let xs' :: [Stored a]
xs' = [Stored a] -> [Stored a]
forall a. Eq a => [a] -> [a]
uniq ([Stored a] -> [Stored a]) -> [Stored a] -> [Stored a]
forall a b. (a -> b) -> a -> b
$ [Stored a] -> [Stored a]
forall a. Ord a => [a] -> [a]
sort [Stored a]
xs
                      in [Stored a] -> [Stored a] -> [Stored a]
forall {a}. Storable a => [Stored a] -> [Stored a] -> [Stored a]
helper [Stored a]
xs' [Stored a]
xs'
    where helper :: [Stored a] -> [Stored a] -> [Stored a]
helper [Stored a]
remains [Stored a]
walk = case [Stored a] -> Maybe (Stored a)
forall a. Storable a => [Stored a] -> Maybe (Stored a)
generationMax [Stored a]
walk of
                                     Just Stored a
x -> let px :: [Stored a]
px = Stored a -> [Stored a]
forall a. Storable a => Stored a -> [Stored a]
previous Stored a
x
                                                   remains' :: [Stored a]
remains' = (Stored a -> Bool) -> [Stored a] -> [Stored a]
forall a. (a -> Bool) -> [a] -> [a]
filter (\Stored a
r -> (Stored a -> Bool) -> [Stored a] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Stored a -> Stored a -> Bool
forall a. Eq a => a -> a -> Bool
/=Stored a
r) [Stored a]
px) [Stored a]
remains
                                                in [Stored a] -> [Stored a] -> [Stored a]
helper [Stored a]
remains' ([Stored a] -> [Stored a]) -> [Stored a] -> [Stored a]
forall a b. (a -> b) -> a -> b
$ [Stored a] -> [Stored a]
forall a. Eq a => [a] -> [a]
uniq ([Stored a] -> [Stored a]) -> [Stored a] -> [Stored a]
forall a b. (a -> b) -> a -> b
$ [Stored a] -> [Stored a]
forall a. Ord a => [a] -> [a]
sort ([Stored a]
px [Stored a] -> [Stored a] -> [Stored a]
forall a. [a] -> [a] -> [a]
++ (Stored a -> Bool) -> [Stored a] -> [Stored a]
forall a. (a -> Bool) -> [a] -> [a]
filter (Stored a -> Stored a -> Bool
forall a. Eq a => a -> a -> Bool
/=Stored a
x) [Stored a]
walk)
                                     Maybe (Stored a)
Nothing -> [Stored a]
remains

storedRoots :: Storable a => Stored a -> [Stored a]
storedRoots :: forall a. Storable a => Stored a -> [Stored a]
storedRoots Stored a
x = do
    let st :: Storage
st = Ref' Complete -> Storage
forall (c :: * -> *). Ref' c -> Storage' c
refStorage (Ref' Complete -> Storage) -> Ref' Complete -> Storage
forall a b. (a -> b) -> a -> b
$ Stored a -> Ref' Complete
forall a. Stored a -> Ref' Complete
storedRef Stored a
x
    IO [Stored a] -> [Stored a]
forall a. IO a -> a
unsafePerformIO (IO [Stored a] -> [Stored a]) -> IO [Stored a] -> [Stored a]
forall a b. (a -> b) -> a -> b
$ MVar (HashTable RealWorld RefDigest [RefDigest])
-> (HashTable RealWorld RefDigest [RefDigest] -> IO [Stored a])
-> IO [Stored a]
forall a b. MVar a -> (a -> IO b) -> IO b
withMVar (Storage -> MVar (BasicHashTable RefDigest [RefDigest])
forall (c :: * -> *).
Storage' c -> MVar (BasicHashTable RefDigest [RefDigest])
stRefRoots Storage
st) ((HashTable RealWorld RefDigest [RefDigest] -> IO [Stored a])
 -> IO [Stored a])
-> (HashTable RealWorld RefDigest [RefDigest] -> IO [Stored a])
-> IO [Stored a]
forall a b. (a -> b) -> a -> b
$ \HashTable RealWorld RefDigest [RefDigest]
ht -> do
        let doLookup :: Stored a -> IO [RefDigest]
doLookup Stored a
y = BasicHashTable RefDigest [RefDigest]
-> RefDigest -> IO (Maybe [RefDigest])
forall (h :: * -> * -> * -> *) k v.
(HashTable h, Eq k, Hashable k) =>
IOHashTable h k v -> k -> IO (Maybe v)
HT.lookup HashTable RealWorld RefDigest [RefDigest]
BasicHashTable RefDigest [RefDigest]
ht (Ref' Complete -> RefDigest
forall (c :: * -> *). Ref' c -> RefDigest
refDigest (Ref' Complete -> RefDigest) -> Ref' Complete -> RefDigest
forall a b. (a -> b) -> a -> b
$ Stored a -> Ref' Complete
forall a. Stored a -> Ref' Complete
storedRef Stored a
y) IO (Maybe [RefDigest])
-> (Maybe [RefDigest] -> IO [RefDigest]) -> IO [RefDigest]
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
                Just [RefDigest]
roots -> [RefDigest] -> IO [RefDigest]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return [RefDigest]
roots
                Maybe [RefDigest]
Nothing -> do
                    [RefDigest]
roots <- case Stored a -> [Stored a]
forall a. Storable a => Stored a -> [Stored a]
previous Stored a
y of
                        [] -> [RefDigest] -> IO [RefDigest]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return [Ref' Complete -> RefDigest
forall (c :: * -> *). Ref' c -> RefDigest
refDigest (Ref' Complete -> RefDigest) -> Ref' Complete -> RefDigest
forall a b. (a -> b) -> a -> b
$ Stored a -> Ref' Complete
forall a. Stored a -> Ref' Complete
storedRef Stored a
y]
                        [Stored a]
ps -> (Stored Object -> RefDigest) -> [Stored Object] -> [RefDigest]
forall a b. (a -> b) -> [a] -> [b]
map (Ref' Complete -> RefDigest
forall (c :: * -> *). Ref' c -> RefDigest
refDigest (Ref' Complete -> RefDigest)
-> (Stored Object -> Ref' Complete) -> Stored Object -> RefDigest
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Stored Object -> Ref' Complete
forall a. Stored a -> Ref' Complete
storedRef) ([Stored Object] -> [RefDigest])
-> ([[RefDigest]] -> [Stored Object])
-> [[RefDigest]]
-> [RefDigest]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Stored Object] -> [Stored Object]
forall a. Storable a => [Stored a] -> [Stored a]
filterAncestors ([Stored Object] -> [Stored Object])
-> ([[RefDigest]] -> [Stored Object])
-> [[RefDigest]]
-> [Stored Object]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (RefDigest -> Stored Object) -> [RefDigest] -> [Stored Object]
forall a b. (a -> b) -> [a] -> [b]
map (forall a. Storable a => Ref' Complete -> Stored a
wrappedLoad @Object (Ref' Complete -> Stored Object)
-> (RefDigest -> Ref' Complete) -> RefDigest -> Stored Object
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Storage -> RefDigest -> Ref' Complete
forall (c :: * -> *). Storage' c -> RefDigest -> Ref' c
Ref Storage
st) ([RefDigest] -> [Stored Object])
-> ([[RefDigest]] -> [RefDigest])
-> [[RefDigest]]
-> [Stored Object]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[RefDigest]] -> [RefDigest]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[RefDigest]] -> [RefDigest])
-> IO [[RefDigest]] -> IO [RefDigest]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Stored a -> IO [RefDigest]) -> [Stored a] -> IO [[RefDigest]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM Stored a -> IO [RefDigest]
doLookup [Stored a]
ps
                    BasicHashTable RefDigest [RefDigest]
-> RefDigest -> [RefDigest] -> IO ()
forall (h :: * -> * -> * -> *) k v.
(HashTable h, Eq k, Hashable k) =>
IOHashTable h k v -> k -> v -> IO ()
HT.insert HashTable RealWorld RefDigest [RefDigest]
BasicHashTable RefDigest [RefDigest]
ht (Ref' Complete -> RefDigest
forall (c :: * -> *). Ref' c -> RefDigest
refDigest (Ref' Complete -> RefDigest) -> Ref' Complete -> RefDigest
forall a b. (a -> b) -> a -> b
$ Stored a -> Ref' Complete
forall a. Stored a -> Ref' Complete
storedRef Stored a
y) [RefDigest]
roots
                    [RefDigest] -> IO [RefDigest]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return [RefDigest]
roots
        (RefDigest -> Stored a) -> [RefDigest] -> [Stored a]
forall a b. (a -> b) -> [a] -> [b]
map (Ref' Complete -> Stored a
forall a. Storable a => Ref' Complete -> Stored a
wrappedLoad (Ref' Complete -> Stored a)
-> (RefDigest -> Ref' Complete) -> RefDigest -> Stored a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Storage -> RefDigest -> Ref' Complete
forall (c :: * -> *). Storage' c -> RefDigest -> Ref' c
Ref Storage
st) ([RefDigest] -> [Stored a]) -> IO [RefDigest] -> IO [Stored a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Stored a -> IO [RefDigest]
doLookup Stored a
x

walkAncestors :: (Storable a, Monoid m) => (Stored a -> m) -> [Stored a] -> m
walkAncestors :: forall a m.
(Storable a, Monoid m) =>
(Stored a -> m) -> [Stored a] -> m
walkAncestors Stored' Complete a -> m
f = [Stored' Complete a] -> m
helper ([Stored' Complete a] -> m)
-> ([Stored' Complete a] -> [Stored' Complete a])
-> [Stored' Complete a]
-> m
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Stored' Complete a -> Stored' Complete a -> Ordering)
-> [Stored' Complete a] -> [Stored' Complete a]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy Stored' Complete a -> Stored' Complete a -> Ordering
forall {a}. Storable a => Stored a -> Stored a -> Ordering
cmp
  where
    helper :: [Stored' Complete a] -> m
helper (Stored' Complete a
x : Stored' Complete a
y : [Stored' Complete a]
xs) | Stored' Complete a
x Stored' Complete a -> Stored' Complete a -> Bool
forall a. Eq a => a -> a -> Bool
== Stored' Complete a
y = [Stored' Complete a] -> m
helper (Stored' Complete a
x Stored' Complete a -> [Stored' Complete a] -> [Stored' Complete a]
forall a. a -> [a] -> [a]
: [Stored' Complete a]
xs)
    helper (Stored' Complete a
x : [Stored' Complete a]
xs) = Stored' Complete a -> m
f Stored' Complete a
x m -> m -> m
forall a. Semigroup a => a -> a -> a
<> [Stored' Complete a] -> m
helper ((Stored' Complete a -> Stored' Complete a -> Ordering)
-> [Stored' Complete a]
-> [Stored' Complete a]
-> [Stored' Complete a]
forall a. (a -> a -> Ordering) -> [a] -> [a] -> [a]
mergeBy Stored' Complete a -> Stored' Complete a -> Ordering
forall {a}. Storable a => Stored a -> Stored a -> Ordering
cmp ((Stored' Complete a -> Stored' Complete a -> Ordering)
-> [Stored' Complete a] -> [Stored' Complete a]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy Stored' Complete a -> Stored' Complete a -> Ordering
forall {a}. Storable a => Stored a -> Stored a -> Ordering
cmp (Stored' Complete a -> [Stored' Complete a]
forall a. Storable a => Stored a -> [Stored a]
previous Stored' Complete a
x)) [Stored' Complete a]
xs)
    helper [] = m
forall a. Monoid a => a
mempty

    cmp :: Stored a -> Stored a -> Ordering
cmp Stored a
x Stored a
y = case Generation -> Generation -> Maybe Ordering
compareGeneration (Stored a -> Generation
forall a. Storable a => Stored a -> Generation
storedGeneration Stored a
x) (Stored a -> Generation
forall a. Storable a => Stored a -> Generation
storedGeneration Stored a
y) of
                   Just Ordering
LT -> Ordering
GT
                   Just Ordering
GT -> Ordering
LT
                   Maybe Ordering
_ -> Stored a -> Stored a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Stored a
x Stored a
y

findProperty :: forall a b. Storable a => (a -> Maybe b) -> [Stored a] -> [b]
findProperty :: forall a b. Storable a => (a -> Maybe b) -> [Stored a] -> [b]
findProperty a -> Maybe b
sel = (Stored a -> b) -> [Stored a] -> [b]
forall a b. (a -> b) -> [a] -> [b]
map (Maybe b -> b
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe b -> b) -> (Stored a -> Maybe b) -> Stored a -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Maybe b
sel (a -> Maybe b) -> (Stored a -> a) -> Stored a -> Maybe b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Stored a -> a
forall a. Stored a -> a
fromStored) ([Stored a] -> [b])
-> ([Stored a] -> [Stored a]) -> [Stored a] -> [b]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Stored a] -> [Stored a]
forall a. Storable a => [Stored a] -> [Stored a]
filterAncestors ([Stored a] -> [Stored a])
-> ([Stored a] -> [Stored a]) -> [Stored a] -> [Stored a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((a -> Maybe b) -> Stored a -> [Stored a]
forall a b. Storable a => (a -> Maybe b) -> Stored a -> [Stored a]
findPropHeads a -> Maybe b
sel (Stored a -> [Stored a]) -> [Stored a] -> [Stored a]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<<)

findPropertyFirst :: forall a b. Storable a => (a -> Maybe b) -> [Stored a] -> Maybe b
findPropertyFirst :: forall a b. Storable a => (a -> Maybe b) -> [Stored a] -> Maybe b
findPropertyFirst a -> Maybe b
sel = (Stored a -> b) -> Maybe (Stored a) -> Maybe b
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Maybe b -> b
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe b -> b) -> (Stored a -> Maybe b) -> Stored a -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Maybe b
sel (a -> Maybe b) -> (Stored a -> a) -> Stored a -> Maybe b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Stored a -> a
forall a. Stored a -> a
fromStored) (Maybe (Stored a) -> Maybe b)
-> ([Stored a] -> Maybe (Stored a)) -> [Stored a] -> Maybe b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Stored a] -> Maybe (Stored a)
forall a. [a] -> Maybe a
listToMaybe ([Stored a] -> Maybe (Stored a))
-> ([Stored a] -> [Stored a]) -> [Stored a] -> Maybe (Stored a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Stored a] -> [Stored a]
forall a. Storable a => [Stored a] -> [Stored a]
filterAncestors ([Stored a] -> [Stored a])
-> ([Stored a] -> [Stored a]) -> [Stored a] -> [Stored a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((a -> Maybe b) -> Stored a -> [Stored a]
forall a b. Storable a => (a -> Maybe b) -> Stored a -> [Stored a]
findPropHeads a -> Maybe b
sel (Stored a -> [Stored a]) -> [Stored a] -> [Stored a]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<<)

findPropHeads :: forall a b. Storable a => (a -> Maybe b) -> Stored a -> [Stored a]
findPropHeads :: forall a b. Storable a => (a -> Maybe b) -> Stored a -> [Stored a]
findPropHeads a -> Maybe b
sel Stored a
sobj | Just b
_ <- a -> Maybe b
sel (a -> Maybe b) -> a -> Maybe b
forall a b. (a -> b) -> a -> b
$ Stored a -> a
forall a. Stored a -> a
fromStored Stored a
sobj = [Stored a
sobj]
                       | Bool
otherwise = (a -> Maybe b) -> Stored a -> [Stored a]
forall a b. Storable a => (a -> Maybe b) -> Stored a -> [Stored a]
findPropHeads a -> Maybe b
sel (Stored a -> [Stored a]) -> [Stored a] -> [Stored a]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Stored a -> [Stored a]
forall a. Storable a => Stored a -> [Stored a]
previous Stored a
sobj