%
+% (c) The University of Glasgow 2006
% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
%
-\section[UniqSupply]{The @UniqueSupply@ data type and a (monadic) supply thereof}
\begin{code}
+{-# OPTIONS -w #-}
+-- The above warning supression flag is a temporary kludge.
+-- While working on this module you are encouraged to remove it and fix
+-- any warnings in the module. See
+-- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
+-- for details
+
module UniqSupply (
UniqSupply, -- Abstractly
mapUs, mapAndUnzipUs, mapAndUnzip3Us,
thenMaybeUs, mapAccumLUs,
lazyThenUs, lazyMapUs,
+ module MonadUtils, mapAndUnzipM,
+ MonadUnique(..),
mkSplitUniqSupply,
- splitUniqSupply
+ splitUniqSupply, listSplitUniqSupply
) where
#include "HsVersions.h"
import Unique
+import FastTypes
-import GLAEXTS
-import UNSAFE_IO ( unsafeInterleaveIO )
+#if __GLASGOW_HASKELL__ >= 607
+import GHC.IOBase (unsafeDupableInterleaveIO)
+#else
+import System.IO.Unsafe ( unsafeInterleaveIO )
+unsafeDupableInterleaveIO :: IO a -> IO a
+unsafeDupableInterleaveIO = unsafeInterleaveIO
+#endif
-w2i x = word2Int# x
-i2w x = int2Word# x
-i2w_s x = (x :: Int#)
\end{code}
\begin{code}
data UniqSupply
- = MkSplitUniqSupply Int# -- make the Unique with this
+ = MkSplitUniqSupply FastInt -- make the Unique with this
UniqSupply UniqSupply
-- when split => these two supplies
\end{code}
mkSplitUniqSupply :: Char -> IO UniqSupply
splitUniqSupply :: UniqSupply -> (UniqSupply, UniqSupply)
+listSplitUniqSupply :: UniqSupply -> [UniqSupply] -- Infinite
uniqFromSupply :: UniqSupply -> Unique
uniqsFromSupply :: UniqSupply -> [Unique] -- Infinite
\end{code}
\begin{code}
-mkSplitUniqSupply (C# c#)
- = let
-#if __GLASGOW_HASKELL__ >= 503
- mask# = (i2w (ord# c#)) `uncheckedShiftL#` (i2w_s 24#)
-#else
- mask# = (i2w (ord# c#)) `shiftL#` (i2w_s 24#)
-#endif
+mkSplitUniqSupply c
+ = case fastOrd (cUnbox c) `shiftLFastInt` _ILIT(24) of
+ mask -> let
-- here comes THE MAGIC:
-- This is one of the most hammered bits in the whole compiler
- mk_supply#
- = unsafeInterleaveIO (
- genSymZh >>= \ (W# u#) ->
- mk_supply# >>= \ s1 ->
- mk_supply# >>= \ s2 ->
- return (MkSplitUniqSupply (w2i (mask# `or#` u#)) s1 s2)
- )
- in
- mk_supply#
-
-foreign import ccall unsafe "genSymZh" genSymZh :: IO Word
+ mk_supply
+ = unsafeDupableInterleaveIO (
+ genSymZh >>= \ u_ -> case iUnbox u_ of { u -> (
+ mk_supply >>= \ s1 ->
+ mk_supply >>= \ s2 ->
+ return (MkSplitUniqSupply (mask `bitOrFastInt` u) s1 s2)
+ )})
+ in
+ mk_supply
+
+foreign import ccall unsafe "genSymZh" genSymZh :: IO Int
splitUniqSupply (MkSplitUniqSupply _ s1 s2) = (s1, s2)
+listSplitUniqSupply (MkSplitUniqSupply _ s1 s2) = s1 : listSplitUniqSupply s2
\end{code}
\begin{code}
-uniqFromSupply (MkSplitUniqSupply n _ _) = mkUniqueGrimily (I# n)
-uniqsFromSupply (MkSplitUniqSupply n _ s2) = mkUniqueGrimily (I# n) : uniqsFromSupply s2
+uniqFromSupply (MkSplitUniqSupply n _ _) = mkUniqueGrimily (iBox n)
+uniqsFromSupply (MkSplitUniqSupply n _ s2) = mkUniqueGrimily (iBox n) : uniqsFromSupply s2
\end{code}
%************************************************************************
getUs :: UniqSM UniqSupply
getUs = USM (\us -> splitUniqSupply us)
+-- | A monad for generating unique identifiers
+class Monad m => MonadUnique m where
+ -- | Get a new UniqueSupply
+ getUniqueSupplyM :: m UniqSupply
+ -- | Get a new unique identifier
+ getUniqueM :: m Unique
+ -- | Get an infinite list of new unique identifiers
+ getUniquesM :: m [Unique]
+
+ getUniqueM = liftM uniqFromSupply getUniqueSupplyM
+ getUniquesM = liftM uniqsFromSupply getUniqueSupplyM
+
+instance MonadUnique UniqSM where
+ getUniqueSupplyM = USM (\us -> splitUniqSupply us)
+ getUniqueM = getUniqueUs
+ getUniquesM = getUniquesUs
+
getUniqueUs :: UniqSM Unique
getUniqueUs = USM (\us -> case splitUniqSupply us of
(us1,us2) -> (uniqFromSupply us1, us2))