stm-hamt-1.2.0.5: library/StmHamt/Focuses.hs
{-|
Utility focuses.
-}
module StmHamt.Focuses where
import StmHamt.Prelude
import StmHamt.Types
import Focus
import qualified StmHamt.IntOps as IntOps
import qualified StmHamt.Constructors.Branch as BranchConstructors
import qualified PrimitiveExtras.By6Bits as By6Bits
import qualified PrimitiveExtras.SmallArray as SmallArray
onBranchElement :: forall a b. Int -> Int -> (a -> Bool) -> Focus a STM b -> Focus (Branch a) STM b
onBranchElement depth hash testElement elementFocus@(Focus concealElement revealElement) =
let
~(Focus concealLeaves revealLeaves) = SmallArray.onFoundElementFocus testElement (const False) elementFocus
branchesVarFocus :: Int -> Focus (TVar (By6Bits (Branch a))) STM b
branchesVarFocus depth = let
!branchIndex = IntOps.indexAtDepth depth hash
in onTVarValue (By6Bits.onElementAtFocus branchIndex (branchFocus ( depth)))
branchFocus :: Int -> Focus (Branch a) STM b
branchFocus depth = Focus concealBranch revealBranch where
concealBranch = fmap (fmap (fmap (LeavesBranch hash))) concealLeaves
revealBranch = \ case
LeavesBranch leavesHash leavesArray ->
case leavesHash == hash of
True -> fmap (fmap (fmap (LeavesBranch leavesHash))) (revealLeaves leavesArray)
False -> let
interpretChange = \ case
Set !newElement -> Set <$> BranchConstructors.pair (IntOps.nextDepth depth) hash (BranchConstructors.singleton hash newElement) leavesHash (LeavesBranch leavesHash leavesArray)
_ -> return Leave
in concealElement >>= traverse interpretChange
BranchesBranch (Hamt var) -> let
Focus _ revealBranchesVar = branchesVarFocus (IntOps.nextDepth depth)
in fmap (fmap (fmap (BranchesBranch . Hamt))) (revealBranchesVar var)
in branchFocus depth
onHamtElement :: Int -> Int -> (a -> Bool) -> Focus a STM b -> Focus (Hamt a) STM b
onHamtElement depth hash test focus =
let
branchIndex = IntOps.indexAtDepth depth hash
Focus concealBranches revealBranches =
By6Bits.onElementAtFocus branchIndex $
onBranchElement depth hash test focus
concealHamt = let
hamtChangeStm = \ case
Leave -> return Leave
Set !branches -> Set . Hamt <$> newTVar branches
Remove -> Set . Hamt <$> newTVar By6Bits.empty
in concealBranches >>= traverse hamtChangeStm
revealHamt (Hamt branchesVar) = do
branches <- readTVar branchesVar
(result, branchesChange) <- revealBranches branches
case branchesChange of
Leave -> return (result, Leave)
Set !newBranches -> writeTVar branchesVar newBranches $> (result, Leave)
Remove -> writeTVar branchesVar By6Bits.empty $> (result, Leave)
in Focus concealHamt revealHamt