{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE RankNTypes #-}

-- | Trace store implementations based on different trace types.
module Test.Mutagen.Tracer.Store
  ( -- * Trace backends
    TraceBackend (..)
  , STraceBackend (..)
  , withTraceBackend

    -- * Re-exports
  , TraceStoreImpl (..)
  )
where

import Test.Mutagen.Tracer.Store.API (TraceStoreImpl (..))
import Test.Mutagen.Tracer.Store.Bitmap ()
import Test.Mutagen.Tracer.Store.Tree ()
import Test.Mutagen.Tracer.Store.Types (TraceBackend (..))

{-------------------------------------------------------------------------------
-- * Trace backends
-------------------------------------------------------------------------------}

-- | Singleton version of 'TraceBackend'.
data STraceBackend trace where
  SBitmap :: STraceBackend Bitmap
  STree :: STraceBackend Tree

-- | Eliminate a 'TraceBackend' by providing a continuation that works for all
-- possible trace store implementations.
withTraceBackend
  :: TraceBackend
  -> (forall trace. (TraceStoreImpl trace) => STraceBackend trace -> r)
  -> r
withTraceBackend :: forall r.
TraceBackend
-> (forall (trace :: TraceBackend).
    TraceStoreImpl trace =>
    STraceBackend trace -> r)
-> r
withTraceBackend TraceBackend
backend forall (trace :: TraceBackend).
TraceStoreImpl trace =>
STraceBackend trace -> r
k =
  case TraceBackend
backend of
    TraceBackend
Bitmap -> STraceBackend 'Bitmap -> r
forall (trace :: TraceBackend).
TraceStoreImpl trace =>
STraceBackend trace -> r
k STraceBackend 'Bitmap
SBitmap
    TraceBackend
Tree -> STraceBackend 'Tree -> r
forall (trace :: TraceBackend).
TraceStoreImpl trace =>
STraceBackend trace -> r
k STraceBackend 'Tree
STree