{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE OverloadedRecordDot #-}

module MonadicBang.Internal.Effect.Uniques where

import Control.Algebra
import Control.Carrier.State.Strict
import Control.Monad.IO.Class
import Data.Functor
import Data.Tuple

import GHC.Types.Unique
import GHC.Types.Unique.Supply

-- | Uniques provides arbitrarily many unique GHC Uniques

data Uniques m a where
  FreshUnique :: Uniques m Unique

freshUnique :: Has Uniques sig m => m Unique
freshUnique :: forall (sig :: (* -> *) -> * -> *) (m :: * -> *).
Has Uniques sig m =>
m Unique
freshUnique = Uniques m Unique -> m Unique
forall (eff :: (* -> *) -> * -> *) (sig :: (* -> *) -> * -> *)
       (m :: * -> *) a.
(Member eff sig, Algebra sig m) =>
eff m a -> m a
send Uniques m Unique
forall {k} (m :: k). Uniques m Unique
FreshUnique

newtype UniquesC m a = UniquesC {forall (m :: * -> *) a. UniquesC m a -> StateC UniqSupply m a
getUniquesState :: StateC UniqSupply m a}
  deriving newtype ((forall a b. (a -> b) -> UniquesC m a -> UniquesC m b)
-> (forall a b. a -> UniquesC m b -> UniquesC m a)
-> Functor (UniquesC m)
forall a b. a -> UniquesC m b -> UniquesC m a
forall a b. (a -> b) -> UniquesC m a -> UniquesC m b
forall (m :: * -> *) a b.
Functor m =>
a -> UniquesC m b -> UniquesC m a
forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> UniquesC m a -> UniquesC m b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> UniquesC m a -> UniquesC m b
fmap :: forall a b. (a -> b) -> UniquesC m a -> UniquesC m b
$c<$ :: forall (m :: * -> *) a b.
Functor m =>
a -> UniquesC m b -> UniquesC m a
<$ :: forall a b. a -> UniquesC m b -> UniquesC m a
Functor, Functor (UniquesC m)
Functor (UniquesC m) =>
(forall a. a -> UniquesC m a)
-> (forall a b.
    UniquesC m (a -> b) -> UniquesC m a -> UniquesC m b)
-> (forall a b c.
    (a -> b -> c) -> UniquesC m a -> UniquesC m b -> UniquesC m c)
-> (forall a b. UniquesC m a -> UniquesC m b -> UniquesC m b)
-> (forall a b. UniquesC m a -> UniquesC m b -> UniquesC m a)
-> Applicative (UniquesC m)
forall a. a -> UniquesC m a
forall a b. UniquesC m a -> UniquesC m b -> UniquesC m a
forall a b. UniquesC m a -> UniquesC m b -> UniquesC m b
forall a b. UniquesC m (a -> b) -> UniquesC m a -> UniquesC m b
forall a b c.
(a -> b -> c) -> UniquesC m a -> UniquesC m b -> UniquesC m c
forall (m :: * -> *). Monad m => Functor (UniquesC m)
forall (m :: * -> *) a. Monad m => a -> UniquesC m a
forall (m :: * -> *) a b.
Monad m =>
UniquesC m a -> UniquesC m b -> UniquesC m a
forall (m :: * -> *) a b.
Monad m =>
UniquesC m a -> UniquesC m b -> UniquesC m b
forall (m :: * -> *) a b.
Monad m =>
UniquesC m (a -> b) -> UniquesC m a -> UniquesC m b
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> c) -> UniquesC m a -> UniquesC m b -> UniquesC m c
forall (f :: * -> *).
Functor f =>
(forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
$cpure :: forall (m :: * -> *) a. Monad m => a -> UniquesC m a
pure :: forall a. a -> UniquesC m a
$c<*> :: forall (m :: * -> *) a b.
Monad m =>
UniquesC m (a -> b) -> UniquesC m a -> UniquesC m b
<*> :: forall a b. UniquesC m (a -> b) -> UniquesC m a -> UniquesC m b
$cliftA2 :: forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> c) -> UniquesC m a -> UniquesC m b -> UniquesC m c
liftA2 :: forall a b c.
(a -> b -> c) -> UniquesC m a -> UniquesC m b -> UniquesC m c
$c*> :: forall (m :: * -> *) a b.
Monad m =>
UniquesC m a -> UniquesC m b -> UniquesC m b
*> :: forall a b. UniquesC m a -> UniquesC m b -> UniquesC m b
$c<* :: forall (m :: * -> *) a b.
Monad m =>
UniquesC m a -> UniquesC m b -> UniquesC m a
<* :: forall a b. UniquesC m a -> UniquesC m b -> UniquesC m a
Applicative, Applicative (UniquesC m)
Applicative (UniquesC m) =>
(forall a b. UniquesC m a -> (a -> UniquesC m b) -> UniquesC m b)
-> (forall a b. UniquesC m a -> UniquesC m b -> UniquesC m b)
-> (forall a. a -> UniquesC m a)
-> Monad (UniquesC m)
forall a. a -> UniquesC m a
forall a b. UniquesC m a -> UniquesC m b -> UniquesC m b
forall a b. UniquesC m a -> (a -> UniquesC m b) -> UniquesC m b
forall (m :: * -> *). Monad m => Applicative (UniquesC m)
forall (m :: * -> *) a. Monad m => a -> UniquesC m a
forall (m :: * -> *) a b.
Monad m =>
UniquesC m a -> UniquesC m b -> UniquesC m b
forall (m :: * -> *) a b.
Monad m =>
UniquesC m a -> (a -> UniquesC m b) -> UniquesC m b
forall (m :: * -> *).
Applicative m =>
(forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
$c>>= :: forall (m :: * -> *) a b.
Monad m =>
UniquesC m a -> (a -> UniquesC m b) -> UniquesC m b
>>= :: forall a b. UniquesC m a -> (a -> UniquesC m b) -> UniquesC m b
$c>> :: forall (m :: * -> *) a b.
Monad m =>
UniquesC m a -> UniquesC m b -> UniquesC m b
>> :: forall a b. UniquesC m a -> UniquesC m b -> UniquesC m b
$creturn :: forall (m :: * -> *) a. Monad m => a -> UniquesC m a
return :: forall a. a -> UniquesC m a
Monad)

-- | The "mask" (Char) supplied is purely cosmetic, making it easier to figure out where a Unique was born.

--

-- See Note [Uniques for wired-in prelude things and known masks] in GHC.Builtin.Uniques

runUniquesIO :: MonadIO m => Char -> UniquesC m a -> m a
runUniquesIO :: forall (m :: * -> *) a. MonadIO m => Char -> UniquesC m a -> m a
runUniquesIO Char
mask (UniquesC StateC UniqSupply m a
s) = (UniqSupply -> StateC UniqSupply m a -> m a)
-> StateC UniqSupply m a -> UniqSupply -> m a
forall a b c. (a -> b -> c) -> b -> a -> c
flip UniqSupply -> StateC UniqSupply m a -> m a
forall s (m :: * -> *) a. Functor m => s -> StateC s m a -> m a
evalState StateC UniqSupply m a
s (UniqSupply -> m a) -> m UniqSupply -> m a
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO UniqSupply -> m UniqSupply
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Char -> IO UniqSupply
mkSplitUniqSupply Char
mask)

