{-# LANGUAGE TypeSynonymInstances, CPP, FlexibleInstances, BangPatterns #-}

-- | This module extends a Par monad with /pedigree/.  That is, it
--   allows a running computation to look up its position in the
--   dynamic binary tree of `fork` calls ("ancestry").

module Control.Monad.Par.Pedigree
 (
   pedigree, ParPedigreeT
 , unpack, runParPedigree
 ) 
 where 

import Control.Monad.Par.Class
import Control.Monad.Par.State
import Control.Monad.Trans.State.Strict as S 

-- It's running slightly better with normal lists for parfib:
#if 0 
import Data.BitList
type BList = BitList
#else
type BList = [Bool]
unpack (Pedigree _ x) = x
cons = (:)
empty = []
#endif

type ParPedigreeT p a = S.StateT Pedigree p a

-- type Pedigree = BList
-- -- | Trivial instance.
-- instance SplittableState Pedigree where
--   splitState bl = (cons False bl, cons True bl)

data Pedigree = 
      Pedigree { ivarCounter :: {-# UNPACK #-} !Int, 
	         treePath    :: !BList }

instance SplittableState Pedigree where
  splitState (Pedigree cnt bl) = 
    (Pedigree cnt (cons False bl), 
     Pedigree cnt (cons True bl))

pedigree :: ParFuture iv p => S.StateT Pedigree p Pedigree
pedigree = S.get

runParPedigree :: Monad p => ParPedigreeT p a -> p a
runParPedigree m = S.evalStateT m (Pedigree 0 empty)