module GHC.Tc.Types.TcRef (TcRef, newTcRef, readTcRef, writeTcRef, updTcRef, updTcRefM) where

import GHC.Prelude

import Control.Monad.IO.Class
import Data.IORef

-- | Type alias for 'IORef'; the convention is we'll use this for mutable
-- bits of data in the typechecker which are updated during typechecking and
-- returned at the end.
type TcRef a = IORef a

-- The following functions are all marked INLINE so that we
-- don't end up passing a Monad or MonadIO dictionary.

newTcRef :: MonadIO m => a -> m (TcRef a)
newTcRef :: forall (m :: * -> *) a. MonadIO m => a -> m (TcRef a)
newTcRef = \ a
a -> IO (TcRef a) -> m (TcRef a)
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (TcRef a) -> m (TcRef a)) -> IO (TcRef a) -> m (TcRef a)
forall a b. (a -> b) -> a -> b
$ a -> IO (TcRef a)
forall a. a -> IO (IORef a)
newIORef a
a
{-# INLINE newTcRef #-}

readTcRef :: MonadIO m => TcRef a -> m a
readTcRef :: forall (m :: * -> *) a. MonadIO m => TcRef a -> m a
readTcRef = \ TcRef a
ref -> IO a -> m a
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a -> m a) -> IO a -> m a
forall a b. (a -> b) -> a -> b
$ TcRef a -> IO a
forall a. IORef a -> IO a
readIORef TcRef a
ref
{-# INLINE readTcRef #-}

writeTcRef :: MonadIO m => TcRef a -> a -> m ()
writeTcRef :: forall (m :: * -> *) a. MonadIO m => TcRef a -> a -> m ()
writeTcRef = \ TcRef a
ref a
a -> IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ TcRef a -> a -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef TcRef a
ref a
a
{-# INLINE writeTcRef #-}

updTcRef :: MonadIO m => TcRef a -> (a -> a) -> m ()
updTcRef :: forall (m :: * -> *) a. MonadIO m => TcRef a -> (a -> a) -> m ()
updTcRef = \ TcRef a
ref a -> a
fn -> IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ TcRef a -> (a -> a) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef' TcRef a
ref a -> a
fn
{-# INLINE updTcRef #-}

updTcRefM :: MonadIO m => TcRef a -> (a -> m a) -> m ()
updTcRefM :: forall (m :: * -> *) a. MonadIO m => TcRef a -> (a -> m a) -> m ()
updTcRefM TcRef a
ref a -> m a
upd
  = do { contents      <- TcRef a -> m a
forall (m :: * -> *) a. MonadIO m => TcRef a -> m a
readTcRef TcRef a
ref
       ; !new_contents <- upd contents
       ; writeTcRef ref new_contents }
{-# INLINE updTcRefM #-}