runUniques :: Functor m => UniqSupply -> UniquesC m a -> m a
runUniques :: forall (m :: * -> *) a.
Functor m =>
UniqSupply -> UniquesC m a -> m a
runUniques UniqSupply
uniqSupply (UniquesC StateC UniqSupply m a
s) = UniqSupply -> StateC UniqSupply m a -> m a
forall s (m :: * -> *) a. Functor m => s -> StateC s m a -> m a
evalState UniqSupply
uniqSupply StateC UniqSupply m a
s

instance Algebra sig m => Algebra (Uniques :+: sig) (UniquesC m) where
  alg :: forall (ctx :: * -> *) (n :: * -> *) a.
Functor ctx =>
Handler ctx n (UniquesC m)
-> (:+:) Uniques sig n a -> ctx () -> UniquesC m (ctx a)
alg Handler ctx n (UniquesC m)
hdl (:+:) Uniques sig n a
sig ctx ()
ctx = case (:+:) Uniques sig n a
sig of
    L Uniques n a
FreshUnique -> StateC UniqSupply m (ctx a) -> UniquesC m (ctx a)
forall (m :: * -> *) a. StateC UniqSupply m a -> UniquesC m a
UniquesC (StateC UniqSupply m (ctx a) -> UniquesC m (ctx a))
-> ((UniqSupply -> (UniqSupply, ctx a))
    -> StateC UniqSupply m (ctx a))
