X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=compiler%2Futils%2FUtil.lhs;h=862b46a8e152430679cf96ca01ba5f90b6bc5697;hb=7eb5e29b4a7b6fef55512bc7bf3308e712ca3eba;hp=1d7f7a4ee211d07d366387753d3dab76ef84e383;hpb=262c142b90c94ca1aa577c950a6ceae1f255e2d6;p=ghc-hetmet.git diff --git a/compiler/utils/Util.lhs b/compiler/utils/Util.lhs index 1d7f7a4..862b46a 100644 --- a/compiler/utils/Util.lhs +++ b/compiler/utils/Util.lhs @@ -5,6 +5,13 @@ \section[Util]{Highly random utility functions} \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 Util ( -- general list processing @@ -13,6 +20,7 @@ module Util ( mapFst, mapSnd, mapAndUnzip, mapAndUnzip3, nOfThem, filterOut, partitionWith, splitEithers, + foldl1', lengthExceeds, lengthIs, lengthAtLeast, listLengthCmp, atLength, equalLength, compareLength, @@ -26,7 +34,7 @@ module Util ( nTimes, -- sorting - sortLe, sortWith, + sortLe, sortWith, on, -- transitive closures transitiveClosure, @@ -42,7 +50,7 @@ module Util ( removeSpaces, -- strictness - foldl', seqList, + seqList, -- pairs unzipWith, @@ -65,40 +73,38 @@ module Util ( later, handleDyn, handle, -- Filename utils - Suffix, - splitFilename, suffixOf, basenameOf, joinFileExt, - splitFilenameDir, joinFileName, - splitFilename3, + Suffix, splitLongestPrefix, - replaceFilenameSuffix, directoryOf, filenameOf, - replaceFilenameDirectory, - escapeSpaces, isPathSeparator, + escapeSpaces, parseSearchPath, - normalisePath, platformPath, pgmPath, ) where #include "HsVersions.h" -import Panic ( panic, trace ) import FastTypes +#if defined(DEBUG) || __GLASGOW_HASKELL__ < 604 +import Panic +#endif + import Control.Exception ( Exception(..), finally, catchDyn, throw ) import qualified Control.Exception as Exception import Data.Dynamic ( Typeable ) import Data.IORef ( IORef, newIORef ) import System.IO.Unsafe ( unsafePerformIO ) import Data.IORef ( readIORef, writeIORef ) +import Data.List hiding (group) -import qualified Data.List as List ( elem, notElem ) - -#ifndef DEBUG -import Data.List ( zipWith4 ) +import qualified Data.List as List ( elem ) +#ifdef DEBUG +import qualified Data.List as List ( notElem ) #endif -import Control.Monad ( when ) +import Control.Monad ( unless ) import SYSTEM_IO_ERROR as IO ( catch, isDoesNotExistError ) import System.Directory ( doesDirectoryExist, createDirectory, getModificationTime ) +import System.FilePath hiding ( searchPathSeparator ) import Data.Char ( isUpper, isAlphaNum, isSpace, ord, isDigit ) import Data.Ratio ( (%) ) import System.Time ( ClockTime ) @@ -352,6 +358,16 @@ isn'tIn msg x ys # endif /* DEBUG */ \end{code} +foldl1' was added in GHC 6.4 + +\begin{code} +#if __GLASGOW_HASKELL__ < 604 +foldl1' :: (a -> a -> a) -> [a] -> a +foldl1' f (x:xs) = foldl' f x xs +foldl1' _ [] = panic "foldl1'" +#endif +\end{code} + %************************************************************************ %* * \subsubsection[Utils-Carsten-mergesort]{A mergesort from Carsten} @@ -453,6 +469,10 @@ sortWith :: Ord b => (a->b) -> [a] -> [a] sortWith get_key xs = sortLe le xs where x `le` y = get_key x < get_key y + +on :: (a -> a -> Ordering) -> (b -> a) -> b -> b -> Ordering +on cmp sel = \x y -> sel x `cmp` sel y + \end{code} %************************************************************************ @@ -487,16 +507,6 @@ transitiveClosure succ eq xs %* * %************************************************************************ -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} @@ -596,6 +606,8 @@ cmpList cmp (a:as) (b:bs) \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 @@ -744,17 +756,20 @@ readRational top_s -- Create a hierarchy of directories createDirectoryHierarchy :: FilePath -> IO () +createDirectoryHierarchy dir | isDrive dir = return () -- XXX Hack createDirectoryHierarchy dir = do b <- doesDirectoryExist dir - when (not b) $ do - createDirectoryHierarchy (directoryOf dir) + unless b $ do + createDirectoryHierarchy (takeDirectory dir) createDirectory dir ----------------------------------------------------------------------------- -- Verify that the 'dirname' portion of a FilePath exists. -- doesDirNameExist :: FilePath -> IO Bool -doesDirNameExist fpath = doesDirectoryExist (directoryOf fpath) +doesDirNameExist fpath = case takeDirectory fpath of + "" -> return True -- XXX Hack + dir -> doesDirectoryExist (takeDirectory fpath) -- ----------------------------------------------------------------------------- -- Exception utils @@ -779,49 +794,6 @@ modificationTimeIfExists f = do then return Nothing else ioError e --- -------------------------------------------------------------- --- Filename manipulation - --- Filenames are kept "normalised" inside GHC, using '/' as the path --- separator. On Windows these functions will also recognise '\\' as --- the path separator, but will generally construct paths using '/'. - -type Suffix = String - -splitFilename :: String -> (String,Suffix) -splitFilename f = splitLongestPrefix f (=='.') - -basenameOf :: FilePath -> String -basenameOf = fst . splitFilename - -suffixOf :: FilePath -> Suffix -suffixOf = snd . splitFilename - -joinFileExt :: String -> String -> FilePath -joinFileExt path "" = path -joinFileExt path ext = path ++ '.':ext - --- "foo/bar/xyzzy.ext" -> ("foo/bar", "xyzzy.ext") -splitFilenameDir :: String -> (String,String) -splitFilenameDir str - = let (dir, rest) = splitLongestPrefix str isPathSeparator - (dir', rest') | null rest = (".", dir) - | otherwise = (dir, rest) - in (dir', rest') - --- "foo/bar/xyzzy.ext" -> ("foo/bar", "xyzzy", ".ext") -splitFilename3 :: String -> (String,String,Suffix) -splitFilename3 str - = let (dir, rest) = splitFilenameDir str - (name, ext) = splitFilename rest - in (dir, name, ext) - -joinFileName :: String -> String -> FilePath -joinFileName "" fname = fname -joinFileName "." fname = fname -joinFileName dir "" = dir -joinFileName dir fname = dir ++ '/':fname - -- split a string at the last character where 'pred' is True, -- returning a pair of strings. The first component holds the string -- up (but not including) the last character for which 'pred' returned @@ -839,32 +811,10 @@ splitLongestPrefix str pred where (r_suf, r_pre) = break pred (reverse str) -replaceFilenameSuffix :: FilePath -> Suffix -> FilePath -replaceFilenameSuffix file suf = basenameOf file `joinFileExt` suf - --- directoryOf strips the filename off the input string, returning --- the directory. -directoryOf :: FilePath -> String -directoryOf = fst . splitFilenameDir - --- filenameOf strips the directory off the input string, returning --- the filename. -filenameOf :: FilePath -> String -filenameOf = snd . splitFilenameDir - -replaceFilenameDirectory :: FilePath -> String -> FilePath -replaceFilenameDirectory path dir = dir `joinFileName` filenameOf path - escapeSpaces :: String -> String escapeSpaces = foldr (\c s -> if isSpace c then '\\':c:s else c:s) "" -isPathSeparator :: Char -> Bool -isPathSeparator ch = -#ifdef mingw32_TARGET_OS - ch == '/' || ch == '\\' -#else - ch == '/' -#endif +type Suffix = String -------------------------------------------------------------- -- * Search path @@ -899,39 +849,4 @@ searchPathSeparator = ';' #else searchPathSeparator = ':' #endif - ------------------------------------------------------------------------------ --- Convert filepath into platform / MSDOS form. - --- We maintain path names in Unix form ('/'-separated) right until --- the last moment. On Windows we dos-ify them just before passing them --- to the Windows command. --- --- The alternative, of using '/' consistently on Unix and '\' on Windows, --- proved quite awkward. There were a lot more calls to platformPath, --- and even on Windows we might invoke a unix-like utility (eg 'sh'), which --- interpreted a command line 'foo\baz' as 'foobaz'. - -normalisePath :: String -> String --- Just changes '\' to '/' - -pgmPath :: String -- Directory string in Unix format - -> String -- Program name with no directory separators - -- (e.g. copy /y) - -> String -- Program invocation string in native format - -#if defined(mingw32_HOST_OS) ---------------------- Windows version ------------------ -normalisePath xs = subst '\\' '/' xs -pgmPath dir pgm = platformPath dir ++ '\\' : pgm -platformPath p = subst '/' '\\' p - -subst a b ls = map (\ x -> if x == a then b else x) ls -#else ---------------------- Non-Windows version -------------- -normalisePath xs = xs -pgmPath dir pgm = dir ++ '/' : pgm -platformPath stuff = stuff --------------------------------------------------------- -#endif \end{code}