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 = \ a -> liftIO $ newIORef a
{-# INLINE newTcRef #-}

readTcRef :: MonadIO m => TcRef a -> m a
readTcRef = \ ref -> liftIO $ readIORef ref
{-# INLINE readTcRef #-}

writeTcRef :: MonadIO m => TcRef a -> a -> m ()
writeTcRef = \ ref a -> liftIO $ writeIORef ref a
{-# INLINE writeTcRef #-}

updTcRef :: MonadIO m => TcRef a -> (a -> a) -> m ()
updTcRef = \ ref fn -> liftIO $ modifyIORef' ref fn
{-# INLINE updTcRef #-}

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