-> (UniqSupply -> (UniqSupply, ctx a))
-> UniquesC m (ctx a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UniqSupply -> (UniqSupply, ctx a)) -> StateC UniqSupply m (ctx a)
forall s (sig :: (* -> *) -> * -> *) (m :: * -> *) a.
Has (State s) sig m =>
(s -> (s, a)) -> m a
state ((UniqSupply -> (UniqSupply, ctx a)) -> UniquesC m (ctx a))
-> (UniqSupply -> (UniqSupply, ctx a)) -> UniquesC m (ctx a)
forall a b. (a -> b) -> a -> b
$ (a -> ctx a) -> (UniqSupply, a) -> (UniqSupply, ctx a)
forall a b. (a -> b) -> (UniqSupply, a) -> (UniqSupply, b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (ctx ()
ctx $>) ((UniqSupply, a) -> (UniqSupply, ctx a))
-> (UniqSupply -> (UniqSupply, a))
-> UniqSupply
-> (UniqSupply, ctx a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a, UniqSupply) -> (UniqSupply, a)
forall a b. (a, b) -> (b, a)
swap ((a, UniqSupply) -> (UniqSupply, a))
-> (UniqSupply -> (a, UniqSupply)) -> UniqSupply -> (UniqSupply, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UniqSupply -> (a, UniqSupply)
UniqSupply -> (Unique, UniqSupply)
takeUniqFromSupply
    R sig n a
other -> StateC UniqSupply m (ctx a) -> UniquesC m (ctx a)
forall (m :: * -> *) a. StateC UniqSupply m a -> UniquesC m a
UniquesC (Handler ctx n (StateC UniqSupply m)
-> (:+:) (State UniqSupply) sig n a
-> ctx ()
-> StateC UniqSupply m (ctx a)
forall (ctx :: * -> *) (n :: * -> *) a.
Functor ctx =>
Handler ctx n (StateC UniqSupply m)
-> (:+:) (State UniqSupply) sig n a
-> ctx ()
-> StateC UniqSupply m (ctx a)
forall (sig :: (* -> *) -> * -> *) (m :: * -> *) (ctx :: * -> *)
       (n :: * -> *) a.
(Algebra sig m, Functor ctx) =>
Handler ctx n m -> sig n a -> ctx () -> m (ctx a)
alg ((.getUniquesState) (UniquesC m (ctx x) -> StateC UniqSupply m (ctx x))
-> (ctx (n x) -> UniquesC m (ctx x))
-> ctx (n x)
-> StateC UniqSupply m (ctx x)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ctx (n x) -> UniquesC m (ctx x)
Handler ctx n (UniquesC m)
hdl) (sig n a -> (:+:) (State UniqSupply) sig n a
forall (f :: (* -> *) -> * -> *) (g :: (* -> *) -> * -> *)
       (m :: * -> *) k.
g m k -> (:+:) f g m k
R sig n a
other) ctx ()
ctx)
  {-# INLINE alg #-}