X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2Futils%2FUtil.lhs;h=119ae82059b70fa4ba607cc1b30efbbbecffcbf7;hb=97906cfcc30dd591e840921d336fdabeb1b8a315;hp=cb2c5b673ecbfb9491a2adde173e44615b7acb85;hpb=e74cd017fc700e503c8a0b0e94d8b8f9d8c92510;p=ghc-hetmet.git diff --git a/ghc/compiler/utils/Util.lhs b/ghc/compiler/utils/Util.lhs index cb2c5b6..119ae82 100644 --- a/ghc/compiler/utils/Util.lhs +++ b/ghc/compiler/utils/Util.lhs @@ -1,84 +1,69 @@ % -% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 +% (c) The University of Glasgow 1992-2002 % \section[Util]{Highly random utility functions} \begin{code} --- IF_NOT_GHC is meant to make this module useful outside the context of GHC -#define IF_NOT_GHC(a) - module Util ( -#if NOT_USED - -- The Eager monad - Eager, thenEager, returnEager, mapEager, appEager, runEager, -#endif -- general list processing zipEqual, zipWithEqual, zipWith3Equal, zipWith4Equal, zipLazy, stretchZipWith, mapAndUnzip, mapAndUnzip3, - nOfThem, lengthExceeds, isSingleton, only, + nOfThem, + lengthExceeds, lengthIs, lengthAtLeast, listLengthCmp, atLength, + isSingleton, only, + notNull, + snocView, isIn, isn'tIn, -- for-loop nTimes, - -- maybe-ish - unJust, - -- sorting - IF_NOT_GHC(quicksort COMMA stableSortLt COMMA mergesort COMMA) - sortLt, - IF_NOT_GHC(mergeSort COMMA) naturalMergeSortLe, -- from Carsten - IF_NOT_GHC(naturalMergeSort COMMA mergeSortLe COMMA) + sortLt, naturalMergeSortLe, -- transitive closures transitiveClosure, -- accumulating - mapAccumL, mapAccumR, mapAccumB, foldl2, count, + mapAccumL, mapAccumR, mapAccumB, + foldl2, count, + + takeList, dropList, splitAtList, -- comparisons + eqListBy, equalLength, compareLength, thenCmp, cmpList, prefixMatch, suffixMatch, -- strictness - seqList, ($!), + foldl', seqList, -- pairs - IF_NOT_GHC(cfst COMMA applyToPair COMMA applyToFst COMMA) - IF_NOT_GHC(applyToSnd COMMA foldPair COMMA) - unzipWith - - -- I/O -#if __GLASGOW_HASKELL__ < 402 - , bracket -#endif - - , global - , myGetProcessID - -#if __GLASGOW_HASKELL__ <= 408 - , catchJust - , ioErrors - , throwTo -#endif + unzipWith, + global, ) where +#include "../includes/config.h" #include "HsVersions.h" -import List ( zipWith4 ) -import Maybe ( Maybe(..) ) -import Panic ( panic ) -import IOExts ( IORef, newIORef, unsafePerformIO ) +import Panic ( panic, trace ) import FastTypes + #if __GLASGOW_HASKELL__ <= 408 -import Exception ( catchIO, justIoErrors, raiseInThread ) +import EXCEPTION ( catchIO, justIoErrors, raiseInThread ) #endif -#ifndef mingw32_TARGET_OS -import Posix +import DATA_IOREF ( IORef, newIORef ) +import UNSAFE_IO ( unsafePerformIO ) + +import qualified List ( elem, notElem ) + +#ifndef DEBUG +import List ( zipWith4 ) #endif + infixr 9 `thenCmp` \end{code} @@ -133,18 +118,6 @@ nTimes n f = f . nTimes (n-1) f %************************************************************************ %* * -\subsection{Maybe-ery} -%* * -%************************************************************************ - -\begin{code} -unJust :: String -> Maybe a -> a -unJust who (Just x) = x -unJust who Nothing = panic ("unJust of Nothing, called by " ++ who) -\end{code} - -%************************************************************************ -%* * \subsection[Utils-lists]{General list processing} %* * %************************************************************************ @@ -234,15 +207,57 @@ mapAndUnzip3 f (x:xs) nOfThem :: Int -> a -> [a] nOfThem n thing = replicate n thing +-- 'atLength atLen atEnd ls n' unravels list 'ls' to position 'n'; +-- specification: +-- +-- atLength atLenPred atEndPred ls n +-- | n < 0 = atLenPred n +-- | length ls < n = atEndPred (n - length ls) +-- | otherwise = atLenPred (drop n ls) +-- +atLength :: ([a] -> b) + -> (Int -> b) + -> [a] + -> Int + -> b +atLength atLenPred atEndPred ls n + | n < 0 = atEndPred n + | otherwise = go n ls + where + go n [] = atEndPred n + go 0 ls = atLenPred ls + go n (_:xs) = go (n-1) xs + +-- special cases. lengthExceeds :: [a] -> Int -> Bool --- (lengthExceeds xs n) is True if length xs > n -(x:xs) `lengthExceeds` n = n < 1 || xs `lengthExceeds` (n - 1) -[] `lengthExceeds` n = n < 0 +-- (lengthExceeds xs n) = (length xs > n) +lengthExceeds = atLength notNull (const False) + +lengthAtLeast :: [a] -> Int -> Bool +lengthAtLeast = atLength notNull (== 0) + +lengthIs :: [a] -> Int -> Bool +lengthIs = atLength null (==0) + +listLengthCmp :: [a] -> Int -> Ordering +listLengthCmp = atLength atLen atEnd + where + atEnd 0 = EQ + atEnd x + | x > 0 = LT -- not yet seen 'n' elts, so list length is < n. + | otherwise = GT + + atLen [] = EQ + atLen _ = GT isSingleton :: [a] -> Bool isSingleton [x] = True isSingleton _ = False +notNull :: [a] -> Bool +notNull [] = False +notNull _ = True + only :: [a] -> a #ifdef DEBUG only [a] = a @@ -281,19 +296,19 @@ isIn msg x ys where elem i _ [] = False elem i x (y:ys) - | i ># _ILIT 100 = panic ("Over-long elem in: " ++ msg) - | otherwise = x == y || elem (i +# _ILIT(1)) x ys + | i ># _ILIT 100 = trace ("Over-long elem in " ++ msg) $ + x `List.elem` (y:ys) + | otherwise = x == y || elem (i +# _ILIT(1)) x ys isn'tIn msg x ys = notElem (_ILIT 0) x ys where notElem i x [] = True notElem i x (y:ys) - | i ># _ILIT 100 = panic ("Over-long notElem in: " ++ msg) - | otherwise = x /= y && notElem (i +# _ILIT(1)) x ys - + | i ># _ILIT 100 = trace ("Over-long notElem in " ++ msg) $ + x `List.notElem` (y:ys) + | otherwise = x /= y && notElem (i +# _ILIT(1)) x ys # endif {- DEBUG -} - \end{code} %************************************************************************ @@ -330,8 +345,6 @@ Quicksort variant from Lennart's Haskell-library contribution. This is a {\em stable} sort. \begin{code} -stableSortLt = sortLt -- synonym; when we want to highlight stable-ness - sortLt :: (a -> a -> Bool) -- Less-than predicate -> [a] -- Input list -> [a] -- Result list @@ -513,12 +526,15 @@ generalMergeSort p xs = (balancedFold (generalMerge p) . map (: [])) xs generalNaturalMergeSort p [] = [] generalNaturalMergeSort p xs = (balancedFold (generalMerge p) . group p) xs +#if NOT_USED mergeSort, naturalMergeSort :: Ord a => [a] -> [a] mergeSort = generalMergeSort (<=) naturalMergeSort = generalNaturalMergeSort (<=) mergeSortLe le = generalMergeSort le +#endif + naturalMergeSortLe le = generalNaturalMergeSort le \end{code} @@ -610,6 +626,16 @@ mapAccumB f a b (x:xs) = (a'',b'',y:ys) (a'',b',ys) = mapAccumB f a' b xs \end{code} +A strict version of foldl. + +\begin{code} +foldl' :: (a -> b -> a) -> a -> [b] -> a +foldl' f z xs = lgo z xs + where + lgo z [] = z + lgo z (x:xs) = (lgo $! (f z x)) xs +\end{code} + A combination of foldl with zip. It works with equal length lists. \begin{code} @@ -627,6 +653,32 @@ count p (x:xs) | p x = 1 + count p xs | otherwise = count p xs \end{code} +@splitAt@, @take@, and @drop@ but with length of another +list giving the break-off point: + +\begin{code} +takeList :: [b] -> [a] -> [a] +takeList [] _ = [] +takeList (_:xs) ls = + case ls of + [] -> [] + (y:ys) -> y : takeList xs ys + +dropList :: [b] -> [a] -> [a] +dropList [] xs = xs +dropList _ xs@[] = xs +dropList (_:xs) (_:ys) = dropList xs ys + + +splitAtList :: [b] -> [a] -> ([a], [a]) +splitAtList [] xs = ([], xs) +splitAtList _ xs@[] = (xs, xs) +splitAtList (_:xs) (y:ys) = (y:ys', ys'') + where + (ys', ys'') = splitAtList xs ys + +\end{code} + %************************************************************************ %* * @@ -635,6 +687,22 @@ count p (x:xs) | p x = 1 + count p xs %************************************************************************ \begin{code} +eqListBy :: (a->a->Bool) -> [a] -> [a] -> Bool +eqListBy eq [] [] = True +eqListBy eq (x:xs) (y:ys) = eq x y && eqListBy eq xs ys +eqListBy eq xs ys = False + +equalLength :: [a] -> [b] -> Bool +equalLength [] [] = True +equalLength (_:xs) (_:ys) = equalLength xs ys +equalLength xs ys = False + +compareLength :: [a] -> [b] -> Ordering +compareLength [] [] = EQ +compareLength (_:xs) (_:ys) = compareLength xs ys +compareLength [] _ys = LT +compareLength _xs [] = GT + thenCmp :: Ordering -> Ordering -> Ordering {-# INLINE thenCmp #-} thenCmp EQ any = any @@ -670,14 +738,17 @@ suffixMatch pat str = prefixMatch (reverse pat) (reverse str) The following are curried versions of @fst@ and @snd@. \begin{code} +#if NOT_USED cfst :: a -> b -> a -- stranal-sem only (Note) cfst x y = x +#endif \end{code} The following provide us higher order functions that, when applied to a function, operate on pairs. \begin{code} +#if NOT_USED applyToPair :: ((a -> c),(b -> d)) -> (a,b) -> (c,d) applyToPair (f,g) (x,y) = (f x, g y) @@ -686,6 +757,7 @@ applyToFst f (x,y) = (f x,y) applyToSnd :: (b -> d) -> (a,b) -> (a,d) applyToSnd f (x,y) = (x,f y) +#endif foldPair :: (a->a->a,b->b->b) -> (a,b) -> [(a,b)] -> (a,b) foldPair fg ab [] = ab @@ -699,29 +771,9 @@ unzipWith f pairs = map ( \ (a, b) -> f a b ) pairs \end{code} \begin{code} -#if __HASKELL1__ > 4 seqList :: [a] -> b -> b -#else -seqList :: (Eval a) => [a] -> b -> b -#endif seqList [] b = b seqList (x:xs) b = x `seq` seqList xs b - -#if __HASKELL1__ <= 4 -($!) :: (Eval a) => (a -> b) -> a -> b -f $! x = x `seq` f x -#endif -\end{code} - -\begin{code} -#if __GLASGOW_HASKELL__ < 402 -bracket :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c -bracket before after thing = do - a <- before - r <- (thing a) `catch` (\err -> after a >> fail err) - after a - return r -#endif \end{code} Global variables: @@ -730,20 +782,3 @@ Global variables: global :: a -> IORef a global a = unsafePerformIO (newIORef a) \end{code} - -Compatibility stuff: - -\begin{code} -#if __GLASGOW_HASKELL__ <= 408 -catchJust = catchIO -ioErrors = justIoErrors -throwTo = raiseInThread -#endif - -#ifdef mingw32_TARGET_OS -foreign import "_getpid" myGetProcessID :: IO Int -#else -myGetProcessID :: IO Int -myGetProcessID = Posix.getProcessID -#endif -\end{code}