{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}

-- |
-- Module      :   Grisette.Unified.Internal.Util
-- Copyright   :   (c) Sirui Lu 2024
-- License     :   BSD-3-Clause (see the LICENSE file)
--
-- Maintainer  :   siruilu@cs.washington.edu
-- Stability   :   Experimental
-- Portability :   GHC only
module Grisette.Unified.Internal.Util (withMode) where

import Data.Typeable (Typeable, eqT, type (:~:) (Refl))
import Grisette.Unified.Internal.EvalModeTag (EvalModeTag (Con, Sym))

-- | Case analysis on the mode.
withMode ::
  forall mode r.
  (Typeable mode) =>
  ((mode ~ 'Con) => r) ->
  ((mode ~ 'Sym) => r) ->
  r
withMode :: forall (mode :: EvalModeTag) r.
Typeable mode =>
((mode ~ 'Con) => r) -> ((mode ~ 'Sym) => r) -> r
withMode (mode ~ 'Con) => r
con (mode ~ 'Sym) => r
sym = case (forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
forall (a :: EvalModeTag) (b :: EvalModeTag).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT @mode @'Con, forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
forall (a :: EvalModeTag) (b :: EvalModeTag).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT @mode @'Sym) of
  (Just mode :~: 'Con
Refl, Maybe (mode :~: 'Sym)
_) -> r
(mode ~ 'Con) => r
con
  (Maybe (mode :~: 'Con)
_, Just mode :~: 'Sym
Refl) -> r
(mode ~ 'Sym) => r
sym
  (Maybe (mode :~: 'Con), Maybe (mode :~: 'Sym))
_ -> [Char] -> r
forall a. HasCallStack => [Char] -> a
error [Char]
"impossible"