-- * List operations controlled by another list
takeList, dropList, splitAtList, split,
+ dropTail,
-- * For loop
nTimes,
-- * Comparisons
isEqual, eqListBy,
- thenCmp, cmpList, maybePrefixMatch,
+ thenCmp, cmpList,
removeSpaces,
-- * Transitive closures
doesDirNameExist,
modificationTimeIfExists,
- global, consIORef,
+ global, consIORef, globalMVar, globalEmptyMVar,
-- * Filenames and paths
Suffix,
import Panic
-import Data.IORef ( IORef, newIORef )
+import Data.IORef ( IORef, newIORef, atomicModifyIORef )
import System.IO.Unsafe ( unsafePerformIO )
-import Data.IORef ( readIORef, writeIORef )
import Data.List hiding (group)
+import Control.Concurrent.MVar ( MVar, newMVar, newEmptyMVar )
-import qualified Data.List as List ( elem )
#ifdef DEBUG
-import qualified Data.List as List ( notElem )
+import qualified Data.List as List ( elem, notElem )
import FastTypes
#endif
%* *
%************************************************************************
+These booleans are global constants, set by CPP flags. They allow us to
+recompile a single module (this one) to change whether or not debug output
+appears. They sometimes let us avoid even running CPP elsewhere.
+
+It's important that the flags are literal constants (True/False). Then,
+with -0, tests of the flags in other modules will simplify to the correct
+branch of the conditional, thereby dropping debug code altogether when
+the flags are off.
+
\begin{code}
ghciSupported :: Bool
#ifdef GHCI
isIn, isn'tIn :: Eq a => String -> a -> [a] -> Bool
# ifndef DEBUG
-isIn _msg x ys = elem__ x ys
-isn'tIn _msg x ys = notElem__ x ys
-
---these are here to be SPECIALIZEd (automagically)
-elem__ :: Eq a => a -> [a] -> Bool
-elem__ _ [] = False
-elem__ x (y:ys) = x == y || elem__ x ys
-
-notElem__ :: Eq a => a -> [a] -> Bool
-notElem__ _ [] = True
-notElem__ x (y:ys) = x /= y && notElem__ x ys
+isIn _msg x ys = x `elem` ys
+isn'tIn _msg x ys = x `notElem` ys
# else /* DEBUG */
isIn msg x ys
- = elem (_ILIT(0)) x ys
+ = elem100 (_ILIT(0)) x ys
where
- elem _ _ [] = False
- elem i x (y:ys)
+ elem100 _ _ [] = False
+ elem100 i x (y:ys)
| i ># _ILIT(100) = trace ("Over-long elem in " ++ msg)
- (x `List.elem` (y:ys))
- | otherwise = x == y || elem (i +# _ILIT(1)) x ys
+ (x `elem` (y:ys))
+ | otherwise = x == y || elem100 (i +# _ILIT(1)) x ys
isn'tIn msg x ys
- = notElem (_ILIT(0)) x ys
+ = notElem100 (_ILIT(0)) x ys
where
- notElem _ _ [] = True
- notElem i x (y:ys)
+ notElem100 _ _ [] = True
+ notElem100 i x (y:ys)
| i ># _ILIT(100) = trace ("Over-long notElem in " ++ msg)
- (x `List.notElem` (y:ys))
- | otherwise = x /= y && notElem (i +# _ILIT(1)) x ys
+ (x `notElem` (y:ys))
+ | otherwise = x /= y && notElem100 (i +# _ILIT(1)) x ys
# endif /* DEBUG */
\end{code}
where
x `le` y = get_key x < get_key y
-on :: (a -> a -> Ordering) -> (b -> a) -> b -> b -> Ordering
+on :: (a -> a -> c) -> (b -> a) -> b -> b -> c
on cmp sel = \x y -> sel x `cmp` sel y
\end{code}
where
(ys', ys'') = splitAtList xs ys
+-- drop from the end of a list
+dropTail :: Int -> [a] -> [a]
+dropTail n = reverse . drop n . reverse
+
snocView :: [a] -> Maybe ([a],a)
-- Split off the last element
snocView [] = Nothing
\end{code}
\begin{code}
--- This (with a more general type) is Data.List.stripPrefix from GHC 6.8.
--- This definition can be removed once we require at least 6.8 to build.
-maybePrefixMatch :: String -> String -> Maybe String
-maybePrefixMatch [] rest = Just rest
-maybePrefixMatch (_:_) [] = Nothing
-maybePrefixMatch (p:pat) (r:rest)
- | p == r = maybePrefixMatch pat rest
- | otherwise = Nothing
-
removeSpaces :: String -> String
removeSpaces = reverse . dropWhile isSpace . reverse . dropWhile isSpace
\end{code}
\begin{code}
consIORef :: IORef [a] -> a -> IO ()
consIORef var x = do
- xs <- readIORef var
- writeIORef var (x:xs)
+ atomicModifyIORef var (\xs -> (x:xs,()))
+\end{code}
+
+\begin{code}
+globalMVar :: a -> MVar a
+globalMVar a = unsafePerformIO (newMVar a)
+
+globalEmptyMVar :: MVar a
+globalEmptyMVar = unsafePerformIO newEmptyMVar
\end{code}
Module